From e2df85ebf581863efad0e358efccde40fcd52ec5 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Tue, 16 Jun 2020 23:39:32 +0100 Subject: [PATCH 01/15] Adds INI parser --- objects/oTestINI/Create_0.gml | 22 +++ objects/oTestINI/oTestINI.yy | 33 ++++ rooms/rMain/rMain.yy | 4 +- .../snap_from_ini_file/snap_from_ini_file.gml | 28 +++ .../snap_from_ini_file/snap_from_ini_file.yy | 12 ++ .../snap_from_ini_string.gml | 173 ++++++++++++++++++ .../snap_from_ini_string.yy | 12 ++ snap.yyp | 3 + 8 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 objects/oTestINI/Create_0.gml create mode 100644 objects/oTestINI/oTestINI.yy create mode 100644 scripts/snap_from_ini_file/snap_from_ini_file.gml create mode 100644 scripts/snap_from_ini_file/snap_from_ini_file.yy create mode 100644 scripts/snap_from_ini_string/snap_from_ini_string.gml create mode 100644 scripts/snap_from_ini_string/snap_from_ini_string.yy 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/rooms/rMain/rMain.yy b/rooms/rMain/rMain.yy index aad308d..cf09098 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":"oTestINI","path":"objects/oTestINI/oTestINI.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_3C0C6F6","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_3C0C6F6","path":"rooms/rMain/rMain.yy",}, ], "inheritCreationOrder": false, "sequenceId": null, 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..d7242f7 --- /dev/null +++ b/scripts/snap_from_ini_string/snap_from_ini_string.gml @@ -0,0 +1,173 @@ +/// @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; + + 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/snap.yyp b/snap.yyp index 14ae6ee..5652525 100644 --- a/snap.yyp +++ b/snap.yyp @@ -3,13 +3,16 @@ {"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_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":"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_ini_string","path":"scripts/snap_from_ini_string/snap_from_ini_string.yy",},"order":8,}, {"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_from_ini_file","path":"scripts/snap_from_ini_file/snap_from_ini_file.yy",},"order":9,}, {"id":{"name":"oTestXML","path":"objects/oTestXML/oTestXML.yy",},"order":5,}, {"id":{"name":"rMain","path":"rooms/rMain/rMain.yy",},"order":1,}, ], From 2d5b2b88bffb786b2136cc285331b24a16316300 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Tue, 16 Jun 2020 23:46:47 +0100 Subject: [PATCH 02/15] Update README.md --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 67779a3..1891f0d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

SNAP: Struct N' Array Parser 3.0.0

+

SNAP: Struct N' Array Parser 3.1.0

Replacement for ds_map/ds_list-based encoding/decoding

@@ -16,6 +16,8 @@ Functions included are: 6. `snap_from_binary(buffer, [offset], [size], [destroyBuffer])` 7. `snap_from_xml(string)` 8. `snap_to_xml(struct/array, [alphabetizeStructs])` +9. `snap_from_ini_string(string, [tryReal])` +10. `snap_from_ini_file(filename, [tryReal])` ----- @@ -115,3 +117,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 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()`. + From 200f5708796fec41753b94e125a44d2d1ae6b5d0 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Tue, 16 Jun 2020 23:47:10 +0100 Subject: [PATCH 03/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1891f0d..6b37fa1 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Turns struct and array nested data into a XML string. The data must be structure 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 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)._ +_**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)._   From 974d38792195035c37247c30cc34af18211f24a1 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Tue, 16 Jun 2020 23:53:12 +0100 Subject: [PATCH 04/15] Adds warning for broken [tryReal] feature --- scripts/snap_from_ini_string/snap_from_ini_string.gml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/snap_from_ini_string/snap_from_ini_string.gml b/scripts/snap_from_ini_string/snap_from_ini_string.gml index d7242f7..f6d7930 100644 --- a/scripts/snap_from_ini_string/snap_from_ini_string.gml +++ b/scripts/snap_from_ini_string/snap_from_ini_string.gml @@ -14,6 +14,12 @@ 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); From 54fa9df30c2ace01f51d48160b6e2338eff1d75b Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 20:04:41 +0100 Subject: [PATCH 05/15] Converts binary read function to messagepack standard --- objects/oTestBinary/Create_0.gml | 7 +- rooms/rMain/rMain.yy | 4 +- scripts/snap_from_binary/snap_from_binary.gml | 298 +++++++++++------- .../snap_from_binary.yy | 12 + .../snap_from_binary_legacy.gml | 155 +++++++++ .../snap_from_binary_legacy.yy | 12 + scripts/snap_to_binary/snap_to_binary.gml | 40 --- .../snap_to_binary_legacy/snap_to_binary.yy | 12 + .../snap_to_binary_legacy.gml | 152 +++++++++ .../snap_to_binary_legacy.yy | 12 + snap.yyp | 4 +- 11 files changed, 556 insertions(+), 152 deletions(-) create mode 100644 scripts/snap_from_binary_legacy/snap_from_binary.yy create mode 100644 scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml create mode 100644 scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy create mode 100644 scripts/snap_to_binary_legacy/snap_to_binary.yy create mode 100644 scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml create mode 100644 scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy diff --git a/objects/oTestBinary/Create_0.gml b/objects/oTestBinary/Create_0.gml index 7830e3e..b54c584 100644 --- a/objects/oTestBinary/Create_0.gml +++ b/objects/oTestBinary/Create_0.gml @@ -25,4 +25,9 @@ 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 +var _base64 = "3wAAAAmhYQGlYXJyYXndAAAABAUGB98AAAACpm5lc3RlZN8AAAACpWFycmF53QAAAAOkbW9yZaRNT1JFp00gTyBSIEWmbmVzdGVkp25lc3RlZCGmc3RydWN0p3N0cnVjdCGhYgChY8ChZMs/vHHHHGWPnaFlyz/DMzMzMzMzpHRlc3SldGV4dCGldGVzdDKuIkhlbGxvIHdvcmxkISKjdXJsumh0dHBzOi8vd3d3Lmp1anVhZGFtcy5jb20v"; +var _buffer = buffer_base64_decode(_base64) + +show_debug_message(snap_to_json(snap_from_binary(_buffer), true, true)); + +//show_debug_message(snap_to_json(snap_from_binary(snap_to_binary(struct)), true, true)); \ No newline at end of file diff --git a/rooms/rMain/rMain.yy b/rooms/rMain/rMain.yy index cf09098..f02a31f 100644 --- a/rooms/rMain/rMain.yy +++ b/rooms/rMain/rMain.yy @@ -14,7 +14,7 @@ ], "layers": [ {"instances":[ - {"properties":[],"isDnd":false,"objectId":{"name":"oTestINI","path":"objects/oTestINI/oTestINI.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_3C0C6F6","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_23E8E0B","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_3C0C6F6","path":"rooms/rMain/rMain.yy",}, + {"name":"inst_23E8E0B","path":"rooms/rMain/rMain.yy",}, ], "inheritCreationOrder": false, "sequenceId": null, diff --git a/scripts/snap_from_binary/snap_from_binary.gml b/scripts/snap_from_binary/snap_from_binary.gml index 389e240..d8e2154 100644 --- a/scripts/snap_from_binary/snap_from_binary.gml +++ b/scripts/snap_from_binary/snap_from_binary.gml @@ -7,19 +7,6 @@ /// /// @jujuadams 2020-05-02 -/* - 0x00 - terminator - 0x01 - struct - 0x02 - array - 0x03 - string - 0x04 - f64 - 0x05 - - 0x06 - - 0x07 - - 0x08 - s32 - 0x09 - u64 -*/ - function snap_from_binary() { var _buffer = argument[0]; @@ -28,10 +15,11 @@ function snap_from_binary() var _destroy_buffer = ((argument_count > 3) && (argument[3] != undefined))? argument[3] : false; if (_size < 0) _size = buffer_get_size(_buffer) - _offset; + var _buffer_limit = _size + _offset; 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,117 +27,211 @@ 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; + buffer = _buffer; - root = undefined; - root_is_struct = false; - root_array_size = 0; - in_key = false; - key = undefined; + 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 _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, + array : _array + }; + } - while(buffer_tell(buffer) < buffer_size) + static buffer_read_litte = function(_datatype) { - if (in_key) + switch(buffer_sizeof(_datatype)) { - value = buffer_read(buffer, buffer_u8); - if (value == 0x00) //Terminator + 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() + { + //while(buffer_tell(buffer) < buffer_limit) + { + var _byte = buffer_read(buffer, buffer_u8); + if (_byte <= 0x7f) //positive fixint 0x00 -> 0x7f { - exit; + //First 7 bits are the integer + return int64(_byte & 0x7f); } - else if (value == 0x03) //String + else if (_byte <= 0x8f) //fixmap 0x80 -> 0x8f { - key = buffer_read(buffer, buffer_string); + //Size is determined by the first 4 bits + return read_struct(_byte & 0x0f); } - else + else if (_byte <= 0x9f) //fixarray 0x90 -> 0x9f { - show_error("Datatype for keys must be string (0x03), found " + string(value) + "\n ", false); - key = undefined; + //Size is determined by the first 4 bits + return read_array(_byte & 0x0f); } - - in_key = false; - } - else - { - value = buffer_read(buffer, buffer_u8); - - if (root == undefined) + else if (_byte <= 0xbf) //fixstr 0xa0 -> 0xbf { - if (value == 0x01) //Struct - { - root = {}; - root_is_struct = true; - } - else if (value == 0x02) //Array - { - root = []; - } - else - { - show_error("Unexpected datatype " + string(value) + ", was looking for a struct (0x01) or array (0x02) (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); - } + //Size is determined by the first 5 bits + return read_string(_byte & 0x1f); } - else + else if ((_byte >= 0xe0) && (_byte <= 0xff)) //negative fixint 0xe0 -> 0xff { - switch(value) - { - case 0x00: //Terminator - exit; - break; - - case 0x01: //Struct - case 0x02: //Array - buffer_seek(buffer, buffer_seek_relative, -1); - value = (new __snap_from_binary_parser(_buffer, _buffer_size)).root; - break; - - case 0x03: //String - value = buffer_read(buffer, buffer_string); - break; - - case 0x04: //f64 - value = buffer_read(buffer, buffer_f64); - break; - - case 0x05: // - value = false; - break; - - case 0x06: // - value = true; - break; - - case 0x07: // - value = undefined; - break; - - case 0x08: //s32 - value = buffer_read(buffer, buffer_s32); - break; - - case 0x09: //u64 - value = int64(buffer_read(buffer, buffer_u64)); - break; - - default: - show_error("Unsupported datatype " + string(value) + " (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); - value = undefined; - break; - } + //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_litte( buffer_u16)); break; //bin 16 + case 0xc6: /*197*/ return read_bin(buffer_read_litte( 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_litte( buffer_u16)); break; //ext 16 + case 0xc9: /*201*/ return read_ext(buffer_read_litte( buffer_u32)); break; //ext 32 + + case 0xca: /*202*/ return buffer_read_litte( buffer_f32); break; //float 32 + case 0xcb: /*203*/ return buffer_read_litte( buffer_f64); break; //float 64 + + case 0xcc: /*204*/ return buffer_read(buffer, buffer_u8 ); break; // uint 8 + case 0xcd: /*205*/ return buffer_read_litte( buffer_u16); break; // uint 16 + case 0xce: /*206*/ return buffer_read_litte( buffer_u32); break; // uint 32 + case 0xcf: /*207*/ return buffer_read_litte( buffer_u64); break; // uint 64 - if (root_is_struct) - { - variable_struct_set(root, key, value); - } - else - { - root[@ root_array_size++] = value; - } + case 0xd0: /*208*/ return buffer_read(buffer, buffer_s8 ); break; // int 8 + case 0xd1: /*209*/ return buffer_read_litte( buffer_s16); break; // int 16 + case 0xd2: /*210*/ return buffer_read_litte( buffer_s32); break; // int 32 + case 0xd3: /*211*/ return buffer_read_litte( 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_litte( buffer_u16)); break; //str 16 + case 0xdb: /*219*/ return read_string(buffer_read_litte( buffer_u32)); break; //str 32 + + case 0xdc: /*220*/ return read_array( buffer_read_litte(buffer_u16)); break; //array 16 + case 0xdd: /*221*/ return read_array( buffer_read_litte(buffer_u32)); break; //array 32 + + case 0xde: /*222*/ return read_struct(buffer_read_litte(buffer_u16)); break; //map 16 + case 0xdf: /*223*/ return read_struct(buffer_read_litte(buffer_u32)); break; //map 32 + + default: + show_debug_message("snap_from_binary(): WARNING! Unsupported datatype " + string(_byte) + " found"); + break; } - in_key = root_is_struct; + 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_binary_legacy/snap_from_binary.yy b/scripts/snap_from_binary_legacy/snap_from_binary.yy new file mode 100644 index 0000000..7104d7e --- /dev/null +++ b/scripts/snap_from_binary_legacy/snap_from_binary.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_binary", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml new file mode 100644 index 0000000..93cb923 --- /dev/null +++ b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml @@ -0,0 +1,155 @@ +/// @return Nested struct/array data decoded from the buffer +/// +/// @param buffer Binary data to be decoded, created by sna_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 + +/* + 0x00 - terminator + 0x01 - struct + 0x02 - array + 0x03 - string + 0x04 - f64 + 0x05 - + 0x06 - + 0x07 - + 0x08 - s32 + 0x09 - u64 +*/ + +function snap_from_binary_legacy() +{ + 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 _old_tell = buffer_tell(_buffer); + buffer_seek(_buffer, buffer_seek_start, _offset); + var _result = (new __snap_from_binary_parser(_buffer, _size)).root; + buffer_seek(_buffer, buffer_seek_start, _old_tell); + + if (_destroy_buffer) buffer_delete(_buffer); + + return _result; +} + +function __snap_from_binary_legacy_parser(_buffer, _buffer_size) 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) + { + if (in_key) + { + value = buffer_read(buffer, buffer_u8); + if (value == 0x00) //Terminator + { + exit; + } + else if (value == 0x03) //String + { + key = buffer_read(buffer, buffer_string); + } + else + { + show_error("Datatype for keys must be string (0x03), found " + string(value) + "\n ", false); + key = undefined; + } + + in_key = false; + } + else + { + value = buffer_read(buffer, buffer_u8); + + if (root == undefined) + { + if (value == 0x01) //Struct + { + root = {}; + root_is_struct = true; + } + else if (value == 0x02) //Array + { + root = []; + } + else + { + show_error("Unexpected datatype " + string(value) + ", was looking for a struct (0x01) or array (0x02) (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); + } + } + else + { + switch(value) + { + case 0x00: //Terminator + exit; + break; + + case 0x01: //Struct + case 0x02: //Array + buffer_seek(buffer, buffer_seek_relative, -1); + value = (new __snap_from_binary_parser(_buffer, _buffer_size)).root; + break; + + case 0x03: //String + value = buffer_read(buffer, buffer_string); + break; + + case 0x04: //f64 + value = buffer_read(buffer, buffer_f64); + break; + + case 0x05: // + value = false; + break; + + case 0x06: // + value = true; + break; + + case 0x07: // + value = undefined; + break; + + case 0x08: //s32 + value = buffer_read(buffer, buffer_s32); + break; + + case 0x09: //u64 + value = int64(buffer_read(buffer, buffer_u64)); + break; + + default: + show_error("Unsupported datatype " + string(value) + " (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); + value = undefined; + break; + } + + if (root_is_struct) + { + variable_struct_set(root, key, value); + } + else + { + root[@ root_array_size++] = value; + } + } + + in_key = root_is_struct; + } + } +} \ No newline at end of file diff --git a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy new file mode 100644 index 0000000..2cda20a --- /dev/null +++ b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.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_binary_legacy", + "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..692ae92 100644 --- a/scripts/snap_to_binary/snap_to_binary.gml +++ b/scripts/snap_to_binary/snap_to_binary.gml @@ -90,46 +90,6 @@ function __snap_to_binary_parser(_ds) constructor } else if (is_string(value)) { - buffer_write(buffer, buffer_u8, 0x03); //String - buffer_write(buffer, buffer_string, value); - } - else if (is_real(value)) - { - if (value == 0) - { - buffer_write(buffer, buffer_u8, 0x05); // - } - else if (value == 1) - { - buffer_write(buffer, buffer_u8, 0x06); // - } - else - { - buffer_write(buffer, buffer_u8, 0x04); //f64 - buffer_write(buffer, buffer_f64, value); - } - } - else if (is_bool(value)) - { - buffer_write(buffer, buffer_u8, value? 0x06 : 0x05); // or - } - else if (is_undefined(value)) - { - buffer_write(buffer, buffer_u8, 0x07); // - } - else if (is_int32(value)) - { - buffer_write(buffer, buffer_u8, 0x08); //s32 - buffer_write(buffer, buffer_s32, value); - } - else if (is_int64(value)) - { - buffer_write(buffer, buffer_u8, 0x09); //u64 - buffer_write(buffer, buffer_u64, value); - } - else - { - show_message("Datatype \"" + typeof(value) + "\" not supported"); } } diff --git a/scripts/snap_to_binary_legacy/snap_to_binary.yy b/scripts/snap_to_binary_legacy/snap_to_binary.yy new file mode 100644 index 0000000..073573d --- /dev/null +++ b/scripts/snap_to_binary_legacy/snap_to_binary.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_binary", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml b/scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml new file mode 100644 index 0000000..574e2dc --- /dev/null +++ b/scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml @@ -0,0 +1,152 @@ +/// @return Buffer that contains binary encoded struct/array nested data +/// +/// @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-05-02 + +/* + 0x00 - terminator + 0x01 - struct + 0x02 - array + 0x03 - string + 0x04 - f64 + 0x05 - + 0x06 - + 0x07 - + 0x08 - s32 + 0x09 - u64 +*/ + +function snap_to_binary_legacy(_ds) +{ + return (new __snap_to_binary_parser(_ds)).buffer; +} + +function __snap_to_binary_legacy_parser(_ds) constructor +{ + root = _ds; + buffer = buffer_create(1024, buffer_grow, 1); + + static parse_struct = function(_struct) + { + buffer_write(buffer, buffer_u8, 0x01); //Struct + + var _names = variable_struct_get_names(_struct); + var _count = array_length(_names); + var _i = 0; + repeat(_count) + { + var _name = _names[_i]; + value = variable_struct_get(_struct, _name); + + if (is_struct(_name) || is_array(_name)) + { + show_error("Key type \"" + typeof(_name) + "\" not supported\n ", false); + _name = string(ptr(_name)); + } + + buffer_write(buffer, buffer_u8, 0x03); //String + buffer_write(buffer, buffer_string, string(_name)); + + write_value(); + + ++_i; + } + + buffer_write(buffer, buffer_u8, 0x00); //Terminator + } + + + + static parse_array = function(_array) + { + + var _count = array_length(_array); + var _i = 0; + + buffer_write(buffer, buffer_u8, 0x02); ///Array + + repeat(_count) + { + value = _array[_i]; + write_value(); + ++_i; + } + + buffer_write(buffer, buffer_u8, 0x00); //Terminator + } + + + + static write_value = function() + { + if (is_struct(value)) + { + parse_struct(value); + } + else if (is_array(value)) + { + parse_array(value); + } + else if (is_string(value)) + { + buffer_write(buffer, buffer_u8, 0x03); //String + buffer_write(buffer, buffer_string, value); + } + else if (is_real(value)) + { + if (value == 0) + { + buffer_write(buffer, buffer_u8, 0x05); // + } + else if (value == 1) + { + buffer_write(buffer, buffer_u8, 0x06); // + } + else + { + buffer_write(buffer, buffer_u8, 0x04); //f64 + buffer_write(buffer, buffer_f64, value); + } + } + else if (is_bool(value)) + { + buffer_write(buffer, buffer_u8, value? 0x06 : 0x05); // or + } + else if (is_undefined(value)) + { + buffer_write(buffer, buffer_u8, 0x07); // + } + else if (is_int32(value)) + { + buffer_write(buffer, buffer_u8, 0x08); //s32 + buffer_write(buffer, buffer_s32, value); + } + else if (is_int64(value)) + { + buffer_write(buffer, buffer_u8, 0x09); //u64 + buffer_write(buffer, buffer_u64, value); + } + else + { + show_message("Datatype \"" + typeof(value) + "\" not supported"); + } + } + + + + if (is_struct(root)) + { + parse_struct(root); + } + else if (is_array(root)) + { + parse_array(root); + } + else + { + show_error("Value not struct or array. Returning empty string\n ", false); + } + + buffer_resize(buffer, buffer_tell(buffer)); +} \ No newline at end of file diff --git a/scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy b/scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy new file mode 100644 index 0000000..42865db --- /dev/null +++ b/scripts/snap_to_binary_legacy/snap_to_binary_legacy.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_binary_legacy", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/snap.yyp b/snap.yyp index 5652525..1d47cad 100644 --- a/snap.yyp +++ b/snap.yyp @@ -7,7 +7,9 @@ {"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_legacy","path":"scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy",},"order":11,}, {"id":{"name":"oTestJSON","path":"objects/oTestJSON/oTestJSON.yy",},"order":2,}, + {"id":{"name":"snap_to_binary_legacy","path":"scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy",},"order":10,}, {"id":{"name":"snap_to_binary","path":"scripts/snap_to_binary/snap_to_binary.yy",},"order":4,}, {"id":{"name":"snap_from_ini_string","path":"scripts/snap_from_ini_string/snap_from_ini_string.yy",},"order":8,}, {"id":{"name":"snap_from_binary","path":"scripts/snap_from_binary/snap_from_binary.yy",},"order":5,}, @@ -54,7 +56,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", From 87c5bcd0760922978739181d430f0095c6be644a Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 21:39:27 +0100 Subject: [PATCH 06/15] Adds writing a messagepack buffer --- objects/oTestBinary/Create_0.gml | 9 +- scripts/snap_from_binary/snap_from_binary.gml | 167 ++++---- .../snap_from_binary_legacy.gml | 4 +- scripts/snap_to_binary/snap_to_binary.gml | 383 +++++++++++++++--- 4 files changed, 409 insertions(+), 154 deletions(-) diff --git a/objects/oTestBinary/Create_0.gml b/objects/oTestBinary/Create_0.gml index b54c584..2739900 100644 --- a/objects/oTestBinary/Create_0.gml +++ b/objects/oTestBinary/Create_0.gml @@ -25,9 +25,6 @@ struct = { url : "https://www.jujuadams.com/" }; -var _base64 = "3wAAAAmhYQGlYXJyYXndAAAABAUGB98AAAACpm5lc3RlZN8AAAACpWFycmF53QAAAAOkbW9yZaRNT1JFp00gTyBSIEWmbmVzdGVkp25lc3RlZCGmc3RydWN0p3N0cnVjdCGhYgChY8ChZMs/vHHHHGWPnaFlyz/DMzMzMzMzpHRlc3SldGV4dCGldGVzdDKuIkhlbGxvIHdvcmxkISKjdXJsumh0dHBzOi8vd3d3Lmp1anVhZGFtcy5jb20v"; -var _buffer = buffer_base64_decode(_base64) - -show_debug_message(snap_to_json(snap_from_binary(_buffer), true, true)); - -//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/scripts/snap_from_binary/snap_from_binary.gml b/scripts/snap_from_binary/snap_from_binary.gml index d8e2154..a1295e8 100644 --- a/scripts/snap_from_binary/snap_from_binary.gml +++ b/scripts/snap_from_binary/snap_from_binary.gml @@ -1,22 +1,17 @@ /// @return Nested struct/array data decoded from the buffer /// -/// @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 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 _buffer_limit = _size + _offset; - var _old_tell = buffer_tell(_buffer); buffer_seek(_buffer, buffer_seek_start, _offset); var _result = (new __snap_from_binary_parser(_buffer)).root; @@ -89,7 +84,10 @@ function __snap_from_binary_parser(_buffer) constructor ++_i; } - return _array; + return { + messagepack_datatype__ : "bin", + data : _array + }; } static read_ext = function(_size) @@ -107,11 +105,11 @@ function __snap_from_binary_parser(_buffer) constructor return { messagepack_datatype__ : "ext", type : _type, - array : _array + data : _array }; } - static buffer_read_litte = function(_datatype) + static buffer_read_little = function(_datatype) { switch(buffer_sizeof(_datatype)) { @@ -148,85 +146,82 @@ function __snap_from_binary_parser(_buffer) constructor static read_value = function() { - //while(buffer_tell(buffer) < buffer_limit) + var _byte = buffer_read(buffer, buffer_u8); + if (_byte <= 0x7f) //positive fixint 0x00 -> 0x7f { - 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_litte( buffer_u16)); break; //bin 16 - case 0xc6: /*197*/ return read_bin(buffer_read_litte( 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_litte( buffer_u16)); break; //ext 16 - case 0xc9: /*201*/ return read_ext(buffer_read_litte( buffer_u32)); break; //ext 32 - - case 0xca: /*202*/ return buffer_read_litte( buffer_f32); break; //float 32 - case 0xcb: /*203*/ return buffer_read_litte( buffer_f64); break; //float 64 - - case 0xcc: /*204*/ return buffer_read(buffer, buffer_u8 ); break; // uint 8 - case 0xcd: /*205*/ return buffer_read_litte( buffer_u16); break; // uint 16 - case 0xce: /*206*/ return buffer_read_litte( buffer_u32); break; // uint 32 - case 0xcf: /*207*/ return buffer_read_litte( buffer_u64); break; // uint 64 - - case 0xd0: /*208*/ return buffer_read(buffer, buffer_s8 ); break; // int 8 - case 0xd1: /*209*/ return buffer_read_litte( buffer_s16); break; // int 16 - case 0xd2: /*210*/ return buffer_read_litte( buffer_s32); break; // int 32 - case 0xd3: /*211*/ return buffer_read_litte( 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_litte( buffer_u16)); break; //str 16 - case 0xdb: /*219*/ return read_string(buffer_read_litte( buffer_u32)); break; //str 32 - - case 0xdc: /*220*/ return read_array( buffer_read_litte(buffer_u16)); break; //array 16 - case 0xdd: /*221*/ return read_array( buffer_read_litte(buffer_u32)); break; //array 32 - - case 0xde: /*222*/ return read_struct(buffer_read_litte(buffer_u16)); break; //map 16 - case 0xdf: /*223*/ return read_struct(buffer_read_litte(buffer_u32)); break; //map 32 - - default: - show_debug_message("snap_from_binary(): WARNING! Unsupported datatype " + string(_byte) + " found"); - break; - } + //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 - return undefined; + 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 diff --git a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml index 93cb923..90149a1 100644 --- a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml +++ b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml @@ -1,6 +1,6 @@ -/// @return Nested struct/array data decoded from the buffer +/// @return Nested struct/array data encoded from the buffer /// -/// @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 diff --git a/scripts/snap_to_binary/snap_to_binary.gml b/scripts/snap_to_binary/snap_to_binary.gml index 692ae92..be5d74d 100644 --- a/scripts/snap_to_binary/snap_to_binary.gml +++ b/scripts/snap_to_binary/snap_to_binary.gml @@ -1,21 +1,8 @@ -/// @return Buffer that contains binary encoded struct/array nested data +/// @return Buffer that encodes the struct/array nested data using the messagepack standard /// /// @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-05-02 - -/* - 0x00 - terminator - 0x01 - struct - 0x02 - array - 0x03 - string - 0x04 - f64 - 0x05 - - 0x06 - - 0x07 - - 0x08 - s32 - 0x09 - u64 -*/ +/// @jujuadams 2020-06-20 function snap_to_binary(_ds) { @@ -24,89 +11,365 @@ function snap_to_binary(_ds) function __snap_to_binary_parser(_ds) constructor { - root = _ds; - buffer = buffer_create(1024, buffer_grow, 1); - - static parse_struct = function(_struct) + static write_struct = function(_struct) { - buffer_write(buffer, buffer_u8, 0x01); //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]; - value = variable_struct_get(_struct, _name); - - if (is_struct(_name) || is_array(_name)) - { - show_error("Key type \"" + typeof(_name) + "\" not supported\n ", false); - _name = string(ptr(_name)); - } - - buffer_write(buffer, buffer_u8, 0x03); //String - buffer_write(buffer, buffer_string, string(_name)); - - write_value(); + write_value(_name); + write_value(variable_struct_get(_struct, _name)); ++_i; } - - buffer_write(buffer, buffer_u8, 0x00); //Terminator } - - - static parse_array = function(_array) + static write_array = function(_array) { - var _count = array_length(_array); - var _i = 0; - buffer_write(buffer, buffer_u8, 0x02); ///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) { - value = _array[_i]; - write_value(); + write_value(_array[_i]); ++_i; } - - buffer_write(buffer, buffer_u8, 0x00); //Terminator } - - - static write_value = function() + static write_string = function(_string) { - if (is_struct(value)) + var _size = string_byte_length(_string); + + if (_size <= 0x1f) { - parse_struct(value); + //Size is determined by the first 5 bits + buffer_write(buffer, buffer_u8, 0xa0 | _size); } - else if (is_array(value)) + else if (_size <= 0xff) { - parse_array(value); + buffer_write(buffer, buffer_u8, 0xd9); + buffer_write(buffer, buffer_u8, _size); } - else if (is_string(value)) + 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; + } + } - if (is_struct(root)) + static write_ext = function(_struct) { - parse_struct(root); + 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; + } } - else if (is_array(root)) + + static buffer_write_little = function(_datatype, _value) { - parse_array(root); + 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; + } } - else + + static write_value = function(_value) { - show_error("Value not struct or array. Returning empty string\n ", false); + 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); + } } - buffer_resize(buffer, buffer_tell(buffer)); + + + //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 From 9c1b95c170d1933a21b35e307bc357a2ad8f4542 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 21:44:10 +0100 Subject: [PATCH 07/15] Renames messagepack functions --- objects/oTestBinary/oTestMessagepack.yy | 33 ++ objects/oTestMessagepack/Create_0.gml | 30 ++ objects/oTestMessagepack/oTestMessagepack.yy | 33 ++ rooms/rMain/rMain.yy | 4 +- scripts/snap_from_binary/snap_from_binary.gml | 319 ++++++--------- .../snap_from_binary_legacy.gml | 155 ------- .../snap_from_binary_legacy.yy | 12 - .../snap_from_messagepack.gml | 232 +++++++++++ .../snap_from_messagepack.yy} | 2 +- scripts/snap_to_binary/snap_to_binary.gml | 387 ++++-------------- .../snap_to_binary_legacy/snap_to_binary.yy | 12 - .../snap_to_binary_legacy.gml | 152 ------- .../snap_to_messagepack.gml | 375 +++++++++++++++++ .../snap_to_messagepack.yy} | 2 +- snap.yyp | 15 +- 15 files changed, 918 insertions(+), 845 deletions(-) create mode 100644 objects/oTestBinary/oTestMessagepack.yy create mode 100644 objects/oTestMessagepack/Create_0.gml create mode 100644 objects/oTestMessagepack/oTestMessagepack.yy delete mode 100644 scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml delete mode 100644 scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy create mode 100644 scripts/snap_from_messagepack/snap_from_messagepack.gml rename scripts/{snap_to_binary_legacy/snap_to_binary_legacy.yy => snap_from_messagepack/snap_from_messagepack.yy} (86%) delete mode 100644 scripts/snap_to_binary_legacy/snap_to_binary.yy delete mode 100644 scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml create mode 100644 scripts/snap_to_messagepack/snap_to_messagepack.gml rename scripts/{snap_from_binary_legacy/snap_from_binary.yy => snap_to_messagepack/snap_to_messagepack.yy} (87%) 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/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 f02a31f..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":32.0,"y":32.0,"resourceVersion":"1.0","name":"inst_23E8E0B","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_23E8E0B","path":"rooms/rMain/rMain.yy",}, + {"name":"inst_6380F5B5","path":"rooms/rMain/rMain.yy",}, ], "inheritCreationOrder": false, "sequenceId": null, diff --git a/scripts/snap_from_binary/snap_from_binary.gml b/scripts/snap_from_binary/snap_from_binary.gml index a1295e8..352230b 100644 --- a/scripts/snap_from_binary/snap_from_binary.gml +++ b/scripts/snap_from_binary/snap_from_binary.gml @@ -1,20 +1,37 @@ -/// @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 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-06-20 +/// @jujuadams 2020-05-02 + +/* + 0x00 - terminator + 0x01 - struct + 0x02 - array + 0x03 - string + 0x04 - f64 + 0x05 - + 0x06 - + 0x07 - + 0x08 - s32 + 0x09 - u64 +*/ 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 _old_tell = buffer_tell(_buffer); buffer_seek(_buffer, buffer_seek_start, _offset); - var _result = (new __snap_from_binary_parser(_buffer)).root; + var _result = (new __snap_from_binary_parser(_buffer, _size)).root; buffer_seek(_buffer, buffer_seek_start, _old_tell); if (_destroy_buffer) buffer_delete(_buffer); @@ -22,211 +39,117 @@ function snap_from_binary() return _result; } -function __snap_from_binary_parser(_buffer) constructor +function __snap_from_binary_parser(_buffer, _buffer_size) 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; - } + buffer = _buffer; + buffer_size = _buffer_size; - 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 - }; - } + root = undefined; + root_is_struct = false; + root_array_size = 0; + in_key = false; + key = undefined; - static buffer_read_little = function(_datatype) + while(buffer_tell(buffer) < buffer_size) { - switch(buffer_sizeof(_datatype)) + if (in_key) { - 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; + value = buffer_read(buffer, buffer_u8); + if (value == 0x00) //Terminator + { + exit; + } + else if (value == 0x03) //String + { + key = buffer_read(buffer, buffer_string); + } + else + { + show_error("Datatype for keys must be string (0x03), found " + string(value) + "\n ", false); + key = undefined; + } - 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; + in_key = false; } - - 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 + else { - //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 + value = buffer_read(buffer, buffer_u8); - 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 + if (root == undefined) + { + if (value == 0x01) //Struct + { + root = {}; + root_is_struct = true; + } + else if (value == 0x02) //Array + { + root = []; + } + else + { + show_error("Unexpected datatype " + string(value) + ", was looking for a struct (0x01) or array (0x02) (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); + } + } + else + { + switch(value) + { + case 0x00: //Terminator + exit; + break; + + case 0x01: //Struct + case 0x02: //Array + buffer_seek(buffer, buffer_seek_relative, -1); + value = (new __snap_from_binary_parser(_buffer, _buffer_size)).root; + break; + + case 0x03: //String + value = buffer_read(buffer, buffer_string); + break; + + case 0x04: //f64 + value = buffer_read(buffer, buffer_f64); + break; + + case 0x05: // + value = false; + break; + + case 0x06: // + value = true; + break; + + case 0x07: // + value = undefined; + break; + + case 0x08: //s32 + value = buffer_read(buffer, buffer_s32); + break; + + case 0x09: //u64 + value = int64(buffer_read(buffer, buffer_u64)); + break; + + default: + show_error("Unsupported datatype " + string(value) + " (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); + value = undefined; + break; + } + + if (root_is_struct) + { + variable_struct_set(root, key, value); + } + else + { + root[@ root_array_size++] = value; + } + } - 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; + in_key = root_is_struct; } - - 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_binary_legacy/snap_from_binary_legacy.gml b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml deleted file mode 100644 index 90149a1..0000000 --- a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.gml +++ /dev/null @@ -1,155 +0,0 @@ -/// @return Nested struct/array data encoded from the buffer -/// -/// @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 - -/* - 0x00 - terminator - 0x01 - struct - 0x02 - array - 0x03 - string - 0x04 - f64 - 0x05 - - 0x06 - - 0x07 - - 0x08 - s32 - 0x09 - u64 -*/ - -function snap_from_binary_legacy() -{ - 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 _old_tell = buffer_tell(_buffer); - buffer_seek(_buffer, buffer_seek_start, _offset); - var _result = (new __snap_from_binary_parser(_buffer, _size)).root; - buffer_seek(_buffer, buffer_seek_start, _old_tell); - - if (_destroy_buffer) buffer_delete(_buffer); - - return _result; -} - -function __snap_from_binary_legacy_parser(_buffer, _buffer_size) 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) - { - if (in_key) - { - value = buffer_read(buffer, buffer_u8); - if (value == 0x00) //Terminator - { - exit; - } - else if (value == 0x03) //String - { - key = buffer_read(buffer, buffer_string); - } - else - { - show_error("Datatype for keys must be string (0x03), found " + string(value) + "\n ", false); - key = undefined; - } - - in_key = false; - } - else - { - value = buffer_read(buffer, buffer_u8); - - if (root == undefined) - { - if (value == 0x01) //Struct - { - root = {}; - root_is_struct = true; - } - else if (value == 0x02) //Array - { - root = []; - } - else - { - show_error("Unexpected datatype " + string(value) + ", was looking for a struct (0x01) or array (0x02) (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); - } - } - else - { - switch(value) - { - case 0x00: //Terminator - exit; - break; - - case 0x01: //Struct - case 0x02: //Array - buffer_seek(buffer, buffer_seek_relative, -1); - value = (new __snap_from_binary_parser(_buffer, _buffer_size)).root; - break; - - case 0x03: //String - value = buffer_read(buffer, buffer_string); - break; - - case 0x04: //f64 - value = buffer_read(buffer, buffer_f64); - break; - - case 0x05: // - value = false; - break; - - case 0x06: // - value = true; - break; - - case 0x07: // - value = undefined; - break; - - case 0x08: //s32 - value = buffer_read(buffer, buffer_s32); - break; - - case 0x09: //u64 - value = int64(buffer_read(buffer, buffer_u64)); - break; - - default: - show_error("Unsupported datatype " + string(value) + " (position = " + string(buffer_tell(buffer) - 1) + ")\n ", false); - value = undefined; - break; - } - - if (root_is_struct) - { - variable_struct_set(root, key, value); - } - else - { - root[@ root_array_size++] = value; - } - } - - in_key = root_is_struct; - } - } -} \ No newline at end of file diff --git a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy b/scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy deleted file mode 100644 index 2cda20a..0000000 --- a/scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy +++ /dev/null @@ -1,12 +0,0 @@ -{ - "isDnD": false, - "isCompatibility": false, - "parent": { - "name": "Struct N' Array Parser", - "path": "folders/Struct N' Array Parser.yy", - }, - "resourceVersion": "1.0", - "name": "snap_from_binary_legacy", - "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..e8ef7f2 --- /dev/null +++ b/scripts/snap_from_messagepack/snap_from_messagepack.gml @@ -0,0 +1,232 @@ +/// @return Nested struct/array data decoded from the buffer, using the messagepack standard +/// +/// @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_to_binary_legacy/snap_to_binary_legacy.yy b/scripts/snap_from_messagepack/snap_from_messagepack.yy similarity index 86% rename from scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy rename to scripts/snap_from_messagepack/snap_from_messagepack.yy index 42865db..64fcf39 100644 --- a/scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy +++ b/scripts/snap_from_messagepack/snap_from_messagepack.yy @@ -6,7 +6,7 @@ "path": "folders/Struct N' Array Parser.yy", }, "resourceVersion": "1.0", - "name": "snap_to_binary_legacy", + "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 be5d74d..fb725f9 100644 --- a/scripts/snap_to_binary/snap_to_binary.gml +++ b/scripts/snap_to_binary/snap_to_binary.gml @@ -1,8 +1,21 @@ -/// @return Buffer that encodes the struct/array nested data using the messagepack standard +/// @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. /// -/// @jujuadams 2020-06-20 +/// @jujuadams 2020-05-02 + +/* + 0x00 - terminator + 0x01 - struct + 0x02 - array + 0x03 - string + 0x04 - f64 + 0x05 - + 0x06 - + 0x07 - + 0x08 - s32 + 0x09 - u64 +*/ function snap_to_binary(_ds) { @@ -11,365 +24,129 @@ function snap_to_binary(_ds) function __snap_to_binary_parser(_ds) constructor { - static write_struct = function(_struct) + root = _ds; + buffer = buffer_create(1024, buffer_grow, 1); + + static parse_struct = function(_struct) { + buffer_write(buffer, buffer_u8, 0x01); //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)); + value = variable_struct_get(_struct, _name); + + if (is_struct(_name) || is_array(_name)) + { + show_error("Key type \"" + typeof(_name) + "\" not supported\n ", false); + _name = string(ptr(_name)); + } + + buffer_write(buffer, buffer_u8, 0x03); //String + buffer_write(buffer, buffer_string, string(_name)); + + write_value(); ++_i; } + + buffer_write(buffer, buffer_u8, 0x00); //Terminator } - static write_array = function(_array) + + + static parse_array = function(_array) { + var _count = array_length(_array); + var _i = 0; - 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); - } + buffer_write(buffer, buffer_u8, 0x02); ///Array - var _i = 0; repeat(_count) { - write_value(_array[_i]); + value = _array[_i]; + write_value(); ++_i; } + + buffer_write(buffer, buffer_u8, 0x00); //Terminator } - static write_string = function(_string) + + + static write_value = function() { - var _size = string_byte_length(_string); - - if (_size <= 0x1f) + if (is_struct(value)) { - //Size is determined by the first 5 bits - buffer_write(buffer, buffer_u8, 0xa0 | _size); + parse_struct(value); } - else if (_size <= 0xff) + else if (is_array(value)) { - buffer_write(buffer, buffer_u8, 0xd9); - buffer_write(buffer, buffer_u8, _size); + parse_array(value); } - else if (_size <= 0xffff) + else if (is_string(value)) { - buffer_write(buffer, buffer_u8, 0xda); - buffer_write_little(buffer_u16, _size); + buffer_write(buffer, buffer_u8, 0x03); //String + buffer_write(buffer, buffer_string, value); } - else if (_size <= 0xffffffffff) + else if (is_real(value)) { - 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) + 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); - } + buffer_write(buffer, buffer_u8, 0x05); // } - else if (_value == 0) + else if (value == 1) { - //Zero exactly - buffer_write(buffer, buffer_u8, 0x00); + buffer_write(buffer, buffer_u8, 0x06); // } 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); - } + buffer_write(buffer, buffer_u8, 0x04); //f64 + buffer_write(buffer, buffer_f64, value); } } - else + else if (is_bool(value)) { - //Floating Point - buffer_write(buffer, buffer_u8, 0xcb); - buffer_write_little(buffer_f64, _value); + buffer_write(buffer, buffer_u8, value? 0x06 : 0x05); // or } - } - - static write_bin = function(_struct) - { - var _array = _struct.data; - var _count = array_length(_array); - - if (_count <= 0xff) + else if (is_undefined(value)) { - buffer_write(buffer, buffer_u8, 0xc4); - buffer_write(buffer, buffer_u8, _count); + buffer_write(buffer, buffer_u8, 0x07); // } - else if (_count <= 0xffff) + else if (is_int32(value)) { - buffer_write(buffer, buffer_u8, 0xc5); - buffer_write_little(buffer_u16, _count); + buffer_write(buffer, buffer_u8, 0x08); //s32 + buffer_write(buffer, buffer_s32, value); } - else if (_count <= 0xffffffff) + else if (is_int64(value)) { - buffer_write(buffer, buffer_u8, 0xc6); - buffer_write_little(buffer_u32, _count); + buffer_write(buffer, buffer_u8, 0x09); //u64 + buffer_write(buffer, buffer_u64, value); } 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; + show_message("Datatype \"" + typeof(value) + "\" not supported"); } } - static write_ext = function(_struct) + + + if (is_struct(root)) { - 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; - } + parse_struct(root); } - - static buffer_write_little = function(_datatype, _value) + else if (is_array(root)) { - 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; - } + parse_array(root); } - - static write_value = function(_value) + else { - 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); - } + show_error("Value not struct or array. Returning empty string\n ", false); } - - - //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); + buffer_resize(buffer, buffer_tell(buffer)); } \ No newline at end of file diff --git a/scripts/snap_to_binary_legacy/snap_to_binary.yy b/scripts/snap_to_binary_legacy/snap_to_binary.yy deleted file mode 100644 index 073573d..0000000 --- a/scripts/snap_to_binary_legacy/snap_to_binary.yy +++ /dev/null @@ -1,12 +0,0 @@ -{ - "isDnD": false, - "isCompatibility": false, - "parent": { - "name": "Struct N' Array Parser", - "path": "folders/Struct N' Array Parser.yy", - }, - "resourceVersion": "1.0", - "name": "snap_to_binary", - "tags": [], - "resourceType": "GMScript", -} \ No newline at end of file diff --git a/scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml b/scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml deleted file mode 100644 index 574e2dc..0000000 --- a/scripts/snap_to_binary_legacy/snap_to_binary_legacy.gml +++ /dev/null @@ -1,152 +0,0 @@ -/// @return Buffer that contains binary encoded struct/array nested data -/// -/// @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-05-02 - -/* - 0x00 - terminator - 0x01 - struct - 0x02 - array - 0x03 - string - 0x04 - f64 - 0x05 - - 0x06 - - 0x07 - - 0x08 - s32 - 0x09 - u64 -*/ - -function snap_to_binary_legacy(_ds) -{ - return (new __snap_to_binary_parser(_ds)).buffer; -} - -function __snap_to_binary_legacy_parser(_ds) constructor -{ - root = _ds; - buffer = buffer_create(1024, buffer_grow, 1); - - static parse_struct = function(_struct) - { - buffer_write(buffer, buffer_u8, 0x01); //Struct - - var _names = variable_struct_get_names(_struct); - var _count = array_length(_names); - var _i = 0; - repeat(_count) - { - var _name = _names[_i]; - value = variable_struct_get(_struct, _name); - - if (is_struct(_name) || is_array(_name)) - { - show_error("Key type \"" + typeof(_name) + "\" not supported\n ", false); - _name = string(ptr(_name)); - } - - buffer_write(buffer, buffer_u8, 0x03); //String - buffer_write(buffer, buffer_string, string(_name)); - - write_value(); - - ++_i; - } - - buffer_write(buffer, buffer_u8, 0x00); //Terminator - } - - - - static parse_array = function(_array) - { - - var _count = array_length(_array); - var _i = 0; - - buffer_write(buffer, buffer_u8, 0x02); ///Array - - repeat(_count) - { - value = _array[_i]; - write_value(); - ++_i; - } - - buffer_write(buffer, buffer_u8, 0x00); //Terminator - } - - - - static write_value = function() - { - if (is_struct(value)) - { - parse_struct(value); - } - else if (is_array(value)) - { - parse_array(value); - } - else if (is_string(value)) - { - buffer_write(buffer, buffer_u8, 0x03); //String - buffer_write(buffer, buffer_string, value); - } - else if (is_real(value)) - { - if (value == 0) - { - buffer_write(buffer, buffer_u8, 0x05); // - } - else if (value == 1) - { - buffer_write(buffer, buffer_u8, 0x06); // - } - else - { - buffer_write(buffer, buffer_u8, 0x04); //f64 - buffer_write(buffer, buffer_f64, value); - } - } - else if (is_bool(value)) - { - buffer_write(buffer, buffer_u8, value? 0x06 : 0x05); // or - } - else if (is_undefined(value)) - { - buffer_write(buffer, buffer_u8, 0x07); // - } - else if (is_int32(value)) - { - buffer_write(buffer, buffer_u8, 0x08); //s32 - buffer_write(buffer, buffer_s32, value); - } - else if (is_int64(value)) - { - buffer_write(buffer, buffer_u8, 0x09); //u64 - buffer_write(buffer, buffer_u64, value); - } - else - { - show_message("Datatype \"" + typeof(value) + "\" not supported"); - } - } - - - - if (is_struct(root)) - { - parse_struct(root); - } - else if (is_array(root)) - { - parse_array(root); - } - else - { - show_error("Value not struct or array. Returning empty string\n ", false); - } - - buffer_resize(buffer, buffer_tell(buffer)); -} \ No newline at end of file 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..94767f0 --- /dev/null +++ b/scripts/snap_to_messagepack/snap_to_messagepack.gml @@ -0,0 +1,375 @@ +/// @return Buffer that represents the struct/array nested data, using the messagepack standard +/// +/// @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_from_binary_legacy/snap_from_binary.yy b/scripts/snap_to_messagepack/snap_to_messagepack.yy similarity index 87% rename from scripts/snap_from_binary_legacy/snap_from_binary.yy rename to scripts/snap_to_messagepack/snap_to_messagepack.yy index 7104d7e..39094eb 100644 --- a/scripts/snap_from_binary_legacy/snap_from_binary.yy +++ b/scripts/snap_to_messagepack/snap_to_messagepack.yy @@ -6,7 +6,7 @@ "path": "folders/Struct N' Array Parser.yy", }, "resourceVersion": "1.0", - "name": "snap_from_binary", + "name": "snap_to_messagepack", "tags": [], "resourceType": "GMScript", } \ No newline at end of file diff --git a/snap.yyp b/snap.yyp index 1d47cad..d03d80d 100644 --- a/snap.yyp +++ b/snap.yyp @@ -1,21 +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":5,}, + {"id":{"name":"snap_to_xml","path":"scripts/snap_to_xml/snap_to_xml.yy",},"order":4,}, {"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_legacy","path":"scripts/snap_from_binary_legacy/snap_from_binary_legacy.yy",},"order":11,}, + {"id":{"name":"snap_from_binary","path":"scripts/snap_from_binary/snap_from_binary.yy",},"order":11,}, {"id":{"name":"oTestJSON","path":"objects/oTestJSON/oTestJSON.yy",},"order":2,}, - {"id":{"name":"snap_to_binary_legacy","path":"scripts/snap_to_binary_legacy/snap_to_binary_legacy.yy",},"order":10,}, - {"id":{"name":"snap_to_binary","path":"scripts/snap_to_binary/snap_to_binary.yy",},"order":4,}, + {"id":{"name":"snap_to_binary","path":"scripts/snap_to_binary/snap_to_binary.yy",},"order":10,}, + {"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":8,}, - {"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_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":9,}, {"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": [ From 27b73e0155e2fdf96f6165fd5fa9cfe9d40fafcb Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 21:48:52 +0100 Subject: [PATCH 08/15] Removes size argument from snap_from_binary() --- scripts/snap_from_binary/snap_from_binary.gml | 16 +++++----------- snap.yyp | 8 ++++---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/scripts/snap_from_binary/snap_from_binary.gml b/scripts/snap_from_binary/snap_from_binary.gml index 352230b..7705795 100644 --- a/scripts/snap_from_binary/snap_from_binary.gml +++ b/scripts/snap_from_binary/snap_from_binary.gml @@ -2,7 +2,6 @@ /// /// @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 @@ -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/snap.yyp b/snap.yyp index d03d80d..db50f06 100644 --- a/snap.yyp +++ b/snap.yyp @@ -7,14 +7,14 @@ {"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":11,}, + {"id":{"name":"snap_from_binary","path":"scripts/snap_from_binary/snap_from_binary.yy",},"order":9,}, {"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":10,}, + {"id":{"name":"snap_to_binary","path":"scripts/snap_to_binary/snap_to_binary.yy",},"order":8,}, {"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":8,}, + {"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":9,}, + {"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,}, From 9439f63b18de354c513b237cddba015e993a7b20 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 21:54:14 +0100 Subject: [PATCH 09/15] Update README.md --- README.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6b37fa1..9a40cd2 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,13 @@ Functions included are: 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])` -9. `snap_from_ini_string(string, [tryReal])` -10. `snap_from_ini_file(filename, [tryReal])` +6. `snap_from_binary(buffer, [offset], [destroyBuffer])` +7. `snap_to_messagepack(struct/array)` +8. `snap_from_messagepack(buffer, [offset], [destroyBuffer])` +9. `snap_from_xml(string)` +10. `snap_to_xml(struct/array, [alphabetizeStructs])` +11. `snap_from_ini_string(string, [tryReal])` +12. `snap_from_ini_file(filename, [tryReal])` ----- @@ -46,7 +48,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.   @@ -58,13 +60,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()`.   From 4252de1a876f99de2c4d94bed8b6101057489eda Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 21:55:45 +0100 Subject: [PATCH 10/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a40cd2..3468fd9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

SNAP: Struct N' Array Parser 3.1.0

+

SNAP: Struct N' Array Parser 3.2.0

Replacement for ds_map/ds_list-based encoding/decoding

From f7a5473eb8bfea36214ac9dd1662dd5eb01b31d9 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sat, 20 Jun 2020 21:56:19 +0100 Subject: [PATCH 11/15] Updates some comments --- scripts/snap_from_binary/snap_from_binary.gml | 2 +- scripts/snap_from_messagepack/snap_from_messagepack.gml | 2 ++ scripts/snap_to_messagepack/snap_to_messagepack.gml | 2 ++ snap.yyp | 8 ++++---- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/snap_from_binary/snap_from_binary.gml b/scripts/snap_from_binary/snap_from_binary.gml index 7705795..9d8c9d4 100644 --- a/scripts/snap_from_binary/snap_from_binary.gml +++ b/scripts/snap_from_binary/snap_from_binary.gml @@ -4,7 +4,7 @@ /// @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-05-02 +/// @jujuadams 2020-06-20 /* 0x00 - terminator diff --git a/scripts/snap_from_messagepack/snap_from_messagepack.gml b/scripts/snap_from_messagepack/snap_from_messagepack.gml index e8ef7f2..0a83e88 100644 --- a/scripts/snap_from_messagepack/snap_from_messagepack.gml +++ b/scripts/snap_from_messagepack/snap_from_messagepack.gml @@ -1,4 +1,6 @@ /// @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 diff --git a/scripts/snap_to_messagepack/snap_to_messagepack.gml b/scripts/snap_to_messagepack/snap_to_messagepack.gml index 94767f0..7d9936c 100644 --- a/scripts/snap_to_messagepack/snap_to_messagepack.gml +++ b/scripts/snap_to_messagepack/snap_to_messagepack.gml @@ -1,4 +1,6 @@ /// @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. /// diff --git a/snap.yyp b/snap.yyp index db50f06..e1695a6 100644 --- a/snap.yyp +++ b/snap.yyp @@ -1,15 +1,15 @@ { "resources": [ - {"id":{"name":"snap_from_xml","path":"scripts/snap_from_xml/snap_from_xml.yy",},"order":5,}, - {"id":{"name":"snap_to_xml","path":"scripts/snap_to_xml/snap_to_xml.yy",},"order":4,}, + {"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":9,}, + {"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":8,}, + {"id":{"name":"snap_to_binary","path":"scripts/snap_to_binary/snap_to_binary.yy",},"order":4,}, {"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,}, From 5ece5bad31b5e7664d323c5377748743ba042a11 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sun, 21 Jun 2020 10:51:55 +0100 Subject: [PATCH 12/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3468fd9..eaed9bf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

SNAP: Struct N' Array Parser 3.2.0

-

Replacement for ds_map/ds_list-based encoding/decoding

+

Easy struct/array saving and loading

Download the .yymps here

From e3a05981c27fe3d5ac3eb7dee7248f0c828259fa Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sun, 21 Jun 2020 10:55:15 +0100 Subject: [PATCH 13/15] Update README.md --- README.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index eaed9bf..0b3eec9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

SNAP: Struct N' Array Parser 3.2.0

+

SNAP: Struct N' Array Parsing 3.2.0

Easy struct/array saving and loading

@@ -6,20 +6,15 @@   -Functions included are: - -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], [destroyBuffer])` -7. `snap_to_messagepack(struct/array)` -8. `snap_from_messagepack(buffer, [offset], [destroyBuffer])` -9. `snap_from_xml(string)` -10. `snap_to_xml(struct/array, [alphabetizeStructs])` -11. `snap_from_ini_string(string, [tryReal])` -12. `snap_from_ini_file(filename, [tryReal])` +Functions included can: + +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 ----- From aeee49e1dfa09b5b3cd009f6e0efb2e33e273218 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Sun, 21 Jun 2020 10:55:42 +0100 Subject: [PATCH 14/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b3eec9..fb932a9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

SNAP: Struct N' Array Parsing 3.2.0

+

SNAP: Struct N' Array Parsing 3.2.0

Easy struct/array saving and loading

From 25d59aa1d3b9297ef9c6044d7db57cb18ea6e129 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Wed, 24 Jun 2020 21:13:57 +0100 Subject: [PATCH 15/15] Fixes bug in snap_deep_copy() --- scripts/snap_deep_copy/snap_deep_copy.gml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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;