Argo  1.0
A C++ library for handling JSON.
unparser.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Andrew Haisley
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
24 
25 #include <ostream>
26 #include <fstream>
27 #include <sstream>
28 
29 #include "common.hpp"
30 #include "unparser.hpp"
31 #include "utf8.hpp"
32 #include "json_exception.hpp"
33 #include "json_io_exception.hpp"
34 #include "file_writer.hpp"
35 #include "stream_writer.hpp"
36 
37 #ifndef _ARGO_WINDOWS_
38 #include "fd_writer.hpp"
39 #endif
40 
41 using namespace std;
42 using namespace NAMESPACE;
43 
44 unparser::unparser(
45  writer &w,
46  const char *space,
47  const char *newline,
48  const char *indent,
49  int indent_inc) :
50  m_writer(w),
51  m_space(space),
52  m_newline(newline),
53  m_indent(indent),
54  m_indent_inc(indent_inc)
55 {
56 }
57 
58 void unparser::print_indent(int indent_level)
59 {
60  for (int i = 0; i < indent_level; i++)
61  {
62  m_writer << m_indent;
63  }
64 }
65 
66 
67 void unparser::unparse_object(const json &j, int indent_level)
68 {
69  print_indent(indent_level);
70  m_writer << '{' << m_space << m_newline;
71  int n = j.get_object().size();
72  for (const auto &p : j.get_object())
73  {
74  print_indent(indent_level + m_indent_inc);
75  m_writer << '"' << p.first << '"' << m_space << ':' << m_space;
76  if (p.second->get_instance_type() == json::object_e ||
77  p.second->get_instance_type() == json::array_e)
78  {
79  m_writer << m_newline;
80  unparse(*(p.second), indent_level + (m_indent_inc * 2));
81  }
82  else
83  {
84  unparse(*(p.second), indent_level + m_indent_inc);
85  }
86  if (n-- > 1)
87  {
88  m_writer << ',';
89  }
90  m_writer << m_newline;
91  }
92  print_indent(indent_level);
93  m_writer << m_space << '}';
94 }
95 
96 void unparser::unparse_array(const json &j, int indent_level)
97 {
98  print_indent(indent_level);
99  m_writer << '[' << m_space << m_newline;
100  int n = j.get_array().size();
101  for (const auto &i : j.get_array())
102  {
103  if (i->get_instance_type() != json::object_e &&
104  i->get_instance_type() != json::array_e)
105  {
106  print_indent(indent_level + m_indent_inc);
107  }
108  unparse(*i, indent_level + m_indent_inc);
109  if (n-- > 1)
110  {
111  m_writer << ',' << m_space;
112  }
113  m_writer << m_newline;
114  }
115  print_indent(indent_level);
116  m_writer << m_space << ']';
117 }
118 
119 void unparser::unparse(const json &j, int indent_level)
120 {
121  if (j.get_raw_value() == "")
122  {
123  switch (j.get_instance_type())
124  {
125  case json::object_e:
126  unparse_object(j, indent_level);
127  break;
128  case json::array_e:
129  unparse_array(j, indent_level);
130  break;
131  case json::boolean_e:
132  m_writer << (static_cast<bool>(j) ? "true" : "false");
133  break;
134  case json::null_e:
135  m_writer << "null";
136  break;
137  case json::number_int_e:
138  m_writer << static_cast<int>(j);
139  break;
140  case json::number_double_e:
141  m_writer << static_cast<double>(j);
142  break;
143  case json::string_e:
144  m_writer << '"' << *(utf8::utf8_to_json_string(j)) << '"';
145  break;
146  default:
148  }
149  }
150  else
151  {
152  if (j.get_instance_type() == json::string_e)
153  {
154  m_writer << '"' << j.get_raw_value() << '"';
155  }
156  else
157  {
158  m_writer << j.get_raw_value();
159  }
160  }
161 }
162 
164  ostream &o,
165  const json &j,
166  const char *space,
167  const char *newline,
168  const char *indent,
169  int indent_inc)
170 {
171  stream_writer w(&o);
172  unparser u(w, space, newline, indent, indent_inc);
173  u.unparse(j, 0);
174 }
175 
176 #ifndef _ARGO_WINDOWS_
178  int fd,
179  const json &j,
180  const char *space,
181  const char *newline,
182  const char *indent,
183  int indent_inc)
184 {
185  fd_writer w(fd);
186  unparser u(w, space, newline, indent, indent_inc);
187  u.unparse(j, 0);
188 }
189 #endif
190 
192  FILE *s,
193  const json &j,
194  const char *space,
195  const char *newline,
196  const char *indent,
197  int indent_inc)
198 {
199  file_writer w(s);
200  unparser u(w, space, newline, indent, indent_inc);
201  u.unparse(j, 0);
202 }
203 
205  const json &j,
206  const string &file_name,
207  const char *space,
208  const char *newline,
209  const char *indent,
210  int indent_inc)
211 {
212  ofstream os(file_name);
213 
214  if (os)
215  {
216  stream_writer w(&os);
217  unparser u(w, space, newline, indent, indent_inc);
218  u.unparse(j, 0);
219  }
220  else
221  {
223  }
224 }
225 
226 ostream &NAMESPACE::operator<<(ostream &stream, const json &j)
227 {
228  unparser::unparse(stream, j);
229  return stream;
230 }
231 
232 void NAMESPACE::operator<<(string &s, const json &j)
233 {
234  stringstream ss;
235  unparser::unparse(ss, j);
236  s = ss.str();
237 }
const std::string & get_raw_value() const
Definition: json.cpp:325
Simple proxy for write operations on various types of stream.
Definition: writer.hpp:41
Base class for all exceptions thrown by the library.
The json_exception class.
A class to write JSON messages to a C++ istream.
static void unparse(std::ostream &o, const json &j, const char *space=" ", const char *newline="", const char *indent=" ", int indent_inc=0)
Definition: unparser.cpp:163
std::vector< std::unique_ptr< json > > & get_array()
Definition: json.cpp:305
#define NAMESPACE
You can change the namespace of the whole library by changing this value.
Definition: common.hpp:29
Specific class of exceptions for IO errors of various types.
static void save(const json &j, const std::string &file_name, const char *space=" ", const char *newline="", const char *indent=" ", int indent_inc=0)
Definition: unparser.cpp:204
Internal error - the m_type member variable has an invalid value.
STL namespace.
Class to unparse json instances into JSON messages.
Definition: unparser.hpp:54
Common defs needed everywhere and, as far as is possible, platform specific changes.
The fd_writer class.
A derived class of writer that writes to POSIX file descriptors.
Definition: fd_writer.hpp:34
A derived class of writer that writes to stdio FILEs.
Definition: file_writer.hpp:36
All json things are represented by instances of this class.
Definition: json.hpp:63
std::map< std::string, std::unique_ptr< json > > & get_object()
Definition: json.cpp:315
The file_writer class.
The stream_writer class.
static std::unique_ptr< std::string > utf8_to_json_string(const std::string &src)
Definition: utf8.cpp:241
The unparser class.
The utf8 class.
type get_instance_type() const
Definition: json.cpp:300
The json_io_exception class.