16 #ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
17 #define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
19 #include <boost/property_tree/ptree.hpp>
20 #include <boost/next_prior.hpp>
21 #include <boost/type_traits/make_unsigned.hpp>
27 namespace property_tree {
32 std::basic_string<Ch> create_escapes(
const std::basic_string<Ch> &s)
34 std::basic_string<Ch> result;
35 typename std::basic_string<Ch>::const_iterator b = s.begin();
36 typename std::basic_string<Ch>::const_iterator e = s.end();
39 typedef typename make_unsigned<Ch>::type UCh;
44 if (c == 0x20 || c == 0x21 || (c >= 0x23 && c <= 0x2E) ||
45 (c >= 0x30 && c <= 0x5B) || (c >= 0x5D && c <= 0xFF) || *b == Ch(
'"'))
47 else if (*b == Ch(
'\b')) result += Ch(
'\\'), result += Ch(
'b');
48 else if (*b == Ch(
'\f')) result += Ch(
'\\'), result += Ch(
'f');
49 else if (*b == Ch(
'\n')) result += Ch(
'\\'), result += Ch(
'n');
50 else if (*b == Ch(
'\r')) result += Ch(
'\\'), result += Ch(
'r');
51 else if (*b == Ch(
'\t')) result += Ch(
'\\'), result += Ch(
't');
52 else if (*b == Ch(
'/')) result += Ch(
'\\'), result += Ch(
'/');
54 else if (*b == Ch(
'\\')) result += Ch(
'\\');
57 const char *hexdigits =
"0123456789ABCDEF";
58 unsigned long u = (std::min)(static_cast<unsigned long>(
59 static_cast<UCh>(*b)),
61 int d1 = u / 4096; u -= d1 * 4096;
62 int d2 = u / 256; u -= d2 * 256;
63 int d3 = u / 16; u -= d3 * 16;
65 result += Ch(
'\\'); result += Ch(
'u');
66 result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
67 result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
75 void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
77 int indent,
bool pretty)
79 typedef typename Ptree::key_type::value_type Ch;
80 typedef typename std::basic_string<Ch> Str;
83 if (indent > 0 && pt.empty())
86 Str data = create_escapes(pt.template get_value<Str>());
90 else if (indent > 0 && pt.count(Str()) == pt.size())
94 if (pretty) stream << Ch(
'\n');
95 typename Ptree::const_iterator it = pt.begin();
96 for (; it != pt.end(); ++it)
98 if (pretty) stream << Str(4 * (indent + 1), Ch(
' '));
99 write_json_helper(stream, it->second, indent + 1, pretty);
100 if (boost::next(it) != pt.end())
102 if (pretty) stream << Ch(
'\n');
104 if (pretty) stream << Str(4 * indent, Ch(
' '));
111 if (pretty) stream << Ch(
'\n');
112 typename Ptree::const_iterator it = pt.begin();
113 for (; it != pt.end(); ++it)
115 if (pretty) stream << Str(4 * (indent + 1), Ch(
' '));
116 stream << Ch(
'"') << create_escapes(it->first) << Ch(
'"') << Ch(
':');
117 if (pretty) stream << Ch(
' ');
118 write_json_helper(stream, it->second, indent + 1, pretty);
119 if (boost::next(it) != pt.end())
121 if (pretty) stream << Ch(
'\n');
123 if (pretty) stream << Str(4 * indent, Ch(
' '));
129 template<
class Ptree>
130 bool verify_json(
const Ptree &pt,
int depth)
132 typedef typename Ptree::key_type::value_type Ch;
133 typedef typename std::basic_string<Ch> Str;
136 if (depth == 0 && !pt.template get_value<Str>().empty())
140 if (!pt.template get_value<Str>().empty() && !pt.empty())
144 typename Ptree::const_iterator it = pt.begin();
145 for (; it != pt.end(); ++it)
146 if (!verify_json(it->second, depth + 1))
154 template<
class Ptree>
155 void write_json_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
157 const std::string &filename,
160 if (!verify_json(pt, 0))
161 BOOST_PROPERTY_TREE_THROW(json_parser_error(
"ptree contains data that cannot be represented in JSON format", filename, 0));
162 write_json_helper(stream, pt, 0, pretty);
165 BOOST_PROPERTY_TREE_THROW(json_parser_error(
"write error", filename, 0));
Definition: json_parser.h:30