200 lines
5.1 KiB
C++
200 lines
5.1 KiB
C++
/*
|
|
* Copyright 2015 - 2024 gary@drinkingtea.net
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <ox/std/bit.hpp>
|
|
#include <utility>
|
|
|
|
#include "read.hpp"
|
|
|
|
namespace ox {
|
|
|
|
OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) {
|
|
auto json = reinterpret_cast<const char*>(buff);
|
|
auto jsonLen = ox::strnlen(json, buffSize);
|
|
Json::CharReaderBuilder parserBuilder;
|
|
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
|
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
|
|
throw ox::Exception(1, "Could not parse JSON");
|
|
}
|
|
}
|
|
|
|
OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
|
|
Json::CharReaderBuilder parserBuilder;
|
|
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
|
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
|
|
throw ox::Exception(1, "Could not parse JSON");
|
|
}
|
|
}
|
|
|
|
OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
|
|
m_json(std::move(json)),
|
|
m_unionIdx(unionIdx) {
|
|
}
|
|
|
|
Error OrganicClawReader::field(const char *key, bool *val) noexcept {
|
|
auto err = ox::Error(0);
|
|
if (targetValid()) {
|
|
const auto &jv = value(key);
|
|
if (jv.empty()) {
|
|
*val = false;
|
|
} else if (jv.isBool()) {
|
|
*val = jv.asBool();
|
|
} else {
|
|
err = ox::Error(1, "Type mismatch");
|
|
}
|
|
}
|
|
++m_fieldIt;
|
|
return err;
|
|
}
|
|
|
|
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
|
|
auto err = ox::Error(0);
|
|
const char *begin = nullptr, *end = nullptr;
|
|
const auto &jv = value(key);
|
|
if (targetValid()) {
|
|
if (jv.empty()) {
|
|
auto data = val;
|
|
if (data) {
|
|
data[0] = 0;
|
|
}
|
|
} else if (jv.isString()) {
|
|
jv.getString(&begin, &end);
|
|
const auto strSize = static_cast<std::size_t>(end - begin);
|
|
auto data = val;
|
|
if (strSize >= buffLen) {
|
|
err = ox::Error(2, "String size exceeds capacity of destination");
|
|
} else {
|
|
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
|
|
data[strSize] = 0;
|
|
}
|
|
} else {
|
|
err = ox::Error(1, "Type mismatch");
|
|
}
|
|
}
|
|
++m_fieldIt;
|
|
return err;
|
|
}
|
|
|
|
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
|
|
auto err = ox::Error(0);
|
|
const char *begin = nullptr, *end = nullptr;
|
|
const auto &jv = value(key);
|
|
auto &data = *val;
|
|
if (targetValid()) {
|
|
if (jv.empty()) {
|
|
if (data) {
|
|
data[0] = 0;
|
|
}
|
|
} else if (jv.isString()) {
|
|
jv.getString(&begin, &end);
|
|
const auto strSize = static_cast<std::size_t>(end - begin);
|
|
safeDelete(*val);
|
|
*val = new char[strSize + 1];
|
|
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
|
|
data[strSize] = 0;
|
|
} else {
|
|
err = ox::Error(1, "Type mismatch");
|
|
}
|
|
}
|
|
++m_fieldIt;
|
|
return err;
|
|
}
|
|
|
|
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
|
|
auto err = ox::Error(0);
|
|
const char *begin = nullptr, *end = nullptr;
|
|
const auto &jv = value(key);
|
|
if (targetValid()) {
|
|
if (jv.empty()) {
|
|
auto data = val;
|
|
if (data) {
|
|
data[0] = nullptr;
|
|
}
|
|
} else if (jv.isString()) {
|
|
jv.getString(&begin, &end);
|
|
const auto strSize = static_cast<std::size_t>(end - begin);
|
|
auto data = val;
|
|
if (strSize >= buffLen) {
|
|
safeDelete(*val);
|
|
*val = new char[strSize + 1];
|
|
}
|
|
ox::memcpy(data, begin, static_cast<std::size_t>(strSize));
|
|
data[strSize] = nullptr;
|
|
} else {
|
|
err = ox::Error(1, "Type mismatch");
|
|
}
|
|
}
|
|
++m_fieldIt;
|
|
return err;
|
|
}
|
|
|
|
Error OrganicClawReader::field(const char *key, UUID *val) noexcept {
|
|
UUIDStr str;
|
|
oxReturnError(field(key, &str));
|
|
return UUID::fromString(str).moveTo(*val);
|
|
}
|
|
|
|
Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept {
|
|
const auto &jv = value(key);
|
|
if (jv.empty()) {
|
|
return 0;
|
|
}
|
|
if (jv.isArray()) {
|
|
return jv.size();
|
|
}
|
|
return ox::Error(1, "Type mismatch");
|
|
}
|
|
|
|
[[nodiscard]]
|
|
std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
|
|
const char *begin = nullptr, *end = nullptr;
|
|
const auto &jv = value(key);
|
|
if (jv.empty()) {
|
|
return 0;
|
|
}
|
|
if (jv.isString()) {
|
|
jv.getString(&begin, &end);
|
|
return static_cast<std::size_t>(end - begin);
|
|
}
|
|
return ox::Error(1, "Type mismatch");
|
|
}
|
|
|
|
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {
|
|
return OrganicClawReader(value(key), unionIdx);
|
|
}
|
|
|
|
bool OrganicClawReader::fieldPresent(const char *key) noexcept {
|
|
return !m_json[key].empty();
|
|
}
|
|
|
|
int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u) const noexcept {
|
|
const auto &obj = m_json[name];
|
|
if (!obj.isObject()) {
|
|
return -1;
|
|
}
|
|
const auto &keys = obj.getMemberNames();
|
|
if (keys.size() != 1) {
|
|
return -1;
|
|
}
|
|
return u.getKeyIdx(keys.front().c_str());
|
|
}
|
|
|
|
Json::Value &OrganicClawReader::value(const char *key) noexcept {
|
|
if (m_json.isArray()) {
|
|
return m_json[m_fieldIt];
|
|
} else {
|
|
return m_json[key];
|
|
}
|
|
}
|
|
|
|
bool OrganicClawReader::targetValid() const noexcept {
|
|
return static_cast<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
|
|
}
|
|
|
|
}
|