瀏覽代碼

added binary API to StreamPeer, fixes #2863

Juan Linietsky 9 年之前
父節點
當前提交
95a469ad28

+ 298 - 1
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);
 }

+ 37 - 1
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

+ 12 - 0
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

+ 7 - 0
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;

+ 2 - 0
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();
 

+ 9 - 0
drivers/unix/stream_peer_tcp_posix.cpp

@@ -38,6 +38,7 @@
 #include <string.h>
 #include <netdb.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 #ifndef NO_FCNTL
 	#ifdef __HAIKU__
 		#include <fcntl.h>
@@ -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;

+ 2 - 0
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;

+ 8 - 0
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 {
 

+ 2 - 0
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;

+ 2 - 3
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 {
 

+ 1 - 1
tools/editor/io_plugins/editor_export_scene.cpp

@@ -100,7 +100,7 @@ Vector<uint8_t> EditorSceneExportPlugin::custom_export(String& p_path,const Ref<
 
 	Vector<uint8_t> ret = FileAccess::get_file_as_array(tmp_path+"scnexp-"+md5+".scn");
 
-	p_path+=".optimized.scn";
+	p_path+=".converted.scn";
 
 	return ret;
 

+ 1 - 1
tools/editor/io_plugins/editor_sample_import_plugin.cpp

@@ -859,7 +859,7 @@ Vector<uint8_t> EditorSampleExportPlugin::custom_export(String& p_path,const Ref
 
 	ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
 
-	p_path=p_path.basename()+".smp";
+	p_path=p_path.basename()+".converted.smp";
 	return FileAccess::get_file_as_array(savepath);
 
 }

+ 2 - 2
tools/editor/io_plugins/editor_texture_import_plugin.cpp

@@ -1666,7 +1666,7 @@ EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode
 		if (pl.is_valid()) {
 			Vector<uint8_t> 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<uint8_t> 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;
 				}
 			}