Compare commits

..

No commits in common. "0d2fefbfb00995e25dc44c87d12599c60e3da75a" and "d4c48ea269cc4533e46021be8a1a919b2c432730" have entirely different histories.

9 changed files with 213 additions and 85 deletions

2
.gitignore vendored
View File

@ -9,4 +9,4 @@ building/*.png
building/*.svg
.idea/
local.sh

View File

@ -49,6 +49,7 @@ struct TestWebsiteBuildScript {
"utf8.cpp",
"jsonobj.cpp",
"quality_of_life.cpp",
"quality_of_life_2.cpp",
"integer.cpp",
"inner_storage.cpp",
"generator.cpp",
@ -68,7 +69,7 @@ struct TestWebsiteBuildScript {
};
for (std::string& u: T.exported_headers)
u = "jsonincpp/" + u;
T.installation_dir = "json";
T.installation_dir = "";
my_targets.push_back(T);
}
if (make_tests) { CTarget T{"libjsonincpp_test0", "executable"};

View File

@ -24,8 +24,6 @@ namespace json {
}
Integer & Integer::operator=(const Integer &other) {
if (this == &other)
return *this;
value = other.value;
free(uncomprehendable_horror); uncomprehendable_horror = NULL;
copy_horror(*this, other.uncomprehendable_horror);

View File

@ -83,4 +83,12 @@ namespace json {
/* This is by far the most serious function I have ever written */
nullify(*this);
}
JSON_reference JSON::r() noexcept {
return {*this, {}};
}
JSON_reference_const JSON::r() const noexcept {
return {*this, false};
}
}

View File

@ -21,10 +21,13 @@ namespace json {
dictionary,
};
struct JSON;
enum imaginary_key_t {
undefined_array_element,
undefined_dictionary_element,
};
typedef std::vector<JSON> jarr;
typedef std::map<std::string, JSON> jdict;
struct JSON_reference;
struct JSON_reference_const;
struct JSON {
void* value = NULL;
@ -44,6 +47,10 @@ namespace json {
JSON& operator=(const JSON& other);
~JSON();
JSON_reference r() noexcept;
JSON_reference_const r() const noexcept;
json_t getType() const;
bool isNull() const;
@ -84,15 +91,58 @@ namespace json {
std::map<std::string, JSON>& asDictionary();
JSON& operator[](size_t index);
JSON& operator[](const std::string& key);
JSON_reference operator[](size_t index);
JSON_reference operator[](const std::string& key);
const JSON& operator[](size_t index) const;
const JSON& operator[](const std::string& key) const;
JSON_reference_const operator[](size_t index) const;
JSON_reference_const operator[](const std::string& key) const;
JSON& operator=(int64_t V);
JSON& operator=(const Integer& V);
JSON& operator=(const char* V);
JSON& operator=(const std::string& V);
bool operator==(const JSON& B) const;
bool operator!=(const JSON& B) const;
};
struct ImaginaryKeyChainEValue {
imaginary_key_t type;
/* Why messing with RAII-ing (int|string) value behind some void pointer when I can just include both.
* C'mon, bros, memory consumption issue does not exist */
size_t when_array_index;
std::string when_dictionary_key;
};
/* These references get invalidated as soon as referenced object or any of its parents get changed */
struct JSON_reference {
JSON& last_real;
std::vector<ImaginaryKeyChainEValue> imaginary_chain;
bool isDefined();
JSON& operator*();
JSON& g();
void operator=(const JSON& obj);
JSON_reference operator[](size_t index);
JSON_reference operator[](const std::string& key);
};
/* text */
struct JSON_reference_const {
const JSON& last_real;
bool bad = false;
bool isDefined();
const JSON& operator*();
const JSON& g();
JSON_reference_const operator[](size_t index);
JSON_reference_const operator[](const std::string& key);
};
}
#endif

View File

@ -165,7 +165,7 @@ namespace json {
skipWhitespaces(pctx);
int herald = peep(pctx);
if (herald == '"') {
result.asString() = demandStringJson(pctx);
result = demandStringJson(pctx);
} else if (isIntegerStart(herald)) {
size_t pos_beg = pctx.pos;
bool terrifying = false;
@ -175,16 +175,16 @@ namespace json {
read_int_int_part(pctx, mantis_abs_max18, terrifying);
read_int_frac_exp_part(pctx, terrifying);
if (terrifying) {
result.asInteger() = Integer(pctx.text.substr(pos_beg, pctx.pos).c_str());
result = Integer(pctx.text.substr(pos_beg, pctx.pos).c_str());
} else if (mantis_minus) {
result.asInteger() = Integer(-mantis_abs_max18);
result = -mantis_abs_max18;
} else {
result.asInteger() = Integer(mantis_abs_max18);
result = mantis_abs_max18;
}
} else if (isSymbolConstituent(herald)) {
std::string sym;
while (isSymbolConstituent(peep(pctx))) {
sym += (char)(uint8_t)peep(pctx);
sym += peep(pctx);
skip(pctx);
}
if (sym == "null") {

View File

@ -83,70 +83,66 @@ namespace json {
}
Integer & JSON::asInteger() {
if (isNull()) {
value = new Integer();
type = integer;
}
if (isInteger())
return const_cast<Integer&>(const_cast<const JSON*>(this)->asInteger());
throw misuse("JSON::asInteger() can't convert non-null to integer");
}
std::string &JSON::asString() {
if (isNull()) {
value = new std::string();
type = string;
}
if (isString())
return const_cast<std::string&>(const_cast<const JSON*>(this)->asString());
throw misuse("JSON::asString() can't convert non-null to string");
}
std::vector<JSON> &JSON::asArray() {
if (isNull()) {
value = new ArrayData();
type = array;
}
if (isArray())
return const_cast<std::vector<JSON>&>(const_cast<const JSON*>(this)->asArray());
throw misuse("JSON::asArray() can't convert non-null to array");
}
std::map<std::string, JSON> &JSON::asDictionary() {
if (isNull()) {
value = new DictionaryData();
type = dictionary;
}
if (isDictionary())
return const_cast<std::map<std::string, JSON>&>(const_cast<const JSON*>(this)->asDictionary());
throw misuse("JSON::asDictionary() can't convert non-null to dictionary");
}
JSON& JSON::operator[](size_t index) {
std::vector<JSON>& arr = asArray();
if (arr.size() <= index)
arr.resize(index + 1);
return arr[index];
JSON_reference JSON::operator[](size_t index) {
return r()[index];
}
JSON& JSON::operator[](const std::string &key) {
std::map<std::string, JSON>& dict = asDictionary();
return dict[key];
JSON_reference JSON::operator[](const std::string &key) {
return r()[key];
}
const JSON& JSON::operator[](size_t index) const {
if (!isArray() || asArray().size() <= index)
throw misuse("Index out of range");
return static_cast<ArrayData*>(value)->data[index];
JSON_reference_const JSON::operator[](size_t index) const {
return r()[index];
}
const JSON& JSON::operator[](const std::string &key) const {
if (!isDictionary() || asDictionary().count(key) != 1)
throw misuse("No such key");
return asDictionary().at(key);
JSON_reference_const JSON::operator[](const std::string &key) const {
return r()[key];
}
JSON& JSON::operator=(int64_t V) {
nullify(*this);
value = new Integer(V);
type = integer;
return *this;
}
JSON & JSON::operator=(const Integer &V) {
nullify(*this);
value = new Integer(V);
type = integer;
return *this;
}
JSON & JSON::operator=(const char *V) {
nullify(*this);
value = new std::string(V);
type = string;
return *this;
}
JSON & JSON::operator=(const std::string &V) {
nullify(*this);
value = new std::string(V);
type = string;
return *this;
}
bool JSON::operator==(const JSON &B) const {

View File

@ -0,0 +1,94 @@
#include "jsonobj.h"
namespace json {
bool JSON_reference::isDefined(){
return imaginary_chain.empty();
}
JSON& JSON_reference::operator*(){
return g();
}
JSON& patch_up(JSON_reference& ref) {
JSON* cur_last_real = &ref.last_real;
for (const auto& ck: ref.imaginary_chain) {
if (ck.type == undefined_array_element) {
if (cur_last_real->type == null_symbol)
*cur_last_real = JSON(array);
if (cur_last_real->type != array)
throw misuse("Implicit array creation on top of neither non-null nor short-array json obj is not allowed");
cur_last_real->asArray().resize(ck.when_array_index + 1);
cur_last_real = &cur_last_real->asArray()[ck.when_array_index];
} else {
if (cur_last_real->type == null_symbol)
*cur_last_real = JSON(dictionary);
if (cur_last_real->type != dictionary)
throw misuse("Implicit dictionary creation on top of neither non-null nor illiterate-dict json obj is not allowed");
cur_last_real = &(cur_last_real->asDictionary()[ck.when_dictionary_key]);
}
}
return *cur_last_real;
}
JSON & JSON_reference::g() {
return patch_up(*this);
}
void JSON_reference::operator=(const JSON &obj) {
patch_up(*this) = obj;
}
JSON_reference JSON_reference::operator[](size_t index) {
if (!imaginary_chain.empty()) {
std::vector<ImaginaryKeyChainEValue> elongated = imaginary_chain;
elongated.push_back({undefined_array_element, index, ""});
return {last_real, elongated};
}
if (last_real.isArray() && last_real.asArray().size() > index) {
return {last_real.asArray()[index], {}};
}
return {last_real, {ImaginaryKeyChainEValue{undefined_array_element, index, ""}}};
}
JSON_reference JSON_reference::operator[](const std::string &key) {
if (!imaginary_chain.empty()) {
std::vector<ImaginaryKeyChainEValue> elongated = imaginary_chain;
elongated.push_back({undefined_dictionary_element, 0, key});
return {last_real, elongated};
}
if (last_real.isDictionary() && last_real.asDictionary().count(key) > 0) {
return {last_real.asDictionary()[key], {}};
}
return {last_real, {ImaginaryKeyChainEValue{undefined_dictionary_element, 0, key}}};
}
bool JSON_reference_const::isDefined() {
return !bad;
}
const JSON & JSON_reference_const::operator*() {
return g();
}
const JSON & JSON_reference_const::g() {
if (bad)
throw misuse("dereferencing const json reference with non-empty imaginary part");
return last_real;
}
JSON_reference_const JSON_reference_const::operator[](size_t index) {
if (bad)
return {last_real, true};
if (last_real.isArray() && last_real.asArray().size() > index)
return {last_real.asArray()[index], false};
return {last_real, true};
}
JSON_reference_const JSON_reference_const::operator[](const std::string &key) {
if (bad)
return {last_real, true};
if (last_real.isDictionary() && last_real.asDictionary().count(key) > 0)
return {last_real.asDictionary().at(key), false};
return {last_real, true};
}
}

View File

@ -31,31 +31,15 @@ void test_obvious(const JSON& A) {
big[1] = A;
test(big, A, false);
big[0] = A;
test(big[0], big[1], true);
}
void ftest(int i) {
JSON A;
JSON B;
A["aaa"][(size_t)i]["bbb"].asArray().push_back(JSON(jarr{JSON("Hihi"), JSON("Haha")}));
A["aaa"][i]["bbb"][4]["hihi"].asInteger() = Integer(4123);
B.asDictionary()["aaa"][(size_t)i].asDictionary()["bbb"][0][0].asString() = "Hihi";
B.asDictionary()["aaa"][(size_t)i].asDictionary()["bbb"][0][1].asString() = "Haha";
B["aaa"].asArray()[i]["bbb"][4].asDictionary()["hihi"] = JSON(4123l);
prettyprint_json(A);
prettyprint_json(B);
test(A, B, true);
test(*big[0], *big[1], true);
}
int main() {
json::JSON A;
A[1].asString();
A[0].asInteger();
json::JSON B;
B[0].asInteger();
B[1].asString();
test(A, B, true);
return 0;
json::JSON cba;
cba["boba"] = json::JSON("<>");
printf("%s\n", generate_str(cba["boba"].g(), print_compact).c_str());
// return 0;
test_obvious(parse_str_flawless("{ \"aaa\": true, \"2\":[true]}"));
test_obvious(parse_str_flawless("{ \"aa\": true, \"tttt\": [true, false]}"));
test_obvious(parse_str_flawless("[[[]]]"));
@ -67,8 +51,5 @@ int main(){
test(parse_str_flawless("132123123123123123123123123123123123"), parse_str_flawless("132123123123123123123123123123123123"), true);
test(parse_str_flawless("{}"), parse_str_flawless("{}"), true);
test(parse_str_flawless("{}"), parse_str_flawless("true"), false);
for (int i = 0; i < 100; i += 10) {
ftest(i);
}
return 0;
}