Skip to content

Commit 80eb559

Browse files
Levi HicksLevi Hicks
Levi Hicks
authored and
Levi Hicks
committed
Switch to nlohmann's json lib
Signed-off-by: Levi Hicks <[email protected]>
1 parent 0877994 commit 80eb559

File tree

15 files changed

+25765
-1046
lines changed

15 files changed

+25765
-1046
lines changed

SConstruct

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ env = Environment(
195195
"#third_party/acados/include/hpipm/include",
196196
"#third_party/catch2/include",
197197
"#third_party/libyuv/include",
198-
"#third_party/json11",
198+
"#third_party/json",
199199
"#third_party/linux/include",
200200
"#third_party/snpe/include",
201201
"#third_party",
@@ -335,7 +335,7 @@ Export('env', 'qt_env', 'arch', 'real_arch')
335335
SConscript(['common/SConscript'])
336336
Import('_common', '_gpucommon')
337337

338-
common = [_common, 'json11', 'zmq']
338+
common = [_common, 'json', 'zmq']
339339
gpucommon = [_gpucommon]
340340

341341
Export('common', 'gpucommon')

common/SConscript

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ common_libs = [
1212
if arch != "Darwin":
1313
common_libs.append('gpio.cc')
1414

15-
_common = env.Library('common', common_libs, LIBS="json11")
15+
_common = env.Library('common', common_libs, LIBS="json")
1616

1717
files = [
1818
'clutil.cc',
@@ -24,10 +24,10 @@ Export('_common', '_gpucommon')
2424
if GetOption('extras'):
2525
env.Program('tests/test_common',
2626
['tests/test_runner.cc', 'tests/test_params.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'],
27-
LIBS=[_common, 'json11', 'zmq', 'pthread'])
27+
LIBS=[_common, 'json', 'zmq', 'pthread'])
2828

2929
# Cython bindings
30-
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
30+
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json'])
3131

3232
SConscript([
3333
'transformations/SConscript',

common/logging_extra.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,23 @@
55
import json
66
import time
77
import uuid
8+
import locale
89
import socket
910
import logging
1011
import traceback
1112
from threading import local
1213
from collections import OrderedDict
1314
from contextlib import contextmanager
1415

16+
# Set locale to use comma as decimal separator for testing
17+
# locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')
18+
1519
LOG_TIMESTAMPS = "LOG_TIMESTAMPS" in os.environ
1620

1721
def json_handler(obj):
18-
# if isinstance(obj, (datetime.date, datetime.time)):
19-
# return obj.isoformat()
22+
# Convert float numbers to use locale-specific formatting
23+
if isinstance(obj, float):
24+
return locale.str(obj)
2025
return repr(obj)
2126

2227
def json_robust_dumps(obj):

common/swaglog.cc

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#include <zmq.h>
1313
#include <stdarg.h>
14-
#include "third_party/json11/json11.hpp"
14+
#include "third_party/json/json_helper.hpp"
1515
#include "common/version.h"
1616
#include "system/hardware/hw.h"
1717

@@ -37,7 +37,7 @@ class SwaglogState {
3737
}
3838
}
3939

40-
ctx_j = json11::Json::object{};
40+
ctx_j = json::Json::object{};
4141
if (char* dongle_id = getenv("DONGLE_ID")) {
4242
ctx_j["dongle_id"] = dongle_id;
4343
}
@@ -75,17 +75,17 @@ class SwaglogState {
7575
void* zctx = nullptr;
7676
void* sock = nullptr;
7777
int print_level;
78-
json11::Json::object ctx_j;
78+
json::Json::object ctx_j;
7979
};
8080

8181
bool LOG_TIMESTAMPS = getenv("LOG_TIMESTAMPS");
8282
uint32_t NO_FRAME_ID = std::numeric_limits<uint32_t>::max();
8383

8484
static void cloudlog_common(int levelnum, const char* filename, int lineno, const char* func,
85-
char* msg_buf, const json11::Json::object &msg_j={}) {
85+
char* msg_buf, const json::Json::object &msg_j={}) {
8686
static SwaglogState s;
8787

88-
json11::Json::object log_j = json11::Json::object {
88+
json::Json::object log_j = json::Json::object {
8989
{"ctx", s.ctx_j},
9090
{"levelnum", levelnum},
9191
{"filename", filename},
@@ -101,7 +101,7 @@ static void cloudlog_common(int levelnum, const char* filename, int lineno, cons
101101

102102
std::string log_s;
103103
log_s += (char)levelnum;
104-
((json11::Json)log_j).dump(log_s);
104+
((json::Json)log_j).dump(log_s);
105105
s.log(levelnum, filename, lineno, func, msg_buf, log_s);
106106

107107
free(msg_buf);
@@ -124,14 +124,14 @@ void cloudlog_t_common(int levelnum, const char* filename, int lineno, const cha
124124
char* msg_buf = nullptr;
125125
int ret = vasprintf(&msg_buf, fmt, args);
126126
if (ret <= 0 || !msg_buf) return;
127-
json11::Json::object tspt_j = json11::Json::object{
127+
json::Json::object tspt_j = json::Json::object{
128128
{"event", msg_buf},
129129
{"time", std::to_string(nanos_since_boot())}
130130
};
131131
if (frame_id < NO_FRAME_ID) {
132132
tspt_j["frame_id"] = std::to_string(frame_id);
133133
}
134-
tspt_j = json11::Json::object{{"timestamp", tspt_j}};
134+
tspt_j = json::Json::object{{"timestamp", tspt_j}};
135135
cloudlog_common(levelnum, filename, lineno, func, msg_buf, tspt_j);
136136
}
137137

common/tests/test_swaglog.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "common/util.h"
88
#include "common/version.h"
99
#include "system/hardware/hw.h"
10-
#include "third_party/json11/json11.hpp"
10+
#include "third_party/json/json_helper.hpp"
1111

1212
std::string daemon_name = "testy";
1313
std::string dongle_id = "test_dongle_id";
@@ -39,7 +39,7 @@ void recv_log(int thread_cnt, int thread_msg_cnt) {
3939

4040
REQUIRE(buf[0] == CLOUDLOG_DEBUG);
4141
std::string err;
42-
auto msg = json11::Json::parse(buf + 1, err);
42+
auto msg = json::Json::parse(buf + 1, err);
4343
REQUIRE(!msg.is_null());
4444

4545
REQUIRE(msg["levelnum"].int_value() == CLOUDLOG_DEBUG);

system/logcatd/logcatd_systemd.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <map>
66
#include <string>
77

8-
#include "third_party/json11/json11.hpp"
8+
#include "third_party/json/json.hpp"
99

1010
#include "cereal/messaging/messaging.h"
1111
#include "common/timing.h"
@@ -62,7 +62,7 @@ int main(int argc, char *argv[]) {
6262
// Build message
6363
auto androidEntry = msg.initEvent().initAndroidLog();
6464
androidEntry.setTs(timestamp);
65-
androidEntry.setMessage(json11::Json(kv).dump());
65+
androidEntry.setMessage(json::Json(kv).dump());
6666
if (kv.count("_PID")) androidEntry.setPid(std::atoi(kv["_PID"].c_str()));
6767
if (kv.count("PRIORITY")) androidEntry.setPriority(std::atoi(kv["PRIORITY"].c_str()));
6868
if (kv.count("SYSLOG_IDENTIFIER")) androidEntry.setTag(kv["SYSLOG_IDENTIFIER"]);

third_party/SConscript

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Import('env')
22

3-
env.Library('json11', ['json11/json11.cpp'], CCFLAGS=env['CCFLAGS'] + ['-Wno-unqualified-std-cast-call'])
3+
env.Library('json', ['json/json.cpp'], CCFLAGS=env['CCFLAGS'] + ['-Wno-unqualified-std-cast-call'])
44
env.Library('kaitai', ['kaitai/kaitaistream.cpp'], CPPDEFINES=['KS_STR_ENCODING_NONE'])

third_party/json/json.cpp

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/* Copyright (c) 2013 Dropbox, Inc.
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy
4+
* of this software and associated documentation files (the "Software"), to deal
5+
* in the Software without restriction, including without limitation the rights
6+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
* copies of the Software, and to permit persons to whom the Software is
8+
* furnished to do so, subject to the following conditions:
9+
*
10+
* The above copyright notice and this permission notice shall be included in
11+
* all copies or substantial portions of the Software.
12+
*
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
* THE SOFTWARE.
20+
*/
21+
22+
#include "json_helper.hpp"
23+
#include "json.hpp"
24+
25+
namespace json {
26+
27+
// Constructors
28+
Json::Json() noexcept : m_json(nullptr) {}
29+
Json::Json(std::nullptr_t) noexcept : m_json(nullptr) {}
30+
Json::Json(double value) : m_json(value) {}
31+
Json::Json(int value) : m_json(value) {}
32+
Json::Json(bool value) : m_json(value) {}
33+
Json::Json(const std::string &value) : m_json(value) {}
34+
Json::Json(std::string &&value) : m_json(std::move(value)) {}
35+
Json::Json(const char * value) : m_json(value) {}
36+
Json::Json(const array &values) : m_json(nlohmann::json::array()) {
37+
for (const auto& v : values) {
38+
m_json.push_back(v.m_json);
39+
}
40+
}
41+
Json::Json(array &&values) : m_json(nlohmann::json::array()) {
42+
for (auto& v : values) {
43+
m_json.push_back(std::move(v.m_json));
44+
}
45+
}
46+
Json::Json(const object &values) : m_json(nlohmann::json::object()) {
47+
for (const auto& kv : values) {
48+
m_json[kv.first] = kv.second.m_json;
49+
}
50+
}
51+
Json::Json(object &&values) : m_json(nlohmann::json::object()) {
52+
for (auto& kv : values) {
53+
m_json[kv.first] = std::move(kv.second.m_json);
54+
}
55+
}
56+
57+
Json::Json(const nlohmann::json& j) : m_json(j) {}
58+
59+
// Type accessors
60+
Json::Type Json::type() const {
61+
if (m_json.is_null()) return NUL;
62+
if (m_json.is_number()) return NUMBER;
63+
if (m_json.is_boolean()) return BOOL;
64+
if (m_json.is_string()) return STRING;
65+
if (m_json.is_array()) return ARRAY;
66+
if (m_json.is_object()) return OBJECT;
67+
return NUL;
68+
}
69+
70+
// Accessors
71+
double Json::number_value() const { return m_json.get<double>(); }
72+
int Json::int_value() const { return m_json.get<int>(); }
73+
bool Json::bool_value() const { return m_json.get<bool>(); }
74+
const std::string& Json::string_value() const {
75+
static const std::string empty;
76+
return m_json.is_string() ? m_json.get_ref<const std::string&>() : empty;
77+
}
78+
79+
const Json::array& Json::array_items() const {
80+
static const array empty;
81+
if (!is_array()) return empty;
82+
static thread_local array items;
83+
items.clear();
84+
for (const auto& item : m_json) {
85+
items.emplace_back(item);
86+
}
87+
return items;
88+
}
89+
90+
const Json::object& Json::object_items() const {
91+
static const object empty;
92+
if (!is_object()) return empty;
93+
static thread_local object items;
94+
items.clear();
95+
for (auto it = m_json.begin(); it != m_json.end(); ++it) {
96+
items.emplace(it.key(), Json(it.value()));
97+
}
98+
return items;
99+
}
100+
101+
// Operators
102+
const Json& Json::operator[](size_t i) const {
103+
static const Json empty;
104+
if (!is_array() || i >= m_json.size()) return empty;
105+
static thread_local Json result;
106+
result = Json(m_json[i]);
107+
return result;
108+
}
109+
110+
const Json& Json::operator[](const std::string& key) const {
111+
static const Json empty;
112+
if (!is_object()) return empty;
113+
auto it = m_json.find(key);
114+
if (it == m_json.end()) return empty;
115+
static thread_local Json result;
116+
result = Json(*it);
117+
return result;
118+
}
119+
120+
bool Json::operator==(const Json& other) const {
121+
return m_json == other.m_json;
122+
}
123+
124+
bool Json::operator<(const Json& other) const {
125+
return m_json < other.m_json;
126+
}
127+
128+
// Parsing
129+
Json Json::parse(const std::string& in, std::string& err, JsonParse strategy) {
130+
try {
131+
auto result = nlohmann::json::parse(in);
132+
err.clear();
133+
return Json(result);
134+
} catch (const nlohmann::json::parse_error& e) {
135+
err = e.what();
136+
return Json();
137+
}
138+
}
139+
140+
std::vector<Json> Json::parse_multi(const std::string& in, std::string::size_type& parser_stop_pos, std::string& err, JsonParse strategy) {
141+
std::vector<Json> result;
142+
try {
143+
auto json_array = nlohmann::json::parse("[" + in + "]");
144+
for (const auto& element : json_array) {
145+
result.emplace_back(element);
146+
}
147+
parser_stop_pos = in.size();
148+
err.clear();
149+
} catch (const nlohmann::json::parse_error& e) {
150+
err = e.what();
151+
}
152+
return result;
153+
}
154+
155+
void Json::dump(std::string& out) const {
156+
out = m_json.dump();
157+
}
158+
159+
bool Json::has_shape(const shape& types, std::string& err) const {
160+
if (!is_object()) {
161+
err = "expected JSON object, got " + dump();
162+
return false;
163+
}
164+
165+
for (const auto& item : types) {
166+
const auto it = m_json.find(item.first);
167+
if (it == m_json.end() || Json(*it).type() != item.second) {
168+
err = "bad type for " + item.first + " in " + dump();
169+
return false;
170+
}
171+
}
172+
return true;
173+
}
174+
175+
} // namespace json

0 commit comments

Comments
 (0)