annotate DEPENDENCIES/generic/include/boost/property_tree/detail/json_parser_write.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@16 4 // Distributed under the Boost Software License, Version 1.0.
Chris@16 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_WRITE_HPP_INCLUDED
Chris@16 11 #define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
Chris@16 12
Chris@16 13 #include <boost/property_tree/ptree.hpp>
Chris@16 14 #include <boost/next_prior.hpp>
Chris@16 15 #include <boost/type_traits/make_unsigned.hpp>
Chris@16 16 #include <string>
Chris@16 17 #include <ostream>
Chris@16 18 #include <iomanip>
Chris@16 19
Chris@16 20 namespace boost { namespace property_tree { namespace json_parser
Chris@16 21 {
Chris@16 22
Chris@16 23 // Create necessary escape sequences from illegal characters
Chris@16 24 template<class Ch>
Chris@16 25 std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
Chris@16 26 {
Chris@16 27 std::basic_string<Ch> result;
Chris@16 28 typename std::basic_string<Ch>::const_iterator b = s.begin();
Chris@16 29 typename std::basic_string<Ch>::const_iterator e = s.end();
Chris@16 30 while (b != e)
Chris@16 31 {
Chris@101 32 typedef typename make_unsigned<Ch>::type UCh;
Chris@101 33 UCh c(*b);
Chris@16 34 // This assumes an ASCII superset. But so does everything in PTree.
Chris@16 35 // We escape everything outside ASCII, because this code can't
Chris@16 36 // handle high unicode characters.
Chris@101 37 if (c == 0x20 || c == 0x21 || (c >= 0x23 && c <= 0x2E) ||
Chris@101 38 (c >= 0x30 && c <= 0x5B) || (c >= 0x5D && c <= 0xFF))
Chris@16 39 result += *b;
Chris@16 40 else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
Chris@16 41 else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
Chris@16 42 else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
Chris@16 43 else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
Chris@101 44 else if (*b == Ch('\t')) result += Ch('\\'), result += Ch('t');
Chris@16 45 else if (*b == Ch('/')) result += Ch('\\'), result += Ch('/');
Chris@16 46 else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"');
Chris@16 47 else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
Chris@16 48 else
Chris@16 49 {
Chris@16 50 const char *hexdigits = "0123456789ABCDEF";
Chris@16 51 unsigned long u = (std::min)(static_cast<unsigned long>(
Chris@16 52 static_cast<UCh>(*b)),
Chris@16 53 0xFFFFul);
Chris@16 54 int d1 = u / 4096; u -= d1 * 4096;
Chris@16 55 int d2 = u / 256; u -= d2 * 256;
Chris@16 56 int d3 = u / 16; u -= d3 * 16;
Chris@16 57 int d4 = u;
Chris@16 58 result += Ch('\\'); result += Ch('u');
Chris@16 59 result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
Chris@16 60 result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
Chris@16 61 }
Chris@16 62 ++b;
Chris@16 63 }
Chris@16 64 return result;
Chris@16 65 }
Chris@16 66
Chris@16 67 template<class Ptree>
Chris@16 68 void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
Chris@16 69 const Ptree &pt,
Chris@16 70 int indent, bool pretty)
Chris@16 71 {
Chris@16 72
Chris@16 73 typedef typename Ptree::key_type::value_type Ch;
Chris@16 74 typedef typename std::basic_string<Ch> Str;
Chris@16 75
Chris@16 76 // Value or object or array
Chris@16 77 if (indent > 0 && pt.empty())
Chris@16 78 {
Chris@16 79 // Write value
Chris@16 80 Str data = create_escapes(pt.template get_value<Str>());
Chris@16 81 stream << Ch('"') << data << Ch('"');
Chris@16 82
Chris@16 83 }
Chris@16 84 else if (indent > 0 && pt.count(Str()) == pt.size())
Chris@16 85 {
Chris@16 86 // Write array
Chris@16 87 stream << Ch('[');
Chris@16 88 if (pretty) stream << Ch('\n');
Chris@16 89 typename Ptree::const_iterator it = pt.begin();
Chris@16 90 for (; it != pt.end(); ++it)
Chris@16 91 {
Chris@16 92 if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
Chris@16 93 write_json_helper(stream, it->second, indent + 1, pretty);
Chris@16 94 if (boost::next(it) != pt.end())
Chris@16 95 stream << Ch(',');
Chris@16 96 if (pretty) stream << Ch('\n');
Chris@16 97 }
Chris@101 98 if (pretty) stream << Str(4 * indent, Ch(' '));
Chris@101 99 stream << Ch(']');
Chris@16 100
Chris@16 101 }
Chris@16 102 else
Chris@16 103 {
Chris@16 104 // Write object
Chris@16 105 stream << Ch('{');
Chris@16 106 if (pretty) stream << Ch('\n');
Chris@16 107 typename Ptree::const_iterator it = pt.begin();
Chris@16 108 for (; it != pt.end(); ++it)
Chris@16 109 {
Chris@16 110 if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
Chris@16 111 stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
Chris@101 112 if (pretty) stream << Ch(' ');
Chris@16 113 write_json_helper(stream, it->second, indent + 1, pretty);
Chris@16 114 if (boost::next(it) != pt.end())
Chris@16 115 stream << Ch(',');
Chris@16 116 if (pretty) stream << Ch('\n');
Chris@16 117 }
Chris@16 118 if (pretty) stream << Str(4 * indent, Ch(' '));
Chris@16 119 stream << Ch('}');
Chris@16 120 }
Chris@16 121
Chris@16 122 }
Chris@16 123
Chris@16 124 // Verify if ptree does not contain information that cannot be written to json
Chris@16 125 template<class Ptree>
Chris@16 126 bool verify_json(const Ptree &pt, int depth)
Chris@16 127 {
Chris@16 128
Chris@16 129 typedef typename Ptree::key_type::value_type Ch;
Chris@16 130 typedef typename std::basic_string<Ch> Str;
Chris@16 131
Chris@16 132 // Root ptree cannot have data
Chris@16 133 if (depth == 0 && !pt.template get_value<Str>().empty())
Chris@16 134 return false;
Chris@16 135
Chris@16 136 // Ptree cannot have both children and data
Chris@16 137 if (!pt.template get_value<Str>().empty() && !pt.empty())
Chris@16 138 return false;
Chris@16 139
Chris@16 140 // Check children
Chris@16 141 typename Ptree::const_iterator it = pt.begin();
Chris@16 142 for (; it != pt.end(); ++it)
Chris@16 143 if (!verify_json(it->second, depth + 1))
Chris@16 144 return false;
Chris@16 145
Chris@16 146 // Success
Chris@16 147 return true;
Chris@16 148
Chris@16 149 }
Chris@16 150
Chris@16 151 // Write ptree to json stream
Chris@16 152 template<class Ptree>
Chris@16 153 void write_json_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
Chris@16 154 const Ptree &pt,
Chris@16 155 const std::string &filename,
Chris@16 156 bool pretty)
Chris@16 157 {
Chris@16 158 if (!verify_json(pt, 0))
Chris@16 159 BOOST_PROPERTY_TREE_THROW(json_parser_error("ptree contains data that cannot be represented in JSON format", filename, 0));
Chris@16 160 write_json_helper(stream, pt, 0, pretty);
Chris@16 161 stream << std::endl;
Chris@16 162 if (!stream.good())
Chris@16 163 BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0));
Chris@16 164 }
Chris@16 165
Chris@16 166 } } }
Chris@16 167
Chris@16 168 #endif