VPN-Check: update
This commit is contained in:
parent
a5bc964a81
commit
6ad1e603c0
430
VPN-Check/scripting/include/json.inc
Normal file
430
VPN-Check/scripting/include/json.inc
Normal file
@ -0,0 +1,430 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* sm-json
|
||||
* Provides a pure SourcePawn implementation of JSON encoding and decoding.
|
||||
* https://github.com/clugg/sm-json
|
||||
*
|
||||
* sm-json (C)2018 James Dickens. (clug)
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#if defined _json_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _json_included
|
||||
|
||||
#include <string>
|
||||
#include <json/definitions>
|
||||
#include <json/string_helpers>
|
||||
#include <json/encode_helpers>
|
||||
#include <json/decode_helpers>
|
||||
#include <json/object>
|
||||
|
||||
/**
|
||||
* Encodes a JSON_Object into its string representation.
|
||||
*
|
||||
* @param obj Object to encode.
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param pretty_print Should the output be pretty printed (newlines and spaces)? [optional, default: false]
|
||||
* @param depth The current depth of the encoder. [optional, default: 0]
|
||||
*/
|
||||
stock void json_encode(JSON_Object obj, char[] output, int maxlen, bool pretty_print = false, int depth = 0) {
|
||||
bool is_array = obj.IsArray;
|
||||
bool is_empty = true;
|
||||
int builder_size;
|
||||
|
||||
// used in key iterator
|
||||
int str_length = 1;
|
||||
int int_value;
|
||||
int cell_length = 0;
|
||||
|
||||
strcopy(output, maxlen, (is_array) ? "[" : "{");
|
||||
|
||||
StringMapSnapshot snap = obj.Snapshot();
|
||||
int key_length = 0;
|
||||
for (int i = 0; i < obj.Length; ++i) {
|
||||
key_length = snap.KeyBufferSize(i);
|
||||
char[] key = new char[key_length];
|
||||
|
||||
if (is_array) {
|
||||
obj.GetIndexString(key, key_length, i);
|
||||
} else {
|
||||
snap.GetKey(i, key, key_length);
|
||||
}
|
||||
|
||||
// skip meta-keys
|
||||
if (json_is_meta_key(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip keys that are marked as hidden
|
||||
if (obj.GetKeyHidden(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip keys of unknown type
|
||||
JSON_CELL_TYPE type = obj.GetKeyType(key);
|
||||
if (type == Type_Invalid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we are dealing with a string, prepare the str_value variable for fetching
|
||||
if (type == Type_String) {
|
||||
str_length = obj.GetKeyLength(key);
|
||||
}
|
||||
char[] str_value = new char[str_length + 1];
|
||||
|
||||
// determine the length of the char[] needed to represent our cell data
|
||||
cell_length = 0;
|
||||
switch (type) {
|
||||
case Type_String: {
|
||||
// get the string value early, as its cell_length is determined by its contents
|
||||
obj.GetString(key, str_value, str_length + 1);
|
||||
cell_length = json_cell_string_size(str_length);
|
||||
}
|
||||
case Type_Int: {
|
||||
// get the int value early, as its cell_length is determined by its contents
|
||||
int_value = obj.GetInt(key);
|
||||
cell_length = json_cell_int_size(int_value);
|
||||
}
|
||||
case Type_Float: {
|
||||
cell_length = json_cell_float_size();
|
||||
}
|
||||
case Type_Bool: {
|
||||
cell_length = json_cell_bool_size();
|
||||
}
|
||||
case Type_Null: {
|
||||
cell_length = json_cell_null_size();
|
||||
}
|
||||
case Type_Object: {
|
||||
cell_length = maxlen;
|
||||
}
|
||||
}
|
||||
|
||||
// fit the contents into the cell
|
||||
char[] cell = new char[cell_length];
|
||||
switch (type) {
|
||||
case Type_String: {
|
||||
json_cell_string(str_value, cell, cell_length);
|
||||
}
|
||||
case Type_Int: {
|
||||
json_cell_int(int_value, cell, cell_length);
|
||||
}
|
||||
case Type_Float: {
|
||||
float value = obj.GetFloat(key);
|
||||
json_cell_float(value, cell, cell_length);
|
||||
}
|
||||
case Type_Bool: {
|
||||
bool value = obj.GetBool(key);
|
||||
json_cell_bool(value, cell, cell_length);
|
||||
}
|
||||
case Type_Null: {
|
||||
json_cell_null(cell, cell_length);
|
||||
}
|
||||
case Type_Object: {
|
||||
JSON_Object value = obj.GetObject(key);
|
||||
json_encode(value, cell, cell_length, pretty_print, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// make the builder fit our key:value
|
||||
builder_size = cell_length + 1; // use previously determined cell length and +1 for comma
|
||||
if (!is_array) {
|
||||
builder_size += json_cell_string_size(strlen(key)) + 1; // get the length of the key, +1 for :
|
||||
}
|
||||
|
||||
if (pretty_print && !is_array) {
|
||||
// 1 space after colon
|
||||
builder_size += strlen(JSON_PP_AFTER_COLON);
|
||||
}
|
||||
|
||||
char[] builder = new char[builder_size];
|
||||
strcopy(builder, builder_size, "");
|
||||
// add the key if it's an object
|
||||
if (!is_array) {
|
||||
json_cell_string(key, builder, builder_size);
|
||||
StrCat(builder, builder_size, ":");
|
||||
if (pretty_print) {
|
||||
StrCat(builder, builder_size, JSON_PP_AFTER_COLON);
|
||||
}
|
||||
}
|
||||
|
||||
// add the value and a trailing comma
|
||||
StrCat(builder, builder_size, cell);
|
||||
StrCat(builder, builder_size, ",");
|
||||
|
||||
if (pretty_print) {
|
||||
StrCat(output, maxlen, JSON_PP_NEWLINE);
|
||||
for (int j = 0; j < depth + 1; ++j) {
|
||||
StrCat(output, maxlen, JSON_PP_INDENT);
|
||||
}
|
||||
}
|
||||
|
||||
// send builder to output
|
||||
StrCat(output, maxlen, builder);
|
||||
|
||||
is_empty = false;
|
||||
}
|
||||
|
||||
delete snap;
|
||||
|
||||
if (!is_empty) {
|
||||
// remove the final comma
|
||||
output[strlen(output) - 1] = '\0';
|
||||
}
|
||||
|
||||
if (pretty_print) {
|
||||
StrCat(output, maxlen, JSON_PP_NEWLINE);
|
||||
}
|
||||
|
||||
if (pretty_print) {
|
||||
for (int j = 0; j < depth; ++j) {
|
||||
StrCat(output, maxlen, JSON_PP_INDENT);
|
||||
}
|
||||
}
|
||||
|
||||
// append closing bracket
|
||||
StrCat(output, maxlen, (is_array) ? "]" : "}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a JSON string into its JSON_Object representation.
|
||||
*
|
||||
* @param buffer Buffer to decode.
|
||||
* @param result Object to store output in. Setting this allows loading over an existing JSON_Object, 'refreshing' it as opposed to creating a new one. [optional, default: null]
|
||||
* @param pos Current position of the decoder as a bytes offset into the buffer.
|
||||
* @param depth Current depth of the decoder as child elements in the object.
|
||||
* @returns JSON_Object representation of buffer, or null if decoding failed (buffer didn't contain valid JSON).
|
||||
*/
|
||||
stock JSON_Object json_decode(const char[] buffer, JSON_Object result = null, int &pos = 0, int depth = 0) {
|
||||
int length = strlen(buffer);
|
||||
bool is_array = false;
|
||||
|
||||
// skip preceding whitespace
|
||||
if (!json_skip_whitespace(buffer, length, pos)) {
|
||||
//LogError("json_decode: buffer ended early at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (json_is_object(buffer[pos])) {
|
||||
is_array = false;
|
||||
} else if (json_is_array(buffer[pos])) {
|
||||
is_array = true;
|
||||
} else {
|
||||
//LogError("json_decode: character not identified as object or array at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
result = new JSON_Object(is_array);
|
||||
}
|
||||
|
||||
bool empty_checked = false;
|
||||
char[] key = new char[length];
|
||||
char[] cell = new char[length];
|
||||
|
||||
// while we haven't reached the end of our structure
|
||||
while ((!is_array && !json_is_object_end(buffer[pos]))
|
||||
|| (is_array && !json_is_array_end(buffer[pos]))) {
|
||||
// pos is either an opening structure or comma, so increment past it
|
||||
++pos;
|
||||
|
||||
// if we are at the end of an object or array
|
||||
// and haven't checked for empty yet, we can stop here (empty structure)
|
||||
if (((!is_array && json_is_object_end(buffer[pos]))
|
||||
|| (is_array && json_is_array_end(buffer[pos])))
|
||||
&& !empty_checked) {
|
||||
break;
|
||||
}
|
||||
|
||||
empty_checked = true;
|
||||
|
||||
// skip any whitespace preceding the element
|
||||
if (!json_skip_whitespace(buffer, length, pos)) {
|
||||
//LogError("json_decode: buffer ended early at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
// if dealing with an object, look for the key
|
||||
if (!is_array) {
|
||||
if (!json_is_string(buffer[pos])) {
|
||||
//LogError("json_decode: expected key string at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
// extract the key from the buffer
|
||||
json_extract_string(buffer, length, pos, key, length, is_array);
|
||||
|
||||
// skip any whitespace following the key
|
||||
if (!json_skip_whitespace(buffer, length, pos)) {
|
||||
//LogError("json_decode: buffer ended early at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
// ensure that we find a colon
|
||||
if (buffer[pos++] != ':') {
|
||||
//LogError("json_decode: expected colon after key at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
// skip any whitespace following the colon
|
||||
if (!json_skip_whitespace(buffer, length, pos)) {
|
||||
//LogError("json_decode: buffer ended early at %d", pos);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (json_is_object(buffer[pos]) || json_is_array(buffer[pos])) {
|
||||
// if we are dealing with an object or array
|
||||
// fetch the existing object if one exists at the key
|
||||
JSON_Object current = (!is_array) ? result.GetObject(key) : null;
|
||||
|
||||
// decode recursively
|
||||
JSON_Object value = json_decode(buffer, current, pos, depth + 1);
|
||||
|
||||
// decoding failed, error will be logged in json_decode
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_array) {
|
||||
result.PushObject(value);
|
||||
} else {
|
||||
result.SetObject(key, value);
|
||||
}
|
||||
} else if (json_is_string(buffer[pos])) {
|
||||
// if we are dealing with a string, attempt to extract it
|
||||
if (!json_extract_string(buffer, length, pos, cell, length, is_array)) {
|
||||
//LogError("json_decode: couldn't extract string at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_array) {
|
||||
result.PushString(cell);
|
||||
} else {
|
||||
result.SetString(key, cell);
|
||||
}
|
||||
} else {
|
||||
if (!json_extract_until_end(buffer, length, pos, cell, length, is_array)) {
|
||||
//LogError("json_decode: couldn't extract until end at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (strlen(cell) == 0) {
|
||||
//LogError("json_decode: empty cell encountered at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (json_is_int(cell)) {
|
||||
int value = json_extract_int(cell);
|
||||
if (is_array) {
|
||||
result.PushInt(value);
|
||||
} else {
|
||||
result.SetInt(key, value);
|
||||
}
|
||||
} else if (json_is_float(cell)) {
|
||||
float value = json_extract_float(cell);
|
||||
if (is_array) {
|
||||
result.PushFloat(value);
|
||||
} else {
|
||||
result.SetFloat(key, value);
|
||||
}
|
||||
} else if (json_is_bool(cell)) {
|
||||
bool value = json_extract_bool(cell);
|
||||
if (is_array) {
|
||||
result.PushBool(value);
|
||||
} else {
|
||||
result.SetBool(key, value);
|
||||
}
|
||||
} else if (json_is_null(cell)) {
|
||||
if (is_array) {
|
||||
result.PushHandle(null);
|
||||
} else {
|
||||
result.SetHandle(key, null);
|
||||
}
|
||||
} else {
|
||||
//LogError("json_decode: unknown type encountered at %d: %s", pos, cell);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!json_skip_whitespace(buffer, length, pos)) {
|
||||
//LogError("json_decode: buffer ended early at %d", pos);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// skip remaining whitespace and ensure we're at the end of the buffer
|
||||
++pos;
|
||||
if (json_skip_whitespace(buffer, length, pos) && depth == 0) {
|
||||
//LogError("json_decode: unexpected data after end of structure at %d", pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively cleans up JSON_Objects and any objects referenced within.
|
||||
*
|
||||
* @param obj JSON_Object to clean up.
|
||||
*/
|
||||
void json_cleanup(JSON_Object obj) {
|
||||
bool is_array = obj.IsArray;
|
||||
|
||||
int key_length = 0;
|
||||
StringMapSnapshot snap = obj.Snapshot();
|
||||
for (int i = 0; i < snap.Length; ++i) {
|
||||
key_length = snap.KeyBufferSize(i);
|
||||
char[] key = new char[key_length];
|
||||
|
||||
// ignore meta keys
|
||||
snap.GetKey(i, key, key_length);
|
||||
if (json_is_meta_key(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only clean up objects
|
||||
JSON_CELL_TYPE type = obj.GetKeyType(key);
|
||||
if (type != Type_Object) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSON_Object nested_obj = obj.GetObject(key);
|
||||
if (nested_obj != null) {
|
||||
nested_obj.Cleanup();
|
||||
delete nested_obj;
|
||||
}
|
||||
}
|
||||
|
||||
obj.Clear();
|
||||
delete snap;
|
||||
|
||||
if (is_array) {
|
||||
obj.SetValue(JSON_ARRAY_INDEX_KEY, 0);
|
||||
}
|
||||
}
|
453
VPN-Check/scripting/include/json/decode_helpers.inc
Normal file
453
VPN-Check/scripting/include/json/decode_helpers.inc
Normal file
@ -0,0 +1,453 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* sm-json
|
||||
* Provides a pure SourcePawn implementation of JSON encoding and decoding.
|
||||
* https://github.com/clugg/sm-json
|
||||
*
|
||||
* sm-json (C)2018 James Dickens. (clug)
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#if defined _json_decode_helpers_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _json_decode_helpers_included
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @section Analysing format of incoming JSON cells.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks whether the character at the given
|
||||
* position in the buffer is whitespace.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @param pos Position to check in buffer.
|
||||
* @returns True if buffer[pos] is whitespace, false otherwise.
|
||||
*/
|
||||
stock bool json_is_whitespace(const char[] buffer, int &pos) {
|
||||
return buffer[pos] == ' '
|
||||
|| buffer[pos] == '\t'
|
||||
|| buffer[pos] == '\r'
|
||||
|| buffer[pos] == '\n';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the character at the beginning
|
||||
* of the buffer is the start of a string.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer[0] is the start of a string, false otherwise.
|
||||
*/
|
||||
stock bool json_is_string(const char[] buffer) {
|
||||
return buffer[0] == '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the buffer provided contains an int.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer contains an int, false otherwise.
|
||||
*/
|
||||
stock bool json_is_int(const char[] buffer) {
|
||||
bool starts_with_zero = false;
|
||||
bool has_digit_gt_zero = false;
|
||||
|
||||
int length = strlen(buffer);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
// allow minus as first character only
|
||||
if (i == 0 && buffer[i] == '-') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsCharNumeric(buffer[i])) {
|
||||
if (buffer[i] == '0') {
|
||||
if (starts_with_zero) {
|
||||
// detect repeating leading zeros
|
||||
return false;
|
||||
} else if (!has_digit_gt_zero) {
|
||||
starts_with_zero = true;
|
||||
}
|
||||
} else {
|
||||
has_digit_gt_zero = true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// buffer must start with zero and have no other numerics before decimal
|
||||
// OR not start with zero and have other numerics
|
||||
return ((starts_with_zero && !has_digit_gt_zero) || (!starts_with_zero && has_digit_gt_zero));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the buffer provided contains a float.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer contains a float, false otherwise.
|
||||
*/
|
||||
stock bool json_is_float(const char[] buffer) {
|
||||
bool starts_with_zero = false;
|
||||
bool has_digit_gt_zero = false;
|
||||
bool after_decimal = false;
|
||||
bool has_digit_after_decimal = false;
|
||||
bool after_exponent = false;
|
||||
bool has_digit_after_exponent = false;
|
||||
|
||||
int length = strlen(buffer);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
// allow minus as first character only
|
||||
if (i == 0 && buffer[i] == '-') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we haven't encountered a decimal or exponent yet
|
||||
if (!after_decimal && !after_exponent) {
|
||||
if (buffer[i] == '.') {
|
||||
// if we encounter a decimal before any digits
|
||||
if (!starts_with_zero && !has_digit_gt_zero) {
|
||||
return false;
|
||||
}
|
||||
|
||||
after_decimal = true;
|
||||
} else if (buffer[i] == 'e' || buffer[i] == 'E') {
|
||||
// if we encounter an exponent before any non-zero digits
|
||||
if (starts_with_zero && !has_digit_gt_zero) {
|
||||
return false;
|
||||
}
|
||||
|
||||
after_exponent = true;
|
||||
} else if (IsCharNumeric(buffer[i])) {
|
||||
if (buffer[i] == '0') {
|
||||
if (starts_with_zero) {
|
||||
// detect repeating leading zeros
|
||||
return false;
|
||||
} else if (!has_digit_gt_zero) {
|
||||
starts_with_zero = true;
|
||||
}
|
||||
} else {
|
||||
has_digit_gt_zero = true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (after_decimal && !after_exponent) {
|
||||
// after decimal has been encountered, allow any numerics
|
||||
if (IsCharNumeric(buffer[i])) {
|
||||
has_digit_after_decimal = true;
|
||||
} else if (buffer[i] == 'e' || buffer[i] == 'E') {
|
||||
if (!has_digit_after_decimal) {
|
||||
// detect exponents directly after decimal
|
||||
return false;
|
||||
}
|
||||
|
||||
after_exponent = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (after_exponent) {
|
||||
if ((buffer[i] == '+' || buffer[i] == '-') && (buffer[i - 1] == 'e' || buffer[i - 1] == 'E')) {
|
||||
// allow + or - directly after exponent
|
||||
continue;
|
||||
} else if (IsCharNumeric(buffer[i])) {
|
||||
has_digit_after_exponent = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (starts_with_zero && has_digit_gt_zero) {
|
||||
// if buffer starts with zero, there should be no other digits before the decimal
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we have a decimal, there should be digit(s) after it
|
||||
if (after_decimal) {
|
||||
if (!has_digit_after_decimal) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have an exponent, there should be digit(s) after it
|
||||
if (after_exponent) {
|
||||
if (!has_digit_after_exponent) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we should have reached an exponent, decimal or both
|
||||
// otherwise, this number can be handled by the int parser
|
||||
return after_decimal || after_exponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the buffer provided contains a bool.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer contains a bool, false otherwise.
|
||||
*/
|
||||
stock bool json_is_bool(const char[] buffer) {
|
||||
return StrEqual(buffer, "true")
|
||||
|| StrEqual(buffer, "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the buffer provided contains null.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer contains null, false otherwise.
|
||||
*/
|
||||
stock bool json_is_null(const char[] buffer) {
|
||||
return StrEqual(buffer, "null");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the character at the beginning
|
||||
* of the buffer is the start of an object.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer[0] is the start of an object, false otherwise.
|
||||
*/
|
||||
stock bool json_is_object(const char[] buffer) {
|
||||
return buffer[0] == '{';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the character at the beginning
|
||||
* of the buffer is the end of an object.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer[0] is the end of an object, false otherwise.
|
||||
*/
|
||||
stock bool json_is_object_end(const char[] buffer) {
|
||||
return buffer[0] == '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the character at the beginning
|
||||
* of the buffer is the start of an array.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer[0] is the start of an array, false otherwise.
|
||||
*/
|
||||
stock bool json_is_array(const char[] buffer) {
|
||||
return buffer[0] == '[';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the character at the beginning
|
||||
* of the buffer is the start of an array.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns True if buffer[0] is the start of an array, false otherwise.
|
||||
*/
|
||||
stock bool json_is_array_end(const char[] buffer) {
|
||||
return buffer[0] == ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the character at the given position in the buffer
|
||||
* is considered a valid 'end point' for some data, such as a
|
||||
* colon (indicating a key), a comma (indicating a new element),
|
||||
* or the end of an object or array.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @param pos Position to check in buffer.
|
||||
* @returns True if buffer[pos] is a valid data end point, false otherwise.
|
||||
*/
|
||||
stock bool json_is_at_end(const char[] buffer, int &pos, bool is_array) {
|
||||
return buffer[pos] == ','
|
||||
|| (!is_array && buffer[pos] == ':')
|
||||
|| json_is_object_end(buffer[pos])
|
||||
|| json_is_array_end(buffer[pos]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the position until it reaches a non-whitespace
|
||||
* character or the end of the buffer's maximum size.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param pos Position to increment.
|
||||
* @returns True if pos is not at the end of the buffer, false otherwise.
|
||||
*/
|
||||
stock bool json_skip_whitespace(const char[] buffer, int maxlen, int &pos) {
|
||||
while (json_is_whitespace(buffer, pos) && pos < maxlen) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
return pos < maxlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a JSON cell from the buffer until
|
||||
* a valid end point is reached.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param pos Position to increment.
|
||||
* @param output String buffer to store output.
|
||||
* @param output_maxlen Maximum size of output string buffer.
|
||||
* @param is_array Whether the decoder is currently processing an array.
|
||||
* @returns True if pos is not at the end of the buffer, false otherwise.
|
||||
*/
|
||||
stock bool json_extract_until_end(const char[] buffer, int maxlen, int &pos, char[] output, int output_maxlen, bool is_array) {
|
||||
strcopy(output, output_maxlen, "");
|
||||
|
||||
int start = pos;
|
||||
// while we haven't reached whitespace, a valid end point or the maxlen, increment position
|
||||
while (!json_is_whitespace(buffer, pos) && !json_is_at_end(buffer, pos, is_array) && pos < maxlen) {
|
||||
++pos;
|
||||
}
|
||||
int end = pos;
|
||||
|
||||
// skip any following whitespace
|
||||
json_skip_whitespace(buffer, maxlen, pos);
|
||||
|
||||
// if we aren't at a valid endpoint, extraction failed
|
||||
if (!json_is_at_end(buffer, pos, is_array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy only from start with length end - start + NULL
|
||||
strcopy(output, end - start + 1, buffer[start]);
|
||||
|
||||
return pos < maxlen;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts a JSON string from the buffer until
|
||||
* a valid end point is reached.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param pos Position to increment.
|
||||
* @param output String buffer to store output.
|
||||
* @param output_maxlen Maximum size of output string buffer.
|
||||
* @param is_array Whether the decoder is currently processing an array.
|
||||
* @returns True if pos is not at the end of the buffer, false otherwise.
|
||||
*/
|
||||
stock bool json_extract_string(const char[] buffer, int maxlen, int &pos, char[] output, int output_maxlen, bool is_array) {
|
||||
// extracts a string which needs to be quote-escaped
|
||||
strcopy(output, output_maxlen, "");
|
||||
|
||||
// increment past opening quote
|
||||
++pos;
|
||||
|
||||
// set start to position of first character in string
|
||||
int start = pos;
|
||||
|
||||
// while we haven't hit the end of the buffer
|
||||
while (pos < maxlen) {
|
||||
// check for unescaped control characters
|
||||
if (buffer[pos] == '\b'
|
||||
|| buffer[pos] == '\f'
|
||||
|| buffer[pos] == '\n'
|
||||
|| buffer[pos] == '\r'
|
||||
|| buffer[pos] == '\t') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// pass over any non-quote character
|
||||
if (buffer[pos] != '"') {
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
// count preceding backslashes to check if quote is escaped
|
||||
int search_pos = pos;
|
||||
int preceding_backslashes = 0;
|
||||
while (search_pos > 0 && buffer[--search_pos] == '\\') {
|
||||
++preceding_backslashes;
|
||||
}
|
||||
|
||||
// if we have an even number of backslashes, the quote is not escaped
|
||||
if (preceding_backslashes % 2 == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise, pass over the quote as it must be escaped
|
||||
++pos;
|
||||
}
|
||||
|
||||
// set end to the current position
|
||||
int end = pos;
|
||||
|
||||
// jump 1 ahead since we ended on " instead of an ending char
|
||||
++pos;
|
||||
|
||||
// skip trailing whitespace
|
||||
if (!json_skip_whitespace(buffer, maxlen, pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we haven't reached an ending character at the end of the cell
|
||||
// there is likely junk data not encapsulated by a string
|
||||
if (!json_is_at_end(buffer, pos, is_array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy only from start with length end - start + NULL
|
||||
strcopy(output, end - start + 1, buffer[start]);
|
||||
json_unescape_string(output, maxlen);
|
||||
|
||||
return pos < maxlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts an int from the buffer.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns Int value of the buffer.
|
||||
*/
|
||||
stock int json_extract_int(const char[] buffer) {
|
||||
return StringToInt(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a float from the buffer.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns Float value of the buffer.
|
||||
*/
|
||||
stock float json_extract_float(const char[] buffer) {
|
||||
return StringToFloat(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a bool from the buffer.
|
||||
*
|
||||
* @param buffer String buffer of data.
|
||||
* @returns Bool value of the buffer.
|
||||
*/
|
||||
stock bool json_extract_bool(const char[] buffer) {
|
||||
return StrEqual(buffer, "true");
|
||||
}
|
112
VPN-Check/scripting/include/json/definitions.inc
Normal file
112
VPN-Check/scripting/include/json/definitions.inc
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* sm-json
|
||||
* Provides a pure SourcePawn implementation of JSON encoding and decoding.
|
||||
* https://github.com/clugg/sm-json
|
||||
*
|
||||
* sm-json (C)2018 James Dickens. (clug)
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#if defined _json_definitions_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _json_definitions_included
|
||||
|
||||
#include <string>
|
||||
#include <json/string_helpers>
|
||||
|
||||
// you may need to tinker with these for large objects/floating point numbers
|
||||
#define JSON_FLOAT_BUFFER_SIZE 32
|
||||
#define JSON_INDEX_BUFFER_SIZE 16
|
||||
|
||||
// meta-key defines
|
||||
#define JSON_ARRAY_INDEX_KEY "__array_index"
|
||||
#define JSON_META_TYPE_KEY ":type"
|
||||
#define JSON_META_LENGTH_KEY ":length"
|
||||
#define JSON_META_HIDDEN_KEY ":hidden"
|
||||
|
||||
// pretty print constants
|
||||
#define JSON_PP_AFTER_COLON " "
|
||||
#define JSON_PP_INDENT " "
|
||||
#define JSON_PP_NEWLINE "\n"
|
||||
|
||||
/**
|
||||
* Types of cells within a JSON object
|
||||
*/
|
||||
enum JSON_CELL_TYPE {
|
||||
Type_Invalid = -1,
|
||||
Type_String = 0,
|
||||
Type_Int,
|
||||
Type_Float,
|
||||
Type_Bool,
|
||||
Type_Null,
|
||||
Type_Object
|
||||
};
|
||||
|
||||
/**
|
||||
* Multi-dimensional char array mapping characters to their escaped form
|
||||
*/
|
||||
char JSON_STRING_NORMAL[][] = {"\\", "\"", "/", "\b", "\f", "\n", "\r", "\t" };
|
||||
char JSON_STRING_ESCAPED[][] = {"\\\\", "\\\"", "\\/", "\\b", "\\f", "\\n", "\\r", "\\t"};
|
||||
|
||||
/**
|
||||
* Escapes a string based on the rules defined in json/definitions.inc
|
||||
*
|
||||
* @param buffer String buffer.
|
||||
* @param maxlength Maximum buffer length.
|
||||
*/
|
||||
public void json_escape_string(char[] buffer, int maxlen) {
|
||||
for (int i = 0; i < sizeof(JSON_STRING_NORMAL); ++i) {
|
||||
ReplaceString(buffer, maxlen, JSON_STRING_NORMAL[i], JSON_STRING_ESCAPED[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes a string based on the rules defined in json/definitions.inc
|
||||
*
|
||||
* @param buffer String buffer.
|
||||
* @param maxlength Maximum buffer length.
|
||||
*/
|
||||
public void json_unescape_string(char[] buffer, int maxlen) {
|
||||
for (int i = 0; i < sizeof(JSON_STRING_NORMAL); ++i) {
|
||||
ReplaceString(buffer, maxlen, JSON_STRING_ESCAPED[i], JSON_STRING_NORMAL[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the key provided is an meta-key that
|
||||
* should only be used internally.
|
||||
*
|
||||
* @param key Key to check.
|
||||
* @returns True when it is a meta-key, false otherwise.
|
||||
*/
|
||||
stock bool json_is_meta_key(char[] key) {
|
||||
return json_string_endswith(key, JSON_META_TYPE_KEY)
|
||||
|| json_string_endswith(key, JSON_META_LENGTH_KEY)
|
||||
|| json_string_endswith(key, JSON_META_HIDDEN_KEY)
|
||||
|| StrEqual(key, JSON_ARRAY_INDEX_KEY);
|
||||
}
|
168
VPN-Check/scripting/include/json/encode_helpers.inc
Normal file
168
VPN-Check/scripting/include/json/encode_helpers.inc
Normal file
@ -0,0 +1,168 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* sm-json
|
||||
* Provides a pure SourcePawn implementation of JSON encoding and decoding.
|
||||
* https://github.com/clugg/sm-json
|
||||
*
|
||||
* sm-json (C)2018 James Dickens. (clug)
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#if defined _json_encode_helpers_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _json_encode_helpers_included
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @section Calculating buffer sizes for JSON cells.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculates the maximum buffer length required to
|
||||
* store the JSON cell representation of a string.
|
||||
*
|
||||
* @param maxlen The string's current length or buffer size.
|
||||
* @returns Maximum buffer length.
|
||||
*/
|
||||
stock int json_cell_string_size(int maxlen) {
|
||||
return (maxlen * 2) + 3; // * 2 for potential escaping, + 2 for surrounding quotes + NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum buffer length required to
|
||||
* store the JSON cell representation of an int.
|
||||
*
|
||||
* @param input The int.
|
||||
* @returns Maximum buffer length.
|
||||
*/
|
||||
stock int json_cell_int_size(int input) {
|
||||
if (input == 0) {
|
||||
return 2; // "0" + NULL
|
||||
}
|
||||
|
||||
return ((input < 0) ? 1 : 0) + RoundToFloor(Logarithm(FloatAbs(float(input)), 10.0)) + 2; // neg sign + number of digits + NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum buffer length required to
|
||||
* store the JSON cell representation of a float.
|
||||
*
|
||||
* @returns Maximum buffer length.
|
||||
*/
|
||||
stock int json_cell_float_size() {
|
||||
return JSON_FLOAT_BUFFER_SIZE; // fixed-length
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum buffer length required to
|
||||
* store the JSON cell representation of a bool.
|
||||
*
|
||||
* @returns Maximum buffer length.
|
||||
*/
|
||||
stock int json_cell_bool_size() {
|
||||
return 6; // "true|false" + NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum buffer length required to
|
||||
* store the JSON cell representation of null.
|
||||
*
|
||||
* @returns Maximum buffer length.
|
||||
*/
|
||||
stock int json_cell_null_size() {
|
||||
return 5; // "null" + NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Generating JSON cells.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates the JSON cell representation of a string.
|
||||
*
|
||||
* @param input Value to generate output for.
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
*/
|
||||
stock void json_cell_string(const char[] input, char[] output, int maxlen) {
|
||||
strcopy(output, maxlen, "?"); // add dummy char at start so we can replace it with a quote later
|
||||
StrCat(output, maxlen, input); // add input string to output
|
||||
json_escape_string(output, maxlen); // run basic escapes on the string
|
||||
|
||||
// surround string with quotations
|
||||
output[0] = '"';
|
||||
StrCat(output, maxlen, "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the JSON cell representation of an int.
|
||||
*
|
||||
* @param input Value to generate output for.
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
*/
|
||||
stock void json_cell_int(int input, char[] output, int maxlen) {
|
||||
IntToString(input, output, maxlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the JSON cell representation of a float.
|
||||
*
|
||||
* @param input Value to generate output for.
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
*/
|
||||
stock void json_cell_float(float input, char[] output, int maxlen) {
|
||||
FloatToString(input, output, maxlen);
|
||||
// trim trailing 0s from float output
|
||||
int last_char = strlen(output) - 1;
|
||||
while (output[last_char] == '0' && output[last_char - 1] != '.') {
|
||||
output[last_char--] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the JSON cell representation of a bool.
|
||||
*
|
||||
* @param input Value to generate output for.
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
*/
|
||||
stock void json_cell_bool(bool input, char[] output, int maxlen) {
|
||||
strcopy(output, maxlen, (input) ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the JSON cell representation of null.
|
||||
*
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
*/
|
||||
stock void json_cell_null(char[] output, int maxlen) {
|
||||
strcopy(output, maxlen, "null");
|
||||
}
|
779
VPN-Check/scripting/include/json/object.inc
Normal file
779
VPN-Check/scripting/include/json/object.inc
Normal file
@ -0,0 +1,779 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* sm-json
|
||||
* Provides a pure SourcePawn implementation of JSON encoding and decoding.
|
||||
* https://github.com/clugg/sm-json
|
||||
*
|
||||
* sm-json (C)2018 James Dickens. (clug)
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#if defined _json_object_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _json_object_included
|
||||
|
||||
#include <string>
|
||||
#include <json/definitions>
|
||||
#include <json/encode_helpers>
|
||||
#include <json>
|
||||
|
||||
methodmap JSON_Object < StringMap {
|
||||
/**
|
||||
* Creates a new JSON_Object.
|
||||
*
|
||||
* @param is_array Should the object created be an array? [optional, default: false]
|
||||
* @returns A new JSON_Object.
|
||||
*/
|
||||
public JSON_Object(bool is_array = false) {
|
||||
StringMap obj = CreateTrie();
|
||||
if (is_array) {
|
||||
obj.SetValue(JSON_ARRAY_INDEX_KEY, 0);
|
||||
}
|
||||
|
||||
return view_as<JSON_Object>(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the object has a key.
|
||||
*
|
||||
* @param key Key to check existence of.
|
||||
* @returns True if the key exists, false otherwise.
|
||||
*/
|
||||
public bool HasKey(const char[] key) {
|
||||
int dummy_int;
|
||||
char dummy_str[1];
|
||||
|
||||
return this.GetValue(key, dummy_int)
|
||||
|| this.GetString(key, dummy_str, sizeof(dummy_str));
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Array helpers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether the current object is an array.
|
||||
*/
|
||||
property bool IsArray {
|
||||
public get() {
|
||||
return this.HasKey(JSON_ARRAY_INDEX_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current index of the object if it is an array, or -1 otherwise.
|
||||
*/
|
||||
property int CurrentIndex {
|
||||
public get() {
|
||||
if (!this.IsArray) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int result;
|
||||
return (this.GetValue(JSON_ARRAY_INDEX_KEY, result)) ? result : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of items in the object if it is an array,
|
||||
* or the number of keys (including meta-keys) otherwise.
|
||||
*/
|
||||
property int Length {
|
||||
public get() {
|
||||
StringMapSnapshot snap = this.Snapshot();
|
||||
int length = (this.IsArray) ? this.CurrentIndex : snap.Length;
|
||||
delete snap;
|
||||
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the current index of the object.
|
||||
*
|
||||
* @returns True on success, false if the current object is not an array.
|
||||
*/
|
||||
public bool IncrementIndex() {
|
||||
int current = this.CurrentIndex;
|
||||
if (current == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetValue(JSON_ARRAY_INDEX_KEY, current + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation of an array index.
|
||||
*
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param key Key to get string for. [optional, default: current index]
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public int GetIndexString(char[] output, int maxlen, int key = -1) {
|
||||
key = (key == -1) ? this.CurrentIndex : key;
|
||||
if (key == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IntToString(key, output, maxlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the object by index.
|
||||
*
|
||||
* @param index Index of object to remove.
|
||||
* @returns True on success, false if the current object
|
||||
* is not an array or the index does not exist.
|
||||
*/
|
||||
public bool RemoveIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.Remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Internal getters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the cell type stored at a key.
|
||||
*
|
||||
* @param key Key to get value type for.
|
||||
* @returns Value type for key provided, or Type_Invalid if it does not exist.
|
||||
*/
|
||||
public JSON_CELL_TYPE GetKeyType(const char[] key) {
|
||||
int maxlen = strlen(key) + strlen(JSON_META_TYPE_KEY) + 1;
|
||||
char[] type_key = new char[maxlen];
|
||||
Format(type_key, maxlen, "%s%s", key, JSON_META_TYPE_KEY);
|
||||
|
||||
JSON_CELL_TYPE type;
|
||||
return (this.GetValue(type_key, type)) ? type : Type_Invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cell type stored at an index.
|
||||
*
|
||||
* @param index Index to get value type for.
|
||||
* @returns Value type for index provided, or Type_Invalid if it does not exist.
|
||||
*/
|
||||
public JSON_CELL_TYPE GetKeyTypeIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return Type_Invalid;
|
||||
}
|
||||
|
||||
return this.GetKeyType(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of the string stored at a key.
|
||||
*
|
||||
* @param key Key to get string length for.
|
||||
* @returns Length of string at key provided, or -1 if it is not a string/does not exist.
|
||||
*/
|
||||
public int GetKeyLength(const char[] key) {
|
||||
int maxlen = strlen(key) + strlen(JSON_META_LENGTH_KEY) + 1;
|
||||
char[] length_key = new char[maxlen];
|
||||
Format(length_key, maxlen, "%s%s", key, JSON_META_LENGTH_KEY);
|
||||
|
||||
int length;
|
||||
return (this.GetValue(length_key, length)) ? length : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of the string stored at an index.
|
||||
*
|
||||
* @param index Index to get string length for.
|
||||
* @returns Length of string at index provided, or -1 if it is not a string/does not exist.
|
||||
*/
|
||||
public int GetKeyLengthIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.GetKeyLength(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the key should be hidden from encoding.
|
||||
*
|
||||
* @param key Key to get hidden state for.
|
||||
* @returns Whether or not the key should be hidden.
|
||||
*/
|
||||
public bool GetKeyHidden(const char[] key) {
|
||||
int maxlen = strlen(key) + strlen(JSON_META_HIDDEN_KEY) + 1;
|
||||
char[] length_key = new char[maxlen];
|
||||
Format(length_key, maxlen, "%s%s", key, JSON_META_HIDDEN_KEY);
|
||||
|
||||
bool hidden;
|
||||
return (this.GetValue(length_key, hidden)) ? hidden : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the index should be hidden from encoding.
|
||||
*
|
||||
* @param index Index to get hidden state for.
|
||||
* @returns Whether or not the index should be hidden.
|
||||
*/
|
||||
public bool GetKeyHiddenIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.GetKeyHidden(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Internal setters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the cell type stored at a key.
|
||||
*
|
||||
* @param key Key to set value type for.
|
||||
* @param type Type to set key to.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetKeyType(const char[] key, JSON_CELL_TYPE type) {
|
||||
int maxlen = strlen(key) + strlen(JSON_META_TYPE_KEY) + 1;
|
||||
char[] type_key = new char[maxlen];
|
||||
Format(type_key, maxlen, "%s%s", key, JSON_META_TYPE_KEY);
|
||||
|
||||
return this.SetValue(type_key, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell type stored at an index.
|
||||
*
|
||||
* @param index Index to set value type for.
|
||||
* @param type Type to set index to.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetKeyTypeIndexed(int index, JSON_CELL_TYPE value) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetKeyType(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the length of the string stored at a key.
|
||||
*
|
||||
* @param key Key to set string length for.
|
||||
* @param length Length to set string to.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetKeyLength(const char[] key, int length) {
|
||||
int maxlen = strlen(key) + strlen(JSON_META_LENGTH_KEY) + 1;
|
||||
char[] length_key = new char[maxlen];
|
||||
Format(length_key, maxlen, "%s%s", key, JSON_META_LENGTH_KEY);
|
||||
|
||||
return this.SetValue(length_key, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the length of the string stored at an index.
|
||||
*
|
||||
* @param index Index to set string length for.
|
||||
* @param length Length to set string to.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetKeyLengthIndexed(int index, int length) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetKeyLength(key, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the key should be hidden from encoding.
|
||||
*
|
||||
* @param key Key to set hidden state for.
|
||||
* @param hidden Wheter or not the key should be hidden.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetKeyHidden(const char[] key, bool hidden) {
|
||||
int maxlen = strlen(key) + strlen(JSON_META_HIDDEN_KEY) + 1;
|
||||
char[] hidden_key = new char[maxlen];
|
||||
Format(hidden_key, maxlen, "%s%s", key, JSON_META_HIDDEN_KEY);
|
||||
|
||||
return this.SetValue(hidden_key, hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the index should be hidden from encoding.
|
||||
*
|
||||
* @param index Index to set hidden state for.
|
||||
* @param hidden Wheter or not the index should be hidden.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetKeyHiddenIndexed(int index, bool hidden) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetKeyHidden(key, hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Object getters.
|
||||
*/
|
||||
|
||||
// GetString is implemented natively by StringMap
|
||||
|
||||
/**
|
||||
* Retrieves the string stored at an index.
|
||||
*
|
||||
* @param index Index to retrieve string value for.
|
||||
* @param value String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @returns True on success. False if the key is not set, or the key is set as a value or array (not a string).
|
||||
*/
|
||||
public bool GetStringIndexed(int index, char[] value, int max_size) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.GetString(key, value, max_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the int stored at a key.
|
||||
*
|
||||
* @param key Key to retrieve int value for.
|
||||
* @returns Value stored at key.
|
||||
*/
|
||||
public int GetInt(const char[] key) {
|
||||
int value;
|
||||
return (this.GetValue(key, value)) ? value : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the int stored at an index.
|
||||
*
|
||||
* @param index Index to retrieve int value for.
|
||||
* @returns Value stored at index.
|
||||
*/
|
||||
public int GetIntIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.GetInt(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the float stored at a key.
|
||||
*
|
||||
* @param key Key to retrieve float value for.
|
||||
* @returns Value stored at key.
|
||||
*/
|
||||
public float GetFloat(const char[] key) {
|
||||
float value;
|
||||
return (this.GetValue(key, value)) ? value : -1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the float stored at an index.
|
||||
*
|
||||
* @param index Index to retrieve float value for.
|
||||
* @returns Value stored at index.
|
||||
*/
|
||||
public float GetFloatIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return this.GetFloat(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the bool stored at a key.
|
||||
*
|
||||
* @param key Key to retrieve bool value for.
|
||||
* @returns Value stored at key.
|
||||
*/
|
||||
public bool GetBool(const char[] key) {
|
||||
bool value;
|
||||
return (this.GetValue(key, value)) ? value : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the bool stored at an index.
|
||||
*
|
||||
* @param index Index to retrieve bool value for.
|
||||
* @returns Value stored at index.
|
||||
*/
|
||||
public bool GetBoolIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.GetBool(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the handle stored at a key.
|
||||
*
|
||||
* @param key Key to retrieve handle value for.
|
||||
* @returns Value stored at key.
|
||||
*/
|
||||
public Handle GetHandle(const char[] key) {
|
||||
Handle value;
|
||||
return (this.GetValue(key, value)) ? value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the handle stored at an index.
|
||||
*
|
||||
* @param index Index to retrieve handle value for.
|
||||
* @returns Value stored at index.
|
||||
*/
|
||||
public Handle GetHandleIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.GetHandle(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the object stored at a key.
|
||||
*
|
||||
* @param key Key to retrieve object value for.
|
||||
* @returns Value stored at key.
|
||||
*/
|
||||
public JSON_Object GetObject(const char[] key) {
|
||||
return view_as<JSON_Object>(this.GetHandle(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the object stored at an index.
|
||||
*
|
||||
* @param index Index to retrieve object value for.
|
||||
* @returns Value stored at index.
|
||||
*/
|
||||
public JSON_Object GetObjectIndexed(int index) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.GetObject(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Object setters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the string stored at a key.
|
||||
*
|
||||
* @param key Key to set to string value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetString(const char[] key, const char[] value, bool replace = true) {
|
||||
return this.SetString(key, value, replace)
|
||||
&& this.SetKeyType(key, Type_String)
|
||||
&& this.SetKeyLength(key, strlen(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the string stored at an index.
|
||||
*
|
||||
* @param index Index to set to string value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetStringIndexed(int index, const char[] value, bool replace = true) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetString(key, value, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the int stored at a key.
|
||||
*
|
||||
* @param key Key to set to int value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetInt(const char[] key, int value, bool replace = true) {
|
||||
return this.SetValue(key, value, replace)
|
||||
&& this.SetKeyType(key, Type_Int);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the int stored at an index.
|
||||
*
|
||||
* @param index Index to set to int value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetIntIndexed(int index, int value, bool replace = true) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetInt(key, value, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the float stored at a key.
|
||||
*
|
||||
* @param key Key to set to float value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetFloat(const char[] key, float value, bool replace = true) {
|
||||
return this.SetValue(key, value, replace)
|
||||
&& this.SetKeyType(key, Type_Float);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the float stored at an index.
|
||||
*
|
||||
* @param index Index to set to float value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetFloatIndexed(int index, float value, bool replace = true) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetFloat(key, value, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bool stored at a key.
|
||||
*
|
||||
* @param key Key to set to bool value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetBool(const char[] key, bool value, bool replace = true) {
|
||||
return this.SetValue(key, value, replace)
|
||||
&& this.SetKeyType(key, Type_Bool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bool stored at an index.
|
||||
*
|
||||
* @param index Index to set to bool value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetBoolIndexed(int index, bool value, bool replace = true) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetBool(key, value, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handle stored at a key.
|
||||
*
|
||||
* @param key Key to set to handle value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetHandle(const char[] key, Handle value = null, bool replace = true) {
|
||||
return this.SetValue(key, value, replace)
|
||||
&& this.SetKeyType(key, Type_Null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handle stored at an index.
|
||||
*
|
||||
* @param index Index to set to handle value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetHandleIndexed(int index, Handle value = null, bool replace = true) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetHandle(key, value, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object stored at a key.
|
||||
*
|
||||
* @param key Key to set to object value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetObject(const char[] key, JSON_Object value, bool replace = true) {
|
||||
return this.SetValue(key, value, replace)
|
||||
&& this.SetKeyType(key, Type_Object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object stored at an index.
|
||||
*
|
||||
* @param index Index to set to object value.
|
||||
* @param value Value to set.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool SetObjectIndexed(int index, JSON_Object value, bool replace = true) {
|
||||
char key[JSON_INDEX_BUFFER_SIZE];
|
||||
if (!this.GetIndexString(key, sizeof(key), index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.SetObject(key, value, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Array setters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pushes a string to the end of the array.
|
||||
*
|
||||
* @param value Value to push.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool PushString(const char[] value) {
|
||||
return this.SetStringIndexed(this.CurrentIndex, value)
|
||||
&& this.IncrementIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes an int to the end of the array.
|
||||
*
|
||||
* @param value Value to push.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool PushInt(int value) {
|
||||
return this.SetIntIndexed(this.CurrentIndex, value)
|
||||
&& this.IncrementIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a float to the end of the array.
|
||||
*
|
||||
* @param value Value to push.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool PushFloat(float value) {
|
||||
return this.SetFloatIndexed(this.CurrentIndex, value)
|
||||
&& this.IncrementIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a bool to the end of the array.
|
||||
*
|
||||
* @param value Value to push.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool PushBool(bool value) {
|
||||
return this.SetBoolIndexed(this.CurrentIndex, value)
|
||||
&& this.IncrementIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a handle to the end of the array.
|
||||
*
|
||||
* @param value Value to push.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool PushHandle(Handle value = null) {
|
||||
return this.SetHandleIndexed(this.CurrentIndex, value)
|
||||
&& this.IncrementIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes an object to the end of the array.
|
||||
*
|
||||
* @param value Value to push.
|
||||
* @returns True on success, false otherwise.
|
||||
*/
|
||||
public bool PushObject(JSON_Object value) {
|
||||
return this.SetObjectIndexed(this.CurrentIndex, value)
|
||||
&& this.IncrementIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @section Generic.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encodes the object into its string representation.
|
||||
*
|
||||
* @param output String buffer to store output.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param pretty_print Should the output be pretty printed (newlines and spaces)? [optional, default: false]
|
||||
* @param depth The current depth of the encoder. [optional, default: 0]
|
||||
*/
|
||||
public void Encode(char[] output, int maxlen, bool pretty_print = false, int depth = 0) {
|
||||
json_encode(this, output, maxlen, pretty_print, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a JSON string into this object.
|
||||
*
|
||||
* @param buffer Buffer to decode.
|
||||
*/
|
||||
public void Decode(const char[] buffer) {
|
||||
json_decode(buffer, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively cleans up the object and any objects referenced within.
|
||||
*/
|
||||
public void Cleanup() {
|
||||
json_cleanup(this);
|
||||
}
|
||||
};
|
85
VPN-Check/scripting/include/json/string_helpers.inc
Normal file
85
VPN-Check/scripting/include/json/string_helpers.inc
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* sm-json
|
||||
* Provides a pure SourcePawn implementation of JSON encoding and decoding.
|
||||
* https://github.com/clugg/sm-json
|
||||
*
|
||||
* sm-json (C)2018 James Dickens. (clug)
|
||||
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#if defined _json_string_helpers_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _json_string_helpers_included
|
||||
|
||||
/**
|
||||
* Checks if a string starts with another string.
|
||||
*
|
||||
* @param haystack String to check that starts with needle.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param needle String to check that haystack starts with.
|
||||
* @returns True if haystack begins with needle, false otherwise.
|
||||
*/
|
||||
stock bool json_string_startswith(const char[] haystack, const char[] needle) {
|
||||
int haystack_length = strlen(haystack);
|
||||
int needle_length = strlen(needle);
|
||||
if (needle_length > haystack_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < needle_length; ++i) {
|
||||
if (haystack[i] != needle[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a string ends with another string.
|
||||
*
|
||||
* @param haystack String to check that ends with needle.
|
||||
* @param maxlen Maximum size of string buffer.
|
||||
* @param needle String to check that haystack ends with.
|
||||
* @returns True if haystack ends with needle, false otherwise.
|
||||
*/
|
||||
stock bool json_string_endswith(const char[] haystack, const char[] needle) {
|
||||
int haystack_length = strlen(haystack);
|
||||
int needle_length = strlen(needle);
|
||||
if (needle_length > haystack_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < needle_length; ++i) {
|
||||
if (haystack[haystack_length - needle_length + i] != needle[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user