diff --git a/README.md b/README.md
index 1fdb351..4752248 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,20 @@
-
SNAP: Struct N' Array Parser 3.0.0
+SNAP: Struct N' Array Parsing 3.2.0
-Replacement for ds_map/ds_list-based encoding/decoding
+Easy struct/array saving and loading
Download the .yymps here
-Functions included are:
+Functions included can:
-1. `foreach(struct/array, method, [dsType])`
-2. `snap_deep_copy(struct/array)`
-3. `snap_to_json(struct/array, [pretty], [alphabetizeStructs])`
-4. `snap_from_json(string)`
-5. `snap_to_binary(struct/array)`
-6. `snap_from_binary(buffer, [offset], [size], [destroyBuffer])`
-7. `snap_from_xml(string)`
-8. `snap_to_xml(struct/array, [alphabetizeStructs])`
+1. Iterate over all elements of a struct/array and execute a function: `foreach()`
+2. Make a deep copy of a struct/array: `snap_deep_copy(struct/array)`
+3. Encode/decode JSON
+4. Encode/decode binary
+5. Encode/decode [messagepack](https://msgpack.org/index.html)
+6. Encode/decode XML
+7. Decode INI
-----
@@ -44,7 +43,7 @@ Returns a copy of the given `struct/array`, including a copy of any nested struc
### snap_to_json(struct/array, [pretty], [alphabetizeStructs]) ###
-Turns struct and array nested data into a JSON string. The root data type can be either a struct or an array. Setting `[pretty]` to `true` will format the JSON string in a more pleasing human-readable way, whereas setting `[alphabetizeStructs]` to `true` will output the struct variables in ascending alphabetical order. Using pretty and/or alphabetized output does incur a performance penalty.
+Turns struct and array nested data into a JSON string. The root datatype can be either a struct or an array. Setting `[pretty]` to `true` will format the JSON string in a more pleasing human-readable way, whereas setting `[alphabetizeStructs]` to `true` will output the struct variables in ascending alphabetical order. Using pretty and/or alphabetized output does incur a performance penalty.
@@ -56,13 +55,25 @@ Decodes a JSON string into nested struct/array data. This function will happily
### snap_to_binary(struct/array) ###
-Returns a buffer that holds binary encoded struct and array nested data. The root data type can be either a struct or an array. This is substantially faster than `snap_to_json()`.
+Returns a buffer that holds binary encoded struct and array nested data. The root datatype can be either a struct or an array. This is substantially faster than `snap_to_json()`.
-### snap_from_binary(buffer, [offset], [size], [destroyBuffer]) ###
+### snap_from_binary(buffer, [offset], [destroyBuffer]) ###
-Unpacks binary encoded struct/array data. An `[offset]` and total `[size]` for the data within the buffer can be specified which is helpful for working with composite buffers. Set `[size]` to `-1` to use the entire size of the buffer. If `[destroyBuffer]` is set to `true` then the input buffer will be destroyed once the function has finished executing. This function is a lot faster than `snap_from_json_string()`.
+Unpacks binary encoded struct/array data. An `[offset]` for the data within the buffer can be specified which is helpful for working with composite buffers. If `[destroyBuffer]` is set to `true` then the input buffer will be destroyed once the function has finished executing. This function is a lot faster than `snap_from_json_string()`.
+
+
+
+### snap_to_messagepack(struct/array) ###
+
+Returns a buffer that holds a binary representation of struct and array nested data according to the [messagepack](https://msgpack.org/index.html) specification. The root datatype can any datatype. This function is slower then the proprietary `snap_to_binary()`, but the [messagepack](https://msgpack.org/index.html) format is widely used and tends to output slightly smaller buffers.
+
+
+
+### snap_from_messagepack(buffer, [offset], [destroyBuffer]) ###
+
+Unpacks [messagepack](https://msgpack.org/index.html) binary data into a struct/array data. An `[offset]` for the data within the buffer can be specified which is helpful for working with composite buffers. If `[destroyBuffer]` is set to `true` then the input buffer will be destroyed once the function has finished executing. `snap_from_messagepack()` is a little slower than `snap_from_binary()`.
@@ -115,3 +126,18 @@ This is a bit wordy, so here's an example. The following XML and struct/array li
### snap_to_xml(struct/array, [alphabetizeStructs]) ###
Turns struct and array nested data into a XML string. The data must be structured as above in GML example for `snap_from_xml()`. Setting `[alphabetizeStructs]` to `true` will output child element in ascending alphabetical order. Using an alphabetized output incurs a performance penalty.
+
+
+
+### snap_from_ini_string(string, [tryReal]) ###
+
+Parses a string representation of an .ini file into nested structs: sections are stored as nested structs inside the root struct. Setting `[tryReal]` to `true` (the default value) will instruct the function to attempt to turn any values into real numbers if possible.
+
+_**N.B.** This script is only intended to read the .ini files and strings that GM generates using the native `ini_close()` function. This is not a full implementation of an .ini specification (not that an official one really exists)._
+
+
+
+### snap_from_ini_file(filename, [tryReal]) ###
+
+Convenience function that loads an .ini file from disk and passes it into `snap_from_ini_string()`.
+
diff --git a/objects/oTestBinary/Create_0.gml b/objects/oTestBinary/Create_0.gml
index 7830e3e..2739900 100644
--- a/objects/oTestBinary/Create_0.gml
+++ b/objects/oTestBinary/Create_0.gml
@@ -25,4 +25,6 @@ struct = {
url : "https://www.jujuadams.com/"
};
-show_debug_message(snap_to_json(snap_from_binary(snap_to_binary(struct)), true, true));
\ No newline at end of file
+buffer = snap_to_binary(struct);
+show_debug_message(buffer_base64_encode(buffer, 0, -1));
+show_debug_message(snap_to_json(snap_from_binary(buffer), true, true));
\ No newline at end of file
diff --git a/objects/oTestBinary/oTestMessagepack.yy b/objects/oTestBinary/oTestMessagepack.yy
new file mode 100644
index 0000000..54ae13d
--- /dev/null
+++ b/objects/oTestBinary/oTestMessagepack.yy
@@ -0,0 +1,33 @@
+{
+ "spriteId": null,
+ "solid": false,
+ "visible": true,
+ "spriteMaskId": null,
+ "persistent": false,
+ "parentObjectId": null,
+ "physicsObject": false,
+ "physicsSensor": false,
+ "physicsShape": 1,
+ "physicsGroup": 1,
+ "physicsDensity": 0.5,
+ "physicsRestitution": 0.1,
+ "physicsLinearDamping": 0.1,
+ "physicsAngularDamping": 0.1,
+ "physicsFriction": 0.2,
+ "physicsStartAwake": true,
+ "physicsKinematic": false,
+ "physicsShapePoints": [],
+ "eventList": [
+ {"isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,"parent":{"name":"oTestMessagepack","path":"objects/oTestMessagepack/oTestMessagepack.yy",},"resourceVersion":"1.0","name":null,"tags":[],"resourceType":"GMEvent",},
+ ],
+ "properties": [],
+ "overriddenProperties": [],
+ "parent": {
+ "name": "snap",
+ "path": "snap.yyp",
+ },
+ "resourceVersion": "1.0",
+ "name": "oTestMessagepack",
+ "tags": [],
+ "resourceType": "GMObject",
+}
\ No newline at end of file
diff --git a/objects/oTestINI/Create_0.gml b/objects/oTestINI/Create_0.gml
new file mode 100644
index 0000000..606c9a5
--- /dev/null
+++ b/objects/oTestINI/Create_0.gml
@@ -0,0 +1,22 @@
+var _text = @'[Section 1]
+; comment
+Option 1 = value 1 ; option "Option 1" has value "value 1"
+oPtion 1 = \ value 2\ \ \ ; option "oPtion 1" has value " value 2 ", "oPtion 1" and "Option 1" are different
+
+[Numbers]
+num = "-1285"
+num_bin = 0b01101001
+num_hex = 0x12ae
+num_oct = 01754
+
+float1 = -124.45667356
+float2 = +4.1234565E+45
+float3 = 412.34565e45
+float4 = -1.1245864E-6
+
+[Other]
+bool1 = 1
+bool2 = on
+bool3=f';
+
+show_debug_message(snap_to_json(snap_from_ini_string(_text, false), true, true));
\ No newline at end of file
diff --git a/objects/oTestINI/oTestINI.yy b/objects/oTestINI/oTestINI.yy
new file mode 100644
index 0000000..71ef6ac
--- /dev/null
+++ b/objects/oTestINI/oTestINI.yy
@@ -0,0 +1,33 @@
+{
+ "spriteId": null,
+ "solid": false,
+ "visible": true,
+ "spriteMaskId": null,
+ "persistent": false,
+ "parentObjectId": null,
+ "physicsObject": false,
+ "physicsSensor": false,
+ "physicsShape": 1,
+ "physicsGroup": 1,
+ "physicsDensity": 0.5,
+ "physicsRestitution": 0.1,
+ "physicsLinearDamping": 0.1,
+ "physicsAngularDamping": 0.1,
+ "physicsFriction": 0.2,
+ "physicsStartAwake": true,
+ "physicsKinematic": false,
+ "physicsShapePoints": [],
+ "eventList": [
+ {"isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,"parent":{"name":"oTestINI","path":"objects/oTestINI/oTestINI.yy",},"resourceVersion":"1.0","name":null,"tags":[],"resourceType":"GMEvent",},
+ ],
+ "properties": [],
+ "overriddenProperties": [],
+ "parent": {
+ "name": "snap",
+ "path": "snap.yyp",
+ },
+ "resourceVersion": "1.0",
+ "name": "oTestINI",
+ "tags": [],
+ "resourceType": "GMObject",
+}
\ No newline at end of file
diff --git a/objects/oTestMessagepack/Create_0.gml b/objects/oTestMessagepack/Create_0.gml
new file mode 100644
index 0000000..ec8643f
--- /dev/null
+++ b/objects/oTestMessagepack/Create_0.gml
@@ -0,0 +1,30 @@
+struct = {
+ a : true,
+ b : false,
+ c : undefined,
+ d : 1/9,
+ e : 15/100,
+ array : [
+ 5,
+ 6,
+ 7,
+ {
+ struct : "struct!",
+ nested : {
+ nested : "nested!",
+ array : [
+ "more",
+ "MORE",
+ "M O R E"
+ ]
+ }
+ }
+ ],
+ test : "text!",
+ test2 : "\"Hello world!\"",
+ url : "https://www.jujuadams.com/"
+};
+
+buffer = snap_to_messagepack(struct);
+show_debug_message(buffer_base64_encode(buffer, 0, -1));
+show_debug_message(snap_to_json(snap_from_messagepack(buffer), true, true));
\ No newline at end of file
diff --git a/objects/oTestMessagepack/oTestMessagepack.yy b/objects/oTestMessagepack/oTestMessagepack.yy
new file mode 100644
index 0000000..54ae13d
--- /dev/null
+++ b/objects/oTestMessagepack/oTestMessagepack.yy
@@ -0,0 +1,33 @@
+{
+ "spriteId": null,
+ "solid": false,
+ "visible": true,
+ "spriteMaskId": null,
+ "persistent": false,
+ "parentObjectId": null,
+ "physicsObject": false,
+ "physicsSensor": false,
+ "physicsShape": 1,
+ "physicsGroup": 1,
+ "physicsDensity": 0.5,
+ "physicsRestitution": 0.1,
+ "physicsLinearDamping": 0.1,
+ "physicsAngularDamping": 0.1,
+ "physicsFriction": 0.2,
+ "physicsStartAwake": true,
+ "physicsKinematic": false,
+ "physicsShapePoints": [],
+ "eventList": [
+ {"isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,"parent":{"name":"oTestMessagepack","path":"objects/oTestMessagepack/oTestMessagepack.yy",},"resourceVersion":"1.0","name":null,"tags":[],"resourceType":"GMEvent",},
+ ],
+ "properties": [],
+ "overriddenProperties": [],
+ "parent": {
+ "name": "snap",
+ "path": "snap.yyp",
+ },
+ "resourceVersion": "1.0",
+ "name": "oTestMessagepack",
+ "tags": [],
+ "resourceType": "GMObject",
+}
\ No newline at end of file
diff --git a/rooms/rMain/rMain.yy b/rooms/rMain/rMain.yy
index aad308d..5d73c45 100644
--- a/rooms/rMain/rMain.yy
+++ b/rooms/rMain/rMain.yy
@@ -14,7 +14,7 @@
],
"layers": [
{"instances":[
- {"properties":[],"isDnd":false,"objectId":{"name":"oTestBinary","path":"objects/oTestBinary/oTestBinary.yy",},"inheritCode":false,"hasCreationCode":false,"colour":4294967295,"rotation":0.0,"scaleX":1.0,"scaleY":1.0,"imageIndex":0,"imageSpeed":1.0,"inheritedItemId":null,"frozen":false,"ignore":false,"inheritItemSettings":false,"x":64.0,"y":32.0,"resourceVersion":"1.0","name":"inst_721877E5","tags":[],"resourceType":"GMRInstance",},
+ {"properties":[],"isDnd":false,"objectId":{"name":"oTestBinary","path":"objects/oTestBinary/oTestBinary.yy",},"inheritCode":false,"hasCreationCode":false,"colour":4294967295,"rotation":0.0,"scaleX":1.0,"scaleY":1.0,"imageIndex":0,"imageSpeed":1.0,"inheritedItemId":null,"frozen":false,"ignore":false,"inheritItemSettings":false,"x":32.0,"y":32.0,"resourceVersion":"1.0","name":"inst_6380F5B5","tags":[],"resourceType":"GMRInstance",},
],"visible":true,"depth":0,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Instances","tags":[],"resourceType":"GMRInstanceLayer",},
{"spriteId":null,"colour":4278190080,"x":0,"y":0,"htiled":false,"vtiled":false,"hspeed":0.0,"vspeed":0.0,"stretch":false,"animationFPS":15.0,"animationSpeedType":0,"userdefinedAnimFPS":false,"visible":true,"depth":100,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Background","tags":[],"resourceType":"GMRBackgroundLayer",},
],
@@ -22,7 +22,7 @@
"creationCodeFile": "",
"inheritCode": false,
"instanceCreationOrder": [
- {"name":"inst_721877E5","path":"rooms/rMain/rMain.yy",},
+ {"name":"inst_6380F5B5","path":"rooms/rMain/rMain.yy",},
],
"inheritCreationOrder": false,
"sequenceId": null,
diff --git a/scripts/snap_deep_copy/snap_deep_copy.gml b/scripts/snap_deep_copy/snap_deep_copy.gml
index b4f3650..f892c5e 100644
--- a/scripts/snap_deep_copy/snap_deep_copy.gml
+++ b/scripts/snap_deep_copy/snap_deep_copy.gml
@@ -2,7 +2,7 @@
///
/// @param struct/array The struct/array to be copied
///
-/// @jujuadams 2020-06-16
+/// @jujuadams 2020-06-24
function snap_deep_copy(_value)
{
@@ -28,11 +28,11 @@ function __snap_deep_copy(_value) constructor
if (is_struct(_value))
{
- _value = copy_struct(_source);
+ _value = copy_struct(_value);
}
else if (is_array(_value))
{
- _value = copy_array(_source);
+ _value = copy_array(_value);
}
variable_struct_set(_copy, _name, _value);
@@ -57,11 +57,11 @@ function __snap_deep_copy(_value) constructor
if (is_struct(_value))
{
- _value = copy_struct(_source);
+ _value = copy_struct(_value);
}
else if (is_array(_value))
{
- _value = copy_array(_source);
+ _value = copy_array(_value);
}
_copy[@ _i] = _value;
diff --git a/scripts/snap_from_binary/snap_from_binary.gml b/scripts/snap_from_binary/snap_from_binary.gml
index 389e240..9d8c9d4 100644
--- a/scripts/snap_from_binary/snap_from_binary.gml
+++ b/scripts/snap_from_binary/snap_from_binary.gml
@@ -1,11 +1,10 @@
-/// @return Nested struct/array data decoded from the buffer
+/// @return Nested struct/array data encoded from the buffer, using a proprietary format
///
-/// @param buffer Binary data to be decoded, created by sna_to_binary()
+/// @param buffer Binary data to be decoded, created by snap_to_binary()
/// @param [offset] Start position for binary decoding in the buffer. Defaults to 0, the start of the buffer
-/// @param [size] Number of bytes of data to be decoded. Set to -1 to use the entire size of the buffer. Defaults to -1
/// @param [destroyBuffer] Set to to destroy the input buffer. Defaults to
///
-/// @jujuadams 2020-05-02
+/// @jujuadams 2020-06-20
/*
0x00 - terminator
@@ -24,14 +23,11 @@ function snap_from_binary()
{
var _buffer = argument[0];
var _offset = ((argument_count > 1) && (argument[1] != undefined))? argument[1] : 0;
- var _size = ((argument_count > 2) && (argument[2] != undefined))? argument[2] : -1;
- var _destroy_buffer = ((argument_count > 3) && (argument[3] != undefined))? argument[3] : false;
-
- if (_size < 0) _size = buffer_get_size(_buffer) - _offset;
+ var _destroy_buffer = ((argument_count > 2) && (argument[2] != undefined))? argument[2] : false;
var _old_tell = buffer_tell(_buffer);
buffer_seek(_buffer, buffer_seek_start, _offset);
- var _result = (new __snap_from_binary_parser(_buffer, _size)).root;
+ var _result = (new __snap_from_binary_parser(_buffer)).root;
buffer_seek(_buffer, buffer_seek_start, _old_tell);
if (_destroy_buffer) buffer_delete(_buffer);
@@ -39,18 +35,16 @@ function snap_from_binary()
return _result;
}
-function __snap_from_binary_parser(_buffer, _buffer_size) constructor
+function __snap_from_binary_parser(_buffer) constructor
{
buffer = _buffer;
- buffer_size = _buffer_size;
-
root = undefined;
root_is_struct = false;
root_array_size = 0;
in_key = false;
key = undefined;
- while(buffer_tell(buffer) < buffer_size)
+ while(true)
{
if (in_key)
{
@@ -102,7 +96,7 @@ function __snap_from_binary_parser(_buffer, _buffer_size) constructor
case 0x01: //Struct
case 0x02: //Array
buffer_seek(buffer, buffer_seek_relative, -1);
- value = (new __snap_from_binary_parser(_buffer, _buffer_size)).root;
+ value = (new __snap_from_binary_parser(_buffer)).root;
break;
case 0x03: //String
diff --git a/scripts/snap_from_ini_file/snap_from_ini_file.gml b/scripts/snap_from_ini_file/snap_from_ini_file.gml
new file mode 100644
index 0000000..2ba4885
--- /dev/null
+++ b/scripts/snap_from_ini_file/snap_from_ini_file.gml
@@ -0,0 +1,28 @@
+/// @return Struct/array that represents the data in the INI file
+///
+/// N.B. That this script is only intended to read the .ini files that GM generates
+/// using the native ini_close() function. This is not a full implementation
+/// of the INI specification
+///
+/// @param filename The INI file to parse
+/// @param [tryReal] Try to convert strings to real values if possible. Defaults to
+///
+/// @jujuadams 2020-06-16
+
+function snap_from_ini_file()
+{
+ var _filename = argument[0];
+ var _try_real = (argument_count > 1)? argument[1] : undefined;
+
+ if (!file_exists(_filename))
+ {
+ show_error("snap_from_ini_file():\nFile \"" + string(_filename) + "\" could not be found\n ", false);
+ return {};
+ }
+
+ var _buffer = buffer_load(_filename);
+ var _string = buffer_read(_buffer, buffer_string);
+ buffer_delete(_buffer);
+
+ return snap_from_ini_string(_string, _try_real);
+}
\ No newline at end of file
diff --git a/scripts/snap_from_ini_file/snap_from_ini_file.yy b/scripts/snap_from_ini_file/snap_from_ini_file.yy
new file mode 100644
index 0000000..d9263d8
--- /dev/null
+++ b/scripts/snap_from_ini_file/snap_from_ini_file.yy
@@ -0,0 +1,12 @@
+{
+ "isDnD": false,
+ "isCompatibility": false,
+ "parent": {
+ "name": "Struct N' Array Parser",
+ "path": "folders/Struct N' Array Parser.yy",
+ },
+ "resourceVersion": "1.0",
+ "name": "snap_from_ini_file",
+ "tags": [],
+ "resourceType": "GMScript",
+}
\ No newline at end of file
diff --git a/scripts/snap_from_ini_string/snap_from_ini_string.gml b/scripts/snap_from_ini_string/snap_from_ini_string.gml
new file mode 100644
index 0000000..f6d7930
--- /dev/null
+++ b/scripts/snap_from_ini_string/snap_from_ini_string.gml
@@ -0,0 +1,179 @@
+/// @return Struct/array that represents the data in the INI file
+///
+/// N.B. That this script is only intended to read the .ini files that GM generates
+/// using the native ini_close() function. This is not a full implementation
+/// of the INI specification
+///
+/// @param string The INI string to parse
+/// @param [tryReal] Try to convert strings to real values if possible. Defaults to
+///
+/// @jujuadams 2020-06-16
+
+function snap_from_ini_string()
+{
+ var _string = argument[0];
+ var _try_real = ((argument_count > 1) && (argument[1] != undefined))? argument[1] : true;
+
+ if (_try_real)
+ {
+ show_error("snap_from_ini_string():\nUnfortunately, the [tryReal] feature is currently broken due to beta bugs.\nHopefully they get fixed soon!\n \nIn the meantime, please set [tryReal] to \n ", false);
+ _try_real = false;
+ }
+
+ var _size = string_byte_length(_string) + 1;
+ var _buffer = buffer_create(_size, buffer_grow, 1);
+ buffer_write(_buffer, buffer_string, _string);
+ buffer_seek(_buffer, buffer_seek_start, 0);
+
+ var _skip_whitespace = true;
+ var _in_comment = false;
+
+ var _in_key = false;
+ var _key_start = -1;
+ var _key = "";
+
+ var _in_value = false;
+ var _in_string = false;
+ var _seen_backslash = false;
+ var _value_start = 0;
+ var _last_non_whitespace = -1;
+
+ var _in_section = false;
+ var _section = undefined;
+ var _section_start = 0;
+ var _section_struct = undefined;
+
+ var _root = {};
+
+ repeat(_size)
+ {
+ var _value = buffer_read(_buffer, buffer_u8);
+
+ if (_in_comment) //Ignore everything apart from a newline if we've seen a comment
+ {
+ if ((_value == 10) || (_value == 13)) //Newline
+ {
+ _in_comment = false;
+ _skip_whitespace = true;
+ }
+ }
+ else if ((_value == ord(";")) && !_in_value) //We handle comments at the end of a key:value pair in the <_in_value> section
+ {
+ _in_comment = true;
+ }
+ else
+ {
+ if (_skip_whitespace && (_value > 32)) _skip_whitespace = false;
+
+ if (!_skip_whitespace)
+ {
+ if (_in_value)
+ {
+ if ((_value == 0) //Null
+ || (_value == 10) //Newline
+ || (_value == 13) //Newline
+ || (_value == ord(";")) //Comment semicolon
+ || (_in_string && (_value == ord("\"")) && (buffer_peek(_buffer, buffer_tell(_buffer)-2, buffer_u8) != ord("\\")))) //Unescaped double quote
+ {
+ if (_value == ord(";")) _in_comment = true;
+
+ var _old_tell = buffer_tell(_buffer);
+ if (_in_string) _value_start++;
+ buffer_poke(_buffer, _last_non_whitespace + 1, buffer_u8, 0x0);
+ buffer_seek(_buffer, buffer_seek_start, _value_start);
+
+ _value = buffer_read(_buffer, buffer_string);
+ buffer_seek(_buffer, buffer_seek_start, _old_tell);
+
+ if (_seen_backslash)
+ {
+ _value = string_replace_all(_value, "\\\\", chr(1)); //Turn all \\ into a system character
+ _value = string_replace_all(_value, "\\", ""); //Turn all single \ into nothing
+ _value = string_replace_all(_value, chr(1), "\\"); //Restore \\ from the system character
+ }
+
+ if (!_in_string && _try_real)
+ {
+ //TODO - Broken in runtime 23.1.1.123
+ try { _value = real(_value); } catch(_) {}
+ }
+
+ variable_struct_set(_section_struct, _key, _value);
+
+ _in_value = false;
+ _in_key = true;
+ _key_start = -1;
+ _skip_whitespace = true;
+ _in_string = false;
+ }
+ else
+ {
+ if (_value_start < 0)
+ {
+ _value_start = buffer_tell(_buffer) - 1;
+ if (_value == ord("\"")) _in_string = true;
+ }
+
+ if (_value > 32) _last_non_whitespace = buffer_tell(_buffer) - 1;
+ if ((_value == 32) && (buffer_peek(_buffer, buffer_tell(_buffer) - 2, buffer_u8) == ord("\\"))) _last_non_whitespace = buffer_tell(_buffer) - 1;
+ if (_value == ord("\\")) _seen_backslash = true;
+ }
+ }
+ else if (_value == ord("[")) //Open a section
+ {
+ _in_value = false;
+ _in_key = false;
+ _in_section = true;
+ _section_start = buffer_tell(_buffer);
+ }
+ else if (_in_section)
+ {
+ if (_value == ord("]"))
+ {
+ buffer_poke(_buffer, buffer_tell(_buffer)-1, buffer_u8, 0x0);
+ buffer_seek(_buffer, buffer_seek_start, _section_start);
+ _section = buffer_read(_buffer, buffer_string);
+
+ var _section_struct = variable_struct_get(_root, _section);
+ if (_section_struct == undefined)
+ {
+ _section_struct = {};
+ variable_struct_set(_root, _section, _section_struct);
+ }
+
+ _in_section = false;
+ _in_key = true;
+ _key_start = -1;
+ _skip_whitespace = true;
+ }
+ }
+ else if (_in_key)
+ {
+ if (_key_start < 0) _key_start = buffer_tell(_buffer)-1;
+
+ if (_value == ord("="))
+ {
+ var _old_tell = buffer_tell(_buffer);
+ buffer_poke(_buffer, _last_non_whitespace + 1, buffer_u8, 0x0);
+ buffer_seek(_buffer, buffer_seek_start, _key_start);
+ _key = buffer_read(_buffer, buffer_string);
+ buffer_seek(_buffer, buffer_seek_start, _old_tell);
+
+ _in_key = false;
+ _skip_whitespace = true;
+ _in_value = true;
+ _value_start = -1;
+ }
+ else
+ {
+ if (_value > 32) _last_non_whitespace = buffer_tell(_buffer) - 1;
+ }
+ }
+ }
+ }
+ }
+
+ buffer_delete(_buffer);
+
+ return _root
+}
\ No newline at end of file
diff --git a/scripts/snap_from_ini_string/snap_from_ini_string.yy b/scripts/snap_from_ini_string/snap_from_ini_string.yy
new file mode 100644
index 0000000..3fb348f
--- /dev/null
+++ b/scripts/snap_from_ini_string/snap_from_ini_string.yy
@@ -0,0 +1,12 @@
+{
+ "isDnD": false,
+ "isCompatibility": false,
+ "parent": {
+ "name": "Struct N' Array Parser",
+ "path": "folders/Struct N' Array Parser.yy",
+ },
+ "resourceVersion": "1.0",
+ "name": "snap_from_ini_string",
+ "tags": [],
+ "resourceType": "GMScript",
+}
\ No newline at end of file
diff --git a/scripts/snap_from_messagepack/snap_from_messagepack.gml b/scripts/snap_from_messagepack/snap_from_messagepack.gml
new file mode 100644
index 0000000..0a83e88
--- /dev/null
+++ b/scripts/snap_from_messagepack/snap_from_messagepack.gml
@@ -0,0 +1,234 @@
+/// @return Nested struct/array data decoded from the buffer, using the messagepack standard
+///
+/// More information on messagepack can be found here: https://msgpack.org/index.html
+///
+/// @param buffer Binary data to be decoded, created by snap_to_binary()
+/// @param [offset] Start position for binary decoding in the buffer. Defaults to 0, the start of the buffer
+/// @param [destroyBuffer] Set to to destroy the input buffer. Defaults to
+///
+/// @jujuadams 2020-06-20
+
+function snap_from_messagepack()
+{
+ var _buffer = argument[0];
+ var _offset = ((argument_count > 1) && (argument[1] != undefined))? argument[1] : 0;
+ var _destroy_buffer = ((argument_count > 3) && (argument[3] != undefined))? argument[3] : false;
+
+ var _old_tell = buffer_tell(_buffer);
+ buffer_seek(_buffer, buffer_seek_start, _offset);
+ var _result = (new __snap_from_messagepack_parser(_buffer)).root;
+ buffer_seek(_buffer, buffer_seek_start, _old_tell);
+
+ if (_destroy_buffer) buffer_delete(_buffer);
+
+ return _result;
+}
+
+function __snap_from_messagepack_parser(_buffer) constructor
+{
+ buffer = _buffer;
+
+ static read_struct = function(_size)
+ {
+ var _struct = {};
+ repeat(_size)
+ {
+ var _key = read_value();
+ var _value = read_value();
+ variable_struct_set(_struct, _key, _value);
+ }
+ return _struct;
+ }
+
+ static read_array = function(_size)
+ {
+ var _array = array_create(_size, undefined);
+ var _i = 0;
+ repeat(_size)
+ {
+ _array[@ _i] = read_value();
+ ++_i;
+ }
+ return _array;
+ }
+
+ static read_string = function(_size)
+ {
+ var _null_position = buffer_tell(buffer) + _size;
+ if (_null_position >= buffer_get_size(buffer))
+ {
+ //If the string runs into the end of the buffer, just read out the string
+ return buffer_read(buffer, buffer_text);
+ }
+
+ //Read the byte just after the end of the string and replace it with 0x00
+ var _peek = buffer_peek(buffer, _null_position, buffer_u8);
+ buffer_poke(buffer, _null_position, buffer_u8, 0x00);
+
+ //Get GM to read from the start of the string to the null byte
+ var _string = buffer_read(buffer, buffer_string);
+
+ //Take a step back and replace the original byte with what we found before
+ buffer_seek(buffer, buffer_seek_relative, -1);
+ buffer_poke(buffer, _null_position, buffer_u8, _peek);
+
+ return _string;
+ }
+
+ static read_bin = function(_size)
+ {
+ var _array = array_create(_size);
+
+ var _i = 0;
+ repeat(_size)
+ {
+ _array[@ _i] = buffer_read(buffer, buffer_u8);
+ ++_i;
+ }
+
+ return {
+ messagepack_datatype__ : "bin",
+ data : _array
+ };
+ }
+
+ static read_ext = function(_size)
+ {
+ var _type = buffer_read(buffer, buffer_s8);
+ var _array = array_create(_size);
+
+ var _i = 0;
+ repeat(_size)
+ {
+ _array[@ _i] = buffer_read(buffer, buffer_u8);
+ ++_i;
+ }
+
+ return {
+ messagepack_datatype__ : "ext",
+ type : _type,
+ data : _array
+ };
+ }
+
+ static buffer_read_little = function(_datatype)
+ {
+ switch(buffer_sizeof(_datatype))
+ {
+ case 1:
+ return buffer_read(buffer, _datatype);
+ break;
+
+ case 2:
+ buffer_poke(flip_buffer, 1, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 0, buffer_u8, buffer_read(buffer, buffer_u8));
+ break;
+
+ case 4:
+ buffer_poke(flip_buffer, 3, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 2, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 1, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 0, buffer_u8, buffer_read(buffer, buffer_u8));
+ break;
+
+ case 8:
+ buffer_poke(flip_buffer, 7, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 6, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 5, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 4, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 3, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 2, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 1, buffer_u8, buffer_read(buffer, buffer_u8));
+ buffer_poke(flip_buffer, 0, buffer_u8, buffer_read(buffer, buffer_u8));
+ break;
+ }
+
+ return buffer_peek(flip_buffer, 0, _datatype);
+ }
+
+ static read_value = function()
+ {
+ var _byte = buffer_read(buffer, buffer_u8);
+ if (_byte <= 0x7f) //positive fixint 0x00 -> 0x7f
+ {
+ //First 7 bits are the integer
+ return int64(_byte & 0x7f);
+ }
+ else if (_byte <= 0x8f) //fixmap 0x80 -> 0x8f
+ {
+ //Size is determined by the first 4 bits
+ return read_struct(_byte & 0x0f);
+ }
+ else if (_byte <= 0x9f) //fixarray 0x90 -> 0x9f
+ {
+ //Size is determined by the first 4 bits
+ return read_array(_byte & 0x0f);
+ }
+ else if (_byte <= 0xbf) //fixstr 0xa0 -> 0xbf
+ {
+ //Size is determined by the first 5 bits
+ return read_string(_byte & 0x1f);
+ }
+ else if ((_byte >= 0xe0) && (_byte <= 0xff)) //negative fixint 0xe0 -> 0xff
+ {
+ //First 5 bites are the integer
+ return -(_byte & 0x1f);
+ }
+ else switch(_byte)
+ {
+ case 0xc0: /*191*/ return undefined; break; //nil
+ case 0xc1: /*192*/ show_debug_message("snap_from_binary(): WARNING! Datatype 0xc1 found, but this value should never be used"); break; //Baby shoes for sale, never worn
+ case 0xc2: /*193*/ return bool(false); break; //false
+ case 0xc3: /*194*/ return bool(true ); break; //true
+
+ case 0xc4: /*195*/ return read_bin(buffer_read(buffer, buffer_u8 )); break; //bin 8
+ case 0xc5: /*196*/ return read_bin(buffer_read_little( buffer_u16)); break; //bin 16
+ case 0xc6: /*197*/ return read_bin(buffer_read_little( buffer_u32)); break; //bin 32
+
+ case 0xc7: /*198*/ return read_ext(buffer_read(buffer, buffer_u8 )); break; //ext 8
+ case 0xc8: /*199*/ return read_ext(buffer_read_little( buffer_u16)); break; //ext 16
+ case 0xc9: /*201*/ return read_ext(buffer_read_little( buffer_u32)); break; //ext 32
+
+ case 0xca: /*202*/ return buffer_read_little(buffer_f32); break; //float 32
+ case 0xcb: /*203*/ return buffer_read_little(buffer_f64); break; //float 64
+
+ case 0xcc: /*204*/ return buffer_read(buffer, buffer_u8 ); break; // uint 8
+ case 0xcd: /*205*/ return buffer_read_little( buffer_u16); break; // uint 16
+ case 0xce: /*206*/ return buffer_read_little( buffer_u32); break; // uint 32
+ case 0xcf: /*207*/ return buffer_read_little( buffer_u64); break; // uint 64
+
+ case 0xd0: /*208*/ return buffer_read(buffer, buffer_s8 ); break; // int 8
+ case 0xd1: /*209*/ return buffer_read_little( buffer_s16); break; // int 16
+ case 0xd2: /*210*/ return buffer_read_little( buffer_s32); break; // int 32
+ case 0xd3: /*211*/ return buffer_read_little( buffer_u64); break; // int 64 !!! No signed 64-bit integer read in GameMaker
+
+ case 0xd4: /*212*/ return read_ext( 1); break; //fixext 1
+ case 0xd5: /*213*/ return read_ext( 2); break; //fixext 2
+ case 0xd6: /*214*/ return read_ext( 4); break; //fixext 4
+ case 0xd7: /*215*/ return read_ext( 8); break; //fixext 8
+ case 0xd8: /*216*/ return read_ext(16); break; //fixext 16
+
+ case 0xd9: /*217*/ return read_string(buffer_read(buffer, buffer_u8 )); break; //str 8
+ case 0xda: /*218*/ return read_string(buffer_read_little( buffer_u16)); break; //str 16
+ case 0xdb: /*219*/ return read_string(buffer_read_little( buffer_u32)); break; //str 32
+
+ case 0xdc: /*220*/ return read_array( buffer_read_little(buffer_u16)); break; //array 16
+ case 0xdd: /*221*/ return read_array( buffer_read_little(buffer_u32)); break; //array 32
+
+ case 0xde: /*222*/ return read_struct(buffer_read_little(buffer_u16)); break; //map 16
+ case 0xdf: /*223*/ return read_struct(buffer_read_little(buffer_u32)); break; //map 32
+
+ default:
+ show_debug_message("snap_from_binary(): WARNING! Unsupported datatype " + string(_byte) + " found");
+ break;
+ }
+
+ return undefined;
+ }
+
+ //messagepack is big-endian because the creator hates normalcy
+ //This means we need to use a separate buffer for flipping values around
+ flip_buffer = buffer_create(8, buffer_fixed, 1);
+ root = read_value();
+ buffer_delete(flip_buffer);
+}
\ No newline at end of file
diff --git a/scripts/snap_from_messagepack/snap_from_messagepack.yy b/scripts/snap_from_messagepack/snap_from_messagepack.yy
new file mode 100644
index 0000000..64fcf39
--- /dev/null
+++ b/scripts/snap_from_messagepack/snap_from_messagepack.yy
@@ -0,0 +1,12 @@
+{
+ "isDnD": false,
+ "isCompatibility": false,
+ "parent": {
+ "name": "Struct N' Array Parser",
+ "path": "folders/Struct N' Array Parser.yy",
+ },
+ "resourceVersion": "1.0",
+ "name": "snap_from_messagepack",
+ "tags": [],
+ "resourceType": "GMScript",
+}
\ No newline at end of file
diff --git a/scripts/snap_to_binary/snap_to_binary.gml b/scripts/snap_to_binary/snap_to_binary.gml
index ff09143..fb725f9 100644
--- a/scripts/snap_to_binary/snap_to_binary.gml
+++ b/scripts/snap_to_binary/snap_to_binary.gml
@@ -1,4 +1,4 @@
-/// @return Buffer that contains binary encoded struct/array nested data
+/// @return Buffer that contains binary encoded struct/array nested data, using a proprietary format
///
/// @param struct/array The data to be encoded. Can contain structs, arrays, strings, and numbers. N.B. Will not encode ds_list, ds_map etc.
///
diff --git a/scripts/snap_to_messagepack/snap_to_messagepack.gml b/scripts/snap_to_messagepack/snap_to_messagepack.gml
new file mode 100644
index 0000000..7d9936c
--- /dev/null
+++ b/scripts/snap_to_messagepack/snap_to_messagepack.gml
@@ -0,0 +1,377 @@
+/// @return Buffer that represents the struct/array nested data, using the messagepack standard
+///
+/// More information on messagepack can be found here: https://msgpack.org/index.html
+///
+/// @param struct/array The data to be encoded. Can contain structs, arrays, strings, and numbers. N.B. Will not encode ds_list, ds_map etc.
+///
+/// @jujuadams 2020-06-20
+
+function snap_to_messagepack(_ds)
+{
+ return (new __snap_to_messagepack_parser(_ds)).buffer;
+}
+
+function __snap_to_messagepack_parser(_ds) constructor
+{
+ static write_struct = function(_struct)
+ {
+ var _names = variable_struct_get_names(_struct);
+ var _count = array_length(_names);
+
+ if (_count <= 0x0f)
+ {
+ //Size is determined by the first 4 bits
+ buffer_write(buffer, buffer_u8, 0x80 | _count);
+ }
+ else if (_count <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xde);
+ buffer_write_little(buffer_u16, _count);
+ }
+ else if (_count <= 0xffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xdf);
+ buffer_write_little(buffer_u32, _count);
+ }
+ else
+ {
+ show_error("snap_to_binary():\nTrying to write a struct longer than 4294967295 elements\n(How did you make a struct this big?!)\n ", true);
+ }
+
+ var _i = 0;
+ repeat(_count)
+ {
+ var _name = _names[_i];
+ write_value(_name);
+ write_value(variable_struct_get(_struct, _name));
+
+ ++_i;
+ }
+ }
+
+ static write_array = function(_array)
+ {
+ var _count = array_length(_array);
+
+ if (_count <= 0x0f)
+ {
+ //Size is determined by the first 4 bits
+ buffer_write(buffer, buffer_u8, 0x90 | _count);
+ }
+ else if (_count <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xdc);
+ buffer_write_little(buffer_u16, _count);
+ }
+ else if (_count <= 0xffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xdd);
+ buffer_write_little(buffer_u32, _count);
+ }
+ else
+ {
+ show_error("snap_to_binary():\nTrying to write an array longer than 4294967295 elements\n(How did you make an array this big?!)\n ", true);
+ }
+
+ var _i = 0;
+ repeat(_count)
+ {
+ write_value(_array[_i]);
+ ++_i;
+ }
+ }
+
+ static write_string = function(_string)
+ {
+ var _size = string_byte_length(_string);
+
+ if (_size <= 0x1f)
+ {
+ //Size is determined by the first 5 bits
+ buffer_write(buffer, buffer_u8, 0xa0 | _size);
+ }
+ else if (_size <= 0xff)
+ {
+ buffer_write(buffer, buffer_u8, 0xd9);
+ buffer_write(buffer, buffer_u8, _size);
+ }
+ else if (_size <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xda);
+ buffer_write_little(buffer_u16, _size);
+ }
+ else if (_size <= 0xffffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xdb);
+ buffer_write_little(buffer_u32, _size);
+ }
+ else
+ {
+ show_error("snap_to_binary():\nTrying to write a string longer than 4294967295 bytes\n(How did you make a string this big?!)\n ", true);
+ }
+
+ buffer_write(buffer, buffer_text, _string);
+ }
+
+ static write_number = function(_value)
+ {
+ if (is_int32(_value) || is_int64(_value) || (floor(_value) == _value))
+ {
+ //Integer
+ if (_value > 0)
+ {
+ //Positive, use an unsigned integer
+ if (_value <= 0x7f)
+ {
+ //First 7 bits are the integer
+ buffer_write(buffer, buffer_u8, _value);
+ }
+ else if (_value <= 0xff)
+ {
+ buffer_write(buffer, buffer_u8, 0xcc);
+ buffer_write(buffer, buffer_u8, _value);
+ }
+ else if (_value <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xcd);
+ buffer_write_little(buffer_u8, _value);
+ }
+ else if (_value <= 0xffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xce);
+ buffer_write_little(buffer_u8, _value);
+ }
+ else
+ {
+ buffer_write(buffer, buffer_u8, 0xcf);
+ buffer_write_little(buffer_u8, _value);
+ }
+ }
+ else if (_value == 0)
+ {
+ //Zero exactly
+ buffer_write(buffer, buffer_u8, 0x00);
+ }
+ else
+ {
+ //Negative, use a signed integer
+ _value = -_value;
+
+ if (_value <= 0x1f)
+ {
+ //First 5 bits are the integer
+ buffer_write(buffer, buffer_u8, 0xe0 | _value);
+ }
+ else if (_value <= 0xff)
+ {
+ buffer_write(buffer, buffer_u8, 0xd0);
+ buffer_write(buffer, buffer_u8, _value);
+ }
+ else if (_value <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xd1);
+ buffer_write_little(buffer_u8, _value);
+ }
+ else if (_value <= 0xffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xd2);
+ buffer_write_little(buffer_u8, _value);
+ }
+ else
+ {
+ //!!! No signed 64-bit integer read in GameMaker so this might be redundant
+ buffer_write(buffer, buffer_u8, 0xd3);
+ buffer_write_little(buffer_u8, _value);
+ }
+ }
+ }
+ else
+ {
+ //Floating Point
+ buffer_write(buffer, buffer_u8, 0xcb);
+ buffer_write_little(buffer_f64, _value);
+ }
+ }
+
+ static write_bin = function(_struct)
+ {
+ var _array = _struct.data;
+ var _count = array_length(_array);
+
+ if (_count <= 0xff)
+ {
+ buffer_write(buffer, buffer_u8, 0xc4);
+ buffer_write(buffer, buffer_u8, _count);
+ }
+ else if (_count <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xc5);
+ buffer_write_little(buffer_u16, _count);
+ }
+ else if (_count <= 0xffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xc6);
+ buffer_write_little(buffer_u32, _count);
+ }
+ else
+ {
+ show_error("snap_to_binary():\nTrying to write a binary array longer than 4294967295 elements\n(How did you make an array this big?!)\n ", true);
+ }
+
+ var _i = 0;
+ repeat(_count)
+ {
+ buffer_write(buffer, buffer_u8, _array[_i]);
+ ++_i;
+ }
+ }
+
+ static write_ext = function(_struct)
+ {
+ var _array = _struct.data;
+ var _count = array_length(_array);
+
+ if (_count == 1)
+ {
+ buffer_write(buffer, buffer_u8, 0xd4);
+ }
+ else if (_count == 2)
+ {
+ buffer_write(buffer, buffer_u8, 0xd5);
+ }
+ else if (_count == 4)
+ {
+ buffer_write(buffer, buffer_u8, 0xd6);
+ }
+ else if (_count == 8)
+ {
+ buffer_write(buffer, buffer_u8, 0xd7);
+ }
+ else if (_count == 16)
+ {
+ buffer_write(buffer, buffer_u8, 0xd8);
+ }
+ else if (_count <= 0xff)
+ {
+ buffer_write(buffer, buffer_u8, 0xc7);
+ buffer_write(buffer, buffer_u8, _count);
+ }
+ else if (_count <= 0xffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xc8);
+ buffer_write_little(buffer_u16, _count);
+ }
+ else if (_count <= 0xffffffff)
+ {
+ buffer_write(buffer, buffer_u8, 0xc9);
+ buffer_write_little(buffer_u32, _count);
+ }
+ else
+ {
+ show_error("snap_to_binary():\nTrying to write an extended binary array longer than 4294967295 elements\n(How did you make an array this big?!)\n ", true);
+ }
+
+ buffer_write(buffer, buffer_s8, _struct.type);
+
+ var _i = 0;
+ repeat(_count)
+ {
+ buffer_write(buffer, buffer_u8, _array[_i]);
+ ++_i;
+ }
+ }
+
+ static buffer_write_little = function(_datatype, _value)
+ {
+ switch(buffer_sizeof(_datatype))
+ {
+ case 1:
+ buffer_write(buffer, _datatype, _value);
+ break;
+
+ case 2:
+ buffer_poke(flip_buffer, 0, _datatype, _value);
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 1, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 0, buffer_u8));
+ break;
+
+ case 4:
+ buffer_poke(flip_buffer, 0, _datatype, _value);
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 3, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 2, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 1, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 0, buffer_u8));
+ break;
+
+ case 8:
+ buffer_poke(flip_buffer, 0, _datatype, _value);
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 7, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 6, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 5, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 4, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 3, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 2, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 1, buffer_u8));
+ buffer_write(buffer, buffer_u8, buffer_peek(flip_buffer, 0, buffer_u8));
+ break;
+ }
+ }
+
+ static write_value = function(_value)
+ {
+ if (is_struct(_value))
+ {
+ var _messagepack_datatype = variable_struct_get(_value, "messagepack_datatype__");
+ if (_messagepack_datatype == "bin")
+ {
+ write_bin(_value);
+ }
+ else if (_messagepack_datatype == "ext")
+ {
+ write_bin(_value);
+ }
+ else
+ {
+ //Normal struct
+ write_struct(_value);
+ }
+ }
+ else if (is_array(_value))
+ {
+ write_array(_value);
+ }
+ else if (is_string(_value))
+ {
+ write_string(_value);
+ }
+ else if (is_bool(_value))
+ {
+ buffer_write(buffer, buffer_u8, _value? 0xc3 : 0xc2);
+ }
+ else if (is_numeric(_value))
+ {
+ write_number(_value);
+ }
+ else if (is_undefined(_value))
+ {
+ buffer_write(buffer, buffer_u8, 0xc0);
+ }
+ else
+ {
+ show_error("snap_to_binary():\nUnsupported datatype \"" + typeof(_value) + "\"\n ", false);
+ buffer_write(buffer, buffer_u8, 0xc0);
+ }
+ }
+
+
+
+ //messagepack is big-endian because the creator hates normalcy
+ //This means we need to use a separate buffer for flipping values around
+ flip_buffer = buffer_create(8, buffer_fixed, 1);
+
+ buffer = buffer_create(1024, buffer_grow, 1);
+ write_value(_ds);
+ buffer_resize(buffer, max(1, buffer_tell(buffer)));
+
+ buffer_delete(flip_buffer);
+}
\ No newline at end of file
diff --git a/scripts/snap_to_messagepack/snap_to_messagepack.yy b/scripts/snap_to_messagepack/snap_to_messagepack.yy
new file mode 100644
index 0000000..39094eb
--- /dev/null
+++ b/scripts/snap_to_messagepack/snap_to_messagepack.yy
@@ -0,0 +1,12 @@
+{
+ "isDnD": false,
+ "isCompatibility": false,
+ "parent": {
+ "name": "Struct N' Array Parser",
+ "path": "folders/Struct N' Array Parser.yy",
+ },
+ "resourceVersion": "1.0",
+ "name": "snap_to_messagepack",
+ "tags": [],
+ "resourceType": "GMScript",
+}
\ No newline at end of file
diff --git a/snap.yyp b/snap.yyp
index 14ae6ee..e1695a6 100644
--- a/snap.yyp
+++ b/snap.yyp
@@ -1,16 +1,22 @@
{
"resources": [
- {"id":{"name":"snap_from_xml","path":"scripts/snap_from_xml/snap_from_xml.yy",},"order":7,},
- {"id":{"name":"snap_to_xml","path":"scripts/snap_to_xml/snap_to_xml.yy",},"order":6,},
+ {"id":{"name":"snap_from_xml","path":"scripts/snap_from_xml/snap_from_xml.yy",},"order":9,},
+ {"id":{"name":"snap_to_xml","path":"scripts/snap_to_xml/snap_to_xml.yy",},"order":8,},
{"id":{"name":"snap_deep_copy","path":"scripts/snap_deep_copy/snap_deep_copy.yy",},"order":1,},
+ {"id":{"name":"oTestINI","path":"objects/oTestINI/oTestINI.yy",},"order":6,},
{"id":{"name":"snap_from_json","path":"scripts/snap_from_json/snap_from_json.yy",},"order":3,},
{"id":{"name":"foreach","path":"scripts/foreach/foreach.yy",},"order":0,},
{"id":{"name":"snap_to_json","path":"scripts/snap_to_json/snap_to_json.yy",},"order":2,},
+ {"id":{"name":"snap_from_binary","path":"scripts/snap_from_binary/snap_from_binary.yy",},"order":5,},
{"id":{"name":"oTestJSON","path":"objects/oTestJSON/oTestJSON.yy",},"order":2,},
{"id":{"name":"snap_to_binary","path":"scripts/snap_to_binary/snap_to_binary.yy",},"order":4,},
- {"id":{"name":"snap_from_binary","path":"scripts/snap_from_binary/snap_from_binary.yy",},"order":5,},
- {"id":{"name":"oTestBinary","path":"objects/oTestBinary/oTestBinary.yy",},"order":3,},
+ {"id":{"name":"snap_to_messagepack","path":"scripts/snap_to_messagepack/snap_to_messagepack.yy",},"order":6,},
+ {"id":{"name":"snap_from_ini_string","path":"scripts/snap_from_ini_string/snap_from_ini_string.yy",},"order":10,},
+ {"id":{"name":"snap_from_messagepack","path":"scripts/snap_from_messagepack/snap_from_messagepack.yy",},"order":7,},
+ {"id":{"name":"oTestMessagepack","path":"objects/oTestMessagepack/oTestMessagepack.yy",},"order":3,},
+ {"id":{"name":"snap_from_ini_file","path":"scripts/snap_from_ini_file/snap_from_ini_file.yy",},"order":11,},
{"id":{"name":"oTestXML","path":"objects/oTestXML/oTestXML.yy",},"order":5,},
+ {"id":{"name":"oTestBinary","path":"objects/oTestBinary/oTestBinary.yy",},"order":7,},
{"id":{"name":"rMain","path":"rooms/rMain/rMain.yy",},"order":1,},
],
"Options": [
@@ -51,7 +57,7 @@
{"CopyToMask":153720560310812910,"filePath":"datafiles","resourceVersion":"1.0","name":"README.md","resourceType":"GMIncludedFile",},
],
"MetaData": {
- "IDEVersion": "23.1.1.141",
+ "IDEVersion": "23.1.1.157",
},
"resourceVersion": "1.3",
"name": "snap",