diff options
author | Juan Linietsky <reduzio@gmail.com> | 2015-12-13 12:53:29 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2015-12-13 12:53:29 -0300 |
commit | 95a469ad28e54fe05c3ae548725e557f91021d79 (patch) | |
tree | 52b9ee5ebd82671f69e4bab9417ebaf751914048 /core | |
parent | 451b1d91446f6e15763b4d6ec3bd6d74c2be8080 (diff) |
added binary API to StreamPeer, fixes #2863
Diffstat (limited to 'core')
-rw-r--r-- | core/io/stream_peer.cpp | 299 | ||||
-rw-r--r-- | core/io/stream_peer.h | 38 | ||||
-rw-r--r-- | core/typedefs.h | 12 |
3 files changed, 347 insertions, 2 deletions
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index b00b462eb6..a76b84bed3 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "stream_peer.h" - +#include "io/marshalls.h" Error StreamPeer::_put_data(const DVector<uint8_t>& p_data) { @@ -115,6 +115,271 @@ Array StreamPeer::_get_partial_data(int p_bytes) { } +void StreamPeer::set_big_endian(bool p_enable) { + + big_endian=p_enable; +} + +bool StreamPeer::is_big_endian_enabled() const { + + return big_endian; +} + + +void StreamPeer::put_u8(uint8_t p_val) { + put_data((const uint8_t*)&p_val,1); + +} + +void StreamPeer::put_8(int8_t p_val){ + + put_data((const uint8_t*)&p_val,1); +} +void StreamPeer::put_u16(uint16_t p_val){ + + if (big_endian) { + p_val=BSWAP16(p_val); + } + uint8_t buf[2]; + encode_uint16(p_val,buf); + put_data(buf,2); + +} +void StreamPeer::put_16(int16_t p_val){ + + if (big_endian) { + p_val=BSWAP16(p_val); + } + uint8_t buf[2]; + encode_uint16(p_val,buf); + put_data(buf,2); + +} +void StreamPeer::put_u32(uint32_t p_val){ + + if (big_endian) { + p_val=BSWAP32(p_val); + } + uint8_t buf[4]; + encode_uint32(p_val,buf); + put_data(buf,4); + +} +void StreamPeer::put_32(int32_t p_val){ + + if (big_endian) { + p_val=BSWAP32(p_val); + } + uint8_t buf[4]; + encode_uint32(p_val,buf); + put_data(buf,4); + +} +void StreamPeer::put_u64(uint64_t p_val){ + + if (big_endian) { + p_val=BSWAP64(p_val); + } + uint8_t buf[8]; + encode_uint64(p_val,buf); + put_data(buf,8); + +} +void StreamPeer::put_64(int64_t p_val){ + + if (big_endian) { + p_val=BSWAP64(p_val); + } + uint8_t buf[8]; + encode_uint64(p_val,buf); + put_data(buf,8); + +} +void StreamPeer::put_float(float p_val){ + + uint8_t buf[4]; + + encode_float(p_val,buf); + if (big_endian) { + uint32_t *p32=(uint32_t *)buf; + *p32=BSWAP32(*p32); + } + + put_data(buf,4); + +} +void StreamPeer::put_double(double p_val){ + + uint8_t buf[8]; + encode_double(p_val,buf); + if (big_endian) { + uint64_t *p64=(uint64_t *)buf; + *p64=BSWAP64(*p64); + } + put_data(buf,8); + +} +void StreamPeer::put_utf8_string(const String& p_string) { + + CharString cs=p_string.utf8(); + put_data((const uint8_t*)cs.get_data(),cs.length()); + +} +void StreamPeer::put_var(const Variant& p_variant){ + + int len=0; + Vector<uint8_t> buf; + encode_variant(p_variant,NULL,len); + buf.resize(len); + put_32(len); + encode_variant(p_variant,buf.ptr(),len); + put_data(buf.ptr(),buf.size()); + + +} + +uint8_t StreamPeer::get_u8(){ + + uint8_t buf[1]; + get_data(buf,1); + return buf[0]; +} +int8_t StreamPeer::get_8(){ + + uint8_t buf[1]; + get_data(buf,1); + return buf[0]; + +} +uint16_t StreamPeer::get_u16(){ + + uint8_t buf[2]; + get_data(buf,2); + uint16_t r = decode_uint16(buf); + if (big_endian) { + r=BSWAP16(r); + } + return r; + +} +int16_t StreamPeer::get_16(){ + + uint8_t buf[2]; + get_data(buf,2); + uint16_t r = decode_uint16(buf); + if (big_endian) { + r=BSWAP16(r); + } + return r; + +} +uint32_t StreamPeer::get_u32(){ + + uint8_t buf[4]; + get_data(buf,4); + uint32_t r = decode_uint32(buf); + if (big_endian) { + r=BSWAP32(r); + } + return r; + +} +int32_t StreamPeer::get_32(){ + + uint8_t buf[4]; + get_data(buf,4); + uint32_t r = decode_uint32(buf); + if (big_endian) { + r=BSWAP32(r); + } + return r; + +} +uint64_t StreamPeer::get_u64(){ + + uint8_t buf[8]; + get_data(buf,8); + uint64_t r = decode_uint64(buf); + if (big_endian) { + r=BSWAP64(r); + } + return r; + +} +int64_t StreamPeer::get_64(){ + + uint8_t buf[8]; + get_data(buf,8); + uint64_t r = decode_uint64(buf); + if (big_endian) { + r=BSWAP64(r); + } + return r; + +} +float StreamPeer::get_float(){ + + uint8_t buf[4]; + get_data(buf,4); + + if (big_endian) { + uint32_t *p32=(uint32_t *)buf; + *p32=BSWAP32(*p32); + } + + return decode_float(buf); +} + +float StreamPeer::get_double(){ + + uint8_t buf[8]; + get_data(buf,8); + + if (big_endian) { + uint64_t *p64=(uint64_t *)buf; + *p64=BSWAP64(*p64); + } + + return decode_double(buf); + +} +String StreamPeer::get_string(int p_bytes){ + + ERR_FAIL_COND_V(p_bytes<0,String()); + + Vector<char> buf; + buf.resize(p_bytes+1); + get_data((uint8_t*)&buf[0],p_bytes); + buf[p_bytes]=0; + return buf.ptr(); + +} +String StreamPeer::get_utf8_string(int p_bytes){ + + ERR_FAIL_COND_V(p_bytes<0,String()); + ERR_FAIL_COND_V(p_bytes<0,String()); + + Vector<uint8_t> buf; + buf.resize(p_bytes); + get_data(buf.ptr(),p_bytes); + + String ret; + ret.parse_utf8((const char*)buf.ptr(),buf.size()); + return ret; + +} +Variant StreamPeer::get_var(){ + + int len = get_32(); + Vector<uint8_t> var; + var.resize(len); + get_data(var.ptr(),len); + + Variant ret; + decode_variant(ret,var.ptr(),len); + return ret; +} + void StreamPeer::_bind_methods() { @@ -123,4 +388,36 @@ void StreamPeer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_data","bytes"),&StreamPeer::_get_data); ObjectTypeDB::bind_method(_MD("get_partial_data","bytes"),&StreamPeer::_get_partial_data); + + ObjectTypeDB::bind_method(_MD("get_available_bytes"),&StreamPeer::get_available_bytes); + + ObjectTypeDB::bind_method(_MD("set_big_endian","enable"),&StreamPeer::set_big_endian); + ObjectTypeDB::bind_method(_MD("is_big_endian_enabled"),&StreamPeer::is_big_endian_enabled); + + ObjectTypeDB::bind_method(_MD("put_8","val"),&StreamPeer::put_8); + ObjectTypeDB::bind_method(_MD("put_u8","val"),&StreamPeer::put_u8); + ObjectTypeDB::bind_method(_MD("put_16","val"),&StreamPeer::put_16); + ObjectTypeDB::bind_method(_MD("put_u16","val"),&StreamPeer::put_u16); + ObjectTypeDB::bind_method(_MD("put_32","val"),&StreamPeer::put_32); + ObjectTypeDB::bind_method(_MD("put_u32","val"),&StreamPeer::put_u32); + ObjectTypeDB::bind_method(_MD("put_64","val"),&StreamPeer::put_64); + ObjectTypeDB::bind_method(_MD("put_u64","val"),&StreamPeer::put_u64); + ObjectTypeDB::bind_method(_MD("put_float","val"),&StreamPeer::put_float); + ObjectTypeDB::bind_method(_MD("put_double","val"),&StreamPeer::put_double); + ObjectTypeDB::bind_method(_MD("put_utf8_string","val"),&StreamPeer::put_utf8_string); + ObjectTypeDB::bind_method(_MD("put_var","val:var"),&StreamPeer::put_var); + + ObjectTypeDB::bind_method(_MD("get_8"),&StreamPeer::get_8); + ObjectTypeDB::bind_method(_MD("get_u8"),&StreamPeer::get_u8); + ObjectTypeDB::bind_method(_MD("get_16"),&StreamPeer::get_16); + ObjectTypeDB::bind_method(_MD("get_u16"),&StreamPeer::get_u16); + ObjectTypeDB::bind_method(_MD("get_32"),&StreamPeer::get_32); + ObjectTypeDB::bind_method(_MD("get_u32"),&StreamPeer::get_u32); + ObjectTypeDB::bind_method(_MD("get_64"),&StreamPeer::get_64); + ObjectTypeDB::bind_method(_MD("get_u64"),&StreamPeer::get_u64); + ObjectTypeDB::bind_method(_MD("get_float"),&StreamPeer::get_float); + ObjectTypeDB::bind_method(_MD("get_double"),&StreamPeer::get_double); + ObjectTypeDB::bind_method(_MD("get_string","bytes"),&StreamPeer::get_string); + ObjectTypeDB::bind_method(_MD("get_utf8_string","bytes"),&StreamPeer::get_utf8_string); + ObjectTypeDB::bind_method(_MD("get_var:var"),&StreamPeer::get_var); } diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index e83fc71b93..2bb8f731b2 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -44,6 +44,8 @@ protected: Array _get_data(int p_bytes); Array _get_partial_data(int p_bytes); + bool big_endian; + public: virtual Error put_data(const uint8_t* p_data,int p_bytes)=0; ///< put a whole chunk of data, blocking until it sent @@ -52,7 +54,41 @@ public: virtual Error get_data(uint8_t* p_buffer, int p_bytes)=0; ///< read p_bytes of data, if p_bytes > available, it will block virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received)=0; ///< read as much data as p_bytes into buffer, if less was read, return in r_received - StreamPeer() {} + virtual int get_available_bytes() const=0; + + void set_big_endian(bool p_enable); + bool is_big_endian_enabled() const; + + void put_8(int8_t p_val); + void put_u8(uint8_t p_val); + void put_16(int16_t p_val); + void put_u16(uint16_t p_val); + void put_32(int32_t p_val); + void put_u32(uint32_t p_val); + void put_64(int64_t p_val); + void put_u64(uint64_t p_val); + void put_float(float p_val); + void put_double(double p_val); + void put_utf8_string(const String& p_string); + void put_var(const Variant& p_variant); + + uint8_t get_u8(); + int8_t get_8(); + uint16_t get_u16(); + int16_t get_16(); + uint32_t get_u32(); + int32_t get_32(); + uint64_t get_u64(); + int64_t get_64(); + float get_float(); + float get_double(); + String get_string(int p_bytes); + String get_utf8_string(int p_bytes); + Variant get_var(); + + + + StreamPeer() { big_endian=false; } }; #endif // STREAM_PEER_H diff --git a/core/typedefs.h b/core/typedefs.h index 6ca31fd137..460b2e2110 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -197,10 +197,22 @@ static inline int get_shift_from_power_of_2( unsigned int p_pixel ) { return -1; } +/** Swap 16 bits value for endianness */ +static inline uint16_t BSWAP16(uint16_t x) { + return (x>>8)|(x<<8); +} /** Swap 32 bits value for endianness */ static inline uint32_t BSWAP32(uint32_t x) { return((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24)); } +/** Swap 64 bits value for endianness */ + +static inline uint64_t BSWAP64(uint64_t x) { + x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; + x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; + x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; + return x; +} /** When compiling with RTTI, we can add an "extra" * layer of safeness in many operations, so dynamic_cast |