Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-12 08:28:43

0001 // ----------------------------------------------------------------------------
0002 // Copyright (C) 2002-2006 Marcin Kalicinski
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. 
0005 // (See accompanying file LICENSE_1_0.txt or copy at 
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // For more information, see www.boost.org
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/json_parser/error.hpp>
0014 #include <boost/property_tree/ptree.hpp>
0015 #include <boost/next_prior.hpp>
0016 #include <boost/type_traits/make_unsigned.hpp>
0017 #include <string>
0018 #include <ostream>
0019 #include <iomanip>
0020 
0021 namespace boost { namespace property_tree { namespace json_parser
0022 {
0023 
0024     // Create necessary escape sequences from illegal characters
0025     template<class Ch>
0026     std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
0027     {
0028         std::basic_string<Ch> result;
0029         typename std::basic_string<Ch>::const_iterator b = s.begin();
0030         typename std::basic_string<Ch>::const_iterator e = s.end();
0031         while (b != e)
0032         {
0033             typedef typename make_unsigned<Ch>::type UCh;
0034             UCh c(*b);
0035             // This assumes an ASCII superset. But so does everything in PTree.
0036             // We escape everything outside ASCII, because this code can't
0037             // handle high unicode characters.
0038             if (c == 0x20 || c == 0x21 || (c >= 0x23 && c <= 0x2E) ||
0039                 (c >= 0x30 && c <= 0x5B) || (c >= 0x5D && c <= 0xFF))
0040                 result += *b;
0041             else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
0042             else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
0043             else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
0044             else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
0045             else if (*b == Ch('\t')) result += Ch('\\'), result += Ch('t');
0046             else if (*b == Ch('/')) result += Ch('\\'), result += Ch('/');
0047             else if (*b == Ch('"'))  result += Ch('\\'), result += Ch('"');
0048             else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
0049             else
0050             {
0051                 const char *hexdigits = "0123456789ABCDEF";
0052                 unsigned long u = (std::min)(static_cast<unsigned long>(
0053                                                  static_cast<UCh>(*b)),
0054                                              0xFFFFul);
0055                 unsigned long d1 = u / 4096; u -= d1 * 4096;
0056                 unsigned long d2 = u / 256; u -= d2 * 256;
0057                 unsigned long d3 = u / 16; u -= d3 * 16;
0058                 unsigned long d4 = u;
0059                 result += Ch('\\'); result += Ch('u');
0060                 result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
0061                 result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
0062             }
0063             ++b;
0064         }
0065         return result;
0066     }
0067 
0068     template<class Ptree>
0069     void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream, 
0070                            const Ptree &pt,
0071                            int indent, bool pretty)
0072     {
0073 
0074         typedef typename Ptree::key_type::value_type Ch;
0075         typedef typename std::basic_string<Ch> Str;
0076 
0077         // Value or object or array
0078         if (indent > 0 && pt.empty())
0079         {
0080             // Write value
0081             Str data = create_escapes(pt.template get_value<Str>());
0082             stream << Ch('"') << data << Ch('"');
0083 
0084         }
0085         else if (indent > 0 && pt.count(Str()) == pt.size())
0086         {
0087             // Write array
0088             stream << Ch('[');
0089             if (pretty) stream << Ch('\n');
0090             typename Ptree::const_iterator it = pt.begin();
0091             for (; it != pt.end(); ++it)
0092             {
0093                 if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
0094                 write_json_helper(stream, it->second, indent + 1, pretty);
0095                 if (boost::next(it) != pt.end())
0096                     stream << Ch(',');
0097                 if (pretty) stream << Ch('\n');
0098             }
0099             if (pretty) stream << Str(4 * indent, Ch(' '));
0100             stream << Ch(']');
0101 
0102         }
0103         else
0104         {
0105             // Write object
0106             stream << Ch('{');
0107             if (pretty) stream << Ch('\n');
0108             typename Ptree::const_iterator it = pt.begin();
0109             for (; it != pt.end(); ++it)
0110             {
0111                 if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
0112                 stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
0113                 if (pretty) stream << Ch(' ');
0114                 write_json_helper(stream, it->second, indent + 1, pretty);
0115                 if (boost::next(it) != pt.end())
0116                     stream << Ch(',');
0117                 if (pretty) stream << Ch('\n');
0118             }
0119             if (pretty) stream << Str(4 * indent, Ch(' '));
0120             stream << Ch('}');
0121         }
0122 
0123     }
0124 
0125     // Verify if ptree does not contain information that cannot be written to json
0126     template<class Ptree>
0127     bool verify_json(const Ptree &pt, int depth)
0128     {
0129 
0130         typedef typename Ptree::key_type::value_type Ch;
0131         typedef typename std::basic_string<Ch> Str;
0132 
0133         // Root ptree cannot have data
0134         if (depth == 0 && !pt.template get_value<Str>().empty())
0135             return false;
0136         
0137         // Ptree cannot have both children and data
0138         if (!pt.template get_value<Str>().empty() && !pt.empty())
0139             return false;
0140 
0141         // Check children
0142         typename Ptree::const_iterator it = pt.begin();
0143         for (; it != pt.end(); ++it)
0144             if (!verify_json(it->second, depth + 1))
0145                 return false;
0146 
0147         // Success
0148         return true;
0149 
0150     }
0151     
0152     // Write ptree to json stream
0153     template<class Ptree>
0154     void write_json_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream, 
0155                              const Ptree &pt,
0156                              const std::string &filename,
0157                              bool pretty)
0158     {
0159         if (!verify_json(pt, 0))
0160             BOOST_PROPERTY_TREE_THROW(json_parser_error("ptree contains data that cannot be represented in JSON format", filename, 0));
0161         write_json_helper(stream, pt, 0, pretty);
0162 
0163         if (pretty) stream << std::endl;
0164         else stream << std::flush;
0165 
0166         if (!stream.good())
0167             BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0));
0168     }
0169 
0170 } } }
0171 
0172 #endif