reader.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. // Copyright 2007-2010 Baptiste Lepilleur
  2. // Distributed under MIT license, or public domain if desired and
  3. // recognized in your jurisdiction.
  4. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
  5. #ifndef CPPTL_JSON_READER_H_INCLUDED
  6. #define CPPTL_JSON_READER_H_INCLUDED
  7. #if !defined(JSON_IS_AMALGAMATION)
  8. #include "features.h"
  9. #include "value.h"
  10. #endif // if !defined(JSON_IS_AMALGAMATION)
  11. #include <deque>
  12. #include <iosfwd>
  13. #include <stack>
  14. #include <string>
  15. // Disable warning C4251: <data member>: <type> needs to have dll-interface to
  16. // be used by...
  17. #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  18. #pragma warning(push)
  19. #pragma warning(disable : 4251)
  20. #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  21. namespace Json {
  22. /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
  23. *Value.
  24. *
  25. */
  26. class JSON_API Reader {
  27. public:
  28. typedef char Char;
  29. typedef const Char* Location;
  30. /** \brief An error tagged with where in the JSON text it was encountered.
  31. *
  32. * The offsets give the [start, limit) range of bytes within the text. Note
  33. * that this is bytes, not codepoints.
  34. *
  35. */
  36. struct StructuredError {
  37. size_t offset_start;
  38. size_t offset_limit;
  39. std::string message;
  40. };
  41. /** \brief Constructs a Reader allowing all features
  42. * for parsing.
  43. */
  44. Reader();
  45. /** \brief Constructs a Reader allowing the specified feature set
  46. * for parsing.
  47. */
  48. Reader(const Features& features);
  49. /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
  50. * document.
  51. * \param document UTF-8 encoded string containing the document to read.
  52. * \param root [out] Contains the root value of the document if it was
  53. * successfully parsed.
  54. * \param collectComments \c true to collect comment and allow writing them
  55. * back during
  56. * serialization, \c false to discard comments.
  57. * This parameter is ignored if
  58. * Features::allowComments_
  59. * is \c false.
  60. * \return \c true if the document was successfully parsed, \c false if an
  61. * error occurred.
  62. */
  63. bool
  64. parse(const std::string& document, Value& root, bool collectComments = true);
  65. /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
  66. document.
  67. * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
  68. document to read.
  69. * \param endDoc Pointer on the end of the UTF-8 encoded string of the
  70. document to read.
  71. \ Must be >= beginDoc.
  72. * \param root [out] Contains the root value of the document if it was
  73. * successfully parsed.
  74. * \param collectComments \c true to collect comment and allow writing them
  75. back during
  76. * serialization, \c false to discard comments.
  77. * This parameter is ignored if
  78. Features::allowComments_
  79. * is \c false.
  80. * \return \c true if the document was successfully parsed, \c false if an
  81. error occurred.
  82. */
  83. bool parse(const char* beginDoc,
  84. const char* endDoc,
  85. Value& root,
  86. bool collectComments = true);
  87. /// \brief Parse from input stream.
  88. /// \see Json::operator>>(std::istream&, Json::Value&).
  89. bool parse(std::istream& is, Value& root, bool collectComments = true);
  90. /** \brief Returns a user friendly string that list errors in the parsed
  91. * document.
  92. * \return Formatted error message with the list of errors with their location
  93. * in
  94. * the parsed document. An empty string is returned if no error
  95. * occurred
  96. * during parsing.
  97. */
  98. std::string getFormatedErrorMessages() const;
  99. /** \brief Returns a user friendly string that list errors in the parsed
  100. * document.
  101. * \return Formatted error message with the list of errors with their location
  102. * in
  103. * the parsed document. An empty string is returned if no error
  104. * occurred
  105. * during parsing.
  106. */
  107. std::string getFormattedErrorMessages() const;
  108. /** \brief Returns a vector of structured erros encounted while parsing.
  109. * \return A (possibly empty) vector of StructuredError objects. Currently
  110. * only one error can be returned, but the caller should tolerate
  111. * multiple
  112. * errors. This can occur if the parser recovers from a non-fatal
  113. * parse error and then encounters additional errors.
  114. */
  115. std::vector<StructuredError> getStructuredErrors() const;
  116. /** \brief Add a semantic error message.
  117. * \param value JSON Value location associated with the error
  118. * \param message The error message.
  119. * \return \c true if the error was successfully added, \c false if the
  120. * Value offset exceeds the document size.
  121. */
  122. bool pushError(const Value& value, const std::string& message);
  123. /** \brief Add a semantic error message with extra context.
  124. * \param value JSON Value location associated with the error
  125. * \param message The error message.
  126. * \param extra Additional JSON Value location to contextualize the error
  127. * \return \c true if the error was successfully added, \c false if either
  128. * Value offset exceeds the document size.
  129. */
  130. bool pushError(const Value& value, const std::string& message, const Value& extra);
  131. /** \brief Return whether there are any errors.
  132. * \return \c true if there are no errors to report \c false if
  133. * errors have occurred.
  134. */
  135. bool good() const;
  136. private:
  137. enum TokenType {
  138. tokenEndOfStream = 0,
  139. tokenObjectBegin,
  140. tokenObjectEnd,
  141. tokenArrayBegin,
  142. tokenArrayEnd,
  143. tokenString,
  144. tokenNumber,
  145. tokenTrue,
  146. tokenFalse,
  147. tokenNull,
  148. tokenArraySeparator,
  149. tokenMemberSeparator,
  150. tokenComment,
  151. tokenError
  152. };
  153. class Token {
  154. public:
  155. TokenType type_;
  156. Location start_;
  157. Location end_;
  158. };
  159. class ErrorInfo {
  160. public:
  161. Token token_;
  162. std::string message_;
  163. Location extra_;
  164. };
  165. typedef std::deque<ErrorInfo> Errors;
  166. bool expectToken(TokenType type, Token& token, const char* message);
  167. bool readToken(Token& token);
  168. void skipSpaces();
  169. bool match(Location pattern, int patternLength);
  170. bool readComment();
  171. bool readCStyleComment();
  172. bool readCppStyleComment();
  173. bool readString();
  174. void readNumber();
  175. bool readValue();
  176. bool readObject(Token& token);
  177. bool readArray(Token& token);
  178. bool decodeNumber(Token& token);
  179. bool decodeNumber(Token& token, Value& decoded);
  180. bool decodeString(Token& token);
  181. bool decodeString(Token& token, std::string& decoded);
  182. bool decodeDouble(Token& token);
  183. bool decodeDouble(Token& token, Value& decoded);
  184. bool decodeUnicodeCodePoint(Token& token,
  185. Location& current,
  186. Location end,
  187. unsigned int& unicode);
  188. bool decodeUnicodeEscapeSequence(Token& token,
  189. Location& current,
  190. Location end,
  191. unsigned int& unicode);
  192. bool addError(const std::string& message, Token& token, Location extra = 0);
  193. bool recoverFromError(TokenType skipUntilToken);
  194. bool addErrorAndRecover(const std::string& message,
  195. Token& token,
  196. TokenType skipUntilToken);
  197. void skipUntilSpace();
  198. Value& currentValue();
  199. Char getNextChar();
  200. void
  201. getLocationLineAndColumn(Location location, int& line, int& column) const;
  202. std::string getLocationLineAndColumn(Location location) const;
  203. void addComment(Location begin, Location end, CommentPlacement placement);
  204. void skipCommentTokens(Token& token);
  205. typedef std::stack<Value*> Nodes;
  206. Nodes nodes_;
  207. Errors errors_;
  208. std::string document_;
  209. Location begin_;
  210. Location end_;
  211. Location current_;
  212. Location lastValueEnd_;
  213. Value* lastValue_;
  214. std::string commentsBefore_;
  215. Features features_;
  216. bool collectComments_;
  217. };
  218. /** \brief Read from 'sin' into 'root'.
  219. Always keep comments from the input JSON.
  220. This can be used to read a file into a particular sub-object.
  221. For example:
  222. \code
  223. Json::Value root;
  224. cin >> root["dir"]["file"];
  225. cout << root;
  226. \endcode
  227. Result:
  228. \verbatim
  229. {
  230. "dir": {
  231. "file": {
  232. // The input stream JSON would be nested here.
  233. }
  234. }
  235. }
  236. \endverbatim
  237. \throw std::exception on parse error.
  238. \see Json::operator<<()
  239. */
  240. JSON_API std::istream& operator>>(std::istream&, Value&);
  241. } // namespace Json
  242. #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  243. #pragma warning(pop)
  244. #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  245. #endif // CPPTL_JSON_READER_H_INCLUDED