simdjson 5.0.2
Ridiculously Fast JSON
Loading...
Searching...
No Matches
json_structure_analyzer.h
1#ifndef SIMDJSON_INTERNAL_JSON_STRUCTURE_ANALYZER_H
2#define SIMDJSON_INTERNAL_JSON_STRUCTURE_ANALYZER_H
3
4#include "simdjson/dom/base.h"
5#include "simdjson/dom/element.h"
6#include "simdjson/dom/array.h"
7#include "simdjson/dom/object.h"
8#include "simdjson/dom/fractured_json.h"
9#include "simdjson/internal/tape_type.h"
10
11#include <vector>
12#include <string>
13#include <string_view>
14#include <utility>
15
16namespace simdjson {
17namespace internal {
18
22enum class layout_mode {
23 single_line, // Single line: [1, 2, 3] or {"a": 1}
24 compact_multiline, // Multiple items per line with breaks
25 table, // Tabular format for arrays of similar objects
26 expanded // Traditional multi-line with indentation
27};
28
30enum class table_column_type {
31 unknown,
32 simple, // string, bool, or null
33 number,
34 array,
35 object,
36 mixed // rows disagree on kind
37};
38
40struct table_column {
42 std::string key{};
44 size_t key_width = 0;
45 table_column_type type = table_column_type::unknown;
47 size_t width = 0;
49 size_t plain_width = 0;
51 std::vector<table_column> children{};
52};
53
56inline bool table_row_is_nested(const std::vector<table_column>& columns) {
57 for (const table_column& col : columns) {
58 if (col.type == table_column_type::object || col.type == table_column_type::array) {
59 return true;
60 }
61 }
62 return false;
63}
64
69struct element_metrics {
71 size_t complexity = 0;
72
74 size_t estimated_inline_len = 0;
75
77 size_t child_count = 0;
78
80 bool can_inline = false;
81
83 bool is_uniform_array = false;
84
86 std::vector<table_column> table_columns{};
88 size_t table_row_width = 0;
90 size_t table_row_width_full = 0;
91
93 std::vector<element_metrics> children{};
94
96 table_column_type scalar_column_type = table_column_type::unknown;
97};
98
100inline const element_metrics& child_metrics_at(const std::vector<element_metrics>& children, size_t idx) {
101 static const element_metrics empty{};
102 return idx < children.size() ? children[idx] : empty;
103}
104
106inline const element_metrics& child_metrics_at(const element_metrics* ptr) {
107 static const element_metrics empty{};
108 return ptr ? *ptr : empty;
109}
110
122class structure_analyzer {
123public:
125 structure_analyzer() : current_opts_(nullptr) {}
126
128 structure_analyzer(const structure_analyzer&) = delete;
129
131 structure_analyzer& operator=(const structure_analyzer&) = delete;
132
134 structure_analyzer(structure_analyzer&&) = default;
135
137 structure_analyzer& operator=(structure_analyzer&&) = default;
138
145 element_metrics analyze(const dom::element& elem,
146 const fractured_json_options& opts);
147
151 void clear();
152
159 element_metrics analyze_array(const dom::array& arr,
160 const fractured_json_options& opts);
161
168 element_metrics analyze_object(const dom::object& obj,
169 const fractured_json_options& opts);
170
173 static layout_mode decide_layout(const element_metrics& metrics,
174 size_t depth,
175 const fractured_json_options& opts,
176 bool has_trailing_comma = false);
177
178private:
179 const fractured_json_options* current_opts_ = nullptr;
180
182 element_metrics analyze_element(const dom::element& elem, size_t depth) const;
183
185 element_metrics analyze_scalar(const dom::element& elem) const;
186
188 element_metrics analyze_array(const dom::array& arr, size_t depth) const;
189
191 element_metrics analyze_object(const dom::object& obj, size_t depth) const;
192
194 size_t estimate_string_length(std::string_view s) const;
195
197 size_t estimate_number_length(double d) const;
198 size_t estimate_number_length(int64_t i) const;
199 size_t estimate_number_length(uint64_t u) const;
200
208 bool check_array_uniformity(const dom::array& arr, element_metrics& metrics, size_t depth) const;
209
210 static table_column_type classify_table_value(dom::element_type type);
211
213 static void classify_and_measure(const std::vector<std::pair<dom::element, const element_metrics*>>& values,
214 table_column_type& common, size_t& max_width);
215
217 void build_table_columns(const std::vector<std::pair<dom::element, const element_metrics*>>& values,
218 std::vector<table_column>& out_columns) const;
219
221 size_t compute_columns_width(const std::vector<table_column>& columns) const;
222
224 static size_t column_height(const table_column& column);
225
227 static bool flatten_deepest_columns(std::vector<table_column>& columns);
228
230 void recompute_column_widths(std::vector<table_column>& columns) const;
231};
232
233} // namespace internal
234} // namespace simdjson
235
236#endif // SIMDJSON_INTERNAL_JSON_STRUCTURE_ANALYZER_H
@ object
A JSON object ( { "a": 1, "b" 2, ... } )
@ number
A JSON number ( 1 or -2.3 or 4.5e6 ...)
element_type
The actual concrete type of a JSON element This is the type it is most easily cast to with get<>.
Definition element.h:16
The top level simdjson namespace, containing everything the library provides.
Definition base.h:8