1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00

Merge branch 'staging' into absl_mutex

This commit is contained in:
Jeff 2019-03-05 17:06:23 -05:00 committed by GitHub
commit 1a09a12ee0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
471 changed files with 52989 additions and 386 deletions

1
.gitignore vendored
View file

@ -40,7 +40,6 @@ daemon.ini
lokinet-win32.exe lokinet-win32.exe
lokinet lokinet
lokinet.exe lokinet.exe
rapidjson/
.gradle/ .gradle/

View file

@ -11,9 +11,9 @@ build:linux:
- linux - linux
stage: build stage: build
before_script: before_script:
- apk add --update g++ make cmake linux-headers libcap-dev rapidjson - apk add --update g++ make cmake linux-headers libcap-dev
script: script:
- make - make
artifacts: artifacts:
paths: paths:
- "lokinet" - "lokinet"

View file

@ -20,7 +20,7 @@ option(WITH_COVERAGE "generate coverage data")
# Basic definitions # Basic definitions
get_filename_component(CORE_INCLUDE include ABSOLUTE) get_filename_component(CORE_INCLUDE include ABSOLUTE)
get_filename_component(ABYSS_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/${ABYSS}/include" ABSOLUTE CACHE) get_filename_component(ABYSS_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/${ABYSS}/include" ABSOLUTE)
find_program(CCACHE_PROGRAM ccache) find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM) if(CCACHE_PROGRAM)
@ -54,6 +54,8 @@ if (WIN32 AND NOT STATIC_LINK_RUNTIME)
#set(STATIC_LINK_RUNTIME ON) #set(STATIC_LINK_RUNTIME ON)
endif(WIN32 AND NOT STATIC_LINK_RUNTIME) endif(WIN32 AND NOT STATIC_LINK_RUNTIME)
add_subdirectory(vendor/nlohmann)
# still need the headers unconditionally # still need the headers unconditionally
set(ABSEIL_DIR vendor/abseil-cpp) set(ABSEIL_DIR vendor/abseil-cpp)
include_directories(${ABSEIL_DIR}) include_directories(${ABSEIL_DIR})

View file

@ -1,7 +1,7 @@
FROM debian:stable FROM debian:stable
RUN apt update && \ RUN apt update && \
apt install -y build-essential cmake git libcap-dev curl rapidjson-dev ninja-build apt install -y build-essential cmake git libcap-dev curl ninja-build
WORKDIR /src/ WORKDIR /src/

View file

@ -2,7 +2,7 @@ FROM fedora:latest
RUN dnf update -y && \ RUN dnf update -y && \
dnf upgrade -y && \ dnf upgrade -y && \
dnf install -y cmake make git gcc gcc-c++ libcap-devel curl rapidjson-devel dnf install -y cmake make git gcc gcc-c++ libcap-devel curl
WORKDIR /src/ WORKDIR /src/

View file

@ -1,7 +1,7 @@
FROM debian:stable FROM debian:stable
RUN apt update && \ RUN apt update && \
apt install -y build-essential cmake git libcap-dev curl rapidjson-dev python3-dev python3-setuptools libsodium-dev apt install -y build-essential cmake git libcap-dev curl python3-dev python3-setuptools libsodium-dev
WORKDIR /src/ WORKDIR /src/
@ -9,4 +9,4 @@ COPY . /src/
RUN make -j 8 SHARED_LIB=ON JSONRPC=ON && make kubernetes-install RUN make -j 8 SHARED_LIB=ON JSONRPC=ON && make kubernetes-install
ENTRYPOINT [ "/usr/bin/python3", "-m", "pylokinet"] ENTRYPOINT [ "/usr/bin/python3", "-m", "pylokinet"]

View file

@ -1,7 +1,7 @@
FROM ubuntu:latest FROM ubuntu:latest
RUN apt update && \ RUN apt update && \
apt install -y build-essential cmake git libcap-dev curl rapidjson-dev ninja-build apt install -y build-essential cmake git libcap-dev curl ninja-build
WORKDIR /src/ WORKDIR /src/

View file

@ -18,8 +18,8 @@ namespace abyss
namespace http namespace http
{ {
using RPC_Method_t = std::string; using RPC_Method_t = std::string;
using RPC_Params = llarp::json::Value; using RPC_Params = nlohmann::json;
using RPC_Response = llarp::json::Document; using RPC_Response = nlohmann::json;
using Headers_t = std::unordered_multimap< std::string, std::string >; using Headers_t = std::unordered_multimap< std::string, std::string >;
struct ConnImpl; struct ConnImpl;

View file

@ -7,6 +7,7 @@
#include <util/string_view.hpp> #include <util/string_view.hpp>
#include <util/time.hpp> #include <util/time.hpp>
#include <absl/types/optional.h>
#include <list> #include <list>
#include <memory> #include <memory>
#include <string> #include <string>
@ -21,14 +22,13 @@ namespace abyss
struct IRPCHandler struct IRPCHandler
{ {
using Method_t = std::string; using Method_t = std::string;
using Params = llarp::json::Value; using Params = nlohmann::json;
using Response = llarp::json::Writer; using Response = nlohmann::json;
IRPCHandler(ConnImpl* impl); IRPCHandler(ConnImpl* impl);
virtual bool virtual absl::optional< Response >
HandleJSONRPC(Method_t method, const Params& params, HandleJSONRPC(Method_t method, const Params& params) = 0;
Response& response) = 0;
virtual ~IRPCHandler(); virtual ~IRPCHandler();

View file

@ -13,14 +13,12 @@ struct DemoHandler : public abyss::httpd::IRPCHandler
{ {
} }
bool absl::optional< Response >
HandleJSONRPC(Method_t method, __attribute__((unused)) const Params& params, HandleJSONRPC(Method_t method,
Response& resp) override __attribute__((unused)) const Params& params) override
{ {
llarp::LogInfo("method: ", method); llarp::LogInfo("method: ", method);
resp.StartObject(); return Response::object();
resp.EndObject();
return true;
} }
}; };
@ -83,9 +81,7 @@ struct DemoClient : public abyss::http::JSONRPC
void void
DoDemoRequest() DoDemoRequest()
{ {
llarp::json::Value params; QueueRPC("test", nlohmann::json::object(),
params.SetObject();
QueueRPC("test", std::move(params),
std::bind(&DemoClient::NewConn, this, std::placeholders::_1)); std::bind(&DemoClient::NewConn, this, std::placeholders::_1));
Flush(); Flush();
}; };

View file

@ -14,11 +14,11 @@ namespace abyss
// big // big
static const size_t MAX_BODY_SIZE = (1024 * 1024); static const size_t MAX_BODY_SIZE = (1024 * 1024);
llarp_tcp_conn* m_Conn; llarp_tcp_conn* m_Conn;
json::Document m_RequestBody; nlohmann::json m_RequestBody;
Headers_t m_SendHeaders; Headers_t m_SendHeaders;
IRPCClientHandler* handler; IRPCClientHandler* handler;
std::unique_ptr< json::IParser > m_BodyParser; std::unique_ptr< json::IParser > m_BodyParser;
json::Document m_Response; nlohmann::json m_Response;
enum State enum State
{ {
@ -31,9 +31,12 @@ namespace abyss
State state; State state;
ConnImpl(llarp_tcp_conn* conn, RPC_Method_t method, RPC_Params params, ConnImpl(llarp_tcp_conn* conn, const RPC_Method_t& method,
JSONRPC::HandlerFactory factory) const RPC_Params& params, JSONRPC::HandlerFactory factory)
: m_Conn(conn), state(eInitial) : m_Conn(conn)
, m_RequestBody(nlohmann::json::object())
, m_Response(nlohmann::json::object())
, state(eInitial)
{ {
srand(time(nullptr)); srand(time(nullptr));
conn->user = this; conn->user = this;
@ -43,18 +46,12 @@ namespace abyss
handler = factory(this); handler = factory(this);
m_RequestBody.SetObject(); m_RequestBody["jsonrpc"] = "2.0";
auto& alloc = m_RequestBody.GetAllocator();
m_RequestBody.AddMember("jsonrpc", json::Value().SetString("2.0"),
alloc);
llarp::AlignedBuffer< 8 > p; llarp::AlignedBuffer< 8 > p;
p.Randomize(); p.Randomize();
std::string str = p.ToHex(); m_RequestBody["id"] = p.ToHex();
m_RequestBody.AddMember( m_RequestBody["method"] = method;
"id", json::Value().SetString(str.c_str(), alloc), alloc); m_RequestBody["params"] = params;
m_RequestBody.AddMember(
"method", json::Value().SetString(method.c_str(), alloc), alloc);
m_RequestBody.AddMember("params", params, alloc);
} }
static void static void
@ -220,8 +217,7 @@ namespace abyss
// create request body // create request body
std::string body; std::string body;
std::stringstream ss; std::stringstream ss;
json::ToString(m_RequestBody, ss); body = m_RequestBody.dump();
body = ss.str();
m_SendHeaders.emplace("Content-Type", "application/json"); m_SendHeaders.emplace("Content-Type", "application/json");
m_SendHeaders.emplace("Content-Length", std::to_string(body.size())); m_SendHeaders.emplace("Content-Length", std::to_string(body.size()));
m_SendHeaders.emplace("Accept", "application/json"); m_SendHeaders.emplace("Accept", "application/json");
@ -347,8 +343,7 @@ namespace abyss
} }
auto& front = m_PendingCalls.front(); auto& front = m_PendingCalls.front();
ConnImpl* connimpl = ConnImpl* connimpl =
new ConnImpl(conn, std::move(front.method), std::move(front.params), new ConnImpl(conn, front.method, front.params, front.createHandler);
std::move(front.createHandler));
m_PendingCalls.pop_front(); m_PendingCalls.pop_front();
m_Conns.emplace_back(connimpl->handler); m_Conns.emplace_back(connimpl->handler);
connimpl->SendRequest(); connimpl->SendRequest();

View file

@ -24,10 +24,7 @@ namespace abyss
llarp_time_t m_ReadTimeout; llarp_time_t m_ReadTimeout;
bool m_Bad; bool m_Bad;
std::unique_ptr< json::IParser > m_BodyParser; std::unique_ptr< json::IParser > m_BodyParser;
json::Document m_Request; nlohmann::json m_Request;
std::stringstream m_ResponseBuffer;
json::Stream m_ResponseStream;
json::Writer m_Response;
enum HTTPState enum HTTPState
{ {
@ -43,10 +40,7 @@ namespace abyss
HTTPState m_State; HTTPState m_State;
ConnImpl(BaseReqHandler* p, llarp_tcp_conn* c, llarp_time_t readtimeout) ConnImpl(BaseReqHandler* p, llarp_tcp_conn* c, llarp_time_t readtimeout)
: _conn(c) : _conn(c), _parent(p)
, _parent(p)
, m_ResponseStream(m_ResponseBuffer)
, m_Response(m_ResponseStream)
{ {
handler = nullptr; handler = nullptr;
m_LastActive = p->now(); m_LastActive = p->now();
@ -154,14 +148,13 @@ namespace abyss
// initialize body parser // initialize body parser
if(m_BodyParser == nullptr) if(m_BodyParser == nullptr)
{ {
ssize_t contentLength = 0; auto itr = Header.Headers.find("content-length");
auto itr = Header.Headers.find("content-length");
if(itr == Header.Headers.end()) if(itr == Header.Headers.end())
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain",
"no content length"); "no content length");
} }
contentLength = std::stoll(itr->second); ssize_t contentLength = std::stoll(itr->second);
if(contentLength <= 0) if(contentLength <= 0)
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain",
@ -186,22 +179,21 @@ namespace abyss
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain",
"bad json object"); "bad json object");
case json::IParser::eDone: case json::IParser::eDone:
if(m_Request.IsObject() && m_Request.HasMember("params") if(m_Request.is_object() && m_Request.count("params")
&& m_Request.HasMember("method") && m_Request.HasMember("id") && m_Request.count("method") && m_Request.count("id")
&& m_Request["id"].IsString() && m_Request["method"].IsString() && m_Request["id"].is_string() && m_Request["method"].is_string()
&& m_Request["params"].IsObject()) && m_Request["params"].is_object())
{ {
m_Response.StartObject(); nlohmann::json response;
m_Response.Key("jsonrpc"); response["jsonrpc"] = "2.0";
m_Response.String("2.0"); response["id"] = m_Request["id"];
m_Response.Key("id"); auto value = handler->HandleJSONRPC(
m_Response.String(m_Request["id"].GetString()); m_Request["method"].get< std::string >(),
m_Response.Key("result"); m_Request["params"]);
if(handler->HandleJSONRPC(m_Request["method"].GetString(), if(value)
m_Request["params"], m_Response))
{ {
m_Response.EndObject(); response["result"] = value.value();
return WriteResponseJSON(); return WriteResponseJSON(response);
} }
} }
return WriteResponseSimple(500, "internal error", "text/plain", return WriteResponseSimple(500, "internal error", "text/plain",
@ -212,13 +204,11 @@ namespace abyss
} }
bool bool
WriteResponseJSON() WriteResponseJSON(const nlohmann::json& response)
{ {
std::string response; std::string responseStr = response.dump();
m_ResponseStream.Flush();
response = m_ResponseBuffer.str();
return WriteResponseSimple(200, "OK", "application/json", return WriteResponseSimple(200, "OK", "application/json",
response.c_str()); responseStr.c_str());
} }
bool bool

View file

@ -35,6 +35,7 @@ set(LIB_UTIL_SRC
add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC}) add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC})
target_include_directories(${UTIL_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include) target_include_directories(${UTIL_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(${UTIL_LIB} PUBLIC absl::synchronization) target_link_libraries(${UTIL_LIB} PUBLIC absl::synchronization)
target_link_libraries(${UTIL_LIB} PUBLIC nlohmann_json::nlohmann_json)
# cut back on fluff # cut back on fluff
if (NOT WIN32) if (NOT WIN32)

View file

@ -5,5 +5,5 @@
#include <stdlib.h> #include <stdlib.h>
constexpr size_t MAX_LINK_MSG_SIZE = 8192; constexpr size_t MAX_LINK_MSG_SIZE = 8192;
constexpr llarp_time_t DefaultLinkSessionLifetime = 10 * 1000; constexpr llarp_time_t DefaultLinkSessionLifetime = 60 * 1000;
#endif #endif

View file

@ -210,7 +210,7 @@ namespace llarp
return router->NumberOfConnectedRouters() return router->NumberOfConnectedRouters()
&& router->GetRandomConnectedRouter(cur); && router->GetRandomConnectedRouter(cur);
size_t tries = 5; size_t tries = 10;
do do
{ {
--tries; --tries;
@ -326,6 +326,7 @@ namespace llarp
Builder::HandlePathBuilt(Path* p) Builder::HandlePathBuilt(Path* p)
{ {
buildIntervalLimit = MIN_PATH_BUILD_INTERVAL; buildIntervalLimit = MIN_PATH_BUILD_INTERVAL;
router->routerProfiling().MarkPathSuccess(p);
PathSet::HandlePathBuilt(p); PathSet::HandlePathBuilt(p);
} }
@ -336,6 +337,7 @@ namespace llarp
static constexpr llarp_time_t MaxBuildInterval = 30 * 1000; static constexpr llarp_time_t MaxBuildInterval = 30 * 1000;
buildIntervalLimit = buildIntervalLimit =
std::max(1000 + buildIntervalLimit, MaxBuildInterval); std::max(1000 + buildIntervalLimit, MaxBuildInterval);
router->routerProfiling().MarkPathFail(p);
PathSet::HandlePathBuildTimeout(p); PathSet::HandlePathBuildTimeout(p);
} }

View file

@ -18,6 +18,8 @@ namespace llarp
return false; return false;
if(!BEncodeWriteDictInt("t", connectTimeoutCount, buf)) if(!BEncodeWriteDictInt("t", connectTimeoutCount, buf))
return false; return false;
if(!BEncodeWriteDictInt("u", lastUpdated, buf))
return false;
if(!BEncodeWriteDictInt("v", version, buf)) if(!BEncodeWriteDictInt("v", version, buf))
return false; return false;
@ -32,6 +34,8 @@ namespace llarp
return false; return false;
if(!BEncodeMaybeReadDictInt("t", connectTimeoutCount, read, k, buf)) if(!BEncodeMaybeReadDictInt("t", connectTimeoutCount, read, k, buf))
return false; return false;
if(!BEncodeMaybeReadDictInt("u", lastUpdated, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("v", version, read, k, buf)) if(!BEncodeMaybeReadDictInt("v", version, read, k, buf))
return false; return false;
if(!BEncodeMaybeReadDictInt("s", pathFailCount, read, k, buf)) if(!BEncodeMaybeReadDictInt("s", pathFailCount, read, k, buf))
@ -41,6 +45,28 @@ namespace llarp
return read; return read;
} }
void
RouterProfile::Clear()
{
connectGoodCount = 0;
connectTimeoutCount = 0;
pathSuccessCount = 0;
pathFailCount = 0;
lastUpdated = llarp::time_now_ms();
}
void
RouterProfile::Tick()
{
// 10 minutes
static constexpr llarp_time_t updateInterval = DEFAULT_PATH_LIFETIME;
auto now = llarp::time_now_ms();
if(lastUpdated < now && now - lastUpdated > updateInterval)
{
Clear();
}
}
bool bool
RouterProfile::IsGood(uint64_t chances) const RouterProfile::IsGood(uint64_t chances) const
{ {
@ -59,11 +85,20 @@ namespace llarp
return !itr->second.IsGood(chances); return !itr->second.IsGood(chances);
} }
void
Profiling::Tick()
{
lock_t lock(m_ProfilesMutex);
std::for_each(m_Profiles.begin(), m_Profiles.end(),
[](auto& item) { item.second.Tick(); });
}
void void
Profiling::MarkTimeout(const RouterID& r) Profiling::MarkTimeout(const RouterID& r)
{ {
lock_t lock(&m_ProfilesMutex); lock_t lock(&m_ProfilesMutex);
m_Profiles[r].connectTimeoutCount += 1; m_Profiles[r].connectTimeoutCount += 1;
m_Profiles[r].lastUpdated = llarp::time_now_ms();
} }
void void
@ -71,6 +106,7 @@ namespace llarp
{ {
lock_t lock(&m_ProfilesMutex); lock_t lock(&m_ProfilesMutex);
m_Profiles[r].connectGoodCount += 1; m_Profiles[r].connectGoodCount += 1;
m_Profiles[r].lastUpdated = llarp::time_now_ms();
} }
void void
@ -81,6 +117,7 @@ namespace llarp
{ {
// TODO: also mark bad? // TODO: also mark bad?
m_Profiles[hop.rc.pubkey].pathFailCount += 1; m_Profiles[hop.rc.pubkey].pathFailCount += 1;
m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms();
} }
} }
@ -91,6 +128,7 @@ namespace llarp
for(const auto& hop : p->hops) for(const auto& hop : p->hops)
{ {
m_Profiles[hop.rc.pubkey].pathSuccessCount += 1; m_Profiles[hop.rc.pubkey].pathSuccessCount += 1;
m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms();
} }
} }

View file

@ -18,6 +18,7 @@ namespace llarp
uint64_t connectGoodCount = 0; uint64_t connectGoodCount = 0;
uint64_t pathSuccessCount = 0; uint64_t pathSuccessCount = 0;
uint64_t pathFailCount = 0; uint64_t pathFailCount = 0;
llarp_time_t lastUpdated = 0;
RouterProfile() : IBEncodeMessage(){}; RouterProfile() : IBEncodeMessage(){};
@ -31,6 +32,14 @@ namespace llarp
bool bool
IsGood(uint64_t chances) const; IsGood(uint64_t chances) const;
/// clear stats
void
Clear();
// rotate stats if timeout reached
void
Tick();
}; };
struct Profiling final : public IBEncodeMessage struct Profiling final : public IBEncodeMessage
@ -59,6 +68,9 @@ namespace llarp
void void
MarkPathSuccess(path::Path* p) LOCKS_EXCLUDED(m_ProfilesMutex); MarkPathSuccess(path::Path* p) LOCKS_EXCLUDED(m_ProfilesMutex);
void
Tick();
bool bool
BEncode(llarp_buffer_t* buf) const override LOCKS_EXCLUDED(m_ProfilesMutex); BEncode(llarp_buffer_t* buf) const override LOCKS_EXCLUDED(m_ProfilesMutex);

View file

@ -1022,6 +1022,8 @@ namespace llarp
// LogDebug("tick router"); // LogDebug("tick router");
auto now = Now(); auto now = Now();
routerProfiling().Tick();
if(_rc.ExpiresSoon(now, randint() % 10000)) if(_rc.ExpiresSoon(now, randint() % 10000))
{ {
LogInfo("regenerating RC"); LogInfo("regenerating RC");

View file

@ -25,23 +25,28 @@ namespace llarp
} }
virtual bool virtual bool
HandleJSONResult(const json::Value& val) = 0; HandleJSONResult(const nlohmann::json& val) = 0;
bool bool
HandleResponse(::abyss::http::RPC_Response response) HandleResponse(::abyss::http::RPC_Response response)
{ {
if(!response.IsObject()) if(!response.is_object())
{ {
return HandleJSONResult({}); return HandleJSONResult({});
} }
const auto itr = response.FindMember("result"); const auto itr = response.find("result");
if(itr == response.MemberEnd()) if(itr == response.end())
{ {
return HandleJSONResult({}); return HandleJSONResult({});
} }
if(itr->value.IsObject()) else if(itr.value().is_object())
return HandleJSONResult(itr->value); {
return false; return HandleJSONResult(itr.value());
}
else
{
return false;
}
} }
void void
@ -65,42 +70,40 @@ namespace llarp
} }
bool bool
HandleJSONResult(const json::Value& result) override HandleJSONResult(const nlohmann::json& result) override
{ {
PubkeyList_t keys; PubkeyList_t keys;
if(!result.IsObject()) if(!result.is_object())
{ {
LogWarn("Invalid result: not an object"); LogWarn("Invalid result: not an object");
handler({}, false); handler({}, false);
return false; return false;
} }
const auto itr = result.FindMember("keys"); const auto itr = result.find("keys");
if(itr == result.MemberEnd()) if(itr == result.end())
{ {
LogWarn("Invalid result: no keys member"); LogWarn("Invalid result: no keys member");
handler({}, false); handler({}, false);
return false; return false;
} }
if(!itr->value.IsArray()) if(!itr.value().is_array())
{ {
LogWarn("Invalid result: keys is not an array"); LogWarn("Invalid result: keys is not an array");
handler({}, false); handler({}, false);
return false; return false;
} }
auto key_itr = itr->value.Begin(); for(const auto item : itr.value())
while(key_itr != itr->value.End())
{ {
if(key_itr->IsString()) if(item.is_string())
{ {
keys.emplace_back(); keys.emplace_back();
std::string str = key_itr->GetString(); std::string str = item.get< std::string >();
if(!Base32Decode(str, keys.back())) if(!Base32Decode(str, keys.back()))
{ {
LogWarn("Invalid key: ", str); LogWarn("Invalid key: ", str);
keys.pop_back(); keys.pop_back();
} }
} }
++key_itr;
} }
handler(keys, true); handler(keys, true);
return true; return true;
@ -149,9 +152,7 @@ namespace llarp
AsyncUpdatePubkeyList() AsyncUpdatePubkeyList()
{ {
LogInfo("Updating service node list"); LogInfo("Updating service node list");
json::Value params; QueueRPC("get_all_service_nodes_keys", nlohmann::json::object(),
params.SetObject();
QueueRPC("get_all_service_nodes_keys", std::move(params),
std::bind(&CallerImpl::NewAsyncUpdatePubkeyListConn, this, std::bind(&CallerImpl::NewAsyncUpdatePubkeyListConn, this,
std::placeholders::_1)); std::placeholders::_1));
} }
@ -211,75 +212,59 @@ namespace llarp
{ {
} }
bool Response
DumpState(Response& resp) const DumpState() const
{ {
util::StatusObject dump = router->ExtractStatus(); util::StatusObject dump = router->ExtractStatus();
dump.Impl.Accept(resp); return dump.get();
return true;
} }
bool Response
ListExitLevels(Response& resp) const ListExitLevels() const
{ {
exit::Context::TrafficStats stats; exit::Context::TrafficStats stats;
router->exitContext().CalculateExitTraffic(stats); router->exitContext().CalculateExitTraffic(stats);
resp.StartArray(); Response resp;
auto itr = stats.begin();
while(itr != stats.end()) for(const auto& stat : stats)
{ {
resp.StartObject(); resp.emplace_back(Response{
resp.Key("ident"); {"ident", stat.first.ToHex()},
resp.String(itr->first.ToHex().c_str()); {"tx", stat.second.first},
resp.Key("tx"); {"rx", stat.second.second},
resp.Uint64(itr->second.first); });
resp.Key("rx");
resp.Uint64(itr->second.second);
resp.EndObject();
++itr;
} }
resp.EndArray(); return resp;
return true;
} }
bool Response
ListNeighboors(Response& resp) const ListNeighboors() const
{ {
resp.StartArray(); Response resp = Response::array();
router->ForEachPeer([&](const ILinkSession* session, bool outbound) { router->ForEachPeer([&](const ILinkSession* session, bool outbound) {
resp.StartObject(); resp.emplace_back(
auto ident = RouterID(session->GetPubKey()).ToString(); Response{{"ident", RouterID(session->GetPubKey()).ToString()},
resp.Key("ident"); {"addr", session->GetRemoteEndpoint().ToString()},
resp.String(ident.c_str()); {"outbound", outbound}});
auto addr = session->GetRemoteEndpoint().ToString();
resp.Key("addr");
resp.String(addr.c_str());
resp.Key("outbound");
resp.Bool(outbound);
resp.EndObject();
}); });
resp.EndArray(); return resp;
return true;
} }
bool absl::optional< Response >
HandleJSONRPC(Method_t method, HandleJSONRPC(Method_t method,
__attribute__((unused)) const Params& params, __attribute__((unused)) const Params& params)
Response& response)
{ {
if(method == "llarp.admin.link.neighboors") if(method == "llarp.admin.link.neighboors")
{ {
return ListNeighboors(response); return ListNeighboors();
} }
else if(method == "llarp.admin.exit.list") else if(method == "llarp.admin.exit.list")
{ {
return ListExitLevels(response); return ListExitLevels();
} }
else if(method == "llarp.admin.dumpstate") else if(method == "llarp.admin.dumpstate")
{ {
return DumpState(response); return DumpState();
} }
return false; return false;
} }

View file

@ -9,10 +9,12 @@ namespace llarp
{ {
namespace json namespace json
{ {
struct RapidJSONParser : public IParser struct NlohmannJSONParser : public IParser
{ {
RapidJSONParser(size_t contentSize) : m_Buf(contentSize + 1), m_Offset(0) NlohmannJSONParser(size_t contentSize)
: m_Buf(contentSize + 1), m_Offset(0)
{ {
assert(contentSize != 0);
} }
std::vector< char > m_Buf; std::vector< char > m_Buf;
@ -23,36 +25,34 @@ namespace llarp
{ {
if(m_Offset + sz > m_Buf.size() - 1) if(m_Offset + sz > m_Buf.size() - 1)
return false; return false;
memcpy(m_Buf.data() + m_Offset, buf, sz); std::copy(buf, buf + sz, m_Buf.begin());
m_Offset += sz; m_Offset += sz;
m_Buf[m_Offset] = 0; m_Buf[m_Offset] = 0;
return true; return true;
} }
Result Result
Parse(Document& obj) const Parse(nlohmann::json& obj) const
{ {
if(m_Offset < m_Buf.size() - 1) if(m_Offset < m_Buf.size() - 1)
return eNeedData; return eNeedData;
obj.Parse(m_Buf.data());
if(obj.HasParseError()) try
{
obj = nlohmann::json::parse(m_Buf.data());
return eDone;
}
catch(const nlohmann::json::exception&)
{
return eParseError; return eParseError;
return eDone; }
} }
}; };
IParser* IParser*
MakeParser(size_t contentSize) MakeParser(size_t contentSize)
{ {
return new RapidJSONParser(contentSize); return new NlohmannJSONParser(contentSize);
}
void
ToString(const json::Document& val, std::ostream& out)
{
Stream s(out);
rapidjson::Writer< Stream > writer(s);
val.Accept(writer);
} }
} // namespace json } // namespace json

View file

@ -3,84 +3,13 @@
#include <util/string_view.hpp> #include <util/string_view.hpp>
#include <rapidjson/document.h> #include <nlohmann/json.hpp>
#include <rapidjson/writer.h>
#include <memory> #include <memory>
#include <iostream> #include <iostream>
namespace llarp namespace llarp
{ {
namespace json
{
/// add this because debian stable doesn't have it
template < typename StreamType >
class BasicOStreamWrapper
{
public:
typedef typename StreamType::char_type Ch;
BasicOStreamWrapper(StreamType& stream) : stream_(stream)
{
}
void
Put(Ch c)
{
stream_.put(c);
}
void
Flush()
{
stream_.flush();
}
// Not implemented
char
Peek() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
char
Take()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t
Tell() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
char*
PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t
PutEnd(char*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
BasicOStreamWrapper(const BasicOStreamWrapper&);
BasicOStreamWrapper&
operator=(const BasicOStreamWrapper&);
StreamType& stream_;
};
using Document = rapidjson::Document;
using Value = rapidjson::Value;
using Stream = BasicOStreamWrapper< std::ostream >;
using Writer = rapidjson::Writer< Stream >;
} // namespace json
namespace json namespace json
{ {
struct IParser struct IParser
@ -103,16 +32,13 @@ namespace llarp
FeedData(const char* buf, size_t sz) = 0; FeedData(const char* buf, size_t sz) = 0;
/// parse internal buffer /// parse internal buffer
virtual Result virtual Result
Parse(Document& obj) const = 0; Parse(nlohmann::json& obj) const = 0;
}; };
/// create new parser /// create new parser
IParser* IParser*
MakeParser(size_t contentSize); MakeParser(size_t contentSize);
void
ToString(const json::Document& obj, std::ostream& out);
} // namespace json } // namespace json
} // namespace llarp } // namespace llarp

View file

@ -1,21 +1,54 @@
#include <util/status.hpp> #include <util/status.hpp>
#include <util/traits.hpp>
namespace llarp namespace llarp
{ {
namespace util namespace util
{ {
StatusObject::StatusObject(const StatusObject& other) struct StatusVisitor
{ {
Impl.SetObject(); std::string name;
auto& a = Impl.GetAllocator(); std::reference_wrapper< nlohmann::json > data;
Impl.CopyFrom(other.Impl, a);
}
StatusObject::~StatusObject()
{
Impl.RemoveAllMembers();
}
StatusVisitor(StatusObject::String_t n, nlohmann::json& d)
: name(n), data(d)
{
}
void
operator()(uint64_t val)
{
data.get()[name] = val;
}
void
operator()(const std::string& val)
{
data.get()[name] = val;
}
void
operator()(bool val)
{
data.get()[name] = val;
}
void
operator()(const StatusObject& obj)
{
data.get()[name] = obj.Impl;
}
void
operator()(const std::vector< std::string >& val)
{
data.get()[name] = val;
}
void
operator()(const std::vector< StatusObject >& val)
{
auto arr = nlohmann::json::array();
std::transform(val.begin(), val.end(), std::back_inserter(arr),
[](const auto& x) { return x.Impl; });
data.get()[name] = arr;
}
};
void void
StatusObject::Put(const value_type& val) StatusObject::Put(const value_type& val)
{ {
@ -23,99 +56,9 @@ namespace llarp
} }
void void
StatusObject::Put(String_t name, const Variant& val) StatusObject::Put(String_t name, const Variant& data)
{ {
if(absl::holds_alternative< uint64_t >(val)) absl::visit(StatusVisitor{name, Impl}, data);
PutInt(name, absl::get< uint64_t >(val));
else if(absl::holds_alternative< std::string >(val))
PutString(name, absl::get< std::string >(val));
else if(absl::holds_alternative< bool >(val))
PutBool(name, absl::get< bool >(val));
else if(absl::holds_alternative< StatusObject >(val))
PutObject(name, absl::get< StatusObject >(val));
else if(absl::holds_alternative< std::vector< std::string > >(val))
PutStringArray(name, absl::get< std::vector< std::string > >(val));
else if(absl::holds_alternative< std::vector< StatusObject > >(val))
PutObjectArray(name, absl::get< std::vector< StatusObject > >(val));
}
void
StatusObject::PutBool(String_t name, bool val)
{
auto& a = Impl.GetAllocator();
Value_t v;
v.SetBool(val);
auto s = llarp::string_view_string(name);
Value_t k(s.c_str(), a);
Impl.AddMember(k, v, a);
}
void
StatusObject::PutInt(String_t name, uint64_t val)
{
auto& a = Impl.GetAllocator();
Value_t v;
v.SetUint64(val);
auto s = llarp::string_view_string(name);
Value_t k(s.c_str(), a);
Impl.AddMember(k, v, a);
}
void
StatusObject::PutObject(String_t name, const StatusObject& val)
{
auto& a = Impl.GetAllocator();
Value_t v;
v.SetObject();
v.CopyFrom(val.Impl, a);
auto s = llarp::string_view_string(name);
Value_t k(s.c_str(), a);
Impl.AddMember(k, v, a);
}
void
StatusObject::PutObjectArray(String_t name,
const std::vector< StatusObject >& arr)
{
auto& a = Impl.GetAllocator();
Value_t v;
v.SetArray();
Value_t i;
for(const auto& obj : arr)
{
v.PushBack(i.SetObject().CopyFrom(obj.Impl, a), a);
}
auto s = llarp::string_view_string(name);
Value_t k(s.c_str(), a);
Impl.AddMember(k, v, a);
}
void
StatusObject::PutStringArray(String_t name,
const std::vector< std::string >& arr)
{
auto& a = Impl.GetAllocator();
Value_t v;
v.SetArray();
Value_t i;
for(const auto& str : arr)
{
v.PushBack(i.SetString(str.c_str(), a), a);
}
auto s = llarp::string_view_string(name);
Value_t k(s.c_str(), a);
Impl.AddMember(k, v, a);
}
void
StatusObject::PutString(String_t name, const std::string& val)
{
auto& a = Impl.GetAllocator();
Value_t v;
v.SetString(val.c_str(), a);
auto s = llarp::string_view_string(name);
Value_t k(s.c_str(), a);
Impl.AddMember(k, v, a);
} }
} // namespace util } // namespace util
} // namespace llarp } // namespace llarp

View file

@ -1,9 +1,10 @@
#ifndef LLARP_UTIL_STATUS_HPP #ifndef LLARP_UTIL_STATUS_HPP
#define LLARP_UTIL_STATUS_HPP #define LLARP_UTIL_STATUS_HPP
#include <util/json.hpp>
#include <util/string_view.hpp> #include <util/string_view.hpp>
#include <nlohmann/json.hpp>
#include <vector> #include <vector>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
@ -13,23 +14,17 @@ namespace llarp
{ {
namespace util namespace util
{ {
using StatusObject_Impl = json::Document; struct StatusVisitor;
using Value_t = json::Value;
struct StatusObject struct StatusObject
{ {
using String_t = string_view; using String_t = string_view;
using Variant = absl::variant< uint64_t, std::string, bool, StatusObject, using Variant = absl::variant< uint64_t, std::string, bool, StatusObject,
std::vector< std::string >, std::vector< std::string >,
std::vector< StatusObject > >; std::vector< StatusObject > >;
using value_type = std::tuple< String_t, Variant >; using value_type = std::pair< String_t, Variant >;
StatusObject(const StatusObject&);
~StatusObject();
StatusObject(std::initializer_list< value_type > vals) StatusObject(std::initializer_list< value_type > vals)
{ {
Impl.SetObject();
std::for_each(vals.begin(), vals.end(), std::for_each(vals.begin(), vals.end(),
[&](const value_type& item) { Put(item); }); [&](const value_type& item) { Put(item); });
} }
@ -40,21 +35,15 @@ namespace llarp
void void
Put(const value_type& value); Put(const value_type& value);
StatusObject_Impl Impl; nlohmann::json
get() const
{
return Impl;
}
private: private:
void friend struct StatusVisitor;
PutBool(String_t name, bool val); nlohmann::json Impl;
void
PutInt(String_t name, uint64_t val);
void
PutObject(String_t name, const StatusObject& val);
void
PutObjectArray(String_t name, const std::vector< StatusObject >& arr);
void
PutStringArray(String_t name, const std::vector< std::string >& arr);
void
PutString(String_t name, const std::string& val);
}; };
/// an entity that has a status that can be extracted /// an entity that has a status that can be extracted

View file

@ -15,14 +15,13 @@ Build requirements:
* GNU Make * GNU Make
* CMake * CMake
* C++ 17 capable C++ compiler * C++ 17 capable C++ compiler
* rapidjson (if enabling jsonrpc server)
* gcovr (if generating test coverage with gcc) * gcovr (if generating test coverage with gcc)
### Linux ### Linux
build: build:
$ sudo apt install build-essential cmake git libcap-dev wget rapidjson-dev $ sudo apt install build-essential cmake git libcap-dev wget
$ git clone https://github.com/loki-project/loki-network $ git clone https://github.com/loki-project/loki-network
$ cd loki-network $ cd loki-network
$ make -j8 $ make -j8
@ -49,7 +48,7 @@ install (root):
build (where `$ARCH` is your platform - `i686` or `x86_64`): build (where `$ARCH` is your platform - `i686` or `x86_64`):
$ pacman -Sy base-devel mingw-w64-$ARCH-toolchain git libtool autoconf mingw-w64-$ARCH-cmake mingw-w64-$ARCH-rapidjson $ pacman -Sy base-devel mingw-w64-$ARCH-toolchain git libtool autoconf mingw-w64-$ARCH-cmake
$ git clone https://github.com/loki-project/loki-network.git $ git clone https://github.com/loki-project/loki-network.git
$ cd loki-network $ cd loki-network
$ mkdir -p build; cd build $ mkdir -p build; cd build

View file

@ -189,7 +189,7 @@ TEST_F(LinkLayerTest, TestUTPAliceRenegWithBob)
return true; return true;
} }
}, },
[&](llarp::ILinkSession * s) -> bool { [&](llarp::ILinkSession* s) -> bool {
const auto rc = s->GetRemoteRC(); const auto rc = s->GetRemoteRC();
return rc.pubkey == Bob.GetRC().pubkey; return rc.pubkey == Bob.GetRC().pubkey;
}, },
@ -228,12 +228,12 @@ TEST_F(LinkLayerTest, TestUTPAliceRenegWithBob)
Bob.gotLIM = true; Bob.gotLIM = true;
return sendDiscardMessage(s); return sendDiscardMessage(s);
}, },
[&](llarp::ILinkSession * s) -> bool { [&](llarp::ILinkSession* s) -> bool {
if(s->GetRemoteRC().pubkey != Alice.GetRC().pubkey) if(s->GetRemoteRC().pubkey != Alice.GetRC().pubkey)
return false; return false;
llarp::LogInfo("bob established with alice"); llarp::LogInfo("bob established with alice");
return Bob.link->VisitSessionByPubkey(Alice.GetRC().pubkey.as_array(), return Bob.link->VisitSessionByPubkey(Alice.GetRC().pubkey.as_array(),
sendDiscardMessage); sendDiscardMessage);
}, },
[&](llarp::RouterContact newrc, llarp::RouterContact oldrc) -> bool { [&](llarp::RouterContact newrc, llarp::RouterContact oldrc) -> bool {
success = newrc.pubkey == oldrc.pubkey; success = newrc.pubkey == oldrc.pubkey;
@ -262,10 +262,21 @@ TEST_F(LinkLayerTest, TestUTPAliceConnectToBob)
Alice.link = llarp::utp::NewServer( Alice.link = llarp::utp::NewServer(
&crypto, Alice.encryptionKey, &crypto, Alice.encryptionKey,
[&]() -> const llarp::RouterContact& { return Alice.GetRC(); }, [&]() -> const llarp::RouterContact& { return Alice.GetRC(); },
[&](llarp::ILinkSession*, const llarp_buffer_t& buf) -> bool { [&](llarp::ILinkSession* s, const llarp_buffer_t& buf) -> bool {
llarp::LinkIntroMessage lim;
llarp_buffer_t copy(buf.base, buf.sz);
if(lim.BDecode(&copy))
{
if(s->GotLIM(&lim))
{
Alice.gotLIM = true;
return true;
}
return false;
}
return AliceGotMessage(buf); return AliceGotMessage(buf);
}, },
[&](llarp::ILinkSession * s) -> bool { [&](llarp::ILinkSession* s) -> bool {
if(s->GetRemoteRC().pubkey != Bob.GetRC().pubkey) if(s->GetRemoteRC().pubkey != Bob.GetRC().pubkey)
return false; return false;
llarp::LogInfo("alice established with bob"); llarp::LogInfo("alice established with bob");
@ -284,24 +295,36 @@ TEST_F(LinkLayerTest, TestUTPAliceConnectToBob)
Bob.link = llarp::utp::NewServer( Bob.link = llarp::utp::NewServer(
&crypto, Bob.encryptionKey, &crypto, Bob.encryptionKey,
[&]() -> const llarp::RouterContact& { return Bob.GetRC(); }, [&]() -> const llarp::RouterContact& { return Bob.GetRC(); },
[&](llarp::ILinkSession*, const llarp_buffer_t& ) -> bool { [&](llarp::ILinkSession* s, const llarp_buffer_t& buf) -> bool {
llarp::LinkIntroMessage lim;
llarp_buffer_t copy(buf.base, buf.sz);
if(lim.BDecode(&copy))
{
if(s->GotLIM(&lim))
{
Bob.gotLIM = true;
return true;
}
return false;
}
return true; return true;
}, },
[&](llarp::ILinkSession * s) -> bool { [&](llarp::ILinkSession* s) -> bool {
if(s->GetRemoteRC().pubkey != Alice.GetRC().pubkey) if(s->GetRemoteRC().pubkey != Alice.GetRC().pubkey)
return false; return false;
llarp::LogInfo("bob established with alice"); llarp::LogInfo("bob established with alice");
logic->queue_job({s, [](void * u) { logic->queue_job({s, [](void* u) {
llarp::ILinkSession * self = static_cast<llarp::ILinkSession*>(u); llarp::ILinkSession* self =
std::array< byte_t, 32 > tmp; static_cast< llarp::ILinkSession* >(u);
llarp_buffer_t otherBuf(tmp); std::array< byte_t, 32 > tmp;
llarp::DiscardMessage discard; llarp_buffer_t otherBuf(tmp);
if(!discard.BEncode(&otherBuf)) llarp::DiscardMessage discard;
return; if(!discard.BEncode(&otherBuf))
otherBuf.sz = otherBuf.cur - otherBuf.base; return;
otherBuf.cur = otherBuf.base; otherBuf.sz = otherBuf.cur - otherBuf.base;
self->SendMessageBuffer(otherBuf); otherBuf.cur = otherBuf.base;
}}); self->SendMessageBuffer(otherBuf);
}});
return true; return true;
}, },
[&](llarp::RouterContact, llarp::RouterContact) -> bool { return true; }, [&](llarp::RouterContact, llarp::RouterContact) -> bool { return true; },

View file

@ -110,7 +110,7 @@ struct ClientHandler : public abyss::http::IRPCClientHandler
void void
HandleError() HandleError()
{ {
ASSERT_TRUE(false); FAIL() << "unexpected error";
} }
void void
@ -134,15 +134,12 @@ struct ServerHandler : public abyss::httpd::IRPCHandler
{ {
} }
bool absl::optional< Response >
HandleJSONRPC(Method_t method, __attribute__((unused)) const Params& params, HandleJSONRPC(Method_t method, __attribute__((unused)) const Params& params)
Response& response)
{ {
test->AssertMethod(method); test->AssertMethod(method);
test->called = true; test->called = true;
response.StartObject(); return Response();
response.EndObject();
return true;
} }
}; };
@ -200,9 +197,7 @@ struct AbyssTest : public AbyssTestBase,
TEST_F(AbyssTest, TestClientAndServer) TEST_F(AbyssTest, TestClientAndServer)
{ {
Start(); Start();
llarp::json::Value params; QueueRPC(method, nlohmann::json::object(),
params.SetObject();
QueueRPC(method, std::move(params),
std::bind(&AbyssTest::NewConn, this, std::placeholders::_1)); std::bind(&AbyssTest::NewConn, this, std::placeholders::_1));
AsyncFlush(); AsyncFlush();

71
vendor/nlohmann/.github/CONTRIBUTING.md vendored Normal file
View file

@ -0,0 +1,71 @@
[![Issue Stats](http://issuestats.com/github/nlohmann/json/badge/pr?style=flat)](http://issuestats.com/github/nlohmann/json) [![Issue Stats](http://issuestats.com/github/nlohmann/json/badge/issue?style=flat)](http://issuestats.com/github/nlohmann/json)
# How to contribute
This project started as a little excuse to exercise some of the cool new C++11 features. Over time, people actually started to use the JSON library (yey!) and started to help improve it by proposing features, finding bugs, or even fixing my mistakes. I am really [thankful](https://github.com/nlohmann/json/blob/master/README.md#thanks) for this and try to keep track of all the helpers.
To make it as easy as possible for you to contribute and for me to keep an overview, here are a few guidelines which should help us avoid all kinds of unnecessary work or disappointment. And of course, this document is subject to discussion, so please [create an issue](https://github.com/nlohmann/json/issues/new) or a pull request if you find a way to improve it!
## Private reports
Usually, all issues are tracked publicly on [GitHub](https://github.com/nlohmann/json/issues). If you want to make a private report (e.g., for a vulnerability or to attach an example that is not meant to be published), please send an email to <mail@nlohmann.me>.
## Prerequisites
Please [create an issue](https://github.com/nlohmann/json/issues/new), assuming one does not already exist, and describe your concern. Note you need a [GitHub account](https://github.com/signup/free) for this.
## Describe your issue
Clearly describe the issue:
- If it is a bug, please describe how to **reproduce** it. If possible, attach a complete example which demonstrates the error. Please also state what you **expected** to happen instead of the error.
- If you propose a change or addition, try to give an **example** how the improved code could look like or how to use it.
- If you found a compilation error, please tell us which **compiler** (version and operating system) you used and paste the (relevant part of) the error messages to the ticket.
Please stick to the [issue template](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE.md) if possible.
## Files to change
:exclamation: Before you make any changes, note the single-header file [`single_include/nlohmann/json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is **generated** from the source files in the [`include/nlohmann` directory](https://github.com/nlohmann/json/tree/develop/include/nlohmann). Please **do not** edit file `single_include/nlohmann/json.hpp` directly, but change the `include/nlohmann` sources and regenerate file `single_include/nlohmann/json.hpp` by executing `make amalgamate`.
To make changes, you need to edit the following files:
1. [`include/nlohmann/*`](https://github.com/nlohmann/json/tree/develop/include/nlohmann) - These files are the sources of the library. Before testing or creating a pull request, execute `make amalgamate` to regenerate `single_include/nlohmann/json.hpp`.
2. [`test/src/unit-*.cpp`](https://github.com/nlohmann/json/tree/develop/test/src) - These files contain the [Catch](https://github.com/philsquared/Catch) unit tests which currently cover [100 %](https://coveralls.io/github/nlohmann/json) of the library's code.
If you add or change a feature, please also add a unit test to this file. The unit tests can be compiled and executed with
```sh
$ mkdir build
$ cd build
$ cmake ..
$ cmake --build .
$ ctest
```
The test cases are also executed with several different compilers on [Travis](https://travis-ci.org/nlohmann/json) once you open a pull request.
## Note
- If you open a pull request, the code will be automatically tested with [Valgrind](http://valgrind.org)'s Memcheck tool to detect memory leaks. Please be aware that the execution with Valgrind _may_ in rare cases yield different behavior than running the code directly. This can result in failing unit tests which run successfully without Valgrind.
- There is a Makefile target `make pretty` which runs [Artistic Style](http://astyle.sourceforge.net) to fix indentation. If possible, run it before opening the pull request. Otherwise, we shall run it afterward.
## Please don't
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
- Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
- We shall not extend the library to **support comments**. There is quite some [controversy](https://www.reddit.com/r/programming/comments/4v6chu/why_json_doesnt_support_comments_douglas_crockford/) around this topic, and there were quite some [issues](https://github.com/nlohmann/json/issues/376) on this. We believe that JSON is fine without comments.
- We do not preserve the **insertion order of object elements**. The [JSON standard](https://tools.ietf.org/html/rfc7159.html) defines objects as "an unordered collection of zero or more name/value pairs". To this end, this library does not preserve insertion order of name/value pairs. (In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default.) Note this behavior conforms to the standard, and we shall not change it to any other order. If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map).
- Please do not open pull requests that address **multiple issues**.
## Wanted
The following areas really need contribution:
- Extending the **continuous integration** toward more exotic compilers such as Android NDK, Intel's Compiler, or the bleeding-edge versions of GCC or Clang.
- Improving the efficiency of the **JSON parser**. The current parser is implemented as a naive recursive descent parser with hand coded string handling. More sophisticated approaches like LALR parsers would be really appreciated. That said, parser generators like Bison or ANTLR do not play nice with single-header files -- I really would like to keep the parser inside the `json.hpp` header, and I am not aware of approaches similar to [`re2c`](http://re2c.org) for parsing.
- Extending and updating existing **benchmarks** to include (the most recent version of) this library. Though efficiency is not everything, speed and memory consumption are very important characteristics for C++ developers, so having proper comparisons would be interesting.

View file

@ -0,0 +1,19 @@
---
name: Bug report
about: Create a report to help us improve
---
- What is the issue you have?
- Please describe the steps to reproduce the issue. Can you provide a small but working code example?
- What is the expected behavior?
- And what is the actual behavior instead?
- Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)?
- Did you use a released version of the library or the version from the `develop` branch?
- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)?

View file

@ -0,0 +1,9 @@
---
name: Feature request
about: Suggest an idea for this project
---
- Describe the feature in as much detail as possible.
- Include sample usage where appropriate.

View file

@ -0,0 +1,19 @@
[Describe your pull request here. Please read the text below the line, and make sure you follow the checklist.]
* * *
## Pull request checklist
Read the [Contribution Guidelines](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md) for detailed information.
- [ ] Changes are described in the pull request, or an [existing issue is referenced](https://github.com/nlohmann/json/issues).
- [ ] The test suite [compiles and runs](https://github.com/nlohmann/json/blob/develop/README.md#execute-unit-tests) without error.
- [ ] [Code coverage](https://coveralls.io/github/nlohmann/json) is 100%. Test cases can be added by editing the [test suite](https://github.com/nlohmann/json/tree/develop/test/src).
- [ ] The source code is amalgamated; that is, after making changes to the sources in the `include/nlohmann` directory, run `make amalgamate` to create the single-header file `single_include/nlohmann/json.hpp`. The whole process is described [here](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md#files-to-change).
## Please don't
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
- Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
- Please do not open pull requests that address **multiple issues**.

19
vendor/nlohmann/.github/config.yml vendored Normal file
View file

@ -0,0 +1,19 @@
# Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot
# *Required* toxicity threshold between 0 and .99 with the higher numbers being the most toxic
# Anything higher than this threshold will be marked as toxic and commented on
sentimentBotToxicityThreshold: .7
# *Required* Comment to reply with
sentimentBotReplyComment: >
Please be sure to review the [code of conduct](https://github.com/nlohmann/json/blob/develop/CODE_OF_CONDUCT.md) and be respectful of other users. cc/ @nlohmann
# Configuration for request-info - https://github.com/behaviorbot/request-info
# *Required* Comment to reply with
requestInfoReplyComment: >
We would appreciate it if you could provide us with more info about this issue or pull request! Please check the [issue template](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE.md) and the [pull request template](https://github.com/nlohmann/json/blob/develop/.github/PULL_REQUEST_TEMPLATE.md).
# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
requestInfoLabelToAdd: "state: needs more info"

17
vendor/nlohmann/.github/stale.yml vendored Normal file
View file

@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: "state: stale"
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

25
vendor/nlohmann/.gitignore vendored Normal file
View file

@ -0,0 +1,25 @@
json_unit
json_benchmarks
json_benchmarks_simple
fuzz-testing
*.dSYM
*.o
*.gcno
*.gcda
build
build_coverage
clang_analyze_build
doc/xml
doc/html
me.nlohmann.json.docset
benchmarks/files/numbers/*.json
.idea
cmake-build-debug
test/test-*
/.vs

338
vendor/nlohmann/.travis.yml vendored Normal file
View file

@ -0,0 +1,338 @@
#########################
# project configuration #
#########################
# C++ project
language: cpp
dist: trusty
sudo: required
group: edge
###################
# global settings #
###################
env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
################
# build matrix #
################
matrix:
include:
# Valgrind
- os: linux
compiler: gcc
env:
- COMPILER=g++-4.9
- CMAKE_OPTIONS=-DJSON_Valgrind=ON
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'valgrind', 'ninja-build']
# clang sanitizer
- os: linux
compiler: clang
env:
- COMPILER=clang++-5.0
- CMAKE_OPTIONS=-DJSON_Sanitizer=ON
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build']
# cppcheck
- os: linux
compiler: gcc
env:
- COMPILER=g++-4.9
- SPECIAL=cppcheck
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'cppcheck', 'ninja-build']
after_success:
- make cppcheck
# no exceptions
- os: linux
compiler: gcc
env:
- COMPILER=g++-4.9
- CMAKE_OPTIONS=-DJSON_NoExceptions=ON
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'ninja-build']
# check amalgamation
- os: linux
compiler: gcc
env:
- COMPILER=g++-4.9
- SPECIAL=amalgamation
- MULTIPLE_HEADERS=ON
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'astyle', 'ninja-build']
after_success:
- make check-amalgamation
# Coveralls (http://gronlier.fr/blog/2015/01/adding-code-coverage-to-your-c-project/)
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'ninja-build']
before_script:
- pip install --user cpp-coveralls
after_success:
- coveralls --build-root test --include include/nlohmann --gcov 'gcov-4.9' --gcov-options '\-lp'
env:
- COMPILER=g++-4.9
- CMAKE_OPTIONS=-DJSON_Coverage=ON
- MULTIPLE_HEADERS=ON
# Coverity (only for branch coverity_scan)
- os: linux
compiler: clang
before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['g++-6', 'clang-3.6', 'ninja-build']
coverity_scan:
project:
name: "nlohmann/json"
description: "Build submitted via Travis CI"
notification_email: niels.lohmann@gmail.com
build_command_prepend: "mkdir coverity_build ; cd coverity_build ; cmake .. ; cd .."
build_command: "make -C coverity_build"
branch_pattern: coverity_scan
env:
- SPECIAL=coverity
- COMPILER=clang++-3.6
# OSX / Clang
- os: osx
osx_image: xcode6.4
- os: osx
osx_image: xcode7.3
- os: osx
osx_image: xcode8
- os: osx
osx_image: xcode8.1
- os: osx
osx_image: xcode8.2
- os: osx
osx_image: xcode8.3
- os: osx
osx_image: xcode9
- os: osx
osx_image: xcode9.1
- os: osx
osx_image: xcode9.2
- os: osx
osx_image: xcode9.3
- os: osx
osx_image: xcode9.4
- os: osx
osx_image: xcode10
# Linux / GCC
- os: linux
compiler: gcc
env: compiler=g++-4.8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8', 'ninja-build']
- os: linux
compiler: gcc
env: compiler=g++-4.9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-5
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-6
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-7
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8', 'ninja-build']
- os: linux
compiler: gcc
env:
- COMPILER=g++-8
- CXXFLAGS=-std=c++17
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8', 'ninja-build']
# Linux / Clang
- os: linux
compiler: clang
env: COMPILER=clang++-3.5
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5']
packages: ['g++-6', 'clang-3.5', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.6
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['g++-6', 'clang-3.6', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.7
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
packages: ['g++-6', 'clang-3.7', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'clang-3.8', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'clang-3.9', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-4.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0']
packages: ['g++-6', 'clang-4.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-5.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-6.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
- os: linux
compiler: clang
env:
- COMPILER=clang++-6.0
- CXXFLAGS=-std=c++1z
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
################
# build script #
################
script:
# get CMake and Ninja (only for systems with brew - macOS)
- |
if [[ (-x $(which brew)) ]]; then
brew update
brew install cmake ninja
brew upgrade cmake
cmake --version
fi
# make sure CXX is correctly set
- if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi
# by default, use the single-header version
- if [[ "${MULTIPLE_HEADERS}" == "" ]]; then export MULTIPLE_HEADERS=OFF; fi
# show OS/compiler version
- uname -a
- $CXX --version
# compile and execute unit tests
- mkdir -p build && cd build
- cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -GNinja && cmake --build . --config Release
- ctest -C Release -V -j
- cd ..
# check if homebrew works (only checks develop branch)
- if [ `which brew` ]; then
brew update ;
brew tap nlohmann/json ;
brew install nlohmann_json --HEAD ;
brew test nlohmann_json ;
fi

111
vendor/nlohmann/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,111 @@
cmake_minimum_required(VERSION 3.7)
##
## PROJECT
## name and version
##
project(nlohmann_json VERSION 3.5.0 LANGUAGES CXX)
##
## INCLUDE
##
##
include(ExternalProject)
##
## OPTIONS
##
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
##
## CONFIGURATION
##
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}"
CACHE INTERNAL "")
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include")
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
if (JSON_MultipleHeaders)
set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")
message(STATUS "Using the multi-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
else()
set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/single_include/")
message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
endif()
##
## TARGET
## create target and add include path
##
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
target_include_directories(
${NLOHMANN_JSON_TARGET_NAME}
INTERFACE
$<BUILD_INTERFACE:${NLOHMANN_JSON_INCLUDE_BUILD_DIR}>
$<INSTALL_INTERFACE:include>
)
## add debug view definition file for msvc (natvis)
if (MSVC)
set(NLOHMANN_ADD_NATVIS TRUE)
set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis")
target_sources(
${NLOHMANN_JSON_TARGET_NAME}
INTERFACE
$<INSTALL_INTERFACE:${NLOHMANN_NATVIS_FILE}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NLOHMANN_NATVIS_FILE}>
)
endif()
##
## INSTALL
## install header files, generate and install cmake config files for find_package()
##
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE} COMPATIBILITY SameMajorVersion
)
configure_file(
${NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE}
${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE}
@ONLY
)
#install(
# DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
# DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
#)
#install(
# FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
# DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
#)
if (NLOHMANN_ADD_NATVIS)
#install(
# FILES ${NLOHMANN_NATVIS_FILE}
# DESTINATION .
#)
endif()
export(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
)
#install(
# TARGETS ${NLOHMANN_JSON_TARGET_NAME}
#EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
#INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
#)
#install(
#EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
#NAMESPACE ${PROJECT_NAME}::
#DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
#)

46
vendor/nlohmann/CODE_OF_CONDUCT.md vendored Normal file
View file

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mail@nlohmann.me. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

1404
vendor/nlohmann/ChangeLog.md vendored Normal file

File diff suppressed because it is too large Load diff

21
vendor/nlohmann/LICENSE.MIT vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2018 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

347
vendor/nlohmann/Makefile vendored Normal file
View file

@ -0,0 +1,347 @@
.PHONY: pretty clean ChangeLog.md
SRCS = include/nlohmann/json.hpp \
include/nlohmann/json_fwd.hpp \
include/nlohmann/adl_serializer.hpp \
include/nlohmann/detail/conversions/from_json.hpp \
include/nlohmann/detail/conversions/to_chars.hpp \
include/nlohmann/detail/conversions/to_json.hpp \
include/nlohmann/detail/exceptions.hpp \
include/nlohmann/detail/input/binary_reader.hpp \
include/nlohmann/detail/input/input_adapters.hpp \
include/nlohmann/detail/input/json_sax.hpp \
include/nlohmann/detail/input/lexer.hpp \
include/nlohmann/detail/input/parser.hpp \
include/nlohmann/detail/input/position_t.hpp \
include/nlohmann/detail/iterators/internal_iterator.hpp \
include/nlohmann/detail/iterators/iter_impl.hpp \
include/nlohmann/detail/iterators/iteration_proxy.hpp \
include/nlohmann/detail/iterators/json_reverse_iterator.hpp \
include/nlohmann/detail/iterators/primitive_iterator.hpp \
include/nlohmann/detail/json_pointer.hpp \
include/nlohmann/detail/json_ref.hpp \
include/nlohmann/detail/macro_scope.hpp \
include/nlohmann/detail/macro_unscope.hpp \
include/nlohmann/detail/meta/cpp_future.hpp \
include/nlohmann/detail/meta/detected.hpp \
include/nlohmann/detail/meta/type_traits.hpp \
include/nlohmann/detail/meta/void_t.hpp \
include/nlohmann/detail/output/binary_writer.hpp \
include/nlohmann/detail/output/output_adapters.hpp \
include/nlohmann/detail/output/serializer.hpp \
include/nlohmann/detail/value_t.hpp
UNAME = $(shell uname)
CXX=clang++
AMALGAMATED_FILE=single_include/nlohmann/json.hpp
# main target
all:
@echo "amalgamate - amalgamate file single_include/nlohmann/json.hpp from the include/nlohmann sources"
@echo "ChangeLog.md - generate ChangeLog file"
@echo "check - compile and execute test suite"
@echo "check-amalgamation - check whether sources have been amalgamated"
@echo "check-fast - compile and execute test suite (skip long-running tests)"
@echo "clean - remove built files"
@echo "coverage - create coverage information with lcov"
@echo "cppcheck - analyze code with cppcheck"
@echo "doctest - compile example files and check their output"
@echo "fuzz_testing - prepare fuzz testing of the JSON parser"
@echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
@echo "fuzz_testing_cbor - prepare fuzz testing of the CBOR parser"
@echo "fuzz_testing_msgpack - prepare fuzz testing of the MessagePack parser"
@echo "fuzz_testing_ubjson - prepare fuzz testing of the UBJSON parser"
@echo "json_unit - create single-file test executable"
@echo "pedantic_clang - run Clang with maximal warning flags"
@echo "pedantic_gcc - run GCC with maximal warning flags"
@echo "pretty - beautify code with Artistic Style"
@echo "run_benchmarks - build and run benchmarks"
##########################################################################
# unit tests
##########################################################################
# build unit tests
json_unit:
@$(MAKE) json_unit -C test
# run unit tests
check:
$(MAKE) check -C test
check-fast:
$(MAKE) check -C test TEST_PATTERN=""
# clean up
clean:
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM
rm -fr benchmarks/files/numbers/*.json
rm -fr build_coverage build_benchmarks
$(MAKE) clean -Cdoc
$(MAKE) clean -Ctest
##########################################################################
# coverage
##########################################################################
coverage:
mkdir build_coverage
cd build_coverage ; CXX=g++-7 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd build_coverage ; ninja
cd build_coverage ; ctest -E '.*_default' -j10
cd build_coverage ; ninja lcov_html
open build_coverage/test/html/index.html
##########################################################################
# documentation tests
##########################################################################
# compile example files and check output
doctest:
$(MAKE) check_output -C doc
##########################################################################
# warning detector
##########################################################################
# calling Clang with all warnings, except:
# -Wno-documentation-unknown-command: code uses user-defined commands like @complexity
# -Wno-exit-time-destructors: warning in Catch code
# -Wno-keyword-macro: unit-tests use "#define private public"
# -Wno-deprecated-declarations: the library deprecated some functions
# -Wno-weak-vtables: exception class is defined inline, but has virtual method
# -Wno-range-loop-analysis: items tests "for(const auto i...)"
# -Wno-float-equal: not all comparisons in the tests can be replaced by Approx
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
# -Wno-padded: padding is nothing to warn about
pedantic_clang:
$(MAKE) json_unit CXXFLAGS="\
-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
-Werror \
-Weverything \
-Wno-documentation-unknown-command \
-Wno-exit-time-destructors \
-Wno-keyword-macro \
-Wno-deprecated-declarations \
-Wno-weak-vtables \
-Wno-range-loop-analysis \
-Wno-float-equal \
-Wno-switch-enum -Wno-covered-switch-default \
-Wno-padded"
# calling GCC with most warnings
pedantic_gcc:
$(MAKE) json_unit CXXFLAGS="\
-std=c++11 \
-Wno-deprecated-declarations \
-Werror \
-Wall -Wpedantic -Wextra \
-Walloca \
-Warray-bounds=2 \
-Wcast-qual -Wcast-align \
-Wchar-subscripts \
-Wconditionally-supported \
-Wconversion \
-Wdate-time \
-Wdeprecated \
-Wdisabled-optimization \
-Wdouble-promotion \
-Wduplicated-branches \
-Wduplicated-cond \
-Wformat-overflow=2 \
-Wformat-signedness \
-Wformat-truncation=2 \
-Wformat=2 \
-Wno-ignored-qualifiers \
-Wimplicit-fallthrough=5 \
-Wlogical-op \
-Wmissing-declarations \
-Wmissing-format-attribute \
-Wmissing-include-dirs \
-Wnoexcept \
-Wnonnull \
-Wnull-dereference \
-Wold-style-cast \
-Woverloaded-virtual \
-Wparentheses \
-Wplacement-new=2 \
-Wredundant-decls \
-Wreorder \
-Wrestrict \
-Wshadow=global \
-Wshift-overflow=2 \
-Wsign-conversion \
-Wsign-promo \
-Wsized-deallocation \
-Wstrict-overflow=5 \
-Wsuggest-attribute=const \
-Wsuggest-attribute=format \
-Wsuggest-attribute=noreturn \
-Wsuggest-attribute=pure \
-Wsuggest-final-methods \
-Wsuggest-final-types \
-Wsuggest-override \
-Wtrigraphs \
-Wundef \
-Wuninitialized -Wunknown-pragmas \
-Wunused \
-Wunused-const-variable=2 \
-Wunused-macros \
-Wunused-parameter \
-Wuseless-cast \
-Wvariadic-macros \
-Wctor-dtor-privacy \
-Winit-self \
-Wstrict-null-sentinel"
##########################################################################
# benchmarks
##########################################################################
run_benchmarks:
mkdir build_benchmarks
cd build_benchmarks ; cmake ../benchmarks
cd build_benchmarks ; make
cd build_benchmarks ; ./json_benchmarks
##########################################################################
# fuzzing
##########################################################################
# the overall fuzz testing target
fuzz_testing:
rm -fr fuzz-testing
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
$(MAKE) parse_afl_fuzzer -C test CXX=afl-clang++
mv test/parse_afl_fuzzer fuzz-testing/fuzzer
find test/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
fuzz_testing_bson:
rm -fr fuzz-testing
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
$(MAKE) parse_bson_fuzzer -C test CXX=afl-clang++
mv test/parse_bson_fuzzer fuzz-testing/fuzzer
find test/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
fuzz_testing_cbor:
rm -fr fuzz-testing
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
$(MAKE) parse_cbor_fuzzer -C test CXX=afl-clang++
mv test/parse_cbor_fuzzer fuzz-testing/fuzzer
find test/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
fuzz_testing_msgpack:
rm -fr fuzz-testing
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
$(MAKE) parse_msgpack_fuzzer -C test CXX=afl-clang++
mv test/parse_msgpack_fuzzer fuzz-testing/fuzzer
find test/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
fuzz_testing_ubjson:
rm -fr fuzz-testing
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
$(MAKE) parse_ubjson_fuzzer -C test CXX=afl-clang++
mv test/parse_ubjson_fuzzer fuzz-testing/fuzzer
find test/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
fuzzing-start:
afl-fuzz -S fuzzer1 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -S fuzzer2 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -S fuzzer3 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -S fuzzer4 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -S fuzzer5 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -S fuzzer6 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -S fuzzer7 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
afl-fuzz -M fuzzer0 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer
fuzzing-stop:
-killall fuzzer
-killall afl-fuzz
##########################################################################
# static analyzer
##########################################################################
# call cppcheck on the main header file
cppcheck:
cppcheck --enable=warning --inconclusive --force --std=c++11 $(AMALGAMATED_FILE) --error-exitcode=1
# compile and check with Clang Static Analyzer
clang_analyze:
rm -fr clang_analyze_build
mkdir clang_analyze_build
cd clang_analyze_build ; CCC_CXX=/Users/niels/Documents/projects/llvm-clang/local/bin/clang++ /Users/niels/Documents/projects/llvm-clang/local/bin/scan-build cmake ..
/Users/niels/Documents/projects/llvm-clang/local/bin/scan-build -enable-checker alpha.core.DynamicTypeChecker,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.cplusplus.DeleteWithNonVirtualDtor,alpha.cplusplus.IteratorRange,alpha.cplusplus.MisusedMovedObject,alpha.security.ArrayBoundV2,alpha.core.Conversion --use-c++=/Users/niels/Documents/projects/llvm-clang/local/bin/clang++ --view -analyze-headers -o clang_analyze_build/report.html make -j10 -C clang_analyze_build
##########################################################################
# maintainer targets
##########################################################################
# pretty printer
pretty:
astyle --style=allman --indent=spaces=4 --indent-modifiers \
--indent-switches --indent-preproc-block --indent-preproc-define \
--indent-col1-comments --pad-oper --pad-header --align-pointer=type \
--align-reference=type --add-brackets --convert-tabs --close-templates \
--lineend=linux --preserve-date --suffix=none --formatted \
$(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp \
benchmarks/src/benchmarks.cpp doc/examples/*.cpp
# create single header file
amalgamate: $(AMALGAMATED_FILE)
$(AMALGAMATED_FILE): $(SRCS)
third_party/amalgamate/amalgamate.py -c third_party/amalgamate/config.json -s . --verbose=yes
$(MAKE) pretty
# check if single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
check-amalgamation:
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
@$(MAKE) amalgamate
@diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
# check if every header in nlohmann includes sufficient headers to be compiled
# individually
check-single-includes:
for x in $(SRCS); do \
echo "#include <$$x>\nint main() {}\n" | sed 's|include/||' > single_include_test.cpp; \
$(CXX) $(CXXFLAGS) -Iinclude -std=c++11 single_include_test.cpp -o single_include_test; \
rm single_include_test.cpp single_include_test; \
done
##########################################################################
# changelog
##########################################################################
NEXT_VERSION ?= "unreleased"
ChangeLog.md:
github_changelog_generator -o ChangeLog.md --simple-list --release-url https://github.com/nlohmann/json/releases/tag/%s --future-release $(NEXT_VERSION)
gsed -i 's|https://github.com/nlohmann/json/releases/tag/HEAD|https://github.com/nlohmann/json/tree/HEAD|' ChangeLog.md
gsed -i '2i All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).' ChangeLog.md
##########################################################################
# release
##########################################################################
release:
mkdir release_files
zip -9 -r include.zip include/*
gpg --armor --detach-sig include.zip
mv include.zip include.zip.asc release_files
gpg --armor --detach-sig single_include/nlohmann/json.hpp
cp single_include/nlohmann/json.hpp release_files
mv single_include/nlohmann/json.hpp.asc release_files
cd release_files ; shasum -a 256 json.hpp > hashes.txt
cd release_files ; shasum -a 256 include.zip >> hashes.txt

1293
vendor/nlohmann/README.md vendored Normal file

File diff suppressed because it is too large Load diff

59
vendor/nlohmann/appveyor.yml vendored Normal file
View file

@ -0,0 +1,59 @@
version: '{build}'
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
COMPILER: mingw
platform: x86
FLAGS: ""
GENERATOR: Ninja
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
platform: x86
FLAGS: ""
GENERATOR: Visual Studio 14 2015
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x86
FLAGS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x86
FLAGS: "/permissive- /std:c++latest /utf-8"
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
platform: x64
FLAGS: ""
GENERATOR: Visual Studio 14 2015
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
FLAGS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
FLAGS: "/permissive- /std:c++latest /utf-8"
GENERATOR: Visual Studio 15 2017
init:
- cmake --version
- msbuild /version
install:
- if "%COMPILER%"=="mingw" appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
- if "%COMPILER%"=="mingw" 7z x ninja.zip -oC:\projects\deps\ninja > nul
- if "%COMPILER%"=="mingw" set PATH=C:\projects\deps\ninja;%PATH%
- if "%COMPILER%"=="mingw" set PATH=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;%PATH%
- if "%COMPILER%"=="mingw" g++ --version
before_build:
- cmake . -G "%GENERATOR%" -DCMAKE_CXX_FLAGS="%FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin"
build_script:
- cmake --build . --config Release
test_script:
- ctest -C Release -V -j

15
vendor/nlohmann/cmake/config.cmake.in vendored Normal file
View file

@ -0,0 +1,15 @@
include(FindPackageHandleStandardArgs)
set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE})
find_package_handle_standard_args(@PROJECT_NAME@ CONFIG_MODE)
if(NOT TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
if((NOT TARGET @NLOHMANN_JSON_TARGET_NAME@) AND
(NOT @PROJECT_NAME@_FIND_VERSION OR
@PROJECT_NAME@_FIND_VERSION VERSION_LESS 3.2.0))
add_library(@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED)
set_target_properties(@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
INTERFACE_LINK_LIBRARIES @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@
)
endif()
endif()

331
vendor/nlohmann/doc/Doxyfile vendored Normal file
View file

@ -0,0 +1,331 @@
# Doxyfile 1.8.15
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "JSON for Modern C++"
PROJECT_NUMBER = 3.5.0
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = NO
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = YES
TAB_SIZE = 4
ALIASES = "complexity=@par Complexity^^" \
"liveexample{2}=@par Example^^ \1 ^^ @includelineno \2.cpp \n Output (play with this example @htmlinclude \2.link):^^ @verbinclude \2.output ^^ The <a href= https://github.com/nlohmann/json/blob/develop/doc/examples/\2.cpp>example code</a> above can be translated with @verbatim g++ -std=c++11 -Isingle_include doc/examples/\2.cpp -o \2 @endverbatim" \
"requirement=@par Requirements^^" \
"exceptionsafety=@par Exception safety^^" \
"iterators=@par Iterator validity^^"
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 0
AUTOLINK_SUPPORT = NO
BUILTIN_STL_SUPPORT = YES
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = YES
SORT_MEMBERS_CTORS_1ST = YES
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_FILES = NO
SHOW_NAMESPACES = NO
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../single_include/nlohmann/json.hpp \
index.md \
faq.md \
binary_formats.md
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS = nlohmann::detail
EXAMPLE_PATH = examples
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH = images
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE = index.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = NO
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
CLANG_ASSISTED_PARSING = YES
CLANG_OPTIONS = -std=c++11
CLANG_COMPILATION_DATABASE_PATH = 0
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET = css/mylayout.css
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = YES
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = YES
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = me.nlohmann.json
DOCSET_PUBLISHER_ID = me.nlohmann
DOCSET_PUBLISHER_NAME = NielsLohmann
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = html/nlohmann_json.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = NO
COLLABORATION_GRAPH = NO
GROUP_GRAPHS = YES
UML_LOOK = YES
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = NO
INCLUDED_BY_GRAPH = NO
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DIRECTORY_GRAPH = NO
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = YES
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

88
vendor/nlohmann/doc/Makefile vendored Normal file
View file

@ -0,0 +1,88 @@
SRCDIR = ../single_include
SED:=$(shell command -v gsed || which sed)
all: doxygen
##########################################################################
# example files
##########################################################################
# where are the example cpp files
EXAMPLES = $(wildcard examples/*.cpp)
# create output from a stand-alone example file
%.output: %.cpp
make $(<:.cpp=) CPPFLAGS="-I $(SRCDIR)" CXXFLAGS="-std=c++11"
./$(<:.cpp=) > $@
rm $(<:.cpp=)
# compare created output with current output of the example files
%.test: %.cpp
make $(<:.cpp=) CPPFLAGS="-I $(SRCDIR)" CXXFLAGS="-std=c++11"
./$(<:.cpp=) > $@
diff $@ $(<:.cpp=.output)
rm $(<:.cpp=) $@
# create links to try the code online
%.link: %.cpp
rm -fr tmp
mkdir tmp
cp -r $(SRCDIR)/nlohmann tmp
python2 scripts/send_to_wandbox.py tmp $< > $@.tmp
/bin/echo -n "<a target=\"_blank\" href=\"`cat $@.tmp`\"><b>online</b></a>" > $@
rm -fr tmp $@.tmp
# create output from all stand-alone example files
create_output: $(EXAMPLES:.cpp=.output)
create_links: $(EXAMPLES:.cpp=.link)
# check output of all stand-alone example files
check_output: $(EXAMPLES:.cpp=.test)
clean:
rm -fr me.nlohmann.json.docset html $(EXAMPLES:.cpp=)
##########################################################################
# Doxygen HTML documentation
##########################################################################
# create Doxygen documentation
doxygen: create_output create_links
doxygen
$(SED) -i 's@&lt; ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType, JSONSerializer &gt;@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberFloatType,&#160;AllocatorType&#160;JSONSerializer&#160;&gt;@@g' html/*.html
$(SED) -i 's@&lt; ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer &gt;@@g' html/*.html
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType&#160;JSONSerializer&#160;&gt;@@g' html/*.html
$(SED) -i 's@template&lt;template&lt; typename U, typename V, typename... Args &gt; class ObjectType = std::map, template&lt; typename U, typename... Args &gt; class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, template&lt; typename U &gt; class AllocatorType = std::allocator, template&lt; typename T, typename SFINAE=void &gt; class JSONSerializer = adl_serializer&gt;@@g' html/*.html
$(SED) -i 's@&lt; ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer &gt;@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType,&#160;JSONSerializer&#160;&gt;@@g' html/*.html
upload: clean doxygen check_output
scripts/git-update-ghpages nlohmann/json html
rm -fr html
open http://nlohmann.github.io/json/
##########################################################################
# docset
##########################################################################
# create docset for Dash
docset: create_output
cp Doxyfile Doxyfile_docset
$(SED) -i 's/DISABLE_INDEX = NO/DISABLE_INDEX = YES/' Doxyfile_docset
$(SED) -i 's/SEARCHENGINE = YES/SEARCHENGINE = NO/' Doxyfile_docset
$(SED) -i 's@HTML_EXTRA_STYLESHEET = css/mylayout.css@HTML_EXTRA_STYLESHEET = css/mylayout_docset.css@' Doxyfile_docset
rm -fr html *.docset
doxygen Doxyfile_docset
$(SED) -i 's@&lt; ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType &gt;@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberFloatType,&#160;AllocatorType&#160;&gt;@@g' html/*.html
make -C html
mv html/*.docset .
$(SED) -i 's@<string>doxygen</string>@<string>json</string>@' me.nlohmann.json.docset/Contents/Info.plist
rm -fr Doxyfile_docset html

BIN
vendor/nlohmann/doc/avatars.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 KiB

171
vendor/nlohmann/doc/binary_formats.md vendored Normal file
View file

@ -0,0 +1,171 @@
# Binary formats
![conversion between JSON and binary formats](images/binary.png)
Several formats exist that encode JSON values in a binary format to reduce the size of the encoded value as well as the required effort to parse encoded value. The library implements three formats, namely
- [CBOR](https://tools.ietf.org/html/rfc7049) (Concise Binary Object Representation)
- [MessagePack](https://msgpack.org)
- [UBJSON](http://ubjson.org) (Universal Binary JSON)
## Interface
### JSON to binary format
For each format, the `to_*` functions (i.e., `to_cbor`, `to_msgpack`, and `to_ubjson`) convert a JSON value into the respective binary format. Taking CBOR as example, the concrete prototypes are:
```cpp
static std::vector<uint8_t> to_cbor(const basic_json& j); // 1
static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o); // 2
static void to_cbor(const basic_json& j, detail::output_adapter<char> o); // 3
```
The first function creates a byte vector from the given JSON value. The second and third function writes to an output adapter of `uint8_t` and `char`, respectively. Output adapters are implemented for strings, output streams, and vectors.
Given a JSON value `j`, the following calls are possible:
```cpp
std::vector<uint8_t> v;
v = json::to_cbor(j); // 1
json::to_cbor(j, v); // 2
std::string s;
json::to_cbor(j, s); // 3
std::ostringstream oss;
json::to_cbor(j, oss); // 3
```
### Binary format to JSON
Likewise, the `from_*` functions (i.e, `from_cbor`, `from_msgpack`, and `from_ubjson`) convert a binary encoded value into a JSON value. Taking CBOR as example, the concrete prototypes are:
```cpp
static basic_json from_cbor(detail::input_adapter i, const bool strict = true); // 1
static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true); // 2
```
Both functions read from an input adapter: the first function takes it directly form argument `i`, whereas the second function creates it from the provided arguments `a1` and `a2`. If the optional parameter `strict` is true, the input must be read completely (or a parse error exception is thrown). If it is false, parsing succeeds even if the input is not completely read.
Input adapters are implemented for input streams, character buffers, string literals, and iterator ranges.
Given several inputs (which we assume to be filled with a CBOR value), the following calls are possible:
```cpp
std::string s;
json j1 = json::from_cbor(s); // 1
std::ifstream is("somefile.cbor", std::ios::binary);
json j2 = json::from_cbor(is); // 1
std::vector<uint8_t> v;
json j3 = json::from_cbor(v); // 1
const char* buff;
std::size_t buff_size;
json j4 = json::from_cbor(buff, buff_size); // 2
```
## Details
### CBOR
The mapping from CBOR to JSON is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors (parse_error.112):
- byte strings (0x40..0x5F)
- date/time (0xC0..0xC1)
- bignum (0xC2..0xC3)
- decimal fraction (0xC4)
- bigfloat (0xC5)
- tagged items (0xC6..0xD4, 0xD8..0xDB)
- expected conversions (0xD5..0xD7)
- simple values (0xE0..0xF3, 0xF8)
- undefined (0xF7)
CBOR further allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected (parse_error.113).
The mapping from JSON to CBOR is **complete** in the sense that any JSON value type can be converted to a CBOR value.
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the dump() function which serializes NaN or Infinity to null.
The following CBOR types are not used in the conversion:
- byte strings (0x40..0x5F)
- UTF-8 strings terminated by "break" (0x7F)
- arrays terminated by "break" (0x9F)
- maps terminated by "break" (0xBF)
- date/time (0xC0..0xC1)
- bignum (0xC2..0xC3)
- decimal fraction (0xC4)
- bigfloat (0xC5)
- tagged items (0xC6..0xD4, 0xD8..0xDB)
- expected conversions (0xD5..0xD7)
- simple values (0xE0..0xF3, 0xF8)
- undefined (0xF7)
- half and single-precision floats (0xF9-0xFA)
- break (0xFF)
### MessagePack
The mapping from MessagePack to JSON is **incomplete** in the sense that not all MessagePack types can be converted to a JSON value. The following MessagePack types are not supported and will yield parse errors:
- bin 8 - bin 32 (0xC4..0xC6)
- ext 8 - ext 32 (0xC7..0xC9)
- fixext 1 - fixext 16 (0xD4..0xD8)
The mapping from JSON to MessagePack is **complete** in the sense that any JSON value type can be converted to a MessagePack value.
The following values can not be converted to a MessagePack value:
- strings with more than 4294967295 bytes
- arrays with more than 4294967295 elements
- objects with more than 4294967295 elements
The following MessagePack types are not used in the conversion:
- bin 8 - bin 32 (0xC4..0xC6)
- ext 8 - ext 32 (0xC7..0xC9)
- float 32 (0xCA)
- fixext 1 - fixext 16 (0xD4..0xD8)
Any MessagePack output created `to_msgpack` can be successfully parsed by `from_msgpack`.
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the `dump()` function which serializes NaN or Infinity to `null`.
### UBJSON
The mapping from UBJSON to JSON is **complete** in the sense that any UBJSON value can be converted to a JSON value.
The mapping from JSON to UBJSON is **complete** in the sense that any JSON value type can be converted to a UBJSON value.
The following values can not be converted to a UBJSON value:
- strings with more than 9223372036854775807 bytes (theoretical)
- unsigned integer numbers above 9223372036854775807
The following markers are not used in the conversion:
- `Z`: no-op values are not created.
- `C`: single-byte strings are serialized with S markers.
Any UBJSON output created to_ubjson can be successfully parsed by from_ubjson.
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the `dump()` function which serializes NaN or Infinity to null.
The optimized formats for containers are supported: Parameter `use_size` adds size information to the beginning of a container and removes the closing marker. Parameter `use_type` further checks whether all elements of a container have the same type and adds the type marker to the beginning of the container. The `use_type` parameter must only be used together with `use_size = true`. Note that `use_size = true` alone may result in larger representations - the benefit of this parameter is that the receiving side is immediately informed on the number of elements of the container.
## Size comparison examples
The following table shows the size compared to the original JSON value for different files from the repository for the different formats.
| format | sample.json | all_unicode.json | floats.json | signed_ints.json | jeopardy.json | canada.json |
| ----------------------- | -----------:| ----------------:| -----------:| ----------------:| -------------:| -----------:|
| JSON | 100.00 % | 100.00 % | 100.00 % | 100.00 % | 100.00 % | 100.00 % |
| CBOR | 87.21 % | 71.18 % | 48.20 % | 44.16 % | 87.96 % | 50.53 % |
| MessagePack | 87.16 % | 71.18 % | 48.20 % | 44.16 % | 87.91 % | 50.56 % |
| UBJSON unoptimized | 88.15 % | 100.00 % | 48.20 % | 44.16 % | 96.58 % | 53.20 % |
| UBJSON size-optimized | 89.26 % | 100.00 % | 48.20 % | 44.16 % | 97.40 % | 58.56 % |
| UBJSON format-optimized | 89.45 % | 100.00 % | 42.85 % | 39.26 % | 94.96 % | 55.93 % |
The results show that there does not exist a "best" encoding. Furthermore, it is not always worthwhile to use UBJSON's optimizations.

26
vendor/nlohmann/doc/css/mylayout.css vendored Normal file
View file

@ -0,0 +1,26 @@
/* hide lengthy template information */
.memtemplate, .memTemplParams {
display: none;
}
/* allow compiler information to wrap */
/* https://css-tricks.com/snippets/css/make-pre-text-wrap/ */
pre.fragment {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
td.paramname {
vertical-align: top;
}
.ok_green {
background-color: #89C35C;
}
.nok_throws {
background-color: #ffa500;
}

View file

@ -0,0 +1,27 @@
.memtemplate {
display: none;
}
.memTemplParams {
display: none;
}
.navtab {
display: none;
}
#top, .footer {
display: none;
}
td.paramname {
vertical-align: top;
}
.ok_green {
background-color: #89C35C;
}
.nok_throws {
background-color: #ffa500;
}

39
vendor/nlohmann/doc/examples/README.cpp vendored Normal file
View file

@ -0,0 +1,39 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON object
json j =
{
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99}
}
}
};
// add new values
j["new"]["key"]["value"] = {"another", "list"};
// count elements
auto s = j.size();
j["size"] = s;
// pretty print with indent of 4 spaces
std::cout << std::setw(4) << j << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/jhAlfAa9ZPKTp8JK"><b>online</b></a>

View file

@ -0,0 +1,27 @@
{
"answer": {
"everything": 42
},
"happy": true,
"list": [
1,
0,
2
],
"name": "Niels",
"new": {
"key": {
"value": [
"another",
"list"
]
}
},
"nothing": null,
"object": {
"currency": "USD",
"value": 42.99
},
"pi": 3.141,
"size": 8
}

19
vendor/nlohmann/doc/examples/array.cpp vendored Normal file
View file

@ -0,0 +1,19 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON arrays
json j_no_init_list = json::array();
json j_empty_init_list = json::array({});
json j_nonempty_init_list = json::array({1, 2, 3, 4});
json j_list_of_pairs = json::array({ {"one", 1}, {"two", 2} });
// serialize the JSON arrays
std::cout << j_no_init_list << '\n';
std::cout << j_empty_init_list << '\n';
std::cout << j_nonempty_init_list << '\n';
std::cout << j_list_of_pairs << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/piWraYhVg2CV3j2H"><b>online</b></a>

View file

@ -0,0 +1,4 @@
[]
[]
[1,2,3,4]
[["one",1],["two",2]]

View file

@ -0,0 +1,48 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON object
json object =
{
{"the good", "il buono"},
{"the bad", "il cattivo"},
{"the ugly", "il brutto"}
};
// output element with key "the ugly"
std::cout << object.at("the ugly") << '\n';
// change element with key "the bad"
object.at("the bad") = "il cattivo";
// output changed array
std::cout << object << '\n';
// exception type_error.304
try
{
// use at() on a non-object type
json str = "I am a string";
str.at("the good") = "Another string";
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to write at a nonexisting key
object.at("the fast") = "il rapido";
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/wtWzPSQWWiuxldVs"><b>online</b></a>

View file

@ -0,0 +1,4 @@
"il brutto"
{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"}
[json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.403] key 'the fast' not found

View file

@ -0,0 +1,42 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON object
json object =
{
{"the good", "il buono"},
{"the bad", "il cattivo"},
{"the ugly", "il brutto"}
};
// output element with key "the ugly"
std::cout << object.at("the ugly") << '\n';
// exception type_error.304
try
{
// use at() on a non-object type
const json str = "I am a string";
std::cout << str.at("the good") << '\n';
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to read from a nonexisting key
std::cout << object.at("the fast") << '\n';
}
catch (json::out_of_range)
{
std::cout << "out of range" << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/Zh3iTnZNxsSgBvm3"><b>online</b></a>

View file

@ -0,0 +1,3 @@
"il brutto"
[json.exception.type_error.304] cannot use at() with string
out of range

View file

@ -0,0 +1,43 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON array
json array = {"first", "2nd", "third", "fourth"};
// output element at index 2 (third element)
std::cout << array.at(2) << '\n';
// change element at index 1 (second element) to "second"
array.at(1) = "second";
// output changed array
std::cout << array << '\n';
// exception type_error.304
try
{
// use at() on a non-array type
json str = "I am a string";
str.at(0) = "Another string";
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to write beyond the array limit
array.at(5) = "sixth";
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/MfM8XIuPWMvxxdeb"><b>online</b></a>

View file

@ -0,0 +1,4 @@
"third"
["first","second","third","fourth"]
[json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.401] array index 5 is out of range

View file

@ -0,0 +1,37 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON array
const json array = {"first", "2nd", "third", "fourth"};
// output element at index 2 (third element)
std::cout << array.at(2) << '\n';
// exception type_error.304
try
{
// use at() on a non-array type
const json str = "I am a string";
std::cout << str.at(0) << '\n';
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to read beyond the array limit
std::cout << array.at(5) << '\n';
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/eFEcnFZxfdLGSMhw"><b>online</b></a>

View file

@ -0,0 +1,3 @@
"third"
[json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.401] array index 5 is out of range

View file

@ -0,0 +1,103 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON value
json j =
{
{"number", 1}, {"string", "foo"}, {"array", {1, 2}}
};
// read-only access
// output element with JSON pointer "/number"
std::cout << j.at("/number"_json_pointer) << '\n';
// output element with JSON pointer "/string"
std::cout << j.at("/string"_json_pointer) << '\n';
// output element with JSON pointer "/array"
std::cout << j.at("/array"_json_pointer) << '\n';
// output element with JSON pointer "/array/1"
std::cout << j.at("/array/1"_json_pointer) << '\n';
// writing access
// change the string
j.at("/string"_json_pointer) = "bar";
// output the changed string
std::cout << j["string"] << '\n';
// change an array element
j.at("/array/1"_json_pointer) = 21;
// output the changed array
std::cout << j["array"] << '\n';
// out_of_range.106
try
{
// try to use an array index with leading '0'
json::reference ref = j.at("/array/01"_json_pointer);
}
catch (json::parse_error& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.109
try
{
// try to use an array index that is not a number
json::reference ref = j.at("/array/one"_json_pointer);
}
catch (json::parse_error& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.401
try
{
// try to use a an invalid array index
json::reference ref = j.at("/array/4"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.402
try
{
// try to use the array index '-'
json::reference ref = j.at("/array/-"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.403
try
{
// try to use a JSON pointer to an nonexistent object key
json::const_reference ref = j.at("/foo"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.404
try
{
// try to use a JSON pointer that cannot be resolved
json::reference ref = j.at("/number/foo"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/ST2lraxpPLdDOUFn"><b>online</b></a>

View file

@ -0,0 +1,12 @@
1
"foo"
[1,2]
2
"bar"
[1,21]
[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'
[json.exception.parse_error.109] parse error: array index 'one' is not a number
[json.exception.out_of_range.401] array index 4 is out of range
[json.exception.out_of_range.402] array index '-' (2) is out of range
[json.exception.out_of_range.403] key 'foo' not found
[json.exception.out_of_range.404] unresolved reference token 'foo'

View file

@ -0,0 +1,79 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON value
const json j =
{
{"number", 1}, {"string", "foo"}, {"array", {1, 2}}
};
// read-only access
// output element with JSON pointer "/number"
std::cout << j.at("/number"_json_pointer) << '\n';
// output element with JSON pointer "/string"
std::cout << j.at("/string"_json_pointer) << '\n';
// output element with JSON pointer "/array"
std::cout << j.at("/array"_json_pointer) << '\n';
// output element with JSON pointer "/array/1"
std::cout << j.at("/array/1"_json_pointer) << '\n';
// out_of_range.109
try
{
// try to use an array index that is not a number
json::const_reference ref = j.at("/array/one"_json_pointer);
}
catch (json::parse_error& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.401
try
{
// try to use a an invalid array index
json::const_reference ref = j.at("/array/4"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.402
try
{
// try to use the array index '-'
json::const_reference ref = j.at("/array/-"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.403
try
{
// try to use a JSON pointer to an nonexistent object key
json::const_reference ref = j.at("/foo"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.404
try
{
// try to use a JSON pointer that cannot be resolved
json::const_reference ref = j.at("/number/foo"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/FkPwquIlr9pojvGf"><b>online</b></a>

View file

@ -0,0 +1,9 @@
1
"foo"
[1,2]
2
[json.exception.parse_error.109] parse error: array index 'one' is not a number
[json.exception.out_of_range.401] array index 4 is out of range
[json.exception.out_of_range.402] array index '-' (2) is out of range
[json.exception.out_of_range.403] key 'foo' not found
[json.exception.out_of_range.404] unresolved reference token 'foo'

38
vendor/nlohmann/doc/examples/back.cpp vendored Normal file
View file

@ -0,0 +1,38 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON values
json j_boolean = true;
json j_number_integer = 17;
json j_number_float = 23.42;
json j_object = {{"one", 1}, {"two", 2}};
json j_object_empty(json::value_t::object);
json j_array = {1, 2, 4, 8, 16};
json j_array_empty(json::value_t::array);
json j_string = "Hello, world";
// call back()
std::cout << j_boolean.back() << '\n';
std::cout << j_number_integer.back() << '\n';
std::cout << j_number_float.back() << '\n';
std::cout << j_object.back() << '\n';
//std::cout << j_object_empty.back() << '\n'; // undefined behavior
std::cout << j_array.back() << '\n';
//std::cout << j_array_empty.back() << '\n'; // undefined behavior
std::cout << j_string.back() << '\n';
// back() called on a null value
try
{
json j_null;
j_null.back();
}
catch (json::invalid_iterator& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/AxHC1Xl6KALWJ0FJ"><b>online</b></a>

View file

@ -0,0 +1,7 @@
true
17
23.42
2
16
"Hello, world"
[json.exception.invalid_iterator.214] cannot get value

View file

@ -0,0 +1,218 @@
#include <iostream>
#include <deque>
#include <list>
#include <forward_list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// ============
// object types
// ============
// create an object from an object_t value
json::object_t object_value = { {"one", 1}, {"two", 2} };
json j_object_t(object_value);
// create an object from std::map
std::map<std::string, int> c_map
{
{"one", 1}, {"two", 2}, {"three", 3}
};
json j_map(c_map);
// create an object from std::unordered_map
std::unordered_map<const char*, double> c_umap
{
{"one", 1.2}, {"two", 2.3}, {"three", 3.4}
};
json j_umap(c_umap);
// create an object from std::multimap
std::multimap<std::string, bool> c_mmap
{
{"one", true}, {"two", true}, {"three", false}, {"three", true}
};
json j_mmap(c_mmap); // only one entry for key "three" is used
// create an object from std::unordered_multimap
std::unordered_multimap<std::string, bool> c_ummap
{
{"one", true}, {"two", true}, {"three", false}, {"three", true}
};
json j_ummap(c_ummap); // only one entry for key "three" is used
// serialize the JSON objects
std::cout << j_object_t << '\n';
std::cout << j_map << '\n';
std::cout << j_umap << '\n';
std::cout << j_mmap << '\n';
std::cout << j_ummap << "\n\n";
// ===========
// array types
// ===========
// create an array from an array_t value
json::array_t array_value = {"one", "two", 3, 4.5, false};
json j_array_t(array_value);
// create an array from std::vector
std::vector<int> c_vector {1, 2, 3, 4};
json j_vec(c_vector);
// create an array from std::valarray
std::valarray<short> c_valarray {10, 9, 8, 7};
json j_valarray(c_valarray);
// create an array from std::deque
std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6};
json j_deque(c_deque);
// create an array from std::list
std::list<bool> c_list {true, true, false, true};
json j_list(c_list);
// create an array from std::forward_list
std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
json j_flist(c_flist);
// create an array from std::array
std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
json j_array(c_array);
// create an array from std::set
std::set<std::string> c_set {"one", "two", "three", "four", "one"};
json j_set(c_set); // only one entry for "one" is used
// create an array from std::unordered_set
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
json j_uset(c_uset); // only one entry for "one" is used
// create an array from std::multiset
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
json j_mset(c_mset); // both entries for "one" are used
// create an array from std::unordered_multiset
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
json j_umset(c_umset); // both entries for "one" are used
// serialize the JSON arrays
std::cout << j_array_t << '\n';
std::cout << j_vec << '\n';
std::cout << j_valarray << '\n';
std::cout << j_deque << '\n';
std::cout << j_list << '\n';
std::cout << j_flist << '\n';
std::cout << j_array << '\n';
std::cout << j_set << '\n';
std::cout << j_uset << '\n';
std::cout << j_mset << '\n';
std::cout << j_umset << "\n\n";
// ============
// string types
// ============
// create string from a string_t value
json::string_t string_value = "The quick brown fox jumps over the lazy dog.";
json j_string_t(string_value);
// create a JSON string directly from a string literal
json j_string_literal("The quick brown fox jumps over the lazy dog.");
// create string from std::string
std::string s_stdstring = "The quick brown fox jumps over the lazy dog.";
json j_stdstring(s_stdstring);
// serialize the JSON strings
std::cout << j_string_t << '\n';
std::cout << j_string_literal << '\n';
std::cout << j_stdstring << "\n\n";
// ============
// number types
// ============
// create a JSON number from number_integer_t
json::number_integer_t value_integer_t = -42;
json j_integer_t(value_integer_t);
// create a JSON number from number_unsigned_t
json::number_integer_t value_unsigned_t = 17;
json j_unsigned_t(value_unsigned_t);
// create a JSON number from an anonymous enum
enum { enum_value = 17 };
json j_enum(enum_value);
// create values of different integer types
short n_short = 42;
int n_int = -23;
long n_long = 1024;
int_least32_t n_int_least32_t = -17;
uint8_t n_uint8_t = 8;
// create (integer) JSON numbers
json j_short(n_short);
json j_int(n_int);
json j_long(n_long);
json j_int_least32_t(n_int_least32_t);
json j_uint8_t(n_uint8_t);
// create values of different floating-point types
json::number_float_t v_ok = 3.141592653589793;
json::number_float_t v_nan = NAN;
json::number_float_t v_infinity = INFINITY;
// create values of different floating-point types
float n_float = 42.23;
float n_float_nan = 1.0f / 0.0f;
double n_double = 23.42;
// create (floating point) JSON numbers
json j_ok(v_ok);
json j_nan(v_nan);
json j_infinity(v_infinity);
json j_float(n_float);
json j_float_nan(n_float_nan);
json j_double(n_double);
// serialize the JSON numbers
std::cout << j_integer_t << '\n';
std::cout << j_unsigned_t << '\n';
std::cout << j_enum << '\n';
std::cout << j_short << '\n';
std::cout << j_int << '\n';
std::cout << j_long << '\n';
std::cout << j_int_least32_t << '\n';
std::cout << j_uint8_t << '\n';
std::cout << j_ok << '\n';
std::cout << j_nan << '\n';
std::cout << j_infinity << '\n';
std::cout << j_float << '\n';
std::cout << j_float_nan << '\n';
std::cout << j_double << "\n\n";
// =============
// boolean types
// =============
// create boolean values
json j_truth = true;
json j_falsity = false;
// serialize the JSON booleans
std::cout << j_truth << '\n';
std::cout << j_falsity << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/pylFciQUhOx6zXW8"><b>online</b></a>

View file

@ -0,0 +1,39 @@
{"one":1,"two":2}
{"one":1,"three":3,"two":2}
{"one":1.2,"three":3.4,"two":2.3}
{"one":true,"three":false,"two":true}
{"one":true,"three":false,"two":true}
["one","two",3,4.5,false]
[1,2,3,4]
[10,9,8,7]
[1.2,2.3,3.4,5.6]
[true,true,false,true]
[12345678909876,23456789098765,34567890987654,45678909876543]
[1,2,3,4]
["four","one","three","two"]
["four","three","two","one"]
["four","one","one","two"]
["four","two","one","one"]
"The quick brown fox jumps over the lazy dog."
"The quick brown fox jumps over the lazy dog."
"The quick brown fox jumps over the lazy dog."
-42
17
17
42
-23
1024
-17
8
3.141592653589793
null
null
42.22999954223633
null
23.42
true
false

View file

@ -0,0 +1,32 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON values
json j_array = {"alpha", "bravo", "charly", "delta", "easy"};
json j_number = 42;
json j_object = {{"one", "eins"}, {"two", "zwei"}};
// create copies using iterators
json j_array_range(j_array.begin() + 1, j_array.end() - 2);
json j_number_range(j_number.begin(), j_number.end());
json j_object_range(j_object.begin(), j_object.find("two"));
// serialize the values
std::cout << j_array_range << '\n';
std::cout << j_number_range << '\n';
std::cout << j_object_range << '\n';
// example for an exception
try
{
json j_invalid(j_number.begin() + 1, j_number.end());
}
catch (json::invalid_iterator& e)
{
std::cout << e.what() << '\n';
}
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/KCfRvbW3QTvghlFb"><b>online</b></a>

View file

@ -0,0 +1,4 @@
["bravo","charly"]
42
{"one":"eins"}
[json.exception.invalid_iterator.204] iterators out of range

View file

@ -0,0 +1,17 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON array
json j1 = {"one", "two", 3, 4.5, false};
// create a copy
json j2(j1);
// serialize the JSON array
std::cout << j1 << " = " << j2 << '\n';
std::cout << std::boolalpha << (j1 == j2) << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/TM0OkdSgEIGBDbrv"><b>online</b></a>

View file

@ -0,0 +1,2 @@
["one","two",3,4.5,false] = ["one","two",3,4.5,false]
true

View file

@ -0,0 +1,18 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON values
json a = 23;
json b = 42;
// copy-assign a to b
b = a;
// serialize the JSON arrays
std::cout << a << '\n';
std::cout << b << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/jWDJPXw490IFoVL1"><b>online</b></a>

View file

@ -0,0 +1,2 @@
23
23

View file

@ -0,0 +1,21 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create JSON values
json j_empty_init_list = json({});
json j_object = { {"one", 1}, {"two", 2} };
json j_array = {1, 2, 3, 4};
json j_nested_object = { {"one", {1}}, {"two", {1, 2}} };
json j_nested_array = { {{1}, "one"}, {{1, 2}, "two"} };
// serialize the JSON value
std::cout << j_empty_init_list << '\n';
std::cout << j_object << '\n';
std::cout << j_array << '\n';
std::cout << j_nested_object << '\n';
std::cout << j_nested_array << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/FR2ImEj05R1bqqZ2"><b>online</b></a>

View file

@ -0,0 +1,5 @@
{}
{"one":1,"two":2}
[1,2,3,4]
{"one":[1],"two":[1,2]}
[[[1],"one"],[[1,2],"two"]]

View file

@ -0,0 +1,17 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON value
json a = 23;
// move contents of a to b
json b(std::move(a));
// serialize the JSON arrays
std::cout << a << '\n';
std::cout << b << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/XTHN0lMT9QsmBcBy"><b>online</b></a>

View file

@ -0,0 +1,2 @@
null
23

View file

@ -0,0 +1,16 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// implicitly create a JSON null value
json j1;
// explicitly create a JSON null value
json j2(nullptr);
// serialize the JSON null value
std::cout << j1 << '\n' << j2 << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/iCwvXJinCVY7q1vi"><b>online</b></a>

View file

@ -0,0 +1,2 @@
null
null

View file

@ -0,0 +1,18 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create an array by creating copies of a JSON value
json value = "Hello";
json array_0 = json(0, value);
json array_1 = json(1, value);
json array_5 = json(5, value);
// serialize the JSON arrays
std::cout << array_0 << '\n';
std::cout << array_1 << '\n';
std::cout << array_5 << '\n';
}

View file

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/BzyeWqt4uTQ2nbfx"><b>online</b></a>

View file

@ -0,0 +1,3 @@
[]
["Hello"]
["Hello","Hello","Hello","Hello","Hello"]

View file

@ -0,0 +1,30 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON object with different entry types
json j =
{
{"integer", 1},
{"floating", 42.23},
{"string", "hello world"},
{"boolean", true},
{"object", {{"key1", 1}, {"key2", 2}}},
{"array", {1, 2, 3}}
};
// access existing values
int v_integer = j.value("integer", 0);
double v_floating = j.value("floating", 47.11);
// access nonexisting values and rely on default value
std::string v_string = j.value("nonexisting", "oops");
bool v_boolean = j.value("nonexisting", false);
// output values
std::cout << std::boolalpha << v_integer << " " << v_floating
<< " " << v_string << " " << v_boolean << "\n";
}

Some files were not shown because too many files have changed in this diff Show more