You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.3 KiB
163 lines
5.3 KiB
/** |
|
* JSON is an open standard file format, and data interchange format, |
|
* that uses human-readable text to store and transmit data objects |
|
* consisting of name–value pairs and array data types. |
|
* For more information refer to https://en.wikipedia.org/wiki/JSON |
|
* This is a base class for implementation of JSON data storage for Acedia. |
|
* It does not implement parsing and printing from/into human-readable |
|
* text representation, just provides means to store such information. |
|
* |
|
* JSON data is stored as an object (represented via `JSONObject`) that |
|
* contains a set of name-value pairs, where value can be |
|
* a number, string, boolean value, another object or |
|
* an array (represented by `JSONArray`). |
|
* Copyright 2020 Anton Tarasenko |
|
*------------------------------------------------------------------------------ |
|
* This file is part of Acedia. |
|
* |
|
* Acedia is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* Acedia is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
|
*/ |
|
class JSON extends AcediaActor |
|
abstract; |
|
|
|
// Enumeration for possible types of JSON values. |
|
enum JType |
|
{ |
|
// Technical type, used to indicate that requested value is missing. |
|
// Undefined values are not part of JSON format. |
|
JSON_Undefined, |
|
// An empty value, in teste representation defined by a single word "null". |
|
JSON_Null, |
|
// A number, recorded as a float. |
|
// JSON itself doesn't specify whether number is an integer or float. |
|
JSON_Number, |
|
// A string. |
|
JSON_String, |
|
// A bool value. |
|
JSON_Boolean, |
|
// Array of other JSON values, stored without names; |
|
// Single array can contain any mix of value types. |
|
JSON_Array, |
|
// Another JSON object, i.e. associative array of name-value pairs |
|
JSON_Object |
|
}; |
|
|
|
// Stores a single JSON value |
|
struct JStorageAtom |
|
{ |
|
// What type is stored exactly? |
|
// Depending on that, uses one of the other fields as a storage. |
|
var protected JType type; |
|
var protected float numberValue; |
|
var protected string stringValue; |
|
var protected bool booleanValue; |
|
// Used for storing both JSON objects and arrays. |
|
var protected JSON complexValue; |
|
// Numeric value might not fit into a `float` very well, so we will store |
|
// them as both `float` and `integer` and allow user to request any version |
|
// of them |
|
var protected int numberValueAsInt; |
|
// Some `string` values might be actually used to represent classes, |
|
// so we will give users an ability to request `string` value as a class. |
|
var protected class<Object> stringValueAsClass; |
|
// To avoid several unsuccessful attempts to load `class` object from |
|
// a `string`, we will record whether we've already tied that. |
|
var protected bool classLoadingWasAttempted; |
|
}; |
|
|
|
enum JComparisonResult |
|
{ |
|
JCR_Incomparable, |
|
JCR_SubSet, |
|
JCR_Overset, |
|
JCR_Equal |
|
}; |
|
|
|
public function JSON Clone() |
|
{ |
|
return none; |
|
} |
|
|
|
public function bool IsSubsetOf(JSON rightJSON) |
|
{ |
|
return false; |
|
} |
|
|
|
public final function JComparisonResult Compare(JSON rightJSON) |
|
{ |
|
local bool firstIsSubset, secondIsSubset; |
|
if (rightJSON == none) return JCR_Incomparable; |
|
firstIsSubset = IsSubsetOf(rightJSON); |
|
secondIsSubset = rightJSON.IsSubsetOf(self); |
|
if (firstIsSubset) |
|
{ |
|
if (secondIsSubset) { |
|
return JCR_Equal; |
|
} |
|
else { |
|
return JCR_SubSet; |
|
} |
|
} |
|
else { |
|
if (secondIsSubset) { |
|
return JCR_Overset; |
|
} |
|
else { |
|
return JCR_Incomparable; |
|
} |
|
} |
|
} |
|
|
|
public final function bool IsEqual(JSON rightJSON) |
|
{ |
|
return (Compare(rightJSON) == JCR_Equal); |
|
} |
|
|
|
protected final function bool AreAtomsEqual( |
|
JStorageAtom atom1, |
|
JStorageAtom atom2) |
|
{ |
|
if (atom1.type != atom2.type) return false; |
|
if (atom1.type == JSON_Undefined) return true; |
|
if (atom1.type == JSON_Null) return true; |
|
if (atom1.type == JSON_Number) { |
|
return ( atom1.numberValue == atom2.numberValue |
|
&& atom1.numberValueAsInt == atom2.numberValueAsInt); |
|
} |
|
if (atom1.type == JSON_Boolean) { |
|
return (atom1.booleanValue == atom2.booleanValue); |
|
} |
|
if (atom1.type == JSON_String) { |
|
return (atom1.stringValue == atom2.stringValue); |
|
} |
|
if (atom1.complexValue == none && atom2.complexValue == none) { |
|
return true; |
|
} |
|
if (atom1.complexValue == none || atom2.complexValue == none) { |
|
return false; |
|
} |
|
return atom1.complexValue.IsEqual(atom2.complexValue); |
|
} |
|
|
|
protected final function TryLoadingStringAsClass(out JStorageAtom atom) |
|
{ |
|
if (atom.classLoadingWasAttempted) return; |
|
atom.classLoadingWasAttempted = true; |
|
atom.stringValueAsClass = |
|
class<Object>(DynamicLoadObject(atom.stringValue, class'Class', true)); |
|
} |
|
|
|
defaultproperties |
|
{ |
|
} |