annotate DEPENDENCIES/generic/include/boost/property_tree/detail/json_parser_read.hpp @ 125:34e428693f5d vext

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