Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:18

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/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     // Create necessary escape sequences from illegal characters
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             // This assumes an ASCII superset. But so does everything in PTree.
0035             // We escape everything outside ASCII, because this code can't
0036             // handle high unicode characters.
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         // Value or object or array
0077         if (indent > 0 && pt.empty())
0078         {
0079             // Write value
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             // Write array
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             // Write object
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     // Verify if ptree does not contain information that cannot be written to json
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         // Root ptree cannot have data
0133         if (depth == 0 && !pt.template get_value<Str>().empty())
0134             return false;
0135         
0136         // Ptree cannot have both children and data
0137         if (!pt.template get_value<Str>().empty() && !pt.empty())
0138             return false;
0139 
0140         // Check children
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         // Success
0147         return true;
0148 
0149     }
0150     
0151     // Write ptree to json stream
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; // outputting endl performs flush
0162         if (!stream.good())
0163             BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0));
0164     }
0165 
0166 } } }
0167 
0168 #endif