From 95a469ad28e54fe05c3ae548725e557f91021d79 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 13 Dec 2015 12:53:29 -0300 Subject: added binary API to StreamPeer, fixes #2863 --- core/io/stream_peer.cpp | 299 ++++++++++++++++++++- core/io/stream_peer.h | 38 ++- core/typedefs.h | 12 + drivers/openssl/stream_peer_openssl.cpp | 7 + drivers/openssl/stream_peer_openssl.h | 2 + drivers/unix/stream_peer_tcp_posix.cpp | 9 + drivers/unix/stream_peer_tcp_posix.h | 2 + platform/windows/stream_peer_winsock.cpp | 8 + platform/windows/stream_peer_winsock.h | 2 + tools/doc/doc_data.cpp | 5 +- tools/editor/io_plugins/editor_export_scene.cpp | 2 +- .../io_plugins/editor_sample_import_plugin.cpp | 2 +- .../io_plugins/editor_texture_import_plugin.cpp | 4 +- 13 files changed, 383 insertions(+), 9 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& 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 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 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 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 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 diff --git a/drivers/openssl/stream_peer_openssl.cpp b/drivers/openssl/stream_peer_openssl.cpp index ef07f11334..81795fdc60 100644 --- a/drivers/openssl/stream_peer_openssl.cpp +++ b/drivers/openssl/stream_peer_openssl.cpp @@ -479,6 +479,13 @@ Error StreamPeerOpenSSL::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_ return OK; } +int StreamPeerOpenSSL::get_available_bytes() const { + + ERR_FAIL_COND_V(!connected,0); + + return SSL_pending(ssl); + +} StreamPeerOpenSSL::StreamPeerOpenSSL() { ctx=NULL; diff --git a/drivers/openssl/stream_peer_openssl.h b/drivers/openssl/stream_peer_openssl.h index a66b641dd4..64f5a1d7ac 100644 --- a/drivers/openssl/stream_peer_openssl.h +++ b/drivers/openssl/stream_peer_openssl.h @@ -71,6 +71,8 @@ public: virtual Error get_data(uint8_t* p_buffer, int p_bytes); virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + virtual int get_available_bytes() const; + static void initialize_ssl(); static void finalize_ssl(); diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 5aa3915893..edf5e02971 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #ifndef NO_FCNTL #ifdef __HAIKU__ #include @@ -367,6 +368,14 @@ Error StreamPeerTCPPosix::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r return read(p_buffer, p_bytes, r_received, false); }; +int StreamPeerTCPPosix::get_available_bytes() const { + + unsigned long len; + int ret = ioctl(sockfd,FIONREAD,&len); + ERR_FAIL_COND_V(ret==-1,0) + return len; + +} IP_Address StreamPeerTCPPosix::get_connected_host() const { return peer_host; diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 9b1716ac42..817f24c91c 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -67,6 +67,8 @@ public: virtual Error get_data(uint8_t* p_buffer, int p_bytes); virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + virtual int get_available_bytes() const; + void set_socket(int p_sockfd, IP_Address p_host, int p_port); virtual IP_Address get_connected_host() const; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index e8245c92e5..5bc3e34107 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -342,6 +342,14 @@ void StreamPeerWinsock::set_nodelay(bool p_enabled) { setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int)); } +int StreamPeerWinsock::get_available_bytes() const { + + unsigned long len; + int ret = ioctlsocket(sockfd,FIONREAD,&len); + ERR_FAIL_COND_V(ret==-1,0) + return len; + +} IP_Address StreamPeerWinsock::get_connected_host() const { diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h index 373b502d2c..5dd836aa0c 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.h @@ -66,6 +66,8 @@ public: virtual Error get_data(uint8_t* p_buffer, int p_bytes); virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + virtual int get_available_bytes() const; + void set_socket(int p_sockfd, IP_Address p_host, int p_port); virtual IP_Address get_connected_host() const; diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index c1d3e5e314..3161e380b9 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -187,14 +187,13 @@ void DocData::generate(bool p_basic_types) { arginfo=E->get().return_val; - if (arginfo.type==Variant::NIL) - continue; #ifdef DEBUG_METHODS_ENABLED if (m && m->get_return_type()!=StringName()) method.return_type=m->get_return_type(); - else + else if (arginfo.type!=Variant::NIL) { #endif method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); + } } else { diff --git a/tools/editor/io_plugins/editor_export_scene.cpp b/tools/editor/io_plugins/editor_export_scene.cpp index cd5c34e53b..dff41a59ed 100644 --- a/tools/editor/io_plugins/editor_export_scene.cpp +++ b/tools/editor/io_plugins/editor_export_scene.cpp @@ -100,7 +100,7 @@ Vector EditorSceneExportPlugin::custom_export(String& p_path,const Ref< Vector ret = FileAccess::get_file_as_array(tmp_path+"scnexp-"+md5+".scn"); - p_path+=".optimized.scn"; + p_path+=".converted.scn"; return ret; diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index 7888246956..28eeb56b4b 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -859,7 +859,7 @@ Vector EditorSampleExportPlugin::custom_export(String& p_path,const Ref ERR_FAIL_COND_V(err!=OK,Vector()); - p_path=p_path.basename()+".smp"; + p_path=p_path.basename()+".converted.smp"; return FileAccess::get_file_as_array(savepath); } diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 8d5a4f1dcf..92ef57a69e 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -1666,7 +1666,7 @@ EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode if (pl.is_valid()) { Vector ce = pl->custom_export(p_path,p_platform); if (ce.size()) { - p_path=p_path.basename()+".tex"; + p_path=p_path.basename()+".converted.tex"; return ce; } } @@ -1680,7 +1680,7 @@ EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode if (pl.is_valid()) { Vector ce = pl->custom_export(p_path,p_platform); if (ce.size()) { - p_path=p_path.basename()+".tex"; + p_path=p_path.basename()+".converted.tex"; return ce; } } -- cgit v1.2.3