Awali
Another Weighted Automata library
smart_printer.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2021 Sylvain Lombardy, Victor Marsault, Jacques Sakarovitch
3 //
4 // Awali is a free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef COMMON_JSON_SMART_PRINTER_HH
18 #define COMMON_JSON_SMART_PRINTER_HH
19 
20 #include <unordered_map>
21 #include <sstream>
22 
25 
26 namespace awali {
27 namespace json {
28 
29 
30 class heighter_t : public visitor_t {
31 protected:
32  std::unordered_map<node_t const*,unsigned> map;
33 
34  void enter(node_t const* node) override;
35 
36  void after_child(node_t const* node, uint_or_string_t const& uos,
37  node_t const* child) override;
38 public:
39  inline unsigned operator[] (node_t const* node);
40 
41  heighter_t(json_ast_t ast) { run(ast); }
42  heighter_t(node_t const* node) { run(node); }
44 };
45 
46 
47 
48 class inline_sizer_t : public visitor_t {
49 protected:
50  std::unordered_map<node_t const*,unsigned> map;
51  std::unordered_map<node_t const*,unsigned> left_weight;
53 
54  void leave(bool_t const* node) override;
55  void leave(int_t const* node) override;
56  void leave(string_t const* node) override;
57  void leave(float_t const* node) override;
58  void leave(null_t const* node) override;
59  void enter(object_t const* node) override;
60  void enter(array_t const* node) override;
61  void after_child(array_t const* node, unsigned i, node_t const* child) override;
62  void after_child(object_t const* node, std::string const& key,
63  node_t const* child) override;
64  void between_children(object_t const* node) override;
65  void between_children(array_t const* node) override;
66 
67 public:
68  unsigned operator[] (node_t const* node);
69 
70  unsigned height_of(node_t const* node);
71 
72  inline_sizer_t(json_ast_t ast) { run(ast); }
73  inline_sizer_t(node_t const* node) { run(node); }
75 };
76 
77 
78 
79 class smart_printer_t : public visitor_t {
80 protected:
82  std::ostream& _out;
84  node_t const* inliner;
85  unsigned _max ;
86  std::vector<unsigned> max_vect;
87  unsigned max ();
88 
89 
90  void indent(int i=0);
91 
92  void leaf(double d) override;
93  void leaf(std::string const& str) override;
94  void leaf(int i) override;
95  void leaf(std::nullptr_t) override;
96  void leaf(bool b) override;
97 
98  void enter(array_t const* node) override;
99  void leave(array_t const* node) override;
100 
101  void enter(object_t const* node) override;
102  void leave(object_t const* node) override;
103 
104  void between_children(object_t const* node) override;
105  void between_children(array_t const* node) override;
106 
107  void after_child(node_t const* node, uint_or_string_t const& uos,
108  node_t const* child) override;
109 
110  void before_child(node_t const* node, uint_or_string_t const& uos,
111  node_t const* child) override;
112 
113  void before_child(array_t const* node, unsigned i,
114  node_t const* child) override;
115 
116  void before_child(object_t const* node, std::string const& key,
117  node_t const* child) override;
118 
119  void incr_indent();
120  void decr_indent();
121 
122  bool is_last (node_t const* child);
123 
124  inline void leave(node_t const* node) override;
125 
126 public:
127  smart_printer_t (std::ostream& o, unsigned m = 80);
128 
129  void run(json_ast_t tree) override;
130  void run(node_t const* tree) override;
131 };
132 
133 /*
134 class yaml_sizer_t : public visitor_t {
135 protected:
136  std::unordered_map<node_t const*,unsigned> map;
137 
138  inline void leave(bool_t const* node) override {map[node] = node->value?3:2;}
139  inline void leave(int_t const* node) override{
140  std::stringstream ss; ss << node->value; map[node] = ss.str().length();}
141  inline void leave(string_t const* node) override {
142  map[node] = size_of(node->value);}
143  inline void leave(float_t const* node) override {
144  std::stringstream ss; ss << node->value; map[node] = ss.str().length();}
145  inline void leave(null_t const* node) override { map[node] = 4;}
146  inline void enter(object_t const* node) override { map[node] = 2;}
147  inline void enter(array_t const* node) override { map[node] = 2;}
148  inline void after_child(array_t const* node,
149  unsigned i, node_t const* child) override {
150  map[node] += map[child];
151  }
152  inline void after_child(object_t const* node,
153  std::string const& key, node_t const* child) override
154  {map[node] += key.length() + 2 + map[child];}
155 
156  inline void between_children(object_t const* node) override {map[node] += 3;}
157  inline void between_children(array_t const* node) override {
158  if (node->height() == 1)
159  map[node] += 1;
160  else
161  map[node] += 2;
162  }
163 
164 
165 public:
166  static bool must_escape(std::string str) {
167  static const std::vector<std::string> reserved
168  = {"Yes", "No", "null"};
169  static const std::string authorized
170  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789" ;
171  if (str.find_first_not_of(authorized) != std::string::npos)
172  return true;
173  for (std::string const& target: reserved)
174  if (str == target)
175  return true;
176  size_t idx = 0;
177  try {
178  std::stod(str, &idx);
179  } catch (std::invalid_argument const&) {}
180  if (idx == str.size())
181  return true;
182  return false;
183  }
184 
185  static unsigned size_of(std::string const& str) {
186  if (must_escape(str))
187  return escape(str).length();
188  else
189  return str.length();
190  }
191 
192  inline unsigned operator[] (node_t const* node) {return map.find(node)->second;}
193 
194 };
195 
196 
197 class yaml_printer_t : public visitor_t {
198 protected:
199  node_t const* inliner = nullptr;
200  std::ostream& _out;
201  std::string hyphen = " - ";
202  unsigned indent_amount = hyphen.size();
203  std::string comma = ", ";
204  bool print_inline = false;
205  yaml_sizer_t sizer;
206  unsigned max;
207 
208  inline void indent() {if (!print_inline) {_out << '\n' << std::string((path().size())*indent_amount, ' ');}}
209 
210  inline void leaf(std::string const& str) override {
211  if (sizer.must_escape(str))
212  parser_t::escape_and_put(_out,str);
213  else
214  _out << str;
215  }
216 
217  inline void enter(array_t const* node) override {
218  if (print_inline)
219  _out << "[";
220  }
221  inline void leave(array_t const* node) override {
222  if (print_inline)
223  _out << "]";
224  }
225 
226  inline void enter(object_t const* node) override {
227  if (print_inline)
228  _out << "{";
229  }
230 
231  inline void leave(object_t const* node) override {
232  if (print_inline)
233  _out << "}";
234  }
235 
236 
237  inline void leaf(int i) override {_out << i;}
238 
239  inline void leaf(bool b) override {_out << (b?"Yes":"True");}
240 
241  inline void leaf(double x) override {_out << "test" << x;}
242 
243  inline void leaf(std::nullptr_t p) override {_out << "null";}
244 
245  inline void before_child(array_t const* node,
246  unsigned i, node_t const* child) override
247  {
248  if (!print_inline) {
249  _out << hyphen;
250  if (depth()*indent_amount+sizer[child]+2<=max) {
251  inliner = child;
252  print_inline = true;
253  }
254  }
255  }
256 
257 
258  inline void between_children(array_t const* node) override
259  { if (print_inline) {
260  _out << ',';
261  if (node->height() > 1)
262  _out << ' ';
263  }
264  else
265  indent();
266  }
267 
268  inline void between_children(object_t const* node) override
269  { if (print_inline) _out << comma; else indent();}
270 
271  inline void before_child(object_t const* node,
272  std::string const& key, node_t const* child) override
273  { _out << key<< ": ";
274  if (!print_inline && !child->is_leaf()) {
275  if (depth()*indent_amount+sizer[child]+key.length()+2<=max) {
276  inliner = child;
277  print_inline = true;
278  }
279  else {
280  indent();
281  _out << std::string(indent_amount, ' ');
282  }
283  }
284  }
285 
286  inline void leave(node_t const* node) override
287  {if (inliner == node) print_inline = false; }
288 
289 public:
290  inline void run(node_t const* tree) override {
291  sizer.run(tree);
292  visit(tree);
293  }
294  yaml_printer_t(std::ostream& out, unsigned m = 80) : _out(out), max(m) {}
295 };
296 
297 //inline void inline_sizer_t::leave(node_t const* node) {
298 // std::cerr << std::endl;
299 // smart_printer_t printer(std::cerr, 0);
300 // printer.run(node);
301 // unsigned m = map.find(node)->second;
302 // std::cerr << std::endl;
303 // for (unsigned i = 1; i <= m; i++)
304 // std::cerr << i%10;
305 // std::cerr << std::endl;
306 // }
307 */
308 
309 std::ostream& put(node_t const* node, std::ostream& out);
310 
311 } //end of namespace json
312 } //end of namespace awali
313 #endif
Definition: node.hh:424
Definition: node.hh:555
Definition: node.hh:503
Definition: smart_printer.hh:30
heighter_t(json_ast_t ast)
Definition: smart_printer.hh:41
void after_child(node_t const *node, uint_or_string_t const &uos, node_t const *child) override
Function called just after the specialized version with the same name.
heighter_t()
Definition: smart_printer.hh:43
std::unordered_map< node_t const *, unsigned > map
Definition: smart_printer.hh:32
unsigned operator[](node_t const *node)
heighter_t(node_t const *node)
Definition: smart_printer.hh:42
void enter(node_t const *node) override
Very first function called when visiting a node.
Definition: smart_printer.hh:48
void after_child(object_t const *node, std::string const &key, node_t const *child) override
void leave(string_t const *node) override
void between_children(array_t const *node) override
Function called between visiting two children, after the function with the same name and argument typ...
std::unordered_map< node_t const *, unsigned > left_weight
Definition: smart_printer.hh:51
std::unordered_map< node_t const *, unsigned > map
Definition: smart_printer.hh:50
void enter(object_t const *node) override
Function called when starting visiting an object_t, just after the kind-independent enter(node_t cons...
void leave(null_t const *node) override
void between_children(object_t const *node) override
Function called between visiting two children, after the function with the same name and argument typ...
unsigned operator[](node_t const *node)
inline_sizer_t()
Definition: smart_printer.hh:74
void leave(int_t const *node) override
heighter_t heighter
Definition: smart_printer.hh:52
void leave(bool_t const *node) override
void after_child(array_t const *node, unsigned i, node_t const *child) override
inline_sizer_t(node_t const *node)
Definition: smart_printer.hh:73
inline_sizer_t(json_ast_t ast)
Definition: smart_printer.hh:72
void enter(array_t const *node) override
Function called when starting visiting an array_t, just after the kind-independent enter(node_t const...
unsigned height_of(node_t const *node)
void leave(float_t const *node) override
Definition: node.hh:483
Definition: node.hh:191
Definition: node.hh:582
Definition: node.hh:365
Definition: smart_printer.hh:79
node_t const * inliner
Definition: smart_printer.hh:84
void before_child(node_t const *node, uint_or_string_t const &uos, node_t const *child) override
Function called just before the specialized version with the same name.
void leaf(bool b) override
Function called when visiting a bool_t, after enter(bool_t const*) but before leave(bool_t const*).
void leaf(double d) override
Function called when visiting a float_t, after enter(float_t const*) but before leave(float_t const*)...
unsigned _max
Definition: smart_printer.hh:85
std::ostream & _out
Definition: smart_printer.hh:82
void run(json_ast_t tree) override
void enter(array_t const *node) override
Function called when starting visiting an array_t, just after the kind-independent enter(node_t const...
void run(node_t const *tree) override
void leave(array_t const *node) override
int indent_amount
Definition: smart_printer.hh:83
bool is_last(node_t const *child)
smart_printer_t(std::ostream &o, unsigned m=80)
void enter(object_t const *node) override
Function called when starting visiting an object_t, just after the kind-independent enter(node_t cons...
std::vector< unsigned > max_vect
Definition: smart_printer.hh:86
void after_child(node_t const *node, uint_or_string_t const &uos, node_t const *child) override
Function called just after the specialized version with the same name.
void before_child(array_t const *node, unsigned i, node_t const *child) override
void leaf(std::string const &str) override
Function called when visiting a string_t, after enter(string_t const*) but before leave(string_t cons...
void leaf(int i) override
Function called when visiting a int_t, after enter(int_t const*) but before leave(int_t const*).
void leave(node_t const *node) override
This function is called for every node type.
void leaf(std::nullptr_t) override
Function called when visiting a null_t, after enter(null_t const*) but before leave(null_t const*).
inline_sizer_t sizer
Definition: smart_printer.hh:81
void between_children(array_t const *node) override
Function called between visiting two children, after the function with the same name and argument typ...
void between_children(object_t const *node) override
Function called between visiting two children, after the function with the same name and argument typ...
void leave(object_t const *node) override
void before_child(object_t const *node, std::string const &key, node_t const *child) override
Function called just before and just after visiting a child node.
Definition: node.hh:526
Definition: node.hh:48
Abstract class that helps implement a visitor of json tree or subtree.
Definition: visitor.hh:71
virtual void run(json_ast_t tree)
Definition: visitor.hh:241
std::ostream & json(automaton_t aut, std::ostream &out)
std::ostream & put(node_t const *node, std::ostream &out)
Main namespace of Awali.
Definition: ato.hh:22
std::shared_ptr< json::object_t > json_ast_t
Definition: json_ast.hh:27