├── .gitignore ├── SCsub ├── config.py ├── register_types.h ├── register_types.cpp ├── raw_packer.h ├── LICENSE.md ├── README.md └── raw_packer.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.pyc 3 | 4 | -------------------------------------------------------------------------------- /SCsub: -------------------------------------------------------------------------------- 1 | # SCsub 2 | Import('env') 3 | 4 | env.add_source_files(env.modules_sources,"*.cpp") 5 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | def can_build(platform): 2 | return True 3 | 4 | def configure(env): 5 | pass 6 | -------------------------------------------------------------------------------- /register_types.h: -------------------------------------------------------------------------------- 1 | /* register_types.h */ 2 | 3 | void register_rawpacker_types(); 4 | void unregister_rawpacker_types(); 5 | -------------------------------------------------------------------------------- /register_types.cpp: -------------------------------------------------------------------------------- 1 | /* register_types.cpp */ 2 | 3 | #include "register_types.h" 4 | #include "object_type_db.h" 5 | #include "raw_packer.h" 6 | 7 | void register_rawpacker_types() { 8 | 9 | ObjectTypeDB::register_type(); 10 | } 11 | 12 | void unregister_rawpacker_types() { 13 | //nothing to do here 14 | } 15 | -------------------------------------------------------------------------------- /raw_packer.h: -------------------------------------------------------------------------------- 1 | /* raw_packer.h */ 2 | 3 | #ifndef RAW_PACKER_H 4 | #define RAW_PACKER_H 5 | 6 | #include "error_list.h" 7 | #include "error_macros.h" 8 | #include "io/marshalls.h" 9 | #include "reference.h" 10 | #include "ustring.h" 11 | #include "variant.h" 12 | 13 | class RawPacker : public Reference { 14 | OBJ_TYPE(RawPacker,Reference); 15 | 16 | Error encode(const String& fmt, const Array& array, uint8_t *buf, int &len); 17 | Error decode(const String& fmt, Array& array, const uint8_t *buf, int size); 18 | 19 | bool is_digit(char c); 20 | 21 | protected: 22 | 23 | static void _bind_methods(); 24 | 25 | public: 26 | 27 | ByteArray pack(const String& fmt, const Array& array); 28 | Array unpack(const String& fmt, const ByteArray& array); 29 | 30 | RawPacker(); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `2015` `James McLean` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RawPacker 2 | 3 | Simple binary packing/unpacking for `RawArray` in Godot. 4 | 5 | ## About 6 | 7 | `RawPacker` allows `Variant` arrays to be packed into and unpacked from a `RawArray` using a format string. The approach was inspired by Python's `struct.pack` and `struct.unpack` functions. 8 | Packing/unpacking `RawArray` is useful for sending and storing data in a compact form. 9 | 10 | ## Installation 11 | 12 | Simply drop the `rawpacker` directory in your `godot/modules` directory and build for the platfom of your choice. 13 | 14 | ## Example 15 | 16 | ```python 17 | var raw_packer = RawPacker.new() 18 | var raw_array = raw_packer.pack("?iis16fhv", [false,1,2,"fixed string",3.14,-42,"variable string"]) 19 | var array = raw_packer.unpack("?iis16fhv", raw_array) 20 | print(array) 21 | ``` 22 | 23 | **Output:** 24 | ``` 25 | False, 1, 2, fixed string, 3.14, -42, variable string 26 | ``` 27 | 28 | ## Format Strings 29 | 30 | | Format | Serialized Type | Godot Type | Size (bytes) | 31 | |:------:|--------------------|------------|:------------:| 32 | | c | char | integer | 1 | 33 | | b | unsigned char | integer | 1 | 34 | | ? | unsigned char | boolean | 1 | 35 | | h | short | integer | 2 | 36 | | H | unsigned short | integer | 2 | 37 | | i | int | integer | 4 | 38 | | I | unsigned int | integer | 4 | 39 | | q | long long | integer | 8 | 40 | | Q | unsigned long long | integer | 8 | 41 | | f | float | real | 4 | 42 | | d | double | real | 8 | 43 | | s# | char[] | string | # | 44 | | v | char[] | string | variable | 45 | 46 | ## License 47 | Copyright (c) 2015 James McLean 48 | Licensed under the MIT license. 49 | -------------------------------------------------------------------------------- /raw_packer.cpp: -------------------------------------------------------------------------------- 1 | /* raw_packer.cpp */ 2 | 3 | #include "raw_packer.h" 4 | 5 | Error RawPacker::encode(const String& fmt, const Array& array, uint8_t *buf, int &len) { 6 | 7 | len=0; 8 | 9 | Variant::Type type; 10 | 11 | int j=0; 12 | 13 | for (int i=0;i=array.size(),ERR_INVALID_DATA); 16 | 17 | type = array[j].get_type(); 18 | 19 | switch (fmt[i]) { 20 | case 'c': 21 | case 'b': 22 | case 'B': { 23 | 24 | ERR_FAIL_COND_V(type!=Variant::INT,ERR_INVALID_DATA); 25 | 26 | if (buf) { 27 | *buf=(uint8_t)array[j]; 28 | buf+=1; 29 | } 30 | 31 | len+=1; 32 | 33 | } break; 34 | 35 | case '?': { 36 | 37 | ERR_FAIL_COND_V(type!=Variant::BOOL,ERR_INVALID_DATA); 38 | 39 | if (buf) { 40 | *buf=(uint8_t)array[j]; 41 | buf+=1; 42 | } 43 | 44 | len+=1; 45 | 46 | } break; 47 | 48 | case 'h': 49 | case 'H': { 50 | 51 | ERR_FAIL_COND_V(type!=Variant::INT,ERR_INVALID_DATA); 52 | 53 | if (buf) { 54 | encode_uint16((uint16_t)array[j],buf); 55 | buf+=2; 56 | } 57 | 58 | len+=2; 59 | 60 | } break; 61 | 62 | case 'i': 63 | case 'I': 64 | 65 | //windows doesn't like longs 66 | /*case 'l': 67 | case 'L':*/ { 68 | 69 | ERR_FAIL_COND_V(type!=Variant::INT,ERR_INVALID_DATA); 70 | 71 | if (buf) { 72 | encode_uint32((uint32_t)array[j],buf); 73 | buf+=4; 74 | } 75 | 76 | len+=4; 77 | 78 | } break; 79 | 80 | 81 | case 'q': 82 | case 'Q': { 83 | 84 | ERR_FAIL_COND_V(type!=Variant::INT,ERR_INVALID_DATA); 85 | 86 | if (buf) { 87 | encode_uint64((uint64_t)array[j],buf); 88 | buf+=8; 89 | } 90 | 91 | len+=8; 92 | 93 | } break; 94 | 95 | case 'f': { 96 | 97 | ERR_FAIL_COND_V(type!=Variant::REAL,ERR_INVALID_DATA); 98 | 99 | if (buf) { 100 | encode_float((float)array[j],buf); 101 | buf+= 4; 102 | } 103 | 104 | len += 4; 105 | 106 | } break; 107 | 108 | case 'd': { 109 | 110 | ERR_FAIL_COND_V(type!=Variant::REAL,ERR_INVALID_DATA); 111 | 112 | if (buf) { 113 | encode_double((double)array[j],buf); 114 | buf+=8; 115 | } 116 | 117 | len+=8; 118 | 119 | } break; 120 | 121 | case 's': { 122 | 123 | ERR_FAIL_COND_V(type!=Variant::STRING,ERR_INVALID_DATA); 124 | 125 | String size_str; 126 | 127 | for (int k=i+1;k