Skip to content

Commit 4ac3acc

Browse files
authored
Merge branch 'main' into fast_clang_tidy
2 parents c66d9de + 97c7391 commit 4ac3acc

File tree

15 files changed

+213
-239
lines changed

15 files changed

+213
-239
lines changed

src/apps/weblib/interface.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <span>
44

55
#include "base/io/log.h"
6-
#include "base/text/jsonoutput.h"
6+
#include "base/conv/auto_json.h"
77

88
#include "interfacejs.h"
99
#include "jscriptcanvas.h"
@@ -60,7 +60,7 @@ void Interface::freeObj(void *ptr) { objects.unreg(ptr); }
6060
const char *Interface::getStyleList()
6161
{
6262
static const std::string res =
63-
Text::toJSON(Styles::Sheet::paramList());
63+
Conv::toJSON(Styles::Sheet::paramList());
6464
return res.c_str();
6565
}
6666

@@ -86,7 +86,7 @@ void Interface::setStyleValue(const char *path, const char *value)
8686
const char *Interface::getChartParamList()
8787
{
8888
static const std::string res =
89-
Text::toJSON(Gen::Config::listParams());
89+
Conv::toJSON(Gen::Config::listParams());
9090
return res.c_str();
9191
}
9292

@@ -281,14 +281,7 @@ const char *Interface::dataMetaInfo()
281281
{
282282
if (chart) {
283283
static std::string res;
284-
res.clear();
285-
auto &table = chart->getTable();
286-
res += "[";
287-
for (auto i = 0U; i < table.columnCount(); ++i) {
288-
res += table.getInfo(Data::ColumnIndex(i)).toJSON();
289-
if (i < table.columnCount() - 1) res += ",";
290-
}
291-
res += "]";
284+
res = Conv::toJSON(chart->getTable().getInfos());
292285
return res.c_str();
293286
}
294287
throw std::logic_error("No chart exists");

src/base/conv/auto_json.h

Lines changed: 147 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef BASE_AUTO_JSON_H
22
#define BASE_AUTO_JSON_H
33

4+
#include <cassert>
45
#include <initializer_list>
56
#include <optional>
67
#include <ranges>
@@ -28,8 +29,7 @@ concept Optional =
2829
*val;
2930
};
3031

31-
template <class T>
32-
concept Tuple = sizeof(std::tuple_size<T>) > 0;
32+
template <class T> concept Tuple = sizeof(std::tuple_size<T>) > 0;
3333

3434
template <class T>
3535
concept Pair = Tuple<T> && std::tuple_size_v<T> == 2;
@@ -46,67 +46,25 @@ concept SerializableRange =
4646

4747
struct JSON
4848
{
49-
template <class IL> void closeOpenObj(IL &&il)
49+
template <class T> inline void primitive(const T &val) const
5050
{
51-
auto from = std::begin(il);
52-
auto end = std::end(il);
53-
54-
if (!std::empty(curr)) {
55-
auto [pre, cur] = std::ranges::mismatch(curr, il);
56-
if (auto cend = std::end(curr); pre != cend) [[likely]]
57-
json.append(cend - pre - 1, '}');
58-
else {
59-
if (cur == end) {
60-
throw std::logic_error(
61-
"Same object but multiple base classes are "
62-
"pure serializable.");
63-
}
64-
throw std::logic_error(
65-
"An already serialized object member is not "
66-
"serializable.");
67-
}
68-
json += ',';
69-
from = cur;
70-
}
71-
else {
72-
json += "{";
51+
if constexpr (std::is_arithmetic_v<T>) {
52+
json += toString(val);
7353
}
74-
75-
if (from != end) [[likely]] {
76-
for (--end; from != end; ++from) {
77-
json += '\"';
78-
json += Text::SmartString::escape(std::string{*from});
79-
json += "\":{";
80-
}
54+
else if constexpr (std::is_enum_v<T>
55+
|| std::is_same_v<T, bool>) {
56+
json += '\"';
57+
json += toString(val);
8158
json += '\"';
82-
json += Text::SmartString::escape(std::string{*end});
83-
json += "\":";
84-
}
85-
else {
86-
throw std::logic_error("Member of a serializable object "
87-
"are already serialized.");
88-
}
89-
if constexpr (std::is_lvalue_reference_v<IL>) { curr = il; }
90-
else {
91-
curr = saved.emplace(std::forward<IL>(il));
92-
}
93-
}
94-
95-
template <class T> inline void primitive(T &&val)
96-
{
97-
if constexpr (std::is_arithmetic_v<
98-
std::remove_reference_t<T>>) {
99-
json += toString(std::forward<T>(val));
10059
}
10160
else {
10261
json += '\"';
103-
json += Text::SmartString::escape(
104-
toString(std::forward<T>(val)));
62+
json += Text::SmartString::escape(toString(val));
10563
json += '\"';
10664
}
10765
}
10866

109-
template <class T> inline void array(T &&val)
67+
template <class T> inline void array(const T &val) const
11068
{
11169
json += '[';
11270
bool not_first = false;
@@ -120,7 +78,24 @@ struct JSON
12078
json += ']';
12179
}
12280

123-
template <class T> inline void any(T &&val)
81+
template <class T> inline void tupleObj(const T &val) const
82+
{
83+
std::apply(
84+
[this](const auto &arg, const auto &...args)
85+
{
86+
json += '[';
87+
any(arg);
88+
((json += ',', any(args)), ...);
89+
json += ']';
90+
},
91+
val);
92+
}
93+
94+
template <class T> void dynamicObj(const T &val) const;
95+
96+
template <class T> void staticObj(const T &val) const;
97+
98+
template <class T> inline void any(const T &val) const
12499
{
125100
if constexpr (JSONSerializable<T>) { json += val.toJSON(); }
126101
else if constexpr (std::is_same_v<std::remove_cvref_t<T>,
@@ -136,75 +111,152 @@ struct JSON
136111
any(*val);
137112
}
138113
else if constexpr (StringConvertable<T>) {
139-
primitive(std::forward<T>(val));
114+
primitive(val);
140115
}
141116
else if constexpr (SerializableRange<T>) {
142117
if constexpr (Pair<std::ranges::range_value_t<T>>) {
143-
if (std::empty(val)) {
144-
json += "{}";
145-
} else {
146-
JSON j{json};
147-
bool which{};
148-
std::array<std::string, 2> strings;
149-
for (const auto& [k, v] : val) {
150-
j(v, {strings[which ^= true] = toString(k)});
151-
}
152-
}
153-
} else {
154-
array(std::forward<T>(val));
118+
dynamicObj(val);
119+
}
120+
else {
121+
array(val);
155122
}
156123
}
157124
else if constexpr (Tuple<T>) {
158-
std::apply([this] (auto&& arg, auto&& ... args) {
159-
json += '[';
160-
any(std::forward<decltype(arg)>(arg));
161-
((json += ',', any(std::forward<decltype(args)>(args))), ...);
162-
json += ']';
163-
}, std::forward<T>(val));
125+
tupleObj(val);
164126
}
165127
else {
166-
Refl::visit(JSON{json}, val);
128+
staticObj(val);
167129
}
168130
}
169131

170-
template <class T>
171-
inline JSON &operator()(T &&val,
172-
std::initializer_list<std::string_view> &&il)
132+
explicit inline JSON(std::string &json) : json(json) {}
133+
134+
std::string &json;
135+
};
136+
137+
struct JSONAutoObj : JSON
138+
{
139+
using JSON::JSON;
140+
141+
inline ~JSONAutoObj()
173142
{
174-
closeOpenObj(
175-
std::forward<std::initializer_list<std::string_view>>(
176-
il));
177-
any(std::forward<T>(val));
178-
return *this;
143+
if (cp)
144+
json.append(std::size(*cp), '}');
145+
else
146+
json += "{}";
147+
}
148+
149+
inline void closeOpenObj(
150+
const std::initializer_list<std::string_view> &il)
151+
{
152+
const auto *from = std::begin(il);
153+
const auto *end = std::end(il);
154+
155+
if (cp) {
156+
auto [pre, cur] = std::ranges::mismatch(*cp, il);
157+
assert(pre != std::end(*cp));
158+
json.append(std::end(*cp) - pre - 1, '}');
159+
json += ',';
160+
from = cur;
161+
}
162+
else
163+
json += '{';
164+
165+
assert(from != end);
166+
while (true) {
167+
json += '\"';
168+
json.append(*from);
169+
json += "\":";
170+
if (++from != end)
171+
json += '{';
172+
else
173+
break;
174+
}
175+
cp = &il;
179176
}
180177

181178
template <class T>
182179
requires(JSONSerializable<T> || Optional<T>
183-
|| StringConvertable<T> || SerializableRange<T> ||
184-
Tuple<T>)
185-
inline JSON &operator()(T &&val,
180+
|| StringConvertable<T> || SerializableRange<T>
181+
|| Tuple<T>)
182+
inline void operator()(const T &val,
186183
const std::initializer_list<std::string_view> &il)
187184
{
188185
closeOpenObj(il);
189-
any(std::forward<T>(val));
190-
return *this;
186+
any(val);
191187
}
192188

193-
JSON(std::string &json) : json(json) {}
189+
template <class T>
190+
inline void operator()(const T &val,
191+
std::initializer_list<std::string_view> &&il) = delete;
192+
193+
const std::initializer_list<std::string_view> *cp{};
194+
};
194195

195-
~JSON()
196+
struct JSONObj : JSON
197+
{
198+
using JSON::JSON;
199+
200+
inline ~JSONObj()
196201
{
197-
if (!std::empty(curr)) json.append(std::size(curr), '}');
202+
if (!was) json += '{';
203+
json += '}';
198204
}
199-
std::string &json;
200-
std::optional<std::vector<std::string_view>> saved;
201-
std::span<const std::string_view> curr;
205+
206+
template <bool KeyNoEscape = true>
207+
inline void key(std::string_view key)
208+
{
209+
json += std::exchange(was, true) ? ',' : '{';
210+
211+
json += '\"';
212+
if constexpr (KeyNoEscape) { json.append(key); }
213+
else {
214+
json += Text::SmartString::escape(std::string{key});
215+
}
216+
json += "\":";
217+
}
218+
219+
template <bool KeyNoEscape = true>
220+
inline JSONObj nested(std::string_view key)
221+
{
222+
this->key<KeyNoEscape>(key);
223+
return JSONObj{json};
224+
}
225+
226+
template <bool KeyNoEscape = true>
227+
inline JSONObj &raw(std::string_view key, const std::string &str)
228+
{
229+
this->key<KeyNoEscape>(key);
230+
json += str;
231+
return *this;
232+
}
233+
234+
template <bool KeyNoEscape = true, class T>
235+
inline JSONObj &operator()(std::string_view key, const T &val)
236+
{
237+
this->key<KeyNoEscape>(key);
238+
any(val);
239+
return *this;
240+
}
241+
242+
bool was{};
202243
};
203244

204-
template <class T> std::string toJSON(T &&v)
245+
template <class T> inline void JSON::dynamicObj(const T &val) const
246+
{
247+
JSONObj j{json};
248+
for (const auto &[k, v] : val) { j(toString(k), v); }
249+
}
250+
251+
template <class T> inline void JSON::staticObj(const T &val) const
252+
{
253+
Refl::visit(JSONAutoObj{json}, val);
254+
}
255+
256+
template <class T> inline std::string toJSON(const T &v)
205257
{
206258
std::string res;
207-
JSON{res}.any(std::forward<T>(v));
259+
JSON{res}.any(v);
208260
return res;
209261
}
210262
}

src/base/geom/line.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef GEOM_LINE
22
#define GEOM_LINE
33

4+
#include <tuple>
5+
46
#include "point.h"
57

68
namespace Geom
@@ -58,14 +60,8 @@ struct Line
5860
return {at(t0), at(t1)};
5961
}
6062

61-
[[nodiscard]] std::string toJSON() const
62-
{
63-
return "{"
64-
"\"begin\":"
65-
+ begin.toJSON()
66-
+ ","
67-
"\"end\":"
68-
+ end.toJSON() + "}";
63+
consteval static auto members() {
64+
return std::tuple{&Line::begin, &Line::end};
6965
}
7066
};
7167

0 commit comments

Comments
 (0)