diff --git a/JSON/Makefile b/JSON/Makefile index 3bd143d60..a539c1a21 100644 --- a/JSON/Makefile +++ b/JSON/Makefile @@ -10,15 +10,9 @@ include $(POCO_BASE)/build/rules/global INCLUDE += -I $(POCO_BASE)/JSON/include/Poco/JSON -POCO_JSON_PARSER := $(if $(POCO_JSON_PARSER),$(POCO_JSON_PARSER),PD_JSON_PARSER) - objects = Array Object Parser ParserImpl Handler \ Stringifier ParseHandler PrintHandler Query \ - JSONException Template TemplateCache - -ifeq ($(POCO_JSON_PARSER),PD_JSON_PARSER) - objects += pd_json -endif + JSONException Template TemplateCache pd_json target = PocoJSON target_version = $(LIBVERSION) diff --git a/JSON/include/Poco/JSON/ParserImpl.h b/JSON/include/Poco/JSON/ParserImpl.h index 5a09a7dce..02d2d5f9a 100644 --- a/JSON/include/Poco/JSON/ParserImpl.h +++ b/JSON/include/Poco/JSON/ParserImpl.h @@ -28,23 +28,15 @@ #include "Poco/UTF8Encoding.h" #include "Poco/Dynamic/Var.h" #include +extern "C" { +#include "pd_json.h" +} -//#define JSON_ORG_PARSER -#define PD_JSON_PARSER - -#ifdef PD_JSON_PARSER - extern "C" { - #include "pd_json.h" - } -#endif namespace Poco { namespace JSON { -#ifdef PD_JSON_PARSER - - class JSON_API ParserImpl { protected: @@ -203,699 +195,6 @@ inline Dynamic::Var ParserImpl::asVarImpl() const } -#elif defined(JSON_ORG_PARSER) - - -/* -Copyright (c) 2005 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - - -class JSON_API ParserImpl -{ -protected: - typedef std::char_traits CharTraits; - typedef CharTraits::int_type CharIntType; - - enum Classes - { - C_SPACE, /* space */ - C_WHITE, /* other whitespace */ - C_LCURB, /* { */ - C_RCURB, /* } */ - C_LSQRB, /* [ */ - C_RSQRB, /* ] */ - C_COLON, /* : */ - C_COMMA, /* , */ - C_QUOTE, /* " */ - C_BACKS, /* \ */ - C_SLASH, /* / */ - C_PLUS, /* + */ - C_MINUS, /* - */ - C_POINT, /* . */ - C_ZERO , /* 0 */ - C_DIGIT, /* 123456789 */ - C_LOW_A, /* a */ - C_LOW_B, /* b */ - C_LOW_C, /* c */ - C_LOW_D, /* d */ - C_LOW_E, /* e */ - C_LOW_F, /* f */ - C_LOW_L, /* l */ - C_LOW_N, /* n */ - C_LOW_R, /* r */ - C_LOW_S, /* s */ - C_LOW_T, /* t */ - C_LOW_U, /* u */ - C_ABCDF, /* ABCDF */ - C_E, /* E */ - C_ETC, /* everything else */ - C_STAR, /* * */ - NR_CLASSES - }; - - enum States - /// State codes - { - GO, /* start */ - OK, /* ok */ - OB, /* object */ - KE, /* key */ - CO, /* colon */ - VA, /* value */ - AR, /* array */ - ST, /* string */ - EC, /* escape */ - U1, /* u1 */ - U2, /* u2 */ - U3, /* u3 */ - U4, /* u4 */ - MI, /* minus */ - ZE, /* zero */ - IT, /* integer */ - FR, /* fraction */ - E1, /* e */ - E2, /* ex */ - E3, /* exp */ - T1, /* tr */ - T2, /* tru */ - T3, /* true */ - F1, /* fa */ - F2, /* fal */ - F3, /* fals */ - F4, /* false */ - N1, /* nu */ - N2, /* nul */ - N3, /* null */ - C1, /* / */ - C2, /* / * */ - C3, /* * */ - FX, /* *.* *eE* */ - D1, /* second UTF-16 character decoding started by \ */ - D2, /* second UTF-16 character proceeded by u */ - NR_STATES - }; - - enum Modes - /// Modes that can be pushed on the _pStack. - { - MODE_ARRAY = 1, - MODE_DONE = 2, - MODE_KEY = 3, - MODE_OBJECT = 4 - }; - - enum Actions - { - CB = -10, /* _comment begin */ - CE = -11, /* _comment end */ - FA = -12, /* 0 */ - TR = -13, /* 0 */ - NU = -14, /* null */ - DE = -15, /* double detected by exponent e E */ - DF = -16, /* double detected by fraction . */ - SB = -17, /* string begin */ - MX = -18, /* integer detected by minus */ - ZX = -19, /* integer detected by zero */ - IX = -20, /* integer detected by 1-9 */ - EX = -21, /* next char is _escaped */ - UC = -22 /* Unicode character read */ - }; - - enum JSONType - { - JSON_T_NONE = 0, - JSON_T_INTEGER, - JSON_T_FLOAT, - JSON_T_NULL, - JSON_T_TRUE, - JSON_T_FALSE, - JSON_T_STRING, - JSON_T_MAX - }; - - static const std::size_t JSON_PARSE_BUFFER_SIZE = 4096; - static const std::size_t JSON_PARSER_STACK_SIZE = 128; - static const int JSON_UNLIMITED_DEPTH = -1; - - ParserImpl(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE); - /// Creates JSON ParserImpl, using the given Handler and buffer size. - - virtual ~ParserImpl(); - /// Destroys JSON ParserImpl. - - void resetImpl(); - /// Resets the parser. - - void setAllowCommentsImpl(bool comments); - /// Allow or disallow comments. By default, comments are not allowed. - - bool getAllowCommentsImpl() const; - /// Returns true if comments are allowed, false otherwise. - /// - /// By default, comments are not allowed. - - void setAllowNullByteImpl(bool nullByte); - /// Allow or disallow null byte in strings. - /// - /// By default, null byte is allowed. - - bool getAllowNullByteImpl() const; - /// Returns true if null byte is allowed, false otherwise. - /// - /// By default, null bytes are allowed. - - void setDepthImpl(std::size_t depth); - /// Sets the allowed JSON depth. - - std::size_t getDepthImpl() const; - /// Returns the allowed JSON depth. - - Dynamic::Var parseImpl(const std::string& json); - /// Parses JSON from a string. - - Dynamic::Var parseImpl(std::istream& in); - /// Parses JSON from an input stream. - - void setHandlerImpl(const Handler::Ptr& pHandler); - /// Set the Handler. - - const Handler::Ptr& getHandlerImpl(); - /// Returns the Handler. - - Dynamic::Var asVarImpl() const; - /// Returns the result of parsing; - - Dynamic::Var resultImpl() const; - /// Returns the result of parsing as Dynamic::Var; - -private: - ParserImpl(const ParserImpl&); - ParserImpl& operator = (const ParserImpl&); - - typedef Poco::Buffer BufType; - - bool push(int mode); - /// Push a mode onto the _pStack. Return false if there is overflow. - - bool pop(int mode); - /// Pops the stack, assuring that the current mode matches the expectation. - /// Returns false if there is underflow or if the modes mismatch. - - void growBuffer(); - void clearBuffer(); - void parseBufferPushBackChar(char c); - void parseBufferPopBackChar(); - void addCharToParseBuffer(CharIntType nextChar, int nextClass); - void addEscapedCharToParseBuffer(CharIntType nextChar); - CharIntType decodeUnicodeChar(); - void assertNotStringNullBool(); - void assertNonContainer(); - void parseBuffer(); - - template - class Source - { - public: - Source(const IT& it, const IT& end) : _it(it), _end(end) - { - } - - ~Source() - { - } - - bool nextChar(CharIntType& c) - { - if (_it == _end) return false; - c = *_it; - ++_it; - return true; - } - - private: - IT _it; - IT _end; - }; - - template - bool parseChar(CharIntType nextChar, S& source) - /// Called for each character (or partial character) in JSON string. - /// It accepts UTF-8, UTF-16, or UTF-32. If the character is accepted, - /// it returns true, otherwise false. - { - CharIntType nextClass, nextState; - unsigned char ch = static_cast(CharTraits::to_char_type(nextChar)); - - // Determine the character's class. - if (!_allowNullByte && ch == 0) return false; - if (ch >= 0x80) - { - nextClass = C_ETC; - CharIntType count = utf8CheckFirst(nextChar); - if (!count) - { - throw Poco::JSON::JSONException("Bad character."); - } - - char buffer[4]; - buffer[0] = nextChar; - for (int i = 1; i < count; ++i) - { - int c = 0; - if (!source.nextChar(c)) throw Poco::JSON::JSONException("Invalid UTF8 sequence found"); - buffer[i] = c; - } - - if (!Poco::UTF8Encoding::isLegal((unsigned char*) buffer, count)) - { - throw Poco::JSON::JSONException("No legal UTF8 found"); - } - - for (int i = 0; i < count; ++i) - { - parseBufferPushBackChar(buffer[i]); - } - return true; - } - else - { - nextClass = _asciiClass[nextChar]; - if (nextClass <= xx) return false; - } - - addCharToParseBuffer(nextChar, nextClass); - - // Get the next _state from the _state transition table. - nextState = _stateTransitionTable[_state][nextClass]; - if (nextState >= 0) - { - _state = nextState; - } - else - { - // Or perform one of the actions. - switch (nextState) - { - // Unicode character - case UC: - if (!decodeUnicodeChar()) return false; - // check if we need to read a second UTF-16 char - if (_utf16HighSurrogate) _state = D1; - else _state = ST; - break; - // _escaped char - case EX: - _escaped = 1; - _state = EC; - break; - // integer detected by minus - case MX: - _type = JSON_T_INTEGER; - _state = MI; - break; - // integer detected by zero - case ZX: - _type = JSON_T_INTEGER; - _state = ZE; - break; - // integer detected by 1-9 - case IX: - _type = JSON_T_INTEGER; - _state = IT; - break; - // floating point number detected by exponent - case DE: - assertNotStringNullBool(); - _type = JSON_T_FLOAT; - _state = E1; - break; - // floating point number detected by fraction - case DF: - assertNotStringNullBool(); - _type = JSON_T_FLOAT; - _state = FX; - break; - // string begin " - case SB: - clearBuffer(); - poco_assert(_type == JSON_T_NONE); - _type = JSON_T_STRING; - _state = ST; - break; - - // n - case NU: - poco_assert(_type == JSON_T_NONE); - _type = JSON_T_NULL; - _state = N1; - break; - // f - case FA: - poco_assert(_type == JSON_T_NONE); - _type = JSON_T_FALSE; - _state = F1; - break; - // t - case TR: - poco_assert(_type == JSON_T_NONE); - _type = JSON_T_TRUE; - _state = T1; - break; - - // closing comment - case CE: - _comment = 0; - poco_assert(_parseBuffer.size() == 0); - poco_assert(_type == JSON_T_NONE); - _state = _beforeCommentState; - break; - - // opening comment - case CB: - if (!_allowComments) return false; - parseBufferPopBackChar(); - parseBuffer(); - poco_assert(_parseBuffer.size() == 0); - poco_assert(_type != JSON_T_STRING); - switch (_stack[_top]) - { - case MODE_ARRAY: - case MODE_OBJECT: - switch (_state) - { - case VA: - case AR: - _beforeCommentState = _state; - break; - default: - _beforeCommentState = OK; - break; - } - break; - default: - _beforeCommentState = _state; - break; - } - _type = JSON_T_NONE; - _state = C1; - _comment = 1; - break; - // empty } - case -9: - { - clearBuffer(); - if (_pHandler) _pHandler->endObject(); - - if (!pop(MODE_KEY)) return false; - _state = OK; - break; - } - // } - case -8: - { - parseBufferPopBackChar(); - parseBuffer(); - if (_pHandler) _pHandler->endObject(); - if (!pop(MODE_OBJECT)) return false; - _type = JSON_T_NONE; - _state = OK; - break; - } - // ] - case -7: - { - parseBufferPopBackChar(); - parseBuffer(); - if (_pHandler) _pHandler->endArray(); - if (!pop(MODE_ARRAY)) return false; - _type = JSON_T_NONE; - _state = OK; - break; - } - // { - case -6: - { - parseBufferPopBackChar(); - if (_pHandler) _pHandler->startObject(); - if (!push(MODE_KEY)) return false; - poco_assert(_type == JSON_T_NONE); - _state = OB; - break; - } - // [ - case -5: - { - parseBufferPopBackChar(); - if (_pHandler) _pHandler->startArray(); - if (!push(MODE_ARRAY)) return false; - poco_assert(_type == JSON_T_NONE); - _state = AR; - break; - } - // string end " - case -4: - parseBufferPopBackChar(); - switch (_stack[_top]) - { - case MODE_KEY: - { - poco_assert(_type == JSON_T_STRING); - _type = JSON_T_NONE; - _state = CO; - - if (_pHandler) - { - _pHandler->key(std::string(_parseBuffer.begin(), _parseBuffer.size())); - } - clearBuffer(); - break; - } - case MODE_ARRAY: - case MODE_OBJECT: - poco_assert(_type == JSON_T_STRING); - parseBuffer(); - _type = JSON_T_NONE; - _state = OK; - break; - default: - return false; - } - break; - - // , - case -3: - { - parseBufferPopBackChar(); - parseBuffer(); - switch (_stack[_top]) - { - case MODE_OBJECT: - //A comma causes a flip from object mode to key mode. - if (!pop(MODE_OBJECT) || !push(MODE_KEY)) return false; - poco_assert(_type != JSON_T_STRING); - _type = JSON_T_NONE; - _state = KE; - break; - case MODE_ARRAY: - poco_assert(_type != JSON_T_STRING); - _type = JSON_T_NONE; - _state = VA; - break; - default: - return false; - } - break; - } - // : - case -2: - // A colon causes a flip from key mode to object mode. - parseBufferPopBackChar(); - if (!pop(MODE_KEY) || !push(MODE_OBJECT)) return false; - poco_assert(_type == JSON_T_NONE); - _state = VA; - break; - //Bad action. - default: - return false; - } - } - return true; - } - - bool done(); - static CharIntType utf8CheckFirst(char byte); - bool isHighSurrogate(unsigned uc); - bool isLowSurrogate(unsigned uc); - unsigned decodeSurrogatePair(unsigned hi, unsigned lo); - - static const int _asciiClass[128]; - /// This array maps the 128 ASCII characters into character classes. - /// The remaining Unicode characters should be mapped to C_ETC. - /// Non-whitespace control characters are errors. - - static const int _stateTransitionTable[NR_STATES][NR_CLASSES]; - static const int xx = -1; - - Handler::Ptr _pHandler; - signed char _state; - signed char _beforeCommentState; - JSONType _type; - signed char _escaped; - signed char _comment; - unsigned short _utf16HighSurrogate; - int _depth; - int _top; - BufType _stack; - BufType _parseBuffer; - char _decimalPoint; - bool _allowNullByte; - bool _allowComments; -}; - - -// -// inlines -// -inline void ParserImpl::setAllowCommentsImpl(bool comments) -{ - _allowComments = comments; -} - - -inline bool ParserImpl::getAllowCommentsImpl() const -{ - return _allowComments; -} - - -inline void ParserImpl::setAllowNullByteImpl(bool nullByte) -{ - _allowNullByte = nullByte; -} - - -inline bool ParserImpl::getAllowNullByteImpl() const -{ - return _allowNullByte; -} - - -inline void ParserImpl::setDepthImpl(std::size_t depth) -{ - _depth = static_cast(depth); -} - - -inline std::size_t ParserImpl::getDepthImpl() const -{ - return static_cast(_depth); -} - - -inline void ParserImpl::setHandlerImpl(const Handler::Ptr& pHandler) -{ - _pHandler = pHandler; -} - - -inline const Handler::Ptr& ParserImpl::getHandlerImpl() -{ - return _pHandler; -} - - -inline Dynamic::Var ParserImpl::resultImpl() const -{ - return asVarImpl(); -} - - -inline Dynamic::Var ParserImpl::asVarImpl() const -{ - if (_pHandler) return _pHandler->asVar(); - - return Dynamic::Var(); -} - - -inline bool ParserImpl::done() -{ - return _state == OK && pop(MODE_DONE); -} - - -inline void ParserImpl::assertNotStringNullBool() -{ - poco_assert(_type != JSON_T_FALSE && - _type != JSON_T_TRUE && - _type != JSON_T_NULL && - _type != JSON_T_STRING); -} - - -inline void ParserImpl::assertNonContainer() -{ - poco_assert(_type == JSON_T_NULL || - _type == JSON_T_FALSE || - _type == JSON_T_TRUE || - _type == JSON_T_FLOAT || - _type == JSON_T_INTEGER || - _type == JSON_T_STRING); -} - - -inline void ParserImpl::growBuffer() -{ - _parseBuffer.setCapacity(_parseBuffer.size() * 2, true); -} - - -inline bool ParserImpl::isHighSurrogate(unsigned uc) -{ - return (uc & 0xFC00) == 0xD800; -} - - -inline bool ParserImpl::isLowSurrogate(unsigned uc) -{ - return (uc & 0xFC00) == 0xDC00; -} - - -inline unsigned ParserImpl::decodeSurrogatePair(unsigned hi, unsigned lo) -{ - return ((hi & 0x3FF) << 10) + (lo & 0x3FF) + 0x10000; -} - - -#else - -#error "No JSON parser defined." - -#endif // JSON_ORG_PARSER - - } } // namespace Poco::JSON diff --git a/JSON/src/ParserImpl.cpp b/JSON/src/ParserImpl.cpp index c4a5dccaa..121d3b309 100644 --- a/JSON/src/ParserImpl.cpp +++ b/JSON/src/ParserImpl.cpp @@ -32,9 +32,6 @@ namespace Poco { namespace JSON { -#ifdef PD_JSON_PARSER - - ParserImpl::ParserImpl(const Handler::Ptr& pHandler, std::size_t bufSize): _pHandler(pHandler), _depth(JSON_UNLIMITED_DEPTH), @@ -229,489 +226,4 @@ void ParserImpl::handle() } -#elif defined(JSON_ORG_PARSER) - - -static const unsigned char UTF8_LEAD_BITS[4] = { 0x00, 0xC0, 0xE0, 0xF0 }; - - -const int ParserImpl::_asciiClass[] = -{ - xx, xx, xx, xx, xx, xx, xx, xx, - xx, C_WHITE, C_WHITE, xx, xx, C_WHITE, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, - - C_SPACE, C_ETC, C_QUOTE, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, - C_ETC, C_ETC, C_STAR, C_PLUS, C_COMMA, C_MINUS, C_POINT, C_SLASH, - C_ZERO, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, - C_DIGIT, C_DIGIT, C_COLON, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, - - C_ETC, C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E, C_ABCDF, C_ETC, - C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, - C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, - C_ETC, C_ETC, C_ETC, C_LSQRB, C_BACKS, C_RSQRB, C_ETC, C_ETC, - - C_ETC, C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC, - C_ETC, C_ETC, C_ETC, C_ETC, C_LOW_L, C_ETC, C_LOW_N, C_ETC, - C_ETC, C_ETC, C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC, C_ETC, - C_ETC, C_ETC, C_ETC, C_LCURB, C_ETC, C_RCURB, C_ETC, C_ETC -}; - - -const int ParserImpl::_stateTransitionTable[NR_STATES][NR_CLASSES] = -{ -/* - white 1-9 ABCDF etc - space | { } [ ] : , " \ / + - . 0 | a b c d e f l n r s t u | E | * */ -/*start GO*/ {GO,GO,-6,xx,-5,xx,xx,xx,xx,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*ok OK*/ {OK,OK,xx,-8,xx,-7,xx,-3,xx,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*object OB*/ {OB,OB,xx,-9,xx,xx,xx,xx,SB,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*key KE*/ {KE,KE,xx,xx,xx,xx,xx,xx,SB,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*colon CO*/ {CO,CO,xx,xx,xx,xx,-2,xx,xx,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*value VA*/ {VA,VA,-6,xx,-5,xx,xx,xx,SB,xx,CB,xx,MX,xx,ZX,IX,xx,xx,xx,xx,xx,FA,xx,NU,xx,xx,TR,xx,xx,xx,xx,xx}, -/*array AR*/ {AR,AR,-6,xx,-5,-7,xx,xx,SB,xx,CB,xx,MX,xx,ZX,IX,xx,xx,xx,xx,xx,FA,xx,NU,xx,xx,TR,xx,xx,xx,xx,xx}, -/*string ST*/ {ST,xx,ST,ST,ST,ST,ST,ST,-4,EX,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST}, -/*escape EC*/ {xx,xx,xx,xx,xx,xx,xx,xx,ST,ST,ST,xx,xx,xx,xx,xx,xx,ST,xx,xx,xx,ST,xx,ST,ST,xx,ST,U1,xx,xx,xx,xx}, -/*u1 U1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,U2,U2,U2,U2,U2,U2,U2,U2,xx,xx,xx,xx,xx,xx,U2,U2,xx,xx}, -/*u2 U2*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,U3,U3,U3,U3,U3,U3,U3,U3,xx,xx,xx,xx,xx,xx,U3,U3,xx,xx}, -/*u3 U3*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,U4,U4,U4,U4,U4,U4,U4,U4,xx,xx,xx,xx,xx,xx,U4,U4,xx,xx}, -/*u4 U4*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,UC,UC,UC,UC,UC,UC,UC,UC,xx,xx,xx,xx,xx,xx,UC,UC,xx,xx}, -/*minus MI*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,ZE,IT,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*zero ZE*/ {OK,OK,xx,-8,xx,-7,xx,-3,xx,xx,CB,xx,xx,DF,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*int IT*/ {OK,OK,xx,-8,xx,-7,xx,-3,xx,xx,CB,xx,xx,DF,IT,IT,xx,xx,xx,xx,DE,xx,xx,xx,xx,xx,xx,xx,xx,DE,xx,xx}, -/*frac FR*/ {OK,OK,xx,-8,xx,-7,xx,-3,xx,xx,CB,xx,xx,xx,FR,FR,xx,xx,xx,xx,E1,xx,xx,xx,xx,xx,xx,xx,xx,E1,xx,xx}, -/*e E1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,E2,E2,xx,E3,E3,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*ex E2*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,E3,E3,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*exp E3*/ {OK,OK,xx,-8,xx,-7,xx,-3,xx,xx,xx,xx,xx,xx,E3,E3,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*tr T1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,T2,xx,xx,xx,xx,xx,xx,xx}, -/*tru T2*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,T3,xx,xx,xx,xx}, -/*1 T3*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,OK,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*fa F1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,F2,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*fal F2*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,F3,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*fals F3*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,F4,xx,xx,xx,xx,xx,xx}, -/*0 F4*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,OK,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*nu N1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,N2,xx,xx,xx,xx}, -/*nul N2*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,N3,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*null N3*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,CB,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,OK,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*/ C1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,C2}, -/*/* C2*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3}, -/** C3*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,CE,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3}, -/*_. FX*/ {OK,OK,xx,-8,xx,-7,xx,-3,xx,xx,xx,xx,xx,xx,FR,FR,xx,xx,xx,xx,E1,xx,xx,xx,xx,xx,xx,xx,xx,E1,xx,xx}, -/*\ D1*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,D2,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx}, -/*\ D2*/ {xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,U1,xx,xx,xx,xx}, -}; - - -ParserImpl::ParserImpl(const Handler::Ptr& pHandler, std::size_t bufSize): - _pHandler(pHandler), - _state(GO), - _beforeCommentState(0), - _type(JSON_T_NONE), - _escaped(0), - _comment(0), - _utf16HighSurrogate(0), - _depth(JSON_UNLIMITED_DEPTH), - _top(-1), - _stack(JSON_PARSER_STACK_SIZE), - _parseBuffer(bufSize), - _decimalPoint('.'), - _allowNullByte(true), - _allowComments(false) -{ - _parseBuffer.resize(0); - push(MODE_DONE); -} - - -ParserImpl::~ParserImpl() -{ -} - - -void ParserImpl::resetImpl() -{ - _state = GO; - _beforeCommentState = 0; - _type = JSON_T_NONE; - _escaped = 0; - _utf16HighSurrogate = 0; - _top = -1; - - _stack.clear(); - _parseBuffer.resize(0); - push(MODE_DONE); - if (_pHandler) _pHandler->reset(); -} - - -Dynamic::Var ParserImpl::parseImpl(const std::string& json) -{ - std::string::const_iterator it = json.begin(); - std::string::const_iterator end = json.end(); - Source source(it, end); - - int c = 0; - while (source.nextChar(c)) - { - if (0 == parseChar(c, source)) - throw SyntaxException("JSON syntax error"); - } - - if (!done()) - throw JSONException("JSON syntax error"); - - return asVarImpl(); -} - - -Dynamic::Var ParserImpl::parseImpl(std::istream& in) -{ - std::istreambuf_iterator it(in.rdbuf()); - std::istreambuf_iterator end; - Source > source(it, end); - - int c = 0; - while (source.nextChar(c)) - { - if (0 == parseChar(c, source)) throw JSONException("JSON syntax error"); - } - - if (!done()) - throw JSONException("JSON syntax error"); - - return asVarImpl(); -} - - -bool ParserImpl::push(int mode) -{ - _top += 1; - if (_depth < 0) - { - if (_top >= _stack.size()) - _stack.resize(_stack.size() * 2, true); - } - else - { - if (_top >= _depth) return false; - } - - _stack[_top] = mode; - return true; -} - - -bool ParserImpl::pop(int mode) -{ - if (_top < 0 || _stack[_top] != mode) - return false; - - _top -= 1; - return true; -} - - -void ParserImpl::clearBuffer() -{ - _parseBuffer.resize(0); -} - - -void ParserImpl::parseBufferPopBackChar() -{ - poco_assert(_parseBuffer.size() >= 1); - _parseBuffer.resize(_parseBuffer.size() - 1); -} - - -void ParserImpl::parseBufferPushBackChar(char c) -{ - if (_parseBuffer.size() + 1 >= _parseBuffer.capacity()) - _parseBuffer.setCapacity(_parseBuffer.capacity() * 2); - - _parseBuffer.append(c); -} - - -void ParserImpl::addEscapedCharToParseBuffer(CharIntType nextChar) -{ - _escaped = 0; - // remove the backslash - parseBufferPopBackChar(); - - switch (nextChar) - { - case 'b': - parseBufferPushBackChar('\b'); - break; - case 'f': - parseBufferPushBackChar('\f'); - break; - case 'n': - parseBufferPushBackChar('\n'); - break; - case 'r': - parseBufferPushBackChar('\r'); - break; - case 't': - parseBufferPushBackChar('\t'); - break; - case '"': - parseBufferPushBackChar('"'); - break; - case '\\': - parseBufferPushBackChar('\\'); - break; - case '/': - parseBufferPushBackChar('/'); - break; - case 'u': - parseBufferPushBackChar('\\'); - parseBufferPushBackChar('u'); - break; - default: - break; - } -} - - -void ParserImpl::addCharToParseBuffer(CharIntType nextChar, int nextClass) -{ - if (_escaped) - { - addEscapedCharToParseBuffer(nextChar); - return; - } - else if (!_comment) - { - if ((_type != JSON_T_NONE) || - !((nextClass == C_SPACE) || (nextClass == C_WHITE))) - { - parseBufferPushBackChar((char) nextChar); - } - } -} - - -ParserImpl::CharIntType ParserImpl::decodeUnicodeChar() -{ - int i; - unsigned uc = 0; - char* p; - int trailBytes; - - poco_assert(_parseBuffer.size() >= 6); - p = &_parseBuffer[_parseBuffer.size() - 4]; - - for (i = 12; i >= 0; i -= 4, ++p) - { - unsigned x = *p; - - if (x >= 'a') x -= ('a' - 10); - else if (x >= 'A') x -= ('A' - 10); - else x &= ~0x30u; - - poco_assert(x < 16); - uc |= x << i; - } - - if (!_allowNullByte && uc == 0) return 0; - - // clear UTF-16 char from buffer - _parseBuffer.resize(_parseBuffer.size() - 6); - - if (_utf16HighSurrogate) - { - if (isLowSurrogate(uc)) - { - uc = decodeSurrogatePair(_utf16HighSurrogate, uc); - trailBytes = 3; - _utf16HighSurrogate = 0; - } - else // high surrogate without a following low surrogate - { - return 0; - } - } - else - { - if (uc < 0x80) - { - trailBytes = 0; - } - else if (uc < 0x800) - { - trailBytes = 1; - } - else if (isHighSurrogate(uc)) - { - // save the high surrogate and wait for the low surrogate - _utf16HighSurrogate = uc; - return 1; - } - else if (isLowSurrogate(uc)) - { - // low surrogate without a preceding high surrogate - return 0; - } - else - { - trailBytes = 2; - } - } - - _parseBuffer.append((char) ((uc >> (trailBytes * 6)) | UTF8_LEAD_BITS[trailBytes])); - - for (i = trailBytes * 6 - 6; i >= 0; i -= 6) - { - _parseBuffer.append((char) (((uc >> i) & 0x3F) | 0x80)); - } - - return 1; -} - - -void ParserImpl::parseBuffer() -{ - if (_pHandler) - { - int type = _type; // just to silence g++ - - if (type != JSON_T_NONE) - { - assertNonContainer(); - - switch (type) - { - case JSON_T_TRUE: - { - _pHandler->value(true); - break; - } - case JSON_T_FALSE: - { - _pHandler->value(false); - break; - } - case JSON_T_NULL: - { - _pHandler->null(); - break; - } - case JSON_T_FLOAT: - { - // Float can't end with a dot - if (_parseBuffer[_parseBuffer.size() - 1] == '.') throw SyntaxException("JSON syntax error"); - - double float_value = NumberParser::parseFloat(std::string(_parseBuffer.begin(), _parseBuffer.size())); - _pHandler->value(float_value); - break; - } - case JSON_T_INTEGER: - { -#if defined(POCO_HAVE_INT64) - std::string numStr(_parseBuffer.begin(), _parseBuffer.size()); - try - { - Poco::trimInPlace(numStr); - Int64 value = NumberParser::parse64(numStr); - // if number is 32-bit, then handle as such - if (value > std::numeric_limits::max() - || value < std::numeric_limits::min()) - { - _pHandler->value(value); - } - else - { - _pHandler->value(static_cast(value)); - } - } - // try to handle error as unsigned in case of overflow - catch (const SyntaxException&) - { - UInt64 value = NumberParser::parseUnsigned64(numStr); - // if number is 32-bit, then handle as such - if (value > std::numeric_limits::max()) - { - _pHandler->value(value); - } - else - { - _pHandler->value(static_cast(value)); - } - } -#else - try - { - int value = NumberParser::parse(numStr); - _pHandler->value(value); - } - // try to handle error as unsigned in case of overflow - catch (const SyntaxException&) - { - unsigned value = NumberParser::parseUnsigned(numStr); - _pHandler->value(value); - } -#endif - } - break; - case JSON_T_STRING: - { - _pHandler->value(std::string(_parseBuffer.begin(), _parseBuffer.size())); - break; - } - } - } - } - - clearBuffer(); -} - - -int ParserImpl::utf8CheckFirst(char byte) -{ - unsigned char u = (unsigned char) byte; - - if (u < 0x80) - return 1; - - if (0x80 <= u && u <= 0xBF) - { - // second, third or fourth byte of a multi-byte - // sequence, i.e. a "continuation byte" - return 0; - } - else if (u == 0xC0 || u == 0xC1) - { - // overlong encoding of an ASCII byte - return 0; - } - else if (0xC2 <= u && u <= 0xDF) - { - // 2-byte sequence - return 2; - } - else if (0xE0 <= u && u <= 0xEF) - { - // 3-byte sequence - return 3; - } - else if (0xF0 <= u && u <= 0xF4) - { - // 4-byte sequence - return 4; - } - else - { - // u >= 0xF5 - // Restricted (start of 4-, 5- or 6-byte sequence) or invalid UTF-8 - return 0; - } -} - - -#endif // JSON_ORG_PARSER - - } } // namespace Poco::JSON