#include "JSON.h" #include "Datei.h" using namespace Framework; using namespace JSON; JSONValue::JSONValue() : ReferenceCounter() { this->type = NULL_; } JSONValue::~JSONValue() {} JSONValue::JSONValue( JSONType type ) : ReferenceCounter() { this->type = type; } JSONType JSONValue::getType() const { return type; } Text JSONValue::toString() const { return Text( "null" ); } JSONBool::JSONBool( bool b ) : JSONValue( BOOLEAN ) { this->b = b; } bool JSONBool::getBool() const { return b; } Text JSONBool::toString() const { if( b ) return Text( "true" ); else return Text( "false" ); } JSONNumber::JSONNumber( double num ) : JSONValue( NUMBER ) { number = num; } double JSONNumber::getNumber() const { return number; } Text JSONNumber::toString() const { return Text( number ); } JSONString::JSONString( Text string ) : JSONValue( STRING ) { this->string = string; } Text JSONString::getString() const { return string; } Text JSONString::toString() const { return Text( Text( "\"" ) += string.getText() ) += "\""; } JSONArray::JSONArray() : JSONValue( ARRAY ) { array = new RCArray< JSONValue >(); } JSONArray::JSONArray( Text string ) : JSONValue( ARRAY ) { array = new RCArray< JSONValue >(); 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( ARRAY ) { array = ( RCArray* )arr.array->getThis(); } JSONArray::~JSONArray() { array->release(); } JSONArray &JSONArray::operator=( const JSONArray &arr ) { array->release(); array = ( RCArray* )arr.array->getThis(); return *this; } void JSONArray::addValue( JSONValue *value ) { array->add( value ); } JSONValue *JSONArray::getValue( int i ) const { return array->get( i ); } int JSONArray::getLength() const { return array->getEintragAnzahl(); } Text JSONArray::toString() const { Text str = "["; for( auto i = array->getIterator(); i; i++ ) { str += i->toString(); if( i.hasNext() ) str += ","; } str += "]"; return str; } JSONObject::JSONObject() : JSONValue( OBJECT ) { fields = new Array< Text >(); values = new RCArray< JSONValue >(); } JSONObject::JSONObject( Text string ) : JSONValue( OBJECT ) { fields = new Array< Text >(); values = new RCArray< JSONValue >(); 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( OBJECT ) { fields = ( Array* )obj.fields->getThis(); values = ( RCArray* )obj.values->getThis(); } JSONObject::~JSONObject() { fields->release(); values->release(); } JSONObject &JSONObject::operator=( const JSONObject &obj ) { fields->release(); values->release(); fields = ( Array* )obj.fields->getThis(); values = ( RCArray* )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 ) { for( int i = 0; i < fields->getEintragAnzahl(); i++ ) { if( fields->get( i ).istGleich( field ) ) return 1; } return 0; } JSONValue *JSONObject::getValue( Text field ) { for( int i = 0; i < fields->getEintragAnzahl(); i++ ) { if( fields->get( i ).istGleich( field ) ) return values->get( i ); } return new JSONValue(); } Iterator< Text > JSONObject::getFields() { return fields->getIterator(); } Iterator< JSONValue * > JSONObject::getValues() { return values->getIterator(); } int JSONObject::getFieldCount() const { return fields->getEintragAnzahl(); } Text JSONObject::toString() const { Text str = "{"; Iterator< Text > k = fields->getIterator(); for( auto v = values->getIterator(); k && v; k++, v++ ) { str += "\""; str += k._.getText(); str += "\":"; str += v->toString().getText(); if( v.hasNext() ) str += ","; } str += "}"; return str; } JSONValue *JSON::loadJSONFromFile( Text path ) { Datei d; d.setDatei( path ); d.open( Datei::Style::lesen ); 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; } 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; ret.fillText( ' ', i - wsc ); i = 0; esc = 0; strO = 0; int index = 0; for( ; str[ i ]; i++ ) { switch( str[ i ] ) { case '\\': if( strO ) esc = !esc; else esc = 0; ret.getText()[ index++ ] = str[ i ]; break; case '"': if( !esc ) strO = !strO; esc = 0; ret.getText()[ index++ ] = str[ i ]; break; case ' ': case '\n': case '\t': case '\r': if( strO ) ret.getText()[ index++ ] = str[ i ]; esc = 0; break; default: ret.getText()[ index++ ] = 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( string ); if( string.anzahlVon( '.' ) == 1 ) { bool isNumber = 1; for( char *c = ( *string.getText() == '-' ) ? string.getText() + 1 : string.getText(); *c; c++ ) isNumber &= ( *c >= '0' && *c <= '9' ) || *c == '.'; if( isNumber ) return new JSONNumber( 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; }