#include "JSON.h" #include "Datei.h" using namespace Framework; using namespace JSON; #pragma region JSONValue JSONValue::JSONValue() : ReferenceCounter() { this->type = AbstractType::NULL_; } JSONValue::~JSONValue() {} JSONValue::JSONValue(AbstractType type) : ReferenceCounter() { this->type = type; } AbstractType JSONValue::getType() const { return type; } Text JSONValue::toString() const { return Text("null"); } JSONValue* JSONValue::clone() const { return new JSONValue(); } JSONBool* JSONValue::asBool() const { return (JSONBool*)this; } JSONNumber* JSONValue::asNumber() const { return (JSONNumber*)this; } JSONString* JSONValue::asString() const { return (JSONString*)this; } JSONArray* JSONValue::asArray() const { return (JSONArray*)this; } JSONObject* JSONValue::asObject() const { return (JSONObject*)this; } const AbstractBool* Framework::JSON::JSONValue::asAbstractBool() const { return dynamic_cast(this); } const AbstractNumber* Framework::JSON::JSONValue::asAbstractNumber() const { return dynamic_cast(this); } const AbstractString* Framework::JSON::JSONValue::asAbstractString() const { return dynamic_cast(this); } const AbstractArray* Framework::JSON::JSONValue::asAbstractArray() const { return dynamic_cast(this); } const AbstractObject* Framework::JSON::JSONValue::asAbstractObject() const { return dynamic_cast(this); } #pragma endregion Cotent #pragma region JSONBool JSONBool::JSONBool(bool b) : JSONValue(AbstractType::BOOLEAN) { this->b = b; } bool JSONBool::getBool() const { return b; } Text JSONBool::toString() const { if (b) return Text("true"); else return Text("false"); } JSONValue* JSONBool::clone() const { return new JSONBool(b); } #pragma endregion Cotent #pragma region JSONNumber JSONNumber::JSONNumber(double num) : JSONValue(AbstractType::NUMBER) { number = num; } double JSONNumber::getNumber() const { return number; } Text JSONNumber::toString() const { return Text(number); } JSONValue* JSONNumber::clone() const { return new JSONNumber(number); } #pragma endregion Cotent #pragma region JSONString JSONString::JSONString(Text string) : JSONValue(AbstractType::STRING) { this->string = string; this->string.ersetzen("\\\"", "\""); this->string.ersetzen("\\n", "\n"); } Text JSONString::getString() const { return string; } Text JSONString::toString() const { Text esc = string; esc.ersetzen("\"", "\\\""); esc.ersetzen("\n", "\\n"); return Text(Text("\"") += esc.getText()) += "\""; } JSONValue* JSONString::clone() const { Text esc = string; esc.ersetzen("\"", "\\\""); esc.ersetzen("\n", "\\n"); return new JSONString(esc); } #pragma endregion Cotent #pragma region JSONArray JSONArray::JSONArray() : JSONValue(AbstractType::ARRAY) { array = new RCArray(); } JSONArray::JSONArray(Text string) : JSONValue(AbstractType::ARRAY) { array = new RCArray(); string = Parser::removeWhitespace(string); if (string.getText()[0] == '[' && string.getText()[string.getLength() - 1] == ']') { string.remove(0, 1); string.remove(string.getLength() - 1, string.getLength()); while (string.getLength()) { int end = Parser::findObjectEndInArray(string); Text* objStr = string.getTeilText(0, end); string.remove(0, end + 1); array->add(Parser::getValue(*objStr)); objStr->release(); } } } JSONArray::JSONArray(const JSONArray& arr) : JSONValue(AbstractType::ARRAY) { array = dynamic_cast*>(arr.array->getThis()); } JSONArray::~JSONArray() { array->release(); } JSONArray& JSONArray::operator=(const JSONArray& arr) { array->release(); array = dynamic_cast*>(arr.array->getThis()); return *this; } void JSONArray::addValue(JSONValue* value) { array->add(value); } void JSONArray::setValue(int i, JSONValue* value) { array->set(value, i); } void JSONArray::removeValue(int i) { array->remove(i); } JSONValue* JSONArray::getValue(int i) const { return array->get(i); } JSONValue* JSONArray::zValue(int i) const { return array->z(i); } AbstractElement* JSONArray::zAbstractValue(int i) const { return zValue(i); } int JSONArray::getLength() const { return array->getEintragAnzahl(); } bool JSONArray::isValueOfType(int i, AbstractType type) const { return i >= 0 && i < array->getEintragAnzahl() && array->z(i)->getType() == type; } ArrayIterator JSONArray::begin() const { return array->begin(); } ArrayIterator JSONArray::end() const { return array->end(); } Text JSONArray::toString() const { Text str = "["; for (auto i = array->begin(); i; i++) { str += i->toString(); if (i.hasNext()) str += ","; } str += "]"; return str; } JSONValue* JSONArray::clone() const { JSONArray* arr = new JSONArray(); for (JSONValue* value : *this) { arr->addValue(value->clone()); } return arr; } #pragma endregion Cotent #pragma region JSONObject JSONObject::JSONObject() : JSONValue(AbstractType::OBJECT) { fields = new Array(); values = new RCArray(); } JSONObject::JSONObject(Text string) : JSONValue(AbstractType::OBJECT) { fields = new Array(); values = new RCArray(); string = Parser::removeWhitespace(string); if (string.getText()[0] == '{' && string.getText()[string.getLength() - 1] == '}') { string.remove(0, 1); string.remove(string.getLength() - 1, string.getLength()); while (string.getLength()) { int endField = Parser::findFieldEndInObject(string); Text* fieldName = string.getTeilText(0, endField); string.remove(0, endField + 1); fieldName->remove(0, 1); fieldName->remove( fieldName->getLength() - 1, fieldName->getLength()); int endValue = Parser::findValueEndInObject(string); Text* value = string.getTeilText(0, endValue); string.remove(0, endValue + 1); fields->add(Text(fieldName->getText())); values->add(Parser::getValue(*value)); fieldName->release(); value->release(); } } } JSONObject::JSONObject(const JSONObject& obj) : JSONValue(AbstractType::OBJECT) { fields = dynamic_cast*>(obj.fields->getThis()); values = dynamic_cast*>(obj.values->getThis()); } JSONObject::~JSONObject() { fields->release(); values->release(); } JSONObject& JSONObject::operator=(const JSONObject& obj) { fields->release(); values->release(); fields = dynamic_cast*>(obj.fields->getThis()); values = dynamic_cast*>(obj.values->getThis()); return *this; } bool JSONObject::addValue(Text field, JSONValue* value) { if (hasValue(field)) return 0; fields->add(field); values->add(value); return 1; } bool JSONObject::removeValue(Text field) { for (int i = 0; i < fields->getEintragAnzahl(); i++) { if (fields->get(i).istGleich(field)) { fields->remove(i); values->remove(i); return 1; } } return 0; } bool JSONObject::hasValue(Text field) const { return zValue(field); } JSONValue* JSONObject::getValue(Text field) const { for (int i = 0; i < fields->getEintragAnzahl(); i++) { if (fields->get(i).istGleich(field)) return values->get(i); } return 0; } JSONValue* JSONObject::zValue(Text field) const { for (int i = 0; i < fields->getEintragAnzahl(); i++) { if (fields->get(i).istGleich(field)) return values->z(i); } return 0; } AbstractElement* JSONObject::zAbstractValue(Text field) const { return zValue(field); } ArrayIterator JSONObject::getFields() { return fields->begin(); } ArrayIterator JSONObject::getValues() { return values->begin(); } Text Framework::JSON::JSONObject::getFieldKey(int i) const { return fields->get(i); } AbstractElement* Framework::JSON::JSONObject::zAbstractValue(int i) const { return values->z(i); } int JSONObject::getFieldCount() const { return fields->getEintragAnzahl(); } bool JSONObject::isValueOfType(Text field, AbstractType type) const { for (int i = 0; i < fields->getEintragAnzahl(); i++) { if (fields->get(i).istGleich(field)) return values->z(i)->getType() == type; } return 0; } Text JSONObject::toString() const { Text str = "{"; ArrayIterator k = fields->begin(); for (auto v = values->begin(); k && v; k++, v++) { str += "\""; str += k._.getText(); str += "\":"; str += v->toString().getText(); if (v.hasNext()) str += ","; } str += "}"; return str; } JSONValue* JSONObject::clone() const { JSONObject* obj = new JSONObject(); auto field = fields->begin(); auto value = values->begin(); for (; field && value; field++, value++) { obj->addValue(field.val(), value->clone()); } return obj; } #pragma endregion Cotent JSONValue* JSON::loadJSONFromFile(Text path) { Datei d; d.setDatei(path); if (!d.open(Datei::Style::lesen)) { return new JSONValue(); } int size = (int)d.getSize(); char* buffer = new char[size + 1]; buffer[size] = 0; d.lese(buffer, size); d.close(); JSONValue* result = Parser::getValue(buffer); delete[] buffer; return result; } #pragma region Parser int Parser::findObjectEndInArray(const char* str) { return findValueEndInObject(str); } Text Parser::removeWhitespace(const char* str) { int wsc = 0; int i = 0; bool esc = 0; bool strO = 0; for (; str[i]; i++) { switch (str[i]) { case '\\': if (strO) esc = !esc; else esc = 0; break; case '"': if (!esc) strO = !strO; esc = 0; break; case ' ': case '\n': case '\t': case '\r': if (!strO) wsc++; esc = 0; break; default: esc = 0; break; } } Text ret; i = 0; esc = 0; strO = 0; for (; str[i]; i++) { switch (str[i]) { case '\\': if (strO) esc = !esc; else esc = 0; ret.append(str[i]); break; case '"': if (!esc) strO = !strO; esc = 0; ret.append(str[i]); break; case ' ': case '\n': case '\t': case '\r': if (strO) ret.append(str[i]); esc = 0; break; default: ret.append(str[i]); esc = 0; break; } } return ret; } JSONValue* Parser::getValue(const char* str) { Text string = Parser::removeWhitespace(str); if (string.istGleich("true")) return new JSONBool(1); if (string.istGleich("false")) return new JSONBool(0); if (string.getText()[0] == '"') { string.remove(0, 1); string.remove(string.getLength() - 1, string.getLength()); return new JSONString(string); } if (string.getText()[0] == '[') return new JSONArray(string); if (string.getText()[0] == '{') return new JSONObject(string); if (Text((int)string).istGleich(string.getText())) return new JSONNumber((double)string); if (string.anzahlVon('.') == 1) { bool isNumber = 1; for (const char* c = (*string.getText() == '-') ? string.getText() + 1 : string.getText(); *c; c++) isNumber &= (*c >= '0' && *c <= '9') || *c == '.'; if (isNumber) return new JSONNumber((double)string); } return new JSONValue(); } int Parser::findFieldEndInObject(const char* str) { int i = 0; bool esc = 0; bool strO = 0; int objOc = 0; int arrayOc = 0; for (; str[i]; i++) { switch (str[i]) { case '\\': if (strO) esc = !esc; else esc = 0; break; case '"': if (!esc) strO = !strO; esc = 0; break; case '[': if (!strO) arrayOc++; esc = 0; break; case ']': if (!strO) arrayOc--; esc = 0; break; case '{': if (!strO) objOc++; esc = 0; break; case '}': if (!strO) objOc--; esc = 0; break; case ':': if (!strO && objOc == 0 && arrayOc == 0) return i; esc = 0; break; default: esc = 0; break; } } return i; } int Parser::findValueEndInObject(const char* str) { int i = 0; bool esc = 0; bool strO = 0; int objOc = 0; int arrayOc = 0; for (; str[i]; i++) { switch (str[i]) { case '\\': if (strO) esc = !esc; else esc = 0; break; case '"': if (!esc) strO = !strO; esc = 0; break; case '[': if (!strO) arrayOc++; esc = 0; break; case ']': if (!strO) arrayOc--; esc = 0; break; case '{': if (!strO) objOc++; esc = 0; break; case '}': if (!strO) objOc--; esc = 0; break; case ',': if (!strO && objOc == 0 && arrayOc == 0) return i; esc = 0; break; default: esc = 0; break; } } return i; } #pragma endregion Cotent