feat: build out Json
This commit is contained in:
1 parent
2c183a8071
commit
9be045c7da
1 file changed
+160
@@ -468,3 +468,163 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string formatNumber(const JsonValue& value) {
|
||||||
|
if (value.isInteger()) return std::to_string(value.intValue());
|
||||||
|
double raw = value.numberValue();
|
||||||
|
if (!std::isfinite(raw)) return "0";
|
||||||
|
char buffer[48];
|
||||||
|
for (int precision = 15; precision <= 17; ++precision) {
|
||||||
|
std::snprintf(buffer, sizeof buffer, "%.*g", precision, raw);
|
||||||
|
if (std::strtod(buffer, nullptr) == raw) break;
|
||||||
|
}
|
||||||
|
std::string text(buffer);
|
||||||
|
// A double that prints without a fraction would come back as an integer and
|
||||||
|
// print differently the next time round, so the writer keeps it a double.
|
||||||
|
if (text.find_first_of(".eE") == std::string::npos) text += ".0";
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeNull() { return JsonValue(); }
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeBool(bool value) {
|
||||||
|
JsonValue made;
|
||||||
|
made.type = JsonType::Bool;
|
||||||
|
made.boolPayload = value;
|
||||||
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeNumber(double value) {
|
||||||
|
JsonValue made;
|
||||||
|
made.type = JsonType::Number;
|
||||||
|
made.numberPayload = value;
|
||||||
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeInt(long long value) {
|
||||||
|
JsonValue made;
|
||||||
|
made.type = JsonType::Number;
|
||||||
|
made.integral = true;
|
||||||
|
made.integerPayload = value;
|
||||||
|
made.numberPayload = static_cast<double>(value);
|
||||||
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeString(std::string value) {
|
||||||
|
JsonValue made;
|
||||||
|
made.type = JsonType::String;
|
||||||
|
made.stringPayload = std::move(value);
|
||||||
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeArray() {
|
||||||
|
JsonValue made;
|
||||||
|
made.type = JsonType::Array;
|
||||||
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue JsonValue::makeObject() {
|
||||||
|
JsonValue made;
|
||||||
|
made.type = JsonType::Object;
|
||||||
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
double JsonValue::numberValue() const {
|
||||||
|
if (type != JsonType::Number) return 0.0;
|
||||||
|
return integral ? static_cast<double>(integerPayload) : numberPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long JsonValue::intValue() const {
|
||||||
|
if (type != JsonType::Number) return 0;
|
||||||
|
if (integral) return integerPayload;
|
||||||
|
double rounded = numberPayload < 0.0 ? std::ceil(numberPayload - 0.5)
|
||||||
|
: std::floor(numberPayload + 0.5);
|
||||||
|
if (rounded >= 9223372036854775296.0) return 9223372036854775807ll;
|
||||||
|
if (rounded <= -9223372036854775296.0) return -9223372036854775807ll - 1ll;
|
||||||
|
return static_cast<long long>(rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t JsonValue::size() const {
|
||||||
|
if (type == JsonType::Array) return arrayPayload.size();
|
||||||
|
if (type == JsonType::Object) return objectPayload.size();
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonValue::push(JsonValue value) {
|
||||||
|
if (type != JsonType::Array) {
|
||||||
|
*this = makeArray();
|
||||||
|
}
|
||||||
|
arrayPayload.push_back(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonValue::set(const std::string& key, JsonValue value) {
|
||||||
|
if (type != JsonType::Object) {
|
||||||
|
*this = makeObject();
|
||||||
|
}
|
||||||
|
for (Member& member : objectPayload) {
|
||||||
|
if (member.first == key) {
|
||||||
|
member.second = std::move(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objectPayload.emplace_back(key, std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonValue::erase(const std::string& key) {
|
||||||
|
for (std::size_t i = 0u; i < objectPayload.size(); ++i) {
|
||||||
|
if (objectPayload[i].first == key) {
|
||||||
|
objectPayload.erase(objectPayload.begin() + static_cast<std::ptrdiff_t>(i));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const JsonValue* JsonValue::find(const std::string& key) const {
|
||||||
|
for (const Member& member : objectPayload)
|
||||||
|
if (member.first == key) return &member.second;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue* JsonValue::find(const std::string& key) {
|
||||||
|
for (Member& member : objectPayload)
|
||||||
|
if (member.first == key) return &member.second;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const JsonValue* JsonValue::at(std::size_t index) const {
|
||||||
|
if (type != JsonType::Array || index >= arrayPayload.size()) return nullptr;
|
||||||
|
return &arrayPayload[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonValue::boolOr(bool fallback) const { return isBool() ? boolPayload : fallback; }
|
||||||
|
|
||||||
|
double JsonValue::numberOr(double fallback) const { return isNumber() ? numberValue() : fallback; }
|
||||||
|
|
||||||
|
long long JsonValue::intOr(long long fallback) const { return isNumber() ? intValue() : fallback; }
|
||||||
|
|
||||||
|
std::string JsonValue::stringOr(const std::string& fallback) const {
|
||||||
|
return isString() ? stringPayload : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonValue::boolOr(const std::string& key, bool fallback) const {
|
||||||
|
const JsonValue* member = find(key);
|
||||||
|
return member ? member->boolOr(fallback) : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
double JsonValue::numberOr(const std::string& key, double fallback) const {
|
||||||
|
const JsonValue* member = find(key);
|
||||||
|
return member ? member->numberOr(fallback) : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long JsonValue::intOr(const std::string& key, long long fallback) const {
|
||||||
|
const JsonValue* member = find(key);
|
||||||
|
return member ? member->intOr(fallback) : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string JsonValue::stringOr(const std::string& key, const std::string& fallback) const {
|
||||||
|
const JsonValue* member = find(key);
|
||||||
|
return member ? member->stringOr(fallback) : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user