_encodeValue($value); } function _encodeArray(&$array) { $tmpArray = array(); // Check for associative array if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) { // Associative array $result = '{'; foreach ($array as $key => $value) { $key = (string) $key; $tmpArray[] = $this->_encodeString($key) . ':' . $this->_encodeValue($value); } $result .= implode(',', $tmpArray); $result .= '}'; } else { // Indexed array $result = '['; $length = count($array); for ($i = 0; $i < $length; ++$i) { $tmpArray[] = $this->_encodeValue($array[$i]); } $result .= implode(',', $tmpArray); $result .= ']'; } return $result; } function _encodeValue(&$value) { if (is_array($value)) { return $this->_encodeArray($value); } else if (is_int($value) || is_float($value)) { return (string) $value; } else if (is_string($value)) { return $this->_encodeString($value); } else if (is_bool($value)) { return $value ? 'true' : 'false'; } } function _encodeString(&$string) { // Escape these characters with a backslash: // " \ / \n \r \t \b \f $search = array('\\', "\n", "\t", "\r", "\b", "\f", '"'); $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'); $string = str_replace($search, $replace, $string); // Escape certain ASCII characters: // 0x08 => \b // 0x0c => \f $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string); return '"' . $string . '"'; } /** * Constructor * * @param string $source String source to decode * @param int $decodeType How objects should be decoded -- see * {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for * valid values * @return void */ function decode($source) { // Set defaults $this->_source = $source; $this->_sourceLength = strlen($source); $this->_token = EOF; $this->_offset = 0; // Set pointer at first token $this->_getNextToken(); return $this->_decodeValue(); } /** * Recursive driving rountine for supported toplevel tops * * @return mixed */ function _decodeValue() { switch ($this->_token) { case DATUM: $result = $this->_tokenValue; $this->_getNextToken(); return $result; break; case LBRACE: return $this->_decodeObject(); break; case LBRACKET: return $this->_decodeArray(); break; default: return null; break; } } /** * Decodes an object of the form: * { "attribute: value, "attribute2" : value,...} * * If ZJsonEnoder or ZJAjax was used to encode the original object * then a special attribute called __className which specifies a class * name that should wrap the data contained within the encoded source. * * Decodes to either an array or StdClass object, based on the value of * {@link $_decodeType}. If invalid $_decodeType present, returns as an * array. * * @return array|StdClass */ function _decodeObject() { $result = array(); $tok = $this->_getNextToken(); while ($tok && $tok != RBRACE) { $key = $this->_tokenValue; $this->_getNextToken(); $tok = $this->_getNextToken(); $result[$key] = $this->_decodeValue(); $tok = $this->_token; if ($tok == RBRACE) { break; } $tok = $this->_getNextToken(); } $this->_getNextToken(); return $result; } /** * Decodes a JSON array format: * [element, element2,...,elementN] * * @return array */ function _decodeArray() { $result = array(); $tok = $this->_getNextToken(); // Move past the '[' $index = 0; while ($tok && $tok != RBRACKET) { $result[$index++] = $this->_decodeValue(); $tok = $this->_token; if ($tok == RBRACKET || !$tok) { break; } $tok = $this->_getNextToken(); } $this->_getNextToken(); return $result; } /** * Retrieves the next token from the source stream * * @return int Token constant value specified in class definition */ function _getNextToken() { $this->_token = EOF; $this->_tokenValue = null; if (preg_match('/([\t\b\f\n\r ]+)/', $this->_source, $matches, PREG_OFFSET_CAPTURE, $this->_offset) && $matches[0][1] == $this->_offset) { $this->_offset += strlen($matches[0][0]); } if ($this->_offset >= $this->_sourceLength) { return EOF; } $str = $this->_source; $str_length = $this->_sourceLength; $i = $this->_offset; $start = $i; switch ($str[$i]) { case '{': $this->_token = LBRACE; break; case '}': $this->_token = RBRACE; break; case '[': $this->_token = LBRACKET; break; case ']': $this->_token = RBRACKET; break; case ',': $this->_token = COMMA; break; case ':': $this->_token = COLON; break; case '"': $result = ''; do { if ($i++ >= $str_length) { break; } $chr = $str[$i]; if ($chr == '\\') { if ($i++ >= $str_length) { break; } $chr = $str[$i]; switch ($chr) { case '"' : $result .= '"'; break; case '\\': $result .= '\\'; break; case '/' : $result .= '/'; break; case 'b' : $result .= chr(8); break; case 'f' : $result .= chr(12); break; case 'n' : $result .= chr(10); break; case 'r' : $result .= chr(13); break; case 't' : $result .= chr(9); break; } } else if ($chr == '"') { break; } else { $result .= $chr; } } while ($i < $str_length); $this->_token = DATUM; //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1); $this->_tokenValue = $result; break; case 't': if (($i + 3) < $str_length && substr($str, $start, 4) == 'true') { $this->_token = DATUM; } $this->_tokenValue = true; $i += 3; break; case 'f': if (($i + 4) < $str_length && substr($str, $start, 5) == 'false') { $this->_token = DATUM; } $this->_tokenValue = false; $i += 4; break; case 'n': if (($i + 3) < $str_length && substr($str, $start, 4) == 'null') { $this->_token = DATUM; } $this->_tokenValue = NULL; $i += 3; break; } if ($this->_token != EOF) { $this->_offset = $i + 1; // Consume the last token character return($this->_token); } $chr = $str[$i]; if (preg_match('/-?([0-9]*)(\.[0-9]*)?(([eE])[-+]?[0-9]+)?/s', $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) { $datum = $matches[0][0]; $val = intval($datum); $fVal = floatval($datum); $this->_tokenValue = ($val == $fVal ? $val : $fVal); $this->_token = DATUM; $this->_offset = $start + strlen($datum); } return($this->_token); } } } ?>