LOGIN • JOININ

CGD::buffer

1... CGD::buffer란...
메모리 버퍼에 데이터의 직렬화를 위해 데이터를 읽고 쓰는 기능을 제공하는 버퍼 시스템입니다.

예를 들어 int형 값 10, 문자열 “Hellow World”, 실수형 값 ’3.14f를 써넣고자 한다면 append<T>()함수를 사용해 아래와 같이 코드를 작성하기만 하면 됩니다.

C++)
CGD::buffer bufTemp(malloc(256));

bufTemp.append<int>(10);
bufTemp.append<char *>("Hellow!");
bufTemp.append<float>(3.14f);


C#)

CGD.buffer bufTemp = new CGD.buffer(new byte[256]);

bufTemp.append<int>(10);
bufTemp.append<string>("Hellow!");
bufTemp.append<float>(3.14f);

이렇게 작성하면 버퍼에 총 18Byte 크기의 메시지를 써넣습니다.
CGDBuffer_Sample1.png



또 값을 간단히 읽을 수 있습니다.

extract<T>()함수를 사용해 써넣은 순서대로 값을 읽어내면 됩니다.
extract<T>()함수는 buf값이 가르키는 곳에서 값을 읽어내 옮니다. 또 읽어온만큼 포인터를 옮깁니다.
C++)
auto temp1 = bufTemp.extract<int>();
auto temp2 = bufTemp.extract<char*>();
auto temp3 = bufTemp.extract<flaot>();
C#)
var temp1 = bufTemp.extract<int>();
var temp2 = bufTemp.extract<string>();
var temp3 = bufTemp.extract<float>();


이렇게 모두 읽어내고 나면 버퍼는 아래처럼 비게 될 것입니다.

CGDbuffer_Sample3.png

CGD::buffer는 이런 식으로 버퍼에 값을 손쉽게 써넣고 손쉽게 읽을 수 있는 라이브러리입니다.     



2... CGD::buffer의 특징
- 사용법이 매우 간단합니다.(사실상 append/extract가 전부...)
- 특별한 설정이나 특별한 스크립트없이 없이 동작이 가능합니다. 
- 사전 설정이나 사후 처리 등의 최소화를 추구합니다. 
- 매우 빠릅니다.
- 매우 작고 가볍습니다. (msgpack-300k~400k, protobuf-100~200k, CGD.buffer-17k~28k)
- 이진데이터, 문자열 등등 모두 사용가능하며 다른 직렬화 라이브러리와의 혼용 역시 사용가능합니다.
- 최소 단위 호완성을 추구합니다.
   (이기종간 최소 단위 데이터의 호완성을 제공하며 이 최소단위 데이터들의 구성으로 데이터를 만듭니다.)


3... CGD::buffer의 기본적 동작


4... CGD::buffer의 간단한 사용 예

버퍼에 데이터를 버퍼에 쓰기는 간단히 append()로 가능합니다.

C++)
CGD::buffer bufTemp(malloc(256));
       
bufTemp.append<uint8_t>(10);
bufTemp.append<char>(20);
bufTemp.append<int>(-100);
bufTemp.append<uint32_t>(1000);
bufTemp.append<std::string>("Test String"); // 문자열도 가능
C#)
CGD.buffer bufTemp = new CGD.buffer(new byte[256]);
       
bufTemp.append<byte>(10);
bufTemp.append<sbyte>(20);
bufTemp.append<int>(-100);
bufTemp.append<uint>(1000);
bufTemp.append<string>("Test String");	// 문자열도 가능



이렇게 작성된 메시지는 extract()로 간단히 읽어낼 수가 있습니다.

C++)
auto temp1 = bufTemp.extract<uint8_t>();
auto temp2 = bufTemp.extract<char>();
auto temp3 = bufTemp.extract<int>();
auto temp4 = bufTemp.extract<uint32_t>();
auto temp5 = bufTemp.extract<std::string>();
C#)
var temp1 = bufTemp.extract<byte>();
var temp2 = bufTemp.extract<sbyte>();
var temp3 = bufTemp.extract<int>();
var temp4 = bufTemp.extract<uint>();
var temp5 = bufTemp.extract<string>();

복합형 데이터도 가능하며 그 복합 데이터들 간의 다계층도 가능합니다.
C#의 List<T>, Dictionary<K,V> ...
C++의 vector<T>, list<T>, set<T>, map<T> ....

C++)
vector<int>                  listTest = { ...};
list<std::string>            listStringTest = { ...};
map<std::string, int>        mapTemp = { ...};
map<int, list<std::string>>  maplistTemp = { ...};
	    
CGD::buffer bufTemp(malloc(256));
	    
// 값을 써넣는다.
bufTemp.append<vector<int>>(listTest);
bufTemp.append<list<std::string>>(listStringTest);
bufTemp.append<map<std::string, int>>(mapTemp);
bufTemp.append<map<int, list<std::string>>>(maplistTemp);
	    
.................
	    
// 값을 읽는다.
auto temp1 = bufTemp.extract<vector<int>>();
auto temp2 = bufTemp.extract<list<std::string>>();
auto temp3 = bufTemp.extract<map<int, std::string>>();
auto temp4 = bufTemp.extract<map<int, list<std::string>>>();

C#)
List<int>                      listTest = new ...;
List<string>                   listStringTest = new ...;
Dictionary<string, int>        dicTest = new ...;
Dictionary<int, List<string>>  dicListTest = new ...;
       
CGD.buffer bufTemp = new CGD.buffer(new byte[256]);
       
// 값을 써넣는다.
bufTemp.append<List<int>> (listTest);
bufTemp.append<List<string>> (listStringTest);
bufTemp.append<Dictionary<string,int>> (dicTest);
bufTemp.append<Dictionary<string,List<int>>> (dicListTest);
       
.................
       
// 값을 읽는다.
var temp1 = bufTemp.extract<List<int>> ();
var temp2 = bufTemp.extract<List<string>> ();
var temp3 = bufTemp.extract<Dictionary<string,int>> ();
var temp4 = bufTemp.extract<Dictionary<string,List<int>>> ();
extract<T>에는 <T>형을 써줘야 하며 c++의 경우 decltype을 쓰면 좀더 편할 수 있습니다.
C#버전의 경우 GetType()이나 typeof()등으로 얻은 Type으로 extract가 가능합니다.


C#의 경우 구조체를 사용해서 복합형 구현도 가능합니다.
(C++의 경우 구조체는 복합형을 제공하지 않습니다. std::tuple등을  통해 할수 가능하나 생략...)

C#)
struct TEST
{
	public int       x;
	public float     y;
	public string    z;
	public List<int> w;
};
	    
struct TEST2
{
	public int       a;
	public List<int> b;
	public TEST      c;
};

위의 TEST2와 같이 복합적이고 다계층 구조체도 처리가 가능합니다.
C#)
TEST2  tempData;
	    
CGD.buffer bufTemp = new CGD.buffer(new byte[256]);
	    
// 값을 써넣는다.
bufTemp.append<test2>(tempData);
	    
.................
	    
// 값을 읽는다.
var temp1 = bufTemp.extract<test2>();

 주의) 아직 C++버전은 struct는 primitive 형으로 취급하기 때문에 아무런 다른 조작없이 내부에 string이나 vector<T>, list<T>같은 것을 지원하지 않습니다.