Advertisement

bytebuffer class

Started by June 23, 2010 01:57 PM
1 comment, last by _orm_ 14 years, 5 months ago
One of the things I found a bit irksome was that I did not know whether the AngelScript arrays were all in a contiguous area of memory. This property is vital for things such as OpenGL where many functions take pointers to areas of memory mapped out via either a char array or an std::vector.

This is a quick code snippet that should help many of youall out with this. Basically it's just a class wrapping the std::vector class with char or unsigned char passed as the template paramater. This should also give you an idea of how to expose many of the types found under the std namespace. I personally am using this class for a sockets extension I wrote (yes I will release it when I am done testing). Use this as you wish:

EDIT1: Added another class, ubytebuffer. Also made the classes suck less by not inheriting from the std::vector, option to hold one internally. Also overloaded the constructor to take a string for when the need arises.

// bytebuffer.h#include <vector>#include <iostream>#define CHECK if(r<0){std::cout<<"Error in angelscript exposure. Line:"<<__LINE__<<"\nFile: "<<std::string(__FILE__)<<"\n";}typedef uint8 unsigned char;class bytebuffer {public:	bytebuffer(){ref_count = 1;};	bytebuffer(const std::string& in);		bytebuffer(const bytebuffer& b){};	~bytebuffer(){}		uint8 front();	uint8 back();	uint8 operator[](int pos);	int size();	void get_str(std::string& in);	void flush();	void AddRef(){ref_count++;};	void Release(){if(--ref_count==0){delete this;}};		std::vector<char> invec;		int ref_count;};class ubytebuffer {public:	ubytebuffer(){ref_count = 1;};	ubytebuffer(const std::string& in);		ubytebuffer(const ubytebuffer& b){};	~ubytebuffer(){}		uint8 front();	uint8 back();	uint8 operator[](int pos);	int size();	void get_str(std::string& in);	void flush();	void AddRef(){ref_count++;};	void Release(){if(--ref_count==0){delete this;}};		std::vector<uint8> invec;		int ref_count;};// bytebuffer.cppbytebuffer::bytebuffer(const std::string& in)	: invec(in.c_str(),in.c_str()+in.size()){}uint8 bytebuffer::front(){	return invec.front();}uint8 bytebuffer::back(){	return invec.back();}uint8 bytebuffer::operator[](int pos){	return invec[pos];}int bytebuffer::size(){	return invec.size();}void bytebuffer::get_str(std::string& in){	for(int i=0;i<invec.size();i++)		in.push_back((char)invec);}void bytebuffer::flush(){	invec.clear();}ubytebuffer::ubytebuffer(const std::string& in)	: invec(in.c_str(),in.c_str()+in.size()){}uint8 ubytebuffer::front(){	return invec.front();}uint8 ubytebuffer::back(){	return invec.back();}uint8 ubytebuffer::operator[](int pos){	return invec[pos];}int ubytebuffer::size(){	return invec.size();}extern "C" ubytebuffer::get_str(std::string& in){	for(int i=0;i<invec.size();i++)		in.push_back((char)invec);}extern "C" ubytebuffer::flush(){	invec.clear();}extern "C" bytebuffer* ByteBufferFactory(){	return new bytebuffer;}extern "C" bytebuffer* ByteBufferFactory__(const std::string& in){	return new bytebuffer(in);}ARAD_C ubytebuffer* uByteBufferFactory(){	return new ubytebuffer;}ARAD_C ubytebuffer* uByteBufferFactory__(const std::string& in){	return new ubytebuffer(in);}ARAD_C void RegisterByteBuffer(asIScriptEngine* e){	int r;	r=e->RegisterObjectType("bytebuffer",sizeof(bytebuffer), asOBJ_REF);CHECK;	r=e->RegisterObjectBehaviour("bytebuffer",asBEHAVE_FACTORY,"bytebuffer@ f()",asFUNCTION(ByteBufferFactory),asCALL_CDECL);CHECK;	r=e->RegisterObjectBehaviour("bytebuffer",asBEHAVE_FACTORY,"bytebuffer@ f(const string ∈)",asFUNCTION(ByteBufferFactory__),asCALL_CDECL);CHECK;	r=e->RegisterObjectBehaviour("bytebuffer",asBEHAVE_ADDREF,"void f()",asMETHOD(bytebuffer,AddRef),asCALL_THISCALL);CHECK;	r=e->RegisterObjectBehaviour("bytebuffer",asBEHAVE_RELEASE,"void f()",asMETHOD(bytebuffer,Release),asCALL_THISCALL);CHECK;	r=e->RegisterObjectBehaviour("bytebuffer",asBEHAVE_INDEX,"int8 f(int)",asMETHOD(bytebuffer,operator[]),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("bytebuffer","int size()",asMETHOD(bytebuffer,size),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("bytebuffer","int8 back()",asMETHOD(bytebuffer,back),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("bytebuffer","int8 front()",asMETHOD(bytebuffer,front),asCALL_THISCALL);CHECK;		r=e->RegisterObjectType("ubytebuffer",sizeof(ubytebuffer), asOBJ_REF);CHECK;	r=e->RegisterObjectBehaviour("ubytebuffer",asBEHAVE_FACTORY,"ubytebuffer@ f()",asFUNCTION(uByteBufferFactory),asCALL_CDECL);CHECK;	r=e->RegisterObjectBehaviour("ubytebuffer",asBEHAVE_FACTORY,"ubytebuffer@ f(const string ∈)",asFUNCTION(uByteBufferFactory__),asCALL_CDECL);CHECK;	r=e->RegisterObjectBehaviour("ubytebuffer",asBEHAVE_ADDREF,"void f()",asMETHOD(ubytebuffer,AddRef),asCALL_THISCALL);CHECK;	r=e->RegisterObjectBehaviour("ubytebuffer",asBEHAVE_RELEASE,"void f()",asMETHOD(ubytebuffer,Release),asCALL_THISCALL);CHECK;	r=e->RegisterObjectBehaviour("ubytebuffer",asBEHAVE_INDEX,"uint8 f(int)",asMETHOD(ubytebuffer,operator[]),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("ubytebuffer","int size()",asMETHOD(ubytebuffer,size),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("ubytebuffer","uint8 back()",asMETHOD(ubytebuffer,back),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("ubytebuffer","uint8 front()",asMETHOD(ubytebuffer,front),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("ubytebuffer","void get_string(string@)",asMETHOD(ubytebuffer,get_str),asCALL_THISCALL);CHECK;	r=e->RegisterObjectMethod("ubytebuffer","void flush(string@)",asMETHOD(ubytebuffer,flush),asCALL_THISCALL);CHECK;}


Then here is a script you can use to test it. Just replace println with whatever function you use to output stuff. println is basically std::cout<<whatever<<"\n":
// ByteBuffer test for AngelRAD... oh crap wasn't supposed to let that one slip =p// Author: ormvoid run(){	println("bytebuffer test");		println("testing string input.\n");		ubytebuffer@ second=ubytebuffer(string("GOBBLE!!!"));	for(int j=0;j!=second.size();j++)	{		string t();		t+=second[j];		println(t);	}	string@ s = string();	second.get_string(s);		println(s);}


[Edited by - _orm_ on June 26, 2010 1:48:11 PM]
The script arrays are using continuous memory layout for primitive types, but not for object types.

Anyway, I'll add a link to this post on the wiki, to better allow others to find it in the future.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement
Sweet. I've made some improvements to the class so I'll post those when I get a chance.

Also, primitivesd are all thatare really needed for functions like those in OpenGL. I personally just find using a dedicated reference class to be easier to work with. Also, I did not see anything in the documentation as to how AngelScript arrays translate to C++ arrays. Maybe that could be clarified next release?

[Edited by - _orm_ on June 26, 2010 1:00:53 PM]

This topic is closed to new replies.

Advertisement