| 1 |
sf-pippijn |
1.1 |
#pragma once |
| 2 |
|
|
|
| 3 |
|
|
#include "features.h" |
| 4 |
|
|
#include "value.h" |
| 5 |
|
|
#include <deque> |
| 6 |
|
|
#include <iostream> |
| 7 |
|
|
#include <stack> |
| 8 |
|
|
#include <string> |
| 9 |
|
|
|
| 10 |
|
|
namespace Json |
| 11 |
|
|
{ |
| 12 |
|
|
/** \brief Unserialize a <a href="http://www.json.org">JSON</a> document into a Value. |
| 13 |
|
|
* |
| 14 |
|
|
*/ |
| 15 |
|
|
class JSON_API Reader |
| 16 |
|
|
{ |
| 17 |
|
|
public: |
| 18 |
|
|
typedef char Char; |
| 19 |
|
|
typedef const Char *Location; |
| 20 |
|
|
|
| 21 |
|
|
/** \brief Constructs a Reader allowing all features |
| 22 |
|
|
* for parsing. |
| 23 |
|
|
*/ |
| 24 |
|
|
Reader (); |
| 25 |
|
|
|
| 26 |
|
|
/** \brief Constructs a Reader allowing the specified feature set |
| 27 |
|
|
* for parsing. |
| 28 |
|
|
*/ |
| 29 |
|
|
Reader (const Features &features); |
| 30 |
|
|
|
| 31 |
|
|
/** \brief Read a Value from a <a href="http://www.json.org">JSON</a> document. |
| 32 |
|
|
* \param document UTF-8 encoded string containing the document to read. |
| 33 |
|
|
* \param root [out] Contains the root value of the document if it was |
| 34 |
|
|
* successfully parsed. |
| 35 |
|
|
* \param collectComments \c true to collect comment and allow writing them back during |
| 36 |
|
|
* serialization, \c false to discard comments. |
| 37 |
|
|
* This parameter is ignored if Features::allowComments_ |
| 38 |
|
|
* is \c false. |
| 39 |
|
|
* \return \c true if the document was successfully parsed, \c false if an error occurred. |
| 40 |
|
|
*/ |
| 41 |
|
|
bool parse (const std::string &document, Value &root, bool collectComments = true); |
| 42 |
|
|
|
| 43 |
|
|
/** \brief Read a Value from a <a href="http://www.json.org">JSON</a> document. |
| 44 |
|
|
* \param document UTF-8 encoded string containing the document to read. |
| 45 |
|
|
* \param root [out] Contains the root value of the document if it was |
| 46 |
|
|
* successfully parsed. |
| 47 |
|
|
* \param collectComments \c true to collect comment and allow writing them back during |
| 48 |
|
|
* serialization, \c false to discard comments. |
| 49 |
|
|
* This parameter is ignored if Features::allowComments_ |
| 50 |
|
|
* is \c false. |
| 51 |
|
|
* \return \c true if the document was successfully parsed, \c false if an error occurred. |
| 52 |
|
|
*/ |
| 53 |
|
|
bool parse (const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true); |
| 54 |
|
|
|
| 55 |
|
|
/* |
| 56 |
|
|
* / \brief Parse from input stream. |
| 57 |
|
|
* / \see Json::operator>>(std::istream&, Json::Value&). |
| 58 |
|
|
*/ |
| 59 |
|
|
bool parse (std::istream &is, Value &root, bool collectComments = true); |
| 60 |
|
|
|
| 61 |
|
|
/** \brief Returns a user friendly string that list errors in the parsed document. |
| 62 |
|
|
* \return Formatted error message with the list of errors with their location in |
| 63 |
|
|
* the parsed document. An empty string is returned if no error occurred |
| 64 |
|
|
* during parsing. |
| 65 |
|
|
*/ |
| 66 |
|
|
std::string getFormatedErrorMessages () const; |
| 67 |
|
|
|
| 68 |
|
|
private: |
| 69 |
|
|
enum TokenType |
| 70 |
|
|
{ |
| 71 |
|
|
tokenEndOfStream = 0, |
| 72 |
|
|
tokenObjectBegin, |
| 73 |
|
|
tokenObjectEnd, |
| 74 |
|
|
tokenArrayBegin, |
| 75 |
|
|
tokenArrayEnd, |
| 76 |
|
|
tokenString, |
| 77 |
|
|
tokenNumber, |
| 78 |
|
|
tokenTrue, |
| 79 |
|
|
tokenFalse, |
| 80 |
|
|
tokenNull, |
| 81 |
|
|
tokenArraySeparator, |
| 82 |
|
|
tokenMemberSeparator, |
| 83 |
|
|
tokenComment, |
| 84 |
|
|
tokenError |
| 85 |
|
|
}; |
| 86 |
|
|
|
| 87 |
|
|
struct Token |
| 88 |
|
|
{ |
| 89 |
|
|
Location start_; |
| 90 |
|
|
Location end_; |
| 91 |
|
|
TokenType type_; |
| 92 |
|
|
}; |
| 93 |
|
|
|
| 94 |
|
|
struct ErrorInfo |
| 95 |
|
|
{ |
| 96 |
|
|
Token token_; |
| 97 |
|
|
std::string message_; |
| 98 |
|
|
Location extra_; |
| 99 |
|
|
}; |
| 100 |
|
|
|
| 101 |
|
|
typedef std::deque<ErrorInfo> Errors; |
| 102 |
|
|
|
| 103 |
|
|
bool expectToken (TokenType type, Token &token, const char *message); |
| 104 |
|
|
bool readToken (Token &token); |
| 105 |
|
|
void skipSpaces (); |
| 106 |
|
|
bool match (Location pattern, int patternLength); |
| 107 |
|
|
bool readComment (); |
| 108 |
|
|
bool readCStyleComment (); |
| 109 |
|
|
bool readCppStyleComment (); |
| 110 |
|
|
bool readString (); |
| 111 |
|
|
void readNumber (); |
| 112 |
|
|
bool readValue (); |
| 113 |
|
|
bool readObject (Token &token); |
| 114 |
|
|
bool readArray (Token &token); |
| 115 |
|
|
bool decodeNumber (Token &token); |
| 116 |
|
|
bool decodeString (Token &token); |
| 117 |
|
|
bool decodeString (Token &token, std::string &decoded); |
| 118 |
|
|
bool decodeDouble (Token &token); |
| 119 |
|
|
bool decodeUnicodeCodePoint (Token &token, Location ¤t, Location end, unsigned int &unicode); |
| 120 |
|
|
bool decodeUnicodeEscapeSequence (Token &token, Location ¤t, Location end, unsigned int &unicode); |
| 121 |
|
|
bool addError (const std::string &message, Token &token, Location extra = 0); |
| 122 |
|
|
bool recoverFromError (TokenType skipUntilToken); |
| 123 |
|
|
bool addErrorAndRecover (const std::string &message, Token &token, TokenType skipUntilToken); |
| 124 |
|
|
void skipUntilSpace (); |
| 125 |
|
|
Value ¤tValue (); |
| 126 |
|
|
Char getNextChar (); |
| 127 |
|
|
void getLocationLineAndColumn (Location location, int &line, int &column) const; |
| 128 |
|
|
std::string getLocationLineAndColumn (Location location) const; |
| 129 |
|
|
void addComment (Location begin, Location end, CommentPlacement placement); |
| 130 |
|
|
void skipCommentTokens (Token &token); |
| 131 |
|
|
|
| 132 |
|
|
typedef std::stack<Value *> Nodes; |
| 133 |
|
|
Nodes nodes_; |
| 134 |
|
|
Errors errors_; |
| 135 |
|
|
std::string document_; |
| 136 |
|
|
Location begin_; |
| 137 |
|
|
Location end_; |
| 138 |
|
|
Location current_; |
| 139 |
|
|
Location lastValueEnd_; |
| 140 |
|
|
Value *lastValue_; |
| 141 |
|
|
std::string commentsBefore_; |
| 142 |
|
|
Features features_; |
| 143 |
|
|
bool collectComments_; |
| 144 |
|
|
}; |
| 145 |
|
|
|
| 146 |
|
|
/** \brief Read from 'sin' into 'root'. |
| 147 |
|
|
* |
| 148 |
|
|
* Always keep comments from the input JSON. |
| 149 |
|
|
* |
| 150 |
|
|
* This can be used to read a file into a particular sub-object. |
| 151 |
|
|
* For example: |
| 152 |
|
|
* \code |
| 153 |
|
|
* Json::Value root; |
| 154 |
|
|
* cin >> root["dir"]["file"]; |
| 155 |
|
|
* cout << root; |
| 156 |
|
|
* \endcode |
| 157 |
|
|
* Result: |
| 158 |
|
|
* \verbatim |
| 159 |
|
|
* { |
| 160 |
|
|
* "dir": { |
| 161 |
|
|
* "file": { |
| 162 |
|
|
* // The input stream JSON would be nested here. |
| 163 |
|
|
* } |
| 164 |
|
|
* } |
| 165 |
|
|
* } |
| 166 |
|
|
* \endverbatim |
| 167 |
|
|
* \throw std::exception on parse error. |
| 168 |
|
|
* \see Json::operator<<() |
| 169 |
|
|
*/ |
| 170 |
|
|
std::istream &operator >> (std::istream &is, Value &value); |
| 171 |
|
|
} /* namespace Json */ |