json_parser_read.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // ----------------------------------------------------------------------------
  2. // Copyright (C) 2002-2006 Marcin Kalicinski
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see www.boost.org
  9. // ----------------------------------------------------------------------------
  10. #ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP_INCLUDED
  11. #define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP_INCLUDED
  12. //#define BOOST_SPIRIT_DEBUG
  13. #include <boost/property_tree/ptree.hpp>
  14. #include <boost/property_tree/detail/ptree_utils.hpp>
  15. #include <boost/property_tree/detail/json_parser_error.hpp>
  16. #include <boost/spirit/include/classic.hpp>
  17. #include <boost/limits.hpp>
  18. #include <string>
  19. #include <locale>
  20. #include <istream>
  21. #include <vector>
  22. #include <algorithm>
  23. namespace boost { namespace property_tree { namespace json_parser
  24. {
  25. ///////////////////////////////////////////////////////////////////////
  26. // Json parser context
  27. template<class Ptree>
  28. struct context
  29. {
  30. typedef typename Ptree::key_type::value_type Ch;
  31. typedef std::basic_string<Ch> Str;
  32. typedef typename std::vector<Ch>::iterator It;
  33. Str string;
  34. Str name;
  35. Ptree root;
  36. std::vector<Ptree *> stack;
  37. struct a_object_s
  38. {
  39. context &c;
  40. a_object_s(context &c): c(c) { }
  41. void operator()(Ch) const
  42. {
  43. if (c.stack.empty())
  44. c.stack.push_back(&c.root);
  45. else
  46. {
  47. Ptree *parent = c.stack.back();
  48. Ptree *child = &parent->push_back(std::make_pair(c.name, Ptree()))->second;
  49. c.stack.push_back(child);
  50. c.name.clear();
  51. }
  52. }
  53. };
  54. struct a_object_e
  55. {
  56. context &c;
  57. a_object_e(context &c): c(c) { }
  58. void operator()(Ch) const
  59. {
  60. BOOST_ASSERT(c.stack.size() >= 1);
  61. c.stack.pop_back();
  62. }
  63. };
  64. struct a_name
  65. {
  66. context &c;
  67. a_name(context &c): c(c) { }
  68. void operator()(It, It) const
  69. {
  70. c.name.swap(c.string);
  71. c.string.clear();
  72. }
  73. };
  74. struct a_string_val
  75. {
  76. context &c;
  77. a_string_val(context &c): c(c) { }
  78. void operator()(It, It) const
  79. {
  80. BOOST_ASSERT(c.stack.size() >= 1);
  81. c.stack.back()->push_back(std::make_pair(c.name, Ptree(c.string)));
  82. c.name.clear();
  83. c.string.clear();
  84. }
  85. };
  86. struct a_literal_val
  87. {
  88. context &c;
  89. a_literal_val(context &c): c(c) { }
  90. void operator()(It b, It e) const
  91. {
  92. BOOST_ASSERT(c.stack.size() >= 1);
  93. c.stack.back()->push_back(std::make_pair(c.name,
  94. Ptree(Str(b, e))));
  95. c.name.clear();
  96. c.string.clear();
  97. }
  98. };
  99. struct a_char
  100. {
  101. context &c;
  102. a_char(context &c): c(c) { }
  103. void operator()(It b, It e) const
  104. {
  105. c.string += *b;
  106. }
  107. };
  108. struct a_escape
  109. {
  110. context &c;
  111. a_escape(context &c): c(c) { }
  112. void operator()(Ch ch) const
  113. {
  114. switch (ch)
  115. {
  116. case Ch('\"'): c.string += Ch('\"'); break;
  117. case Ch('\\'): c.string += Ch('\\'); break;
  118. case Ch('/'): c.string += Ch('/'); break;
  119. case Ch('b'): c.string += Ch('\b'); break;
  120. case Ch('f'): c.string += Ch('\f'); break;
  121. case Ch('n'): c.string += Ch('\n'); break;
  122. case Ch('r'): c.string += Ch('\r'); break;
  123. case Ch('t'): c.string += Ch('\t'); break;
  124. default: BOOST_ASSERT(0);
  125. }
  126. }
  127. };
  128. struct a_unicode
  129. {
  130. context &c;
  131. a_unicode(context &c): c(c) { }
  132. void operator()(unsigned long u) const
  133. {
  134. u = (std::min)(u, static_cast<unsigned long>((std::numeric_limits<Ch>::max)()));
  135. c.string += Ch(u);
  136. }
  137. };
  138. };
  139. ///////////////////////////////////////////////////////////////////////
  140. // Json grammar
  141. template<class Ptree>
  142. struct json_grammar :
  143. public boost::spirit::classic::grammar<json_grammar<Ptree> >
  144. {
  145. typedef context<Ptree> Context;
  146. typedef typename Ptree::key_type::value_type Ch;
  147. mutable Context c;
  148. template<class Scanner>
  149. struct definition
  150. {
  151. boost::spirit::classic::rule<Scanner>
  152. root, object, member, array, item, value, string, number;
  153. boost::spirit::classic::rule<
  154. typename boost::spirit::classic::lexeme_scanner<Scanner>::type>
  155. character, escape;
  156. definition(const json_grammar &self)
  157. {
  158. using namespace boost::spirit::classic;
  159. // There's a boost::assertion too, so another explicit using
  160. // here:
  161. using boost::spirit::classic::assertion;
  162. // Assertions
  163. assertion<std::string> expect_root("expected object or array");
  164. assertion<std::string> expect_eoi("expected end of input");
  165. assertion<std::string> expect_objclose("expected ',' or '}'");
  166. assertion<std::string> expect_arrclose("expected ',' or ']'");
  167. assertion<std::string> expect_name("expected object name");
  168. assertion<std::string> expect_colon("expected ':'");
  169. assertion<std::string> expect_value("expected value");
  170. assertion<std::string> expect_escape("invalid escape sequence");
  171. // JSON grammar rules
  172. root
  173. = expect_root(object | array)
  174. >> expect_eoi(end_p)
  175. ;
  176. object
  177. = ch_p('{')[typename Context::a_object_s(self.c)]
  178. >> (ch_p('}')[typename Context::a_object_e(self.c)]
  179. | (list_p(member, ch_p(','))
  180. >> expect_objclose(ch_p('}')[typename Context::a_object_e(self.c)])
  181. )
  182. )
  183. ;
  184. member
  185. = expect_name(string[typename Context::a_name(self.c)])
  186. >> expect_colon(ch_p(':'))
  187. >> expect_value(value)
  188. ;
  189. array
  190. = ch_p('[')[typename Context::a_object_s(self.c)]
  191. >> (ch_p(']')[typename Context::a_object_e(self.c)]
  192. | (list_p(item, ch_p(','))
  193. >> expect_arrclose(ch_p(']')[typename Context::a_object_e(self.c)])
  194. )
  195. )
  196. ;
  197. item
  198. = expect_value(value)
  199. ;
  200. value
  201. = string[typename Context::a_string_val(self.c)]
  202. | (number | str_p("true") | "false" | "null")[typename Context::a_literal_val(self.c)]
  203. | object
  204. | array
  205. ;
  206. number
  207. = !ch_p("-") >>
  208. (ch_p("0") | (range_p(Ch('1'), Ch('9')) >> *digit_p)) >>
  209. !(ch_p(".") >> +digit_p) >>
  210. !(chset_p(detail::widen<Ch>("eE").c_str()) >>
  211. !chset_p(detail::widen<Ch>("-+").c_str()) >>
  212. +digit_p)
  213. ;
  214. string
  215. = +(lexeme_d[confix_p('\"', *character, '\"')])
  216. ;
  217. character
  218. = (anychar_p - "\\" - "\"")
  219. [typename Context::a_char(self.c)]
  220. | ch_p("\\") >> expect_escape(escape)
  221. ;
  222. escape
  223. = chset_p(detail::widen<Ch>("\"\\/bfnrt").c_str())
  224. [typename Context::a_escape(self.c)]
  225. | 'u' >> uint_parser<unsigned long, 16, 4, 4>()
  226. [typename Context::a_unicode(self.c)]
  227. ;
  228. // Debug
  229. BOOST_SPIRIT_DEBUG_RULE(root);
  230. BOOST_SPIRIT_DEBUG_RULE(object);
  231. BOOST_SPIRIT_DEBUG_RULE(member);
  232. BOOST_SPIRIT_DEBUG_RULE(array);
  233. BOOST_SPIRIT_DEBUG_RULE(item);
  234. BOOST_SPIRIT_DEBUG_RULE(value);
  235. BOOST_SPIRIT_DEBUG_RULE(string);
  236. BOOST_SPIRIT_DEBUG_RULE(number);
  237. BOOST_SPIRIT_DEBUG_RULE(escape);
  238. BOOST_SPIRIT_DEBUG_RULE(character);
  239. }
  240. const boost::spirit::classic::rule<Scanner> &start() const
  241. {
  242. return root;
  243. }
  244. };
  245. };
  246. template<class It, class Ch>
  247. unsigned long count_lines(It begin, It end)
  248. {
  249. return static_cast<unsigned long>(std::count(begin, end, Ch('\n')) + 1);
  250. }
  251. template<class Ptree>
  252. void read_json_internal(std::basic_istream<typename Ptree::key_type::value_type> &stream,
  253. Ptree &pt,
  254. const std::string &filename)
  255. {
  256. using namespace boost::spirit::classic;
  257. typedef typename Ptree::key_type::value_type Ch;
  258. typedef typename std::vector<Ch>::iterator It;
  259. // Load data into vector
  260. std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
  261. std::istreambuf_iterator<Ch>());
  262. if (!stream.good())
  263. BOOST_PROPERTY_TREE_THROW(json_parser_error("read error", filename, 0));
  264. // Prepare grammar
  265. json_grammar<Ptree> g;
  266. // Parse
  267. try
  268. {
  269. parse_info<It> pi = parse(v.begin(), v.end(), g,
  270. space_p | comment_p("//") | comment_p("/*", "*/"));
  271. if (!pi.hit || !pi.full)
  272. BOOST_PROPERTY_TREE_THROW((parser_error<std::string, It>(v.begin(), "syntax error")));
  273. }
  274. catch (parser_error<std::string, It> &e)
  275. {
  276. BOOST_PROPERTY_TREE_THROW(json_parser_error(e.descriptor, filename, count_lines<It, Ch>(v.begin(), e.where)));
  277. }
  278. // Swap grammar context root and pt
  279. pt.swap(g.c.root);
  280. }
  281. } } }
  282. #endif