CBMC
structured_data.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Classes for representing generic structured data
4 
5 Author: Thomas Kiley
6 
7 \*******************************************************************/
8 
9 #include "structured_data.h"
10 #include "range.h"
11 #include "string_utils.h"
12 #include <algorithm>
13 
14 labelt::labelt(std::vector<std::string> components) : components(components)
15 {
16  PRECONDITION(!components.empty());
17  PRECONDITION(std::all_of(
18  components.begin(), components.end(), [](const std::string &component) {
19  return !component.empty() &&
20  std::none_of(component.begin(), component.end(), ::isupper);
21  }));
22 }
23 
24 std::string labelt::camel_case() const
25 {
26  std::ostringstream output;
27  output << *components.begin();
29  output, std::next(components.begin()), components.end(), "", capitalize);
30  return output.str();
31 }
32 
33 std::string labelt::snake_case() const
34 {
35  std::ostringstream output;
36  join_strings(output, components.begin(), components.end(), '_');
37  return output.str();
38 }
39 
40 std::string labelt::kebab_case() const
41 {
42  std::ostringstream output;
43  join_strings(output, components.begin(), components.end(), '-');
44  return output.str();
45 }
46 
47 std::string labelt::pretty() const
48 {
49  std::ostringstream output;
50  const auto range =
51  make_range(components.begin(), std::next(components.begin()))
52  .map(capitalize)
53  .concat(make_range(std::next(components.begin()), components.end()));
54 
55  join_strings(output, range.begin(), range.end(), ' ');
56  return output.str();
57 }
58 
59 bool labelt::operator<(const labelt &other) const
60 {
61  return components < other.components;
62 }
63 
65 {
66  // Structured data (e.g. arrays and objects) should use an entry
69 }
70 
72 structured_data_entryt::entry(std::map<labelt, structured_data_entryt> children)
73 {
74  return structured_data_entryt(std::move(children));
75 }
76 
78  : data(std::move(data))
79 {
80 }
81 
83  std::map<labelt, structured_data_entryt> children)
84  : _children(std::move(children))
85 {
86 }
87 
89 {
90  return _children.empty();
91 }
92 
94 {
95  return data.value;
96 }
97 const std::map<labelt, structured_data_entryt> &
99 {
100  return _children;
101 }
102 
104 {
105  return data;
106 }
107 
109  std::map<labelt, structured_data_entryt> data)
110  : _data(std::move(data))
111 {
112 }
113 
114 std::vector<std::string>
115 pretty_node(const std::pair<labelt, structured_data_entryt> &entry)
116 {
117  const labelt &label = entry.first;
118  const structured_data_entryt &data = entry.second;
119  if(data.is_leaf())
120  {
121  std::ostringstream line;
122  line << label.pretty() << ": " << data.leaf_data();
123  return {line.str()};
124  }
125  else
126  {
127  const auto indent = [](const std::string &line) { return "\t" + line; };
128 
129  const auto &children = data.children();
130  std::vector<std::vector<std::string>> lines =
131  make_range(children)
132  .map(pretty_node)
133  .map([&](std::vector<std::string> sub_lines) {
134  return make_range(sub_lines)
135  .map(indent)
136  .collect<std::vector<std::string>>();
137  })
138  .collect<std::vector<std::vector<std::string>>>();
139 
140  std::vector<std::string> result;
141  for(const auto &sub_lines : lines)
142  {
143  result.insert(result.end(), sub_lines.begin(), sub_lines.end());
144  }
145  return result;
146  }
147 }
148 
149 std::string to_pretty(const structured_datat &data)
150 {
151  if(data.data().empty())
152  return "";
153 
154  std::vector<std::vector<std::string>> lines =
155  make_range(data.data())
156  .map(pretty_node)
157  .collect<std::vector<std::vector<std::string>>>();
158  std::vector<std::string> flattened_lines;
159  for(const auto &line_section : lines)
160  {
161  flattened_lines.insert(
162  flattened_lines.end(), line_section.begin(), line_section.end());
163  }
164  std::ostringstream output;
165  join_strings(output, flattened_lines.begin(), flattened_lines.end(), "\n");
166  return output.str();
167 }
168 
169 const std::map<labelt, structured_data_entryt> &structured_datat::data() const
170 {
171  return _data;
172 }
Definition: json.h:27
bool is_array() const
Definition: json.h:61
std::string value
Definition: json.h:132
bool is_object() const
Definition: json.h:56
A way of representing nested key/value data.
const std::map< labelt, structured_data_entryt > & data() const
structured_datat(std::map< labelt, structured_data_entryt > data)
std::map< labelt, structured_data_entryt > _data
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition: range.h:522
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:80
std::string capitalize(const std::string &str)
Stream & join_strings(Stream &&os, const It b, const It e, const Delimiter &delimiter, TransformFunc &&transform_func)
Prints items to an stream, separated by a constant delimiter.
Definition: string_utils.h:61
std::string camel_case() const
labelt(std::vector< std::string > components)
std::string kebab_case() const
std::vector< std::string > components
std::string snake_case() const
std::string pretty() const
bool operator<(const labelt &other) const
static structured_data_entryt data_node(const jsont &data)
std::string leaf_data() const
std::map< labelt, structured_data_entryt > _children
const std::map< labelt, structured_data_entryt > & children() const
static structured_data_entryt entry(std::map< labelt, structured_data_entryt > children)
structured_data_entryt(jsont data)
std::vector< std::string > pretty_node(const std::pair< labelt, structured_data_entryt > &entry)
std::string to_pretty(const structured_datat &data)
Convert the structured_data into plain text.