PDA

View Full Version : [ANY] MessagePack


bottiger
03-07-2014, 23:16
Extension for http://msgpack.org/

Linux build included. See the sourcepawn file for more examples.

Example


// format [1, -1, 65536, "foobar"]
new Handle:pack = MsgPack_NewPack();

MsgPack_PackArray(pack, 4);
MsgPack_PackInt(pack, 1);
MsgPack_PackInt(pack, -1);
MsgPack_PackInt(pack, 65536);
MsgPack_PackString(pack, "foobar");

new size = MsgPack_GetPackSize(pack);
decl String:dumped[size];
MsgPack_GetPackBuffer(pack, dumped, size);
CloseHandle(pack);
Unpacking Example


// format [nil, false, true, {true=>false, "foo"=>1.234200}]

new Handle:root = MsgPack_NewUnpack(dumped, size);
new Handle:map = MsgPack_UnpackArray(root, 3);
new Handle:k = MsgPack_UnpackKey(map, 1);
new Handle:v = MsgPack_UnpackValue(map, 1);

decl String:key[64];
MsgPack_UnpackString(k, key, sizeof(key));
new Float:value = MsgPack_UnpackFloat(v);

CloseHandle(root);
CloseHandle(map);
CloseHandle(k);
CloseHandle(v);



enum MsgPack_Type {
MSGPACK_OBJECT_NIL = 0x00,
MSGPACK_OBJECT_BOOLEAN = 0x01,
MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02,
MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03,
MSGPACK_OBJECT_DOUBLE = 0x04,
MSGPACK_OBJECT_RAW = 0x05,
MSGPACK_OBJECT_ARRAY = 0x06,
MSGPACK_OBJECT_MAP = 0x07,
};

/*
* Packing Functions
*/

// create a pack handle to pack with
native Handle:MsgPack_NewPack();

native MsgPack_PackInt(Handle:pack, value);
native MsgPack_PackFloat(Handle:pack, Float:value);
native MsgPack_PackNil(Handle:pack);
native MsgPack_PackTrue(Handle:pack);
native MsgPack_PackFalse(Handle:pack);
native MsgPack_PackArray(Handle:pack, size);
native MsgPack_PackMap(Handle:pack, size);

// pack some bytes. does not null terminate
native MsgPack_PackRaw(Handle:pack, const String:buffer[], buffer_length);

stock MsgPack_PackString(Handle:pack, const String:null_terminated_string[]) {
return MsgPack_PackRaw(pack, null_terminated_string, strlen(null_terminated_string));
}

// get the pack length in bytes
native MsgPack_GetPackSize(Handle:pack);

// get the buffer so you can send it somewhere
native MsgPack_GetPackBuffer(Handle:pack, const String:buffer[], buffer_length);

/*
* Unpacking Functions
*/

// create a messagepack object handle.
// offset is the number of bytes consumed
// enabling save_buffer copies the buffer so objects still work properly when the buffer goes out of scope
// the buffer is shared between all objects that come from here and will be deleted when they are all closed
native Handle:MsgPack_NewUnpack(const String:buffer[], buffer_length, &offset=0, bool:save_buffer=true);


// pretty print object to console for debugging
native MsgPack_UnpackPrint(Handle:obj);

// get the object type
native MsgPack_Type:MsgPack_UnpackType(Handle:obj);

// get the number of elements for maps, arrays, and raws. returns 0 if not one of those types
native MsgPack_UnpackCount(Handle:obj);

native bool:MsgPack_UnpackBool(Handle:obj);
native MsgPack_UnpackInt(Handle:obj);
native Float:MsgPack_UnpackFloat(Handle:obj);
native MsgPack_UnpackRaw(Handle:obj, String:buffer[], buffer_length);
stock MsgPack_UnpackString(Handle:obj, String:buffer[], buffer_length) {
new written = MsgPack_UnpackRaw(obj, buffer, buffer_length);
if(written-1 >= buffer_length)
buffer[buffer_length] = 0;
else
buffer[written] = 0;

return written;
}
native Handle:MsgPack_UnpackArray(Handle:obj, index);
native Handle:MsgPack_UnpackKey(Handle:obj, index);
native Handle:MsgPack_UnpackValue(Handle:obj, index);
native Handle:MsgPack_UnpackNext(Handle:obj);
native any:MsgPack_UnpackArrayCell(Handle:obj, index);


Changelog

4/23/2015


Renamed MsgPack_Object* to MsgPack_Unpack*
Added MsgPack_UnpackArrayCell.

Nefarius
03-15-2014, 05:40
Fantastic! You may submit your implementation (https://github.com/msgpack/website/blob/master/README.md) to msgpack.org (http://msgpack.org/) so it get's listed among the other supported languages.

I'll have a go with it and tell you how it worked out.

Mitchell
03-17-2014, 11:05
Just a question, havent looked into it, but can i send a message pack to be stored on a site?

Nefarius
03-17-2014, 12:15
Since it's a protocol by it's own you'd have to have your receiving site use a Message Pack implementation too. For PHP look here (https://github.com/msgpack/msgpack-php).

Mitchell
03-17-2014, 12:58
Yeah i get that, but how would i go about sending it to an external site? as this saves them in handles?

Nefarius
03-17-2014, 13:34
I guess you need an extension like cURL (https://forums.alliedmods.net/showthread.php?t=152216) to encapsulate the data within a web request. I'd burn to try it out myself but sadly my time this week is limited for community stuff.

bottiger
03-17-2014, 17:33
Yeah i get that, but how would i go about sending it to an external site? as this saves them in handles?


new size = MsgPack_GetPackSize(pack);
decl String:dumped[size];
MsgPack_GetPackBuffer(pack, dumped, size);

Mitchell
03-18-2014, 09:24
new size = MsgPack_GetPackSize(pack);
decl String:dumped[size];
MsgPack_GetPackBuffer(pack, dumped, size);


gotcha, hmm just thinking of something good to use with this, would it be a bad idea to mix this with sql? lol.

edit: most sites dont have msgpack installed, so that sucks.

bottiger
03-19-2014, 00:49
gotcha, hmm just thinking of something good to use with this, would it be a bad idea to mix this with sql? lol.

edit: most sites dont have msgpack installed, so that sucks.

I have many reasons for making this instead of using the SQL protocol.


You can't put your SQL database behind Cloudflare for DDoS protection. You can make an HTTP api that uses messagepack and put it behind Cloudflare.
Sourcemod doesn't support encrypted MySQL while HTTPS encryption is supported everywhere.
Sourcemod doesn't support threaded SQL transactions, and if you use non-threaded SQL, you will lag your server. You can easily put these transactions in your HTTP server without lagging your server.
If you use threaded sql connections, you will not share connections with other plugins. So if you have 10 plugins using the same database connection, they will each have 10 connections to the database.