|
|
|
@ -5,7 +5,7 @@
|
|
|
|
|
* Path "/a/b/c" will be stored as a sequence of components "a", "b" and "c", |
|
|
|
|
* path "/" will be stored as a singular empty component "" |
|
|
|
|
* and empty path "" would mean that there is not components at all. |
|
|
|
|
* Copyright 2021 Anton Tarasenko |
|
|
|
|
* Copyright 2021-2023 Anton Tarasenko |
|
|
|
|
*------------------------------------------------------------------------------ |
|
|
|
|
* This file is part of Acedia. |
|
|
|
|
* |
|
|
|
@ -293,6 +293,30 @@ public final function int GetNumericComponent(int index)
|
|
|
|
|
return components[index].asNumber; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks whether component at given index can be used to index array. |
|
|
|
|
* |
|
|
|
|
* This method accepts numeric components plus component equal to "-", that can |
|
|
|
|
* be used to point at the element after the last on in the `JSONArray`. |
|
|
|
|
* |
|
|
|
|
* @param index Index of the component to check. |
|
|
|
|
* @param `true` if component with given index exists and it either positive |
|
|
|
|
* number or "-". |
|
|
|
|
*/ |
|
|
|
|
public final function bool IsComponentArrayApplicable(int index) |
|
|
|
|
{ |
|
|
|
|
local bool isAddElementAlias; |
|
|
|
|
local Text component; |
|
|
|
|
|
|
|
|
|
if (GetNumericComponent(index) >= 0) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
component = GetComponent(index); |
|
|
|
|
isAddElementAlias = P("-").IsEqual(component); |
|
|
|
|
_.memory.Free(component); |
|
|
|
|
return isAddElementAlias; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Converts caller `JSONPointer` into it's `Text` representation. |
|
|
|
|
* |
|
|
|
@ -418,6 +442,85 @@ public final function JSONPointer Copy(
|
|
|
|
|
return newPointer; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Appends path, contained in JSON pointer `other` to the caller JSON pointer. |
|
|
|
|
* Appending "/A/B/7/C" to "/object/hey/1/there/" produces |
|
|
|
|
* "/object/hey/1/there//A/B/7/C". |
|
|
|
|
* |
|
|
|
|
* @param other Pointer to append. If `none` - caller `JSONPointer` will |
|
|
|
|
* not change. |
|
|
|
|
* @return Reference to the caller `JSONPointer` to allow for method chaining. |
|
|
|
|
*/ |
|
|
|
|
public final function JSONPointer Append(JSONPointer other) |
|
|
|
|
{ |
|
|
|
|
local int i; |
|
|
|
|
local array<Component> otherComponents; |
|
|
|
|
|
|
|
|
|
if (other == none) { |
|
|
|
|
return self; |
|
|
|
|
} |
|
|
|
|
otherComponents = other.components; |
|
|
|
|
for (i = 0; i < otherComponents.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
if (otherComponents[i].asText != none) { |
|
|
|
|
otherComponents[i].asText = otherComponents[i].asText.MutableCopy(); |
|
|
|
|
} |
|
|
|
|
components[components.length] = otherComponents[i]; |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks if given pointer corresponds with the beginning of the caller one. |
|
|
|
|
* |
|
|
|
|
* Pointer starts with another one if it includes all of its fields from |
|
|
|
|
* the beginning and in order |
|
|
|
|
* E.g. "/A/B/C" starts with "/A/B", but not with "/A/B/C/D", "/D/A/B/C" or |
|
|
|
|
* "/A/B/CD". |
|
|
|
|
* |
|
|
|
|
* @param other Candidate into being caller pointer's prefix. |
|
|
|
|
* @return `true` if `other` is prefix and `false` otherwise. `none` is |
|
|
|
|
* considered to be an empty pointer and, therefore, prefix to any other |
|
|
|
|
* pointer. |
|
|
|
|
*/ |
|
|
|
|
public final function bool StartsWith(JSONPointer other) |
|
|
|
|
{ |
|
|
|
|
local int i; |
|
|
|
|
local array<Component> otherComponents; |
|
|
|
|
|
|
|
|
|
// `none` is same as empty |
|
|
|
|
if (other == none) return true; |
|
|
|
|
otherComponents = other.components; |
|
|
|
|
// Not enough length |
|
|
|
|
if (components.length < otherComponents.length) return false; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < otherComponents.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
// Compare numeric components if at least one is such |
|
|
|
|
if ( components[i].testedForBeingNumeric |
|
|
|
|
|| otherComponents[i].testedForBeingNumeric) |
|
|
|
|
{ |
|
|
|
|
if (GetNumericComponent(i) != other.GetNumericComponent(i)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
// End this iteration for numeric component, but continue for |
|
|
|
|
// text ones |
|
|
|
|
if (GetNumericComponent(i) >= 0) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// We can reach here if: |
|
|
|
|
// 1. Neither components have `testedForBeingNumeric` set to |
|
|
|
|
// `true`, neither `asText` fields are `none` by the invariant; |
|
|
|
|
// 2. At least one had `testedForBeingNumeric`, but they tested |
|
|
|
|
// negative for being numeric. |
|
|
|
|
if (!components[i].asText.Compare(otherComponents[i].asText)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
defaultproperties |
|
|
|
|
{ |
|
|
|
|
TSLASH = 0 |
|
|
|
|