RedBencode bencode encoder and decoder
Read about this format here... http://en.wikipedia.org/wiki/Bencode
see also: RedBase64
*encode
Encodes an array of items as a bencoded string.
Expects an Array with items of the following kind...
Dictionary (or Event etc.)
For example here is a valid argument with different items...
["test", 4766, [555, [24, -50]], 40000, Dictionary[\one->111, \two->222]]
Returns a string containing the encoded data. For example...
"4:testi4766eli555eli24ei-50eeei40000ed3:onei111e3:twoi222ee"
*encodeBytes
Same as *encode but returns an array with 8bit bytes suitable for sending over serial port.
Returns an Int8Array containing the encoded data as 8bit bytes. For example...
Int8Array[52, 58, 116, 101, 115, 116, 105, 52, 55, 54, 54, 101, 108, 105, 53, 53, 53, 101, 108, 105, 50, 52, 101, 105, 45, 53, 48, 101, 101, 101, 105, 52, 48, 48, 48, 48, 101, 100, 51, 58, 111, 110, 101, 105, 49, 49, 49, 101, 51, 58, 116, 119, 111, 105, 50, 50, 50, 101, 101]
*decodeBytes
Same as *decode but useful when decoding data received from the serial port.
Expects an Int8Array with 8bit values.
*decodeString
Same as *decode but takes a String as argument. This is the more common method for decoding (compare *decode and *decodeBytes).
*decode
Decodes a bencoded stream of characters in to an array of items (Integer, String, Array, Dictionary). Usually it is easier to use the *decodeString method as it will automatically create a CollStream out of the argument string.
Note that Event will become Dictionary and List will become Array.
//--examples
//some items in an array to be encoded
a= ["test", 4766, [555, [24, -50]], 40000, Dictionary[\one->111, \two->222]];
//encode
b= RedBencode.encode(a);
b//this is now the bencode string
//decode
c= RedBencode.decodeString(b);
a==c//convert back - should be the same array as above
//--arduino real world test reading bencoded data from the serial port
//upload the serialSend example from https://github.com/jcw/embencode to an arduino
(
var port= SerialPort("/dev/tty.usbmodemfa131", 57600);//modify this port name
CmdPeriod.doOnce({port.close});
Routine.run({
var lastByte= -1, stream;
inf.do{
var byte;
while({byte= port.read; byte.notNil}, {
if(byte==10 and:{lastByte==13}, {
if(stream.notNil, {//skip the initial "\n[serialSend]"
stream.pos= 0;
RedBencode.decode(stream).postln;//should post the result every 3sec
});
stream= CollStream.new;
lastByte= -1;
}, {
if(lastByte!= -1, {
if(stream.notNil, {//skip the initial "\n[serialSend]"
stream.put(lastByte.asAscii);
});
});
lastByte= byte;
});
});
};
});
)
//--arduino real world test sending bencoded data to the serial port
//upload the serialReceive example from https://github.com/jcw/embencode to an arduino
(
var port= SerialPort("/dev/tty.usbmodemfa131", 57600);//modify this port name
CmdPeriod.doOnce({port.close});
Routine.run({
var lastByte= -1, stream= CollStream.new;
inf.do{
var byte;
while({byte= port.read; byte.notNil}, {
if(byte==10 and:{lastByte==13}, {
stream.contents.postln;
stream= CollStream.new;
lastByte= -1;
}, {
if(lastByte!= -1, {
stream.put(byte.asAscii);
});
lastByte= byte;
});
});
};
});
Routine.run({
var arr;
inf.do{
3.wait;
arr= RedBencode.encodeBytes(["abcde", "123", 12345, [987, [654], 321], 999999999, Dictionary[\one->11, \two->22], "bye!"]);
port.putAll(arr);
};
});
)
//--arduino real world test
//upload the blinky example from https://github.com/jcw/embencode to an arduino
(
~port= SerialPort("/dev/tty.usbmodemfa131", 57600);//modify this port name
CmdPeriod.doOnce({~port.close});
Routine.run({
var stream= CollStream.new;
inf.do{
var byte;
while({byte= ~port.next; byte.notNil}, {
stream.put(byte.asAscii);
});
if(stream.pos>0, {
stream.pos= 0;
RedBencode.decode(stream).postln;
stream= CollStream.new;
});
0.01.wait;
};
});
)
~port.putAll(RedBencode.encode([["rate", 250], ["trigger", 4], ["count", 10]]));
~port.putAll(RedBencode.encode([["rate", 100], ["trigger", 10], ["count", 20]]));