mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-20 22:31:23 +01:00
Integrate Poco::Web::JSON parser
This commit is contained in:
parent
9ad116745b
commit
87d955ecde
@ -53,19 +53,211 @@
|
||||
namespace Poco {
|
||||
namespace JSON {
|
||||
|
||||
class JSON_API CharacterFeeder
|
||||
{
|
||||
public:
|
||||
virtual ~CharacterFeeder() {}
|
||||
virtual bool nextChar(int& c) = 0;
|
||||
};
|
||||
|
||||
|
||||
class JSON_API StreamCharacterFeeder : public CharacterFeeder
|
||||
{
|
||||
public:
|
||||
StreamCharacterFeeder(std::istream& in) : _in(in) {}
|
||||
virtual ~StreamCharacterFeeder() {}
|
||||
|
||||
bool nextChar(int& c);
|
||||
|
||||
private:
|
||||
|
||||
std::istream& _in;
|
||||
};
|
||||
|
||||
|
||||
inline bool StreamCharacterFeeder::nextChar(int& c)
|
||||
{
|
||||
if ( _in.good() )
|
||||
{
|
||||
c = _in.get();
|
||||
return _in.good();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class JSON_API StringCharacterFeeder : public CharacterFeeder
|
||||
{
|
||||
public:
|
||||
StringCharacterFeeder(std::string::const_iterator begin, std::string::const_iterator end) : _it(begin), _end(end)
|
||||
{
|
||||
}
|
||||
virtual ~StringCharacterFeeder() {}
|
||||
|
||||
bool nextChar(int& c);
|
||||
|
||||
private:
|
||||
|
||||
std::string::const_iterator _it;
|
||||
std::string::const_iterator _end;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline bool StringCharacterFeeder::nextChar(int& c)
|
||||
{
|
||||
if ( _it == _end )
|
||||
return false;
|
||||
|
||||
c = *_it++;
|
||||
return true;
|
||||
}
|
||||
|
||||
class JSON_API Parser
|
||||
/// A class for passing JSON strings or streams.
|
||||
{
|
||||
public:
|
||||
|
||||
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 */
|
||||
ES, /* 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_ARRAY_BEGIN,
|
||||
JSON_T_ARRAY_END,
|
||||
JSON_T_OBJECT_BEGIN,
|
||||
JSON_T_OBJECT_END,
|
||||
JSON_T_INTEGER,
|
||||
JSON_T_FLOAT,
|
||||
JSON_T_NULL,
|
||||
JSON_T_TRUE,
|
||||
JSON_T_FALSE,
|
||||
JSON_T_STRING,
|
||||
JSON_T_KEY,
|
||||
JSON_T_VALUE_SEPARATOR,
|
||||
JSON_T_MAX
|
||||
};
|
||||
|
||||
|
||||
static const int PARSE_BUFFER_SIZE = 3500;
|
||||
static const int PARSER_STACK_SIZE = 128;
|
||||
|
||||
Parser(const Handler::Ptr& pHandler = new ParseHandler);
|
||||
/// Constructor.
|
||||
|
||||
virtual ~Parser();
|
||||
/// Destructor.
|
||||
|
||||
Dynamic::Var parse(const std::string& source);
|
||||
|
||||
void allowComments(bool sw);
|
||||
/// Allow comments. By default this is false.
|
||||
|
||||
void allowNullByte(bool sw);
|
||||
/// Allow a null byte in strings. By default this is true.
|
||||
|
||||
Dynamic::Var parse(const std::string& json);
|
||||
/// Parses a string.
|
||||
|
||||
Dynamic::Var parse(std::istream& in);
|
||||
@ -81,33 +273,95 @@ public:
|
||||
/// Returns the result of parsing;
|
||||
|
||||
private:
|
||||
const Token* nextToken();
|
||||
/// Returns the next token.
|
||||
|
||||
void readObject();
|
||||
/// Starts reading an object.
|
||||
|
||||
void readArray();
|
||||
/// Starts reading an array.
|
||||
|
||||
bool readRow(bool firstCall = false);
|
||||
/// Reads a property value pair. Returns true when a next row is expected.
|
||||
|
||||
void readValue(const Token* token);
|
||||
/// Read a value from the token.
|
||||
|
||||
bool readElements(bool firstCall = false);
|
||||
/// Read all elements of an array.
|
||||
|
||||
StreamTokenizer _tokenizer;
|
||||
Handler::Ptr _pHandler;
|
||||
|
||||
|
||||
typedef Poco::Buffer<char> 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(int nextChar, int nextClass);
|
||||
|
||||
|
||||
void addEscapedCharToParseBuffer(int nextChar);
|
||||
|
||||
|
||||
int decodeUnicodeChar();
|
||||
|
||||
|
||||
void assertNotStringNullBool();
|
||||
|
||||
|
||||
void assertNonContainer();
|
||||
|
||||
|
||||
void parseBuffer();
|
||||
|
||||
|
||||
bool parseChar(int nextChar);
|
||||
/// Called for each character (or partial character) in JSON string.
|
||||
/// It accepts UTF-8, UTF-16, or UTF-32. If it the character is accpeted,
|
||||
/// it returns true, otherwise false.
|
||||
|
||||
bool done();
|
||||
|
||||
|
||||
static int utf8_check_first(char byte);
|
||||
|
||||
|
||||
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;
|
||||
|
||||
signed char _state;
|
||||
signed char _beforeCommentState;
|
||||
JSONType _type;
|
||||
signed char _escaped;
|
||||
signed char _comment;
|
||||
unsigned short _utf16HighSurrogate;
|
||||
long _depth;
|
||||
long _top;
|
||||
BufType _stack;
|
||||
BufType _parseBuffer;
|
||||
size_t _parseBufferCount;
|
||||
size_t _commentBeginOffset;
|
||||
char _decimalPoint;
|
||||
bool _allowNullByte;
|
||||
bool _allowComments;
|
||||
SharedPtr<CharacterFeeder> feeder;
|
||||
};
|
||||
|
||||
|
||||
inline Dynamic::Var Parser::parse(const std::string& source)
|
||||
inline void Parser::allowComments(bool sw)
|
||||
{
|
||||
std::istringstream is(source);
|
||||
return parse(is);
|
||||
_allowComments = sw;
|
||||
}
|
||||
|
||||
|
||||
inline void Parser::allowNullByte(bool sw)
|
||||
{
|
||||
_allowNullByte = sw;
|
||||
}
|
||||
|
||||
|
||||
@ -129,6 +383,37 @@ inline Dynamic::Var Parser::result() const
|
||||
}
|
||||
|
||||
|
||||
inline bool Parser::done()
|
||||
{
|
||||
return _state == OK && pop(MODE_DONE);
|
||||
}
|
||||
|
||||
|
||||
inline void Parser::assertNotStringNullBool()
|
||||
{
|
||||
poco_assert(_type != JSON_T_FALSE &&
|
||||
_type != JSON_T_TRUE &&
|
||||
_type != JSON_T_NULL &&
|
||||
_type != JSON_T_STRING);
|
||||
}
|
||||
|
||||
|
||||
inline void Parser::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 Parser::growBuffer()
|
||||
{
|
||||
_parseBuffer.resize(_parseBuffer.size() * 2, true);
|
||||
}
|
||||
|
||||
}} // namespace Poco::JSON
|
||||
|
||||
|
||||
|
1379
JSON/src/Parser.cpp
1379
JSON/src/Parser.cpp
File diff suppressed because it is too large
Load Diff
@ -1193,6 +1193,7 @@ void JSONTest::testInvalidJanssonFiles()
|
||||
std::cout << filePath.toString() << std::endl;
|
||||
|
||||
Parser parser;
|
||||
parser.allowNullByte(false);
|
||||
Var result;
|
||||
|
||||
try
|
||||
@ -1235,6 +1236,7 @@ void JSONTest::testInvalidUnicodeJanssonFiles()
|
||||
std::cout << filePath.toString() << std::endl;
|
||||
|
||||
Parser parser;
|
||||
parser.allowNullByte(false);
|
||||
Var result;
|
||||
|
||||
try
|
||||
|
Loading…
x
Reference in New Issue
Block a user