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-2022 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  /* Attribute `columns` is set to >0 if we are in half-inline mode for array nodes. */
85  unsigned columns;
86  node_t const* inliner;
87  unsigned _max ;
88  std::vector<unsigned> max_vect;
89  unsigned max ();
90 
91 
92  void indent(int i=0);
93 
94  void leaf(double d) override;
95  void leaf(std::string const& str) override;
96  void leaf(int i) override;
97  void leaf(std::nullptr_t) override;
98  void leaf(bool b) override;
99 
100  void enter(array_t const* node) override;
101  void leave(array_t const* node) override;
102 
103  void enter(object_t const* node) override;
104  void leave(object_t const* node) override;
105 
106  void between_children(object_t const* node) override;
107  void between_children(array_t const* node) override;
108 
109  void after_child(node_t const* node, uint_or_string_t const& uos,
110  node_t const* child) override;
111 
112  void before_child(node_t const* node, uint_or_string_t const& uos,
113  node_t const* child) override;
114 
115  void before_child(array_t const* node, unsigned i,
116  node_t const* child) override;
117 
118  void before_child(object_t const* node, std::string const& key,
119  node_t const* child) override;
120 
121  void incr_indent();
122  void decr_indent();
123 
124  bool is_last (node_t const* child);
125 
126  inline void leave(node_t const* node) override;
127 
128 public:
129  smart_printer_t (std::ostream& o, unsigned m = 80);
130 
131  void run(json_ast_t tree) override;
132  void run(node_t const* tree) override;
133 };
134 
135 /*
136 class yaml_sizer_t : public visitor_t {
137 protected:
138  std::unordered_map<node_t const*,unsigned> map;
139 
140  inline void leave(bool_t const* node) override {map[node] = node->value?3:2;}
141  inline void leave(int_t const* node) override{
142  std::stringstream ss; ss << node->value; map[node] = ss.str().length();}
143  inline void leave(string_t const* node) override {
144  map[node] = size_of(node->value);}
145  inline void leave(float_t const* node) override {
146  std::stringstream ss; ss << node->value; map[node] = ss.str().length();}
147  inline void leave(null_t const* node) override { map[node] = 4;}
148  inline void enter(object_t const* node) override { map[node] = 2;}
149  inline void enter(array_t const* node) override { map[node] = 2;}
150  inline void after_child(array_t const* node,
151  unsigned i, node_t const* child) override {
152  map[node] += map[child];
153  }
154  inline void after_child(object_t const* node,
155  std::string const& key, node_t const* child) override
156  {map[node] += key.length() + 2 + map[child];}
157 
158  inline void between_children(object_t const* node) override {map[node] += 3;}
159  inline void between_children(array_t const* node) override {
160  if (node->height() == 1)
161  map[node] += 1;
162  else
163  map[node] += 2;
164  }
165 
166 
167 public:
168  static bool must_escape(std::string str) {
169  static const std::vector<std::string> reserved
170  = {"Yes", "No", "null"};
171  static const std::string authorized
172  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789" ;
173  if (str.find_first_not_of(authorized) != std::string::npos)
174  return true;
175  for (std::string const& target: reserved)
176  if (str == target)
177  return true;
178  size_t idx = 0;
179  try {
180  std::stod(str, &idx);
181  } catch (std::invalid_argument const&) {}
182  if (idx == str.size())
183  return true;
184  return false;
185  }
186 
187  static unsigned size_of(std::string const& str) {
188  if (must_escape(str))
189  return escape(str).length();
190  else
191  return str.length();
192  }
193 
194  inline unsigned operator[] (node_t const* node) {return map.find(node)->second;}
195 
196 };
197 
198 
199 class yaml_printer_t : public visitor_t {
200 protected:
201  node_t const* inliner = nullptr;
202  std::ostream& _out;
203  std::string hyphen = " - ";
204  unsigned indent_amount = hyphen.size();
205  std::string comma = ", ";
206  bool print_inline = false;
207  yaml_sizer_t sizer;
208  unsigned max;
209 
210  inline void indent() {if (!print_inline) {_out << '\n' << std::string((path().size())*indent_amount, ' ');}}
211 
212  inline void leaf(std::string const& str) override {
213  if (sizer.must_escape(str))
214  parser_t::escape_and_put(_out,str);
215  else
216  _out << str;
217  }
218 
219  inline void enter(array_t const* node) override {
220  if (print_inline)
221  _out << "[";
222  }
223  inline void leave(array_t const* node) override {
224  if (print_inline)
225  _out << "]";
226  }
227 
228  inline void enter(object_t const* node) override {
229  if (print_inline)
230  _out << "{";
231  }
232 
233  inline void leave(object_t const* node) override {
234  if (print_inline)
235  _out << "}";
236  }
237 
238 
239  inline void leaf(int i) override {_out << i;}
240 
241  inline void leaf(bool b) override {_out << (b?"Yes":"True");}
242 
243  inline void leaf(double x) override {_out << "test" << x;}
244 
245  inline void leaf(std::nullptr_t p) override {_out << "null";}
246 
247  inline void before_child(array_t const* node,
248  unsigned i, node_t const* child) override
249  {
250  if (!print_inline) {
251  _out << hyphen;
252  if (depth()*indent_amount+sizer[child]+2<=max) {
253  inliner = child;
254  print_inline = true;
255  }
256  }
257  }
258 
259 
260  inline void between_children(array_t const* node) override
261  { if (print_inline) {
262  _out << ',';
263  if (node->height() > 1)
264  _out << ' ';
265  }
266  else
267  indent();
268  }
269 
270  inline void between_children(object_t const* node) override
271  { if (print_inline) _out << comma; else indent();}
272 
273  inline void before_child(object_t const* node,
274  std::string const& key, node_t const* child) override
275  { _out << key<< ": ";
276  if (!print_inline && !child->is_leaf()) {
277  if (depth()*indent_amount+sizer[child]+key.length()+2<=max) {
278  inliner = child;
279  print_inline = true;
280  }
281  else {
282  indent();
283  _out << std::string(indent_amount, ' ');
284  }
285  }
286  }
287 
288  inline void leave(node_t const* node) override
289  {if (inliner == node) print_inline = false; }
290 
291 public:
292  inline void run(node_t const* tree) override {
293  sizer.run(tree);
294  visit(tree);
295  }
296  yaml_printer_t(std::ostream& out, unsigned m = 80) : _out(out), max(m) {}
297 };
298 
299 //inline void inline_sizer_t::leave(node_t const* node) {
300 // std::cerr << std::endl;
301 // smart_printer_t printer(std::cerr, 0);
302 // printer.run(node);
303 // unsigned m = map.find(node)->second;
304 // std::cerr << std::endl;
305 // for (unsigned i = 1; i <= m; i++)
306 // std::cerr << i%10;
307 // std::cerr << std::endl;
308 // }
309 */
310 
311 std::ostream& put_inline(std::ostream& out, node_t const* node);
312 std::ostream& put(std::ostream& out, node_t const* node);
313 
314 } //end of namespace json
315 } //end of namespace awali
316 #endif
Definition: node.hh:431
Definition: node.hh:555
Definition: node.hh:508
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 (node_t const*).
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 (node_t const*).
unsigned height_of(node_t const *node)
void leave(float_t const *node) override
Definition: node.hh:488
Definition: node.hh:193
Definition: node.hh:578
Definition: node.hh:367
Definition: smart_printer.hh:79
node_t const * inliner
Definition: smart_printer.hh:86
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 (bool_t const*) but before leave(bool_t const*).
void leaf(double d) override
Function called when visiting a float_t, after (float_t const*) but before leave(float_t const*).
unsigned _max
Definition: smart_printer.hh:87
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 (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 (node_t const*).
std::vector< unsigned > max_vect
Definition: smart_printer.hh:88
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
unsigned columns
Definition: smart_printer.hh:85
void leaf(std::string const &str) override
Function called when visiting a string_t, after (string_t const*) but before leave(string_t const*).
void leaf(int i) override
Function called when visiting a int_t, after (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 (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:529
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(std::ostream &out, node_t const *node)
std::ostream & put_inline(std::ostream &out, node_t const *node)
Main namespace of Awali.
Definition: ato.hh:22
std::shared_ptr< json::object_t > json_ast_t
Definition: json_ast.hh:27