<?php
if (!function_exists('json_encode')) {
	function json_encode($data) {
		switch (gettype($data)) {
			case 'boolean':
				return $data ? 'true' : 'false';
			case 'integer':
			case 'double':
				return $data;
			case 'resource':
			case 'string':
				# Escape non-printable or Non-ASCII characters.
				# I also put the \\ character first, as suggested in comments on the 'addclashes' page.
				$json = '';

				$string = '"' . addcslashes($data, "\\\"\n\r\t/" . chr(8) . chr(12)) . '"';

				# Convert UTF-8 to Hexadecimal Codepoints.
				for ($i = 0; $i < strlen($string); $i++) {
					$char = $string[$i];
					$c1 = ord($char);

					# Single byte;
					if ($c1 < 128) {
						$json .= ($c1 > 31) ? $char : sprintf("\\u%04x", $c1);

						continue;
					}

					# Double byte
					$c2 = ord($string[++$i]);

					if (($c1 & 32) === 0) {
						$json .= sprintf("\\u%04x", ($c1 - 192) * 64 + $c2 - 128);

						continue;
					}

					# Triple
					$c3 = ord($string[++$i]);

					if (($c1 & 16) === 0) {
						$json .= sprintf("\\u%04x", (($c1 - 224) <<12) + (($c2 - 128) << 6) + ($c3 - 128));

						continue;
					}

					# Quadruple
					$c4 = ord($string[++$i]);

					if (($c1 & 8 ) === 0) {
						$u = (($c1 & 15) << 2) + (($c2 >> 4) & 3) - 1;

						$w1 = (54 << 10) + ($u << 6) + (($c2 & 15) << 2) + (($c3 >> 4) & 3);
						$w2 = (55 << 10) + (($c3 & 15) << 6) + ($c4 - 128);

						$json .= sprintf("\\u%04x\\u%04x", $w1, $w2);
					}
				}

				return $json;
			case 'array':
				if (empty($data) || array_keys($data) === range(0, sizeof($data) - 1)) {
					$output = array();

					foreach ($data as $value) {
						$output[] = json_encode($value);
					}

					return '[' . implode(',', $output) . ']';
				}
			case 'object':
				$output = array();

				foreach ($data as $key => $value) {
					$output[] = json_encode(strval($key)) . ':' . json_encode($value);
				}

				return '{' . implode(',', $output) . '}';
			default:
				return 'null';
		}
	}
}

if (!function_exists('json_decode')) {
	function json_decode($json, $assoc = false) {
		$match = '/".*?(?<!\\\\)"/';

		$string = preg_replace($match, '', $json);
		$string = preg_replace('/[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/', '', $string);

		if ($string != '') {
			return null;
		}

		$s2m = array();
		$m2s = array();

		preg_match_all($match, $json, $m);

		foreach ($m[0] as $s) {
			$hash = '"' . md5($s) . '"';
			$s2m[$s] = $hash;
			$m2s[$hash] = str_replace('$', '\$', $s);
		}

		$json = strtr($json, $s2m);

		$a = ($assoc) ? '' : '(object) ';

		$data = array(
			':' => '=>',
			'[' => 'array(',
			'{' => "{$a}array(",
			']' => ')',
			'}' => ')'
		);

		$json = strtr($json, $data);

		$json = preg_replace('~([\s\(,>])(-?)0~', '$1$2', $json);

		$json = strtr($json, $m2s);

		$function = @create_function('', "return {$json};");
		$return = ($function) ? $function() : null;

		unset($s2m);
		unset($m2s);
		unset($function);

		return $return;
	}
}