reader.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. * \deprecated Use getFormattedErrorMessages() instead (typo fix).
  98. */
  99. JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
  100. std::string getFormatedErrorMessages() const;
  101. /** \brief Returns a user friendly string that list errors in the parsed
  102. * document.
  103. * \return Formatted error message with the list of errors with their location
  104. * in
  105. * the parsed document. An empty string is returned if no error
  106. * occurred
  107. * during parsing.
  108. */
  109. std::string getFormattedErrorMessages() const;
  110. /** \brief Returns a vector of structured erros encounted while parsing.
  111. * \return A (possibly empty) vector of StructuredError objects. Currently
  112. * only one error can be returned, but the caller should tolerate
  113. * multiple
  114. * errors. This can occur if the parser recovers from a non-fatal
  115. * parse error and then encounters additional errors.
  116. */
  117. std::vector<StructuredError> getStructuredErrors() const;
  118. /** \brief Add a semantic error message.
  119. * \param value JSON Value location associated with the error
  120. * \param message The error message.
  121. * \return \c true if the error was successfully added, \c false if the
  122. * Value offset exceeds the document size.
  123. */
  124. bool pushError(const Value& value, const std::string& message);
  125. /** \brief Add a semantic error message with extra context.
  126. * \param value JSON Value location associated with the error
  127. * \param message The error message.
  128. * \param extra Additional JSON Value location to contextualize the error
  129. * \return \c true if the error was successfully added, \c false if either
  130. * Value offset exceeds the document size.
  131. */
  132. bool pushError(const Value& value, const std::string& message, const Value& extra);
  133. /** \brief Return whether there are any errors.
  134. * \return \c true if there are no errors to report \c false if
  135. * errors have occurred.
  136. */
  137. bool good() const;
  138. private:
  139. enum TokenType {
  140. tokenEndOfStream = 0,
  141. tokenObjectBegin,
  142. tokenObjectEnd,
  143. tokenArrayBegin,
  144. tokenArrayEnd,
  145. tokenString,
  146. tokenNumber,
  147. tokenTrue,
  148. tokenFalse,
  149. tokenNull,
  150. tokenArraySeparator,
  151. tokenMemberSeparator,
  152. tokenComment,
  153. tokenError
  154. };
  155. class Token {
  156. public:
  157. TokenType type_;
  158. Location start_;
  159. Location end_;
  160. };
  161. class ErrorInfo {
  162. public:
  163. Token token_;
  164. std::string message_;
  165. Location extra_;
  166. };
  167. typedef std::deque<ErrorInfo> Errors;
  168. bool expectToken(TokenType type, Token& token, const char* message);
  169. bool readToken(Token& token);
  170. void skipSpaces();
  171. bool match(Location pattern, int patternLength);
  172. bool readComment();
  173. bool readCStyleComment();
  174. bool readCppStyleComment();
  175. bool readString();
  176. void readNumber();
  177. bool readValue();
  178. bool readObject(Token& token);
  179. bool readArray(Token& token);
  180. bool decodeNumber(Token& token);
  181. bool decodeNumber(Token& token, Value& decoded);
  182. bool decodeString(Token& token);
  183. bool decodeString(Token& token, std::string& decoded);
  184. bool decodeDouble(Token& token);
  185. bool decodeDouble(Token& token, Value& decoded);
  186. bool decodeUnicodeCodePoint(Token& token,
  187. Location& current,
  188. Location end,
  189. unsigned int& unicode);
  190. bool decodeUnicodeEscapeSequence(Token& token,
  191. Location& current,
  192. Location end,
  193. unsigned int& unicode);
  194. bool addError(const std::string& message, Token& token, Location extra = 0);
  195. bool recoverFromError(TokenType skipUntilToken);
  196. bool addErrorAndRecover(const std::string& message,
  197. Token& token,
  198. TokenType skipUntilToken);
  199. void skipUntilSpace();
  200. Value& currentValue();
  201. Char getNextChar();
  202. void
  203. getLocationLineAndColumn(Location location, int& line, int& column) const;
  204. std::string getLocationLineAndColumn(Location location) const;
  205. void addComment(Location begin, Location end, CommentPlacement placement);
  206. void skipCommentTokens(Token& token);
  207. typedef std::stack<Value*> Nodes;
  208. Nodes nodes_;
  209. Errors errors_;
  210. std::string document_;
  211. Location begin_;
  212. Location end_;
  213. Location current_;
  214. Location lastValueEnd_;
  215. Value* lastValue_;
  216. std::string commentsBefore_;
  217. Features features_;
  218. bool collectComments_;
  219. };
  220. /** \brief Read from 'sin' into 'root'.
  221. Always keep comments from the input JSON.
  222. This can be used to read a file into a particular sub-object.
  223. For example:
  224. \code
  225. Json::Value root;
  226. cin >> root["dir"]["file"];
  227. cout << root;
  228. \endcode
  229. Result:
  230. \verbatim
  231. {
  232. "dir": {
  233. "file": {
  234. // The input stream JSON would be nested here.
  235. }
  236. }
  237. }
  238. \endverbatim
  239. \throw std::exception on parse error.
  240. \see Json::operator<<()
  241. */
  242. JSON_API std::istream& operator>>(std::istream&, Value&);
  243. } // namespace Json
  244. #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  245. #pragma warning(pop)
  246. #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  247. #endif // CPPTL_JSON_READER_H_INCLUDED