File indexing completed on 2025-01-18 09:50:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
0011 #define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
0012
0013 #include <boost/property_tree/ptree.hpp>
0014 #include <boost/next_prior.hpp>
0015 #include <boost/type_traits/make_unsigned.hpp>
0016 #include <string>
0017 #include <ostream>
0018 #include <iomanip>
0019
0020 namespace boost { namespace property_tree { namespace json_parser
0021 {
0022
0023
0024 template<class Ch>
0025 std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
0026 {
0027 std::basic_string<Ch> result;
0028 typename std::basic_string<Ch>::const_iterator b = s.begin();
0029 typename std::basic_string<Ch>::const_iterator e = s.end();
0030 while (b != e)
0031 {
0032 typedef typename make_unsigned<Ch>::type UCh;
0033 UCh c(*b);
0034
0035
0036
0037 if (c == 0x20 || c == 0x21 || (c >= 0x23 && c <= 0x2E) ||
0038 (c >= 0x30 && c <= 0x5B) || (c >= 0x5D && c <= 0xFF))
0039 result += *b;
0040 else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
0041 else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
0042 else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
0043 else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
0044 else if (*b == Ch('\t')) result += Ch('\\'), result += Ch('t');
0045 else if (*b == Ch('/')) result += Ch('\\'), result += Ch('/');
0046 else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"');
0047 else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
0048 else
0049 {
0050 const char *hexdigits = "0123456789ABCDEF";
0051 unsigned long u = (std::min)(static_cast<unsigned long>(
0052 static_cast<UCh>(*b)),
0053 0xFFFFul);
0054 unsigned long d1 = u / 4096; u -= d1 * 4096;
0055 unsigned long d2 = u / 256; u -= d2 * 256;
0056 unsigned long d3 = u / 16; u -= d3 * 16;
0057 unsigned long d4 = u;
0058 result += Ch('\\'); result += Ch('u');
0059 result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
0060 result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
0061 }
0062 ++b;
0063 }
0064 return result;
0065 }
0066
0067 template<class Ptree>
0068 void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
0069 const Ptree &pt,
0070 int indent, bool pretty)
0071 {
0072
0073 typedef typename Ptree::key_type::value_type Ch;
0074 typedef typename std::basic_string<Ch> Str;
0075
0076
0077 if (indent > 0 && pt.empty())
0078 {
0079
0080 Str data = create_escapes(pt.template get_value<Str>());
0081 stream << Ch('"') << data << Ch('"');
0082
0083 }
0084 else if (indent > 0 && pt.count(Str()) == pt.size())
0085 {
0086
0087 stream << Ch('[');
0088 if (pretty) stream << Ch('\n');
0089 typename Ptree::const_iterator it = pt.begin();
0090 for (; it != pt.end(); ++it)
0091 {
0092 if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
0093 write_json_helper(stream, it->second, indent + 1, pretty);
0094 if (boost::next(it) != pt.end())
0095 stream << Ch(',');
0096 if (pretty) stream << Ch('\n');
0097 }
0098 if (pretty) stream << Str(4 * indent, Ch(' '));
0099 stream << Ch(']');
0100
0101 }
0102 else
0103 {
0104
0105 stream << Ch('{');
0106 if (pretty) stream << Ch('\n');
0107 typename Ptree::const_iterator it = pt.begin();
0108 for (; it != pt.end(); ++it)
0109 {
0110 if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
0111 stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
0112 if (pretty) stream << Ch(' ');
0113 write_json_helper(stream, it->second, indent + 1, pretty);
0114 if (boost::next(it) != pt.end())
0115 stream << Ch(',');
0116 if (pretty) stream << Ch('\n');
0117 }
0118 if (pretty) stream << Str(4 * indent, Ch(' '));
0119 stream << Ch('}');
0120 }
0121
0122 }
0123
0124
0125 template<class Ptree>
0126 bool verify_json(const Ptree &pt, int depth)
0127 {
0128
0129 typedef typename Ptree::key_type::value_type Ch;
0130 typedef typename std::basic_string<Ch> Str;
0131
0132
0133 if (depth == 0 && !pt.template get_value<Str>().empty())
0134 return false;
0135
0136
0137 if (!pt.template get_value<Str>().empty() && !pt.empty())
0138 return false;
0139
0140
0141 typename Ptree::const_iterator it = pt.begin();
0142 for (; it != pt.end(); ++it)
0143 if (!verify_json(it->second, depth + 1))
0144 return false;
0145
0146
0147 return true;
0148
0149 }
0150
0151
0152 template<class Ptree>
0153 void write_json_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
0154 const Ptree &pt,
0155 const std::string &filename,
0156 bool pretty)
0157 {
0158 if (!verify_json(pt, 0))
0159 BOOST_PROPERTY_TREE_THROW(json_parser_error("ptree contains data that cannot be represented in JSON format", filename, 0));
0160 write_json_helper(stream, pt, 0, pretty);
0161 stream << std::endl;
0162 if (!stream.good())
0163 BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0));
0164 }
0165
0166 } } }
0167
0168 #endif