reader.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. private:
  119. enum TokenType {
  120. tokenEndOfStream = 0,
  121. tokenObjectBegin,
  122. tokenObjectEnd,
  123. tokenArrayBegin,
  124. tokenArrayEnd,
  125. tokenString,
  126. tokenNumber,
  127. tokenTrue,
  128. tokenFalse,
  129. tokenNull,
  130. tokenArraySeparator,
  131. tokenMemberSeparator,
  132. tokenComment,
  133. tokenError
  134. };
  135. class Token {
  136. public:
  137. TokenType type_;
  138. Location start_;
  139. Location end_;
  140. };
  141. class ErrorInfo {
  142. public:
  143. Token token_;
  144. std::string message_;
  145. Location extra_;
  146. };
  147. typedef std::deque<ErrorInfo> Errors;
  148. bool expectToken(TokenType type, Token& token, const char* message);
  149. bool readToken(Token& token);
  150. void skipSpaces();
  151. bool match(Location pattern, int patternLength);
  152. bool readComment();
  153. bool readCStyleComment();
  154. bool readCppStyleComment();
  155. bool readString();
  156. void readNumber();
  157. bool readValue();
  158. bool readObject(Token& token);
  159. bool readArray(Token& token);
  160. bool decodeNumber(Token& token);
  161. bool decodeNumber(Token& token, Value& decoded);
  162. bool decodeString(Token& token);
  163. bool decodeString(Token& token, std::string& decoded);
  164. bool decodeDouble(Token& token);
  165. bool decodeDouble(Token& token, Value& decoded);
  166. bool decodeUnicodeCodePoint(Token& token,
  167. Location& current,
  168. Location end,
  169. unsigned int& unicode);
  170. bool decodeUnicodeEscapeSequence(Token& token,
  171. Location& current,
  172. Location end,
  173. unsigned int& unicode);
  174. bool addError(const std::string& message, Token& token, Location extra = 0);
  175. bool recoverFromError(TokenType skipUntilToken);
  176. bool addErrorAndRecover(const std::string& message,
  177. Token& token,
  178. TokenType skipUntilToken);
  179. void skipUntilSpace();
  180. Value& currentValue();
  181. Char getNextChar();
  182. void
  183. getLocationLineAndColumn(Location location, int& line, int& column) const;
  184. std::string getLocationLineAndColumn(Location location) const;
  185. void addComment(Location begin, Location end, CommentPlacement placement);
  186. void skipCommentTokens(Token& token);
  187. typedef std::stack<Value*> Nodes;
  188. Nodes nodes_;
  189. Errors errors_;
  190. std::string document_;
  191. Location begin_;
  192. Location end_;
  193. Location current_;
  194. Location lastValueEnd_;
  195. Value* lastValue_;
  196. std::string commentsBefore_;
  197. Features features_;
  198. bool collectComments_;
  199. };
  200. /** \brief Read from 'sin' into 'root'.
  201. Always keep comments from the input JSON.
  202. This can be used to read a file into a particular sub-object.
  203. For example:
  204. \code
  205. Json::Value root;
  206. cin >> root["dir"]["file"];
  207. cout << root;
  208. \endcode
  209. Result:
  210. \verbatim
  211. {
  212. "dir": {
  213. "file": {
  214. // The input stream JSON would be nested here.
  215. }
  216. }
  217. }
  218. \endverbatim
  219. \throw std::exception on parse error.
  220. \see Json::operator<<()
  221. */
  222. JSON_API std::istream& operator>>(std::istream&, Value&);
  223. } // namespace Json
  224. #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  225. #pragma warning(pop)
  226. #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
  227. #endif // CPPTL_JSON_READER_H_INCLUDED