Skip to content

Commit

Permalink
ver 1.0.7
Browse files Browse the repository at this point in the history
refactor: improve memory management and error handling

Memory management improvements:
- Add custom deleter for yyjson_mut_doc in shared_ptr
- Add CreateDocument and CopyDocument helper method for consistent document creation and copy
- Update all document creation points to use shared_ptr
- Keep m_pVal_mut as raw pointer since it's managed by document

Error handling improvements:
- Add int64 value validity check
- Add bounds checking for array operations
- Add key existence validation for object operations
- Enhance error messages with more context and details
- Add type checking with descriptive error messages
- Improve error reporting for JSON pointer operations

Add methods to find the index of values in JSON arrays:
- IndexOfBool: Find boolean value
- IndexOfString: Find string value
- IndexOfInt: Find integer value
- IndexOfFloat: Find float value

Add YYJSONArray.Sort method to sort array elements
- Support ascending/descending order
- Compare elements based on their types and values
- Handle different value types (string, number, bool)
- Use stable sort to maintain relative order of equal elements

Add YYJSONObject.Sort method to sort object by keys
- Support ascending/descending order for key names
- Maintain key-value associations during sorting
- Use stable sort to preserve order of equal keys

Update README and API documentation
- Add detailed comments for sort methods
  • Loading branch information
ProjectSky committed Nov 4, 2024
1 parent 4878acf commit 99c0e82
Show file tree
Hide file tree
Showing 7 changed files with 1,066 additions and 345 deletions.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ A [SourceMod](http://www.sourcemod.net/) extension that provides comprehensive J
* Support for [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) operations
* x64 support
* Easy-to-use API for both objects and arrays
* Pretty printing support
* Pretty printing and writing support
* Array and object sorting support
* Iteration methods for arrays and objects

## Building from Source
```bash
Expand Down Expand Up @@ -152,6 +154,41 @@ for (int i = 0; i < arr.Length; i++)
delete arr;
```

### Sorting Arrays and Objects
```cpp
// Sorting JSON arrays
YYJSONArray arr = YYJSON.Parse(
"[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]"
);
arr.Sort(); // Ascending order (default)
// [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

arr.Sort(YYJSON_SORT_DESC); // Descending order
// [9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1]

// Arrays with mixed types are sorted by type first, then by value
YYJSONArray mixed = YYJSON.Parse(
"[true, 42, \"hello\", 1.23, false, \"world\"]"
);
mixed.Sort();
// [false, true, 1.23, 42, "hello", "world"]

// Sorting JSON objects by keys
YYJSONObject obj = YYJSON.Parse(
"{\"zebra\": 1, \"alpha\": 2, \"beta\": 3, \"gamma\": 4}"
);

obj.Sort(); // Ascending order by keys (default)
// {"alpha": 2, "beta": 3, "gamma": 4, "zebra": 1}

obj.Sort(YYJSON_SORT_DESC); // Descending order by keys
// {"zebra": 1, "gamma": 4, "beta": 3, "alpha": 2}

delete arr;
delete mixed;
delete obj;
```

## Notes
* Beta version - some functions may require additional testing
* Please report any issues on GitHub
Expand Down
3 changes: 2 additions & 1 deletion pushbuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
0x3
0x4
0x5
0x6
0x6
0x7
135 changes: 114 additions & 21 deletions scripting/include/yyjson.inc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ enum YYJSON_SUBTYPE
YYJSON_SUBTYPE_UINT = 0 << 3,
YYJSON_SUBTYPE_SINT = 1 << 3,
YYJSON_SUBTYPE_REAL = 2 << 3,
YYJSON_SUBTYPE_NOESC = 1 << 3,
YYJSON_SUBTYPE_NOESC = 1 << 3
}

enum YYJSON_READ_FLAG
Expand All @@ -36,7 +36,7 @@ enum YYJSON_READ_FLAG
YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4,
YYJSON_READ_NUMBER_AS_RAW = 1 << 5,
YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6,
YYJSON_READ_BIGNUM_AS_RAW = 1 << 7,
YYJSON_READ_BIGNUM_AS_RAW = 1 << 7
}

enum YYJSON_WRITE_FLAG
Expand All @@ -49,14 +49,24 @@ enum YYJSON_WRITE_FLAG
YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4,
YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5,
YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6,
YYJSON_WRITE_NEWLINE_AT_END = 1 << 7,
YYJSON_WRITE_NEWLINE_AT_END = 1 << 7
}

/**
* Write floating-point number using fixed-point notation
* - This is similar to ECMAScript `Number.prototype.toFixed(prec)`, but with trailing zeros removed. The `prec` ranges from 1 to 15
* - This will produce shorter output but may lose some precision
*/
enum YYJSON_SORT_ORDER
{
YYJSON_SORT_ASC = 0,
YYJSON_SORT_DESC = 1
}

/**
* Creates a write flag to control floating-point number precision in JSON output
* Similar to JavaScript's Number.prototype.toFixed(prec), but removes trailing zeros
*
* @param n Precision value (number of decimal places), must be between 1 and 15
* @return Write flag that can be combined with other YYJSON_WRITE_FLAG values
*
* @note This will produce shorter output but may lose some precision
*/
stock YYJSON_WRITE_FLAG YYJSON_REAL_PRECISION(int n)
{
return view_as<YYJSON_WRITE_FLAG>(n << 28);
Expand Down Expand Up @@ -283,11 +293,11 @@ methodmap YYJSON < Handle
/**
* Get JSON Handle serialized size in bytes (including null-terminator)
*
* @param value JSON handle
* @param flag The JSON write options
*
* @return serialized size
*/
public static native int GetSize(const YYJSON value);
public native int GetSerializedSize(YYJSON_WRITE_FLAG flag = YYJSON_WRITE_NOFLAG);

/**
* Get value by a JSON Pointer
Expand Down Expand Up @@ -554,13 +564,6 @@ methodmap YYJSON < Handle
property bool IsObject {
public native get();
}

/**
* Retrieves json serialized size
*/
property int Size {
public native get();
}
};

methodmap YYJSONObject < YYJSON
Expand Down Expand Up @@ -686,17 +689,18 @@ methodmap YYJSONObject < YYJSON

/**
* Replaces all matching keys with the new key
* The key and new_key should be a null-terminated UTF-8 string
* The old_key and new_key should be a null-terminated UTF-8 string
* The new_key is copied and held by doc
*
* @note This function takes a linear search time
*
* @param key Key string
* @param new_key New key set
* @param old_key The key to rename
* @param new_key The new key name
* @param allow_duplicate Whether to allow renaming even if new key exists
*
* @return True if at least one key was renamed, false otherwise
*/
public native bool RenameKey(const char[] key, const char[] new_key);
public native bool RenameKey(const char[] old_key, const char[] new_key, bool allow_duplicate = false);

/**
* Gets string data from the object
Expand Down Expand Up @@ -795,6 +799,21 @@ methodmap YYJSONObject < YYJSON
*/
public native bool Clear();

/**
* Sorts the object's keys
*
* @note This function performs a lexicographical sort on the object's keys
* - The values maintain their association with their respective keys
*
* @param order Sort order, use YYJSON_SORT_ASC for ascending (default)
* or YYJSON_SORT_DESC for descending
*
* @return True on success, false on failure
*
* @error Invalid handle or handle is not an object
*/
public native bool Sort(YYJSON_SORT_ORDER order = YYJSON_SORT_ASC);

/**
* Retrieves the size of the object
*/
Expand Down Expand Up @@ -1069,13 +1088,87 @@ methodmap YYJSONArray < YYJSON
*/
public native bool RemoveRange(int start_index, int end_index);

/**
* Searches for a boolean value in the array and returns its index
*
* @param value The boolean value to search for
*
* @return The index of the first matching element, or -1 if not found
*
* @error Invalid handle or handle is not an array
*/
public native int IndexOfBool(bool value);

/**
* Searches for a string value in the array and returns its index
*
* @param value The string value to search for
*
* @return The index of the first matching element, or -1 if not found
*
* @error Invalid handle or handle is not an array
*/
public native int IndexOfString(const char[] value);

/**
* Searches for an integer value in the array and returns its index
*
* @param value The integer value to search for
*
* @return The index of the first matching element, or -1 if not found
*
* @error Invalid handle or handle is not an array
*/
public native int IndexOfInt(int value);

/**
* Searches for an integer64 value in the array and returns its index
*
* @param value The integer64 value to search for as string
*
* @return The index of the first matching element, or -1 if not found
*
* @error Invalid handle, handle is not an array, or invalid integer64 string format
*/
public native int IndexOfInt64(const char[] value);

/**
* Searches for a float value in the array and returns its index
*
* @param value The float value to search for
*
* @return The index of the first matching element, or -1 if not found
*
* @error Invalid handle or handle is not an array
*/
public native int IndexOfFloat(float value);

/**
* Removes all elements from the array
*
* @return True if succeed, false otherwise
*/
public native bool Clear();

/**
* Sorts the array elements
*
* @note Sorting rules:
* - Different types are sorted by their type ID
* - Strings are sorted lexicographically
* - Numbers are sorted by their numeric value
* - Booleans are sorted with false before true
* - Other types (null, object, array) are sorted by type only
*
* @param order Sort order, use YYJSON_SORT_ASC for ascending (default)
* or YYJSON_SORT_DESC for descending
*
* @return True on success, false on failure
*
* @error Invalid handle or handle is not an array
*/
public native bool Sort(YYJSON_SORT_ORDER order = YYJSON_SORT_ASC);

/**
* Retrieves the size of the array
*/
Expand Down
5 changes: 3 additions & 2 deletions src/extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ bool JsonExtension::SDK_OnLoad(char* error, size_t maxlen, bool late)
handlesys->InitAccessDefaults(nullptr, &haJSON);
haJSON.access[HandleAccess_Delete] = 0;

g_htJSON = handlesys->CreateType("YYJSON", &g_JSONHandler, 0, nullptr, &haJSON, myself->GetIdentity(), nullptr);
HandleError err;
g_htJSON = handlesys->CreateType("YYJSON", &g_JSONHandler, 0, nullptr, &haJSON, myself->GetIdentity(), &err);

if (!g_htJSON) {
strncpy(error, "Failed to create YYJSON handle type", maxlen);
snprintf(error, maxlen, "Failed to create YYJSON handle type (err: %d)", err);
return false;
}

Expand Down
Loading

0 comments on commit 99c0e82

Please sign in to comment.