Packages
Basic library that enables easy interaction with the PRU cores present in the BeagleBone Black.
Current section
Files
Jump to
Current section
Files
pru/lib/msgpack/msgpck.c
/**
* Copyright (C) 2014 SINTEF <nicolas.harrand@gmail.com>
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/lgpl-3.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an F("AS IS") BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// #include "Arduino.h"
#include "msgpck.h"
// #define msgpck_empty 0xff
// #define msgpck_nil 0xc0
// #define msgpck_bool 0xc2
// #define msgpck_uint 0xcc
// #define msgpck_sint 0xd0
// #define msgpck_float 0xca
// #define msgpck_string 0xd9
// #define msgpck_bin 0xc4
// #define msgpck_ext 0xc7
// #define msgpck_array 0xdc
// #define msgpck_map 0xde
// #define msgpck_unknown 0x00
void stream_setup(Stream * sb, uint8_t *data_buffer, ssize_t data_len)
{
sb->data = data_buffer;
sb->len = data_len;
sb->pos = 0;
}
// StreamBuff(uint8_t *data_buffer, ssize_t data_len)
// : data(data_buffer), len(data_len), pos(0)
// {
// }
int stream_available(Stream * sb) {
return sb->len - sb->pos;
}
/* int read() { */
/* if (available() <= 0) */
/* return -1; */
/* max_position = pos + 1; */
/* return data[pos++]; */
/* } */
int stream_readBytes(Stream * sb, uint8_t * buffer, int length) {
if (stream_available(sb) < length)
return -1;
uint32_t i;
for(i=0; i < length; i++) {
*(buffer+i) = *(sb->data + sb->pos++);
}
sb->max_position = sb->pos + 1;
return length;
}
ssize_t stream_write(Stream * sb, uint8_t d) {
if (stream_available(sb) <= 0)
return -1;
sb->max_position = sb->pos+1;
sb->data[sb->pos++] = d;
return 1;
};
int stream_peek(Stream * sb) {
return sb->data[sb->pos];
}
void stream_flush(Stream * sb) {
ssize_t i;
for (i = 0; i < sb->len; ++i) {
sb->data[i] = 0;
}
sb->pos = 0;
sb->max_position = 0;
}
void stream_clear(Stream * sb) {
stream_flush(sb);
}
void stream_reset(Stream * sb) {
sb->pos = 0;
}
void stream_resetAllPositions(Stream * sb) {
sb->pos = 0;
sb->max_position = 0;
}
uint8_t msgpck_what_next(Stream * s) {
int b = stream_peek(s);
switch(b){
case -1:
return msgpck_empty;
case 0xc0:
return msgpck_nil;
case 0xc2:
return msgpck_bool;
case 0xc3:
return msgpck_bool;
case 0xc4:
return msgpck_bin;
case 0xc5:
return msgpck_bin;
case 0xc6:
return msgpck_bin;
case 0xca:
return msgpck_float;
case 0xcb:
return msgpck_float;
case 0xcc:
return msgpck_uint;
case 0xcd:
return msgpck_uint;
case 0xce:
return msgpck_uint;
case 0xcf:
return msgpck_uint;
case 0xd0:
return msgpck_sint;
case 0xd1:
return msgpck_sint;
case 0xd2:
return msgpck_sint;
case 0xd3:
return msgpck_sint;
case 0xd4:
return msgpck_ext;
case 0xd5:
return msgpck_ext;
case 0xd6:
return msgpck_ext;
case 0xd7:
return msgpck_ext;
case 0xd8:
return msgpck_ext;
case 0xd9:
return msgpck_string;
case 0xda:
return msgpck_string;
case 0xdb:
return msgpck_string;
case 0xdc:
return msgpck_array;
case 0xdd:
return msgpck_array;
case 0xde:
return msgpck_map;
case 0xdf:
return msgpck_map;
default:
if(b >= 224)
return msgpck_uint;
if(b < 128)
return msgpck_sint;
if((b >> 5) == 5)
return msgpck_string;
if((b >> 4) == 8)
return msgpck_map;
if((b >> 4) == 9)
return msgpck_array;
return msgpck_unknown;
}
}
bool msgpck_nil_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && (b == 0xc0);
}
bool msgpck_bool_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && ((b == 0xc2) || (b == 0xc3));
}
bool msgpck_integer_next(Stream * s) {
int b = stream_peek(s);
return ((b < 128) ||
(b >= 224) ||
(b == 0xcc) ||
(b == 0xcd) ||
(b == 0xce) ||
(b == 0xcf) ||
(b == 0xd0) ||
(b == 0xd1) ||
(b == 0xd2) ||
(b == 0xd3));
}
bool msgpck_signed_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && ((b >= 224) ||
(b == 0xd0) ||
(b == 0xd1) ||
(b == 0xd2) ||
(b == 0xd3));
}
bool msgpck_float_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && ((b == 0xca) || (b == 0xcb));
}
bool msgpck_string_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && (((b >> 5) == 5) ||
(b == 0xd9) ||
(b == 0xda) ||
(b == 0xdb));
}
bool msgpck_bin_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && ((b == 0xc4) ||
(b == 0xc5) ||
(b == 0xc6));
}
bool msgpck_array_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && (((b >> 4) == 9) ||
(b == 0xdc) ||
(b == 0xdd));
}
bool msgpck_map_next(Stream * s) {
int b = stream_peek(s);
return (b != -1) && (((b >> 4) == 8) ||
(b == 0xde) ||
(b == 0xdf));
}
bool msgpck_read_nil(Stream * s) {
uint8_t rfb;
return ((stream_readBytes(s, &rfb,1) == 1) && (rfb == 0xc0));
}
bool msgpck_read_bool(Stream * s, bool *b) {
uint8_t rfb;
uint8_t dmp = stream_readBytes(s, &rfb,1);
*b = (rfb == 0xc3);
return ((dmp == 1) && ((rfb == 0xc3) || (rfb == 0xc2)));
}
bool msgpck_read_sint(Stream * s, byte *b, uint8_t max_size) {
byte fb;
uint8_t read_size;
if (stream_readBytes(s, &fb,1) != 1) {
return false;
} if(fb < 128) {
return false;
} else if (fb >= 224) {
/* Little Endian (?) */
b[0] = fb;
int8_t i;
for(i = max_size-1; i >= 1; i--) {
b[i] = 0xff;
}
return true;
} else if (fb == 0xd0) {
read_size = 1;
} else if (fb == 0xd1) {
read_size = 2;
} else if (fb == 0xd2) {
read_size = 4;
} else if (fb == 0xd3) {
read_size = 8;
} else {
return false;
}
if(read_size > max_size)
return false;
bool res = true;
int8_t i;
for(i = read_size-1; i >= 0; i--) {
res &= stream_readBytes(s, &b[i],1);
}
uint8_t prefix = (b[read_size-1] >> 7) == 1 ? 0xFF : 0x00;
for(i = max_size-1; i >= read_size; i--) {
b[i] = prefix;
}
return res;
}
bool msgpck_read_uint(Stream * s, byte *b, uint8_t max_size) {
byte fb;
uint8_t read_size;
if (stream_readBytes(s, &fb,1) != 1) {
return false;
} if(fb < 128) {
/* Little Endian (?) */
b[0] = fb;
int8_t i;
for(i = max_size-1; i >= 1; i--) {
b[i] = 0x0;
}
return true;
} else if (fb >= 224) {
return false;
} else if (fb == 0xcc) {
read_size = 1;
} else if (fb == 0xcd) {
read_size = 2;
} else if (fb == 0xce) {
read_size = 4;
} else if (fb == 0xcf) {
read_size = 8;
} else {
return false;
}
if(read_size > max_size)
return false;
bool res = true;
int8_t i;
for(i = read_size-1; i >= 0; i--) {
res &= stream_readBytes(s, &b[i],1);
}
for(i = max_size-1; i >= read_size; i--) {
b[i] = 0x00;
}
return res;
}
bool msgpack_read_float(Stream * s, float *f) {
byte fb;
uint8_t read_size;
bool b = true;
if (stream_readBytes(s, &fb,1) != 1)
return false;
if(fb == 0xca) {
read_size = 4;
union float_to_byte {
float f;
byte b[4];
} b2f;
b = stream_readBytes(s, &(b2f.b[3]),1) == 1;
b = stream_readBytes(s, &(b2f.b[2]),1) == 1;
b = stream_readBytes(s, &(b2f.b[1]),1) == 1;
b = stream_readBytes(s, &(b2f.b[0]),1) == 1;
*f = b2f.f;
return b;
} else if (fb == 0xcb) {
uint64_t dmp;
uint8_t * p = (uint8_t *) &dmp;
read_size = 8;
stream_readBytes(s, p,read_size);
} else {
return false;
}
return false;
}
bool msgpck_read_string_sz(Stream * s, char * str, uint32_t max_size, uint32_t *str_size) {
uint8_t * str_buff = (uint8_t *)str;
*str_size = 0;
uint8_t fb;
bool b = true;
uint32_t read_size = 0;
uint8_t * p = (uint8_t *) &read_size;
if(stream_readBytes(s, &fb,1) == 1) {
if((fb >> 5) == 5) {
read_size = fb & 0x1f;
} else if(fb == 0xd9) {
b &= stream_readBytes(s, &p[0],1) == 1;
} else if(fb == 0xda) {
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else if(fb == 0xdb) {
b &= stream_readBytes(s, &p[3],1) == 1;
b &= stream_readBytes(s, &p[2],1) == 1;
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else {
return false;
}
*str_size = read_size;
if(read_size > max_size)
return false;
//b &= stream_readBytes(s, str,read_size) == read_size;
uint32_t i;
for(i = 0; i < read_size; i++) {
b &= stream_readBytes(s, &(str_buff[i]),1) == 1;
}
return b;
}
return false;
}
bool msgpck_read_string(Stream * s, char * str, uint32_t max_size) {
uint32_t read_size;
return msgpck_read_string_sz(s, str, max_size, &read_size);
}
bool msgpck_read_bin_sz(Stream * s, byte * bin, uint32_t max_size, uint32_t *bin_size) {
uint8_t fb;
bool b = true;
uint32_t read_size = 0;
uint8_t * p = (uint8_t *) &read_size;
if(stream_readBytes(s, &fb,1) == 1) {
if(fb == 0xc4) {
b &= stream_readBytes(s, &p[0],1) == 1;
} else if(fb == 0xc5) {
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else if(fb == 0xc6) {
b &= stream_readBytes(s, &p[3],1) == 1;
b &= stream_readBytes(s, &p[2],1) == 1;
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else {
return false;
}
*bin_size = read_size;
if(read_size > max_size)
return false;
b &= stream_readBytes(s, bin,read_size) == read_size;
return b;
}
return false;
}
bool msgpck_read_bin(Stream * s, byte * bin, uint32_t max_size) {
uint32_t read_size;
return msgpck_read_bin_sz(s, bin, max_size, &read_size);
}
bool msgpck_read_array_size(Stream * s, uint32_t * array_size) {
uint8_t fb;
bool b = true;
uint8_t * p = (uint8_t *) array_size;
if(stream_readBytes(s, &fb,1) == 1) {
if((fb >> 4) == 0x09) {
*array_size = fb & 0x0f;
} else if(fb == 0xdc) {
*array_size = 0;
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
return b;
} else if(fb == 0xdd) {
*array_size = 0;
b &= stream_readBytes(s, &p[3],1) == 1;
b &= stream_readBytes(s, &p[2],1) == 1;
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else {
return false;
}
return b;
}
return false;
}
bool msgpck_read_map_size(Stream * s, uint32_t * map_size) {
uint8_t fb;
bool b = true;
uint8_t * p = (uint8_t *) map_size;
if(stream_readBytes(s, &fb,1) == 1) {
if((fb >> 4) == 0x08) {
*map_size = fb & 0x0f;
} else if(fb == 0xde) {
*map_size = 0;
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else if(fb == 0xdf) {
*map_size = 0;
b &= stream_readBytes(s, &p[3],1) == 1;
b &= stream_readBytes(s, &p[2],1) == 1;
b &= stream_readBytes(s, &p[1],1) == 1;
b &= stream_readBytes(s, &p[0],1) == 1;
} else {
return false;
}
return b;
}
return false;
}
void msgpck_write_nil(Stream * s) {
stream_write(s, 0xc0);
}
void msgpck_write_bool(Stream * s, bool b) {
b ? stream_write(s, 0xc3) : stream_write(s, 0xc2);
}
void msgpck_write_integer_u8(Stream * s, uint8_t u) {
if(u < 128) {
stream_write(s, u);
} else {
stream_write(s, 0xcc);
stream_write(s, u);
}
}
void msgpck_write_integer_u16(Stream * s, uint16_t u) {
if(u < 256) {
msgpck_write_integer_u8(s, (uint8_t) u);
} else {
stream_write(s, 0xcd);
stream_write(s, u >> 8);
stream_write(s, u & 0xff);
}
}
void msgpck_write_integer_u32(Stream * s, uint32_t u) {
if(u < 65536) {
msgpck_write_integer_u16(s, (uint16_t) u);
} else {
stream_write(s, 0xce);
stream_write(s, u >> 24);
stream_write(s, u >> 16);
stream_write(s, u >> 8);
stream_write(s, u & 0xff);
}
}
void msgpck_write_integer_u64(Stream * s, uint64_t u) {
if(u < 4294967296) {
msgpck_write_integer_u32(s, (uint32_t) u);
} else {
stream_write(s, 0xcd);
stream_write(s, u >> 56);
stream_write(s, u >> 48);
stream_write(s, u >> 40);
stream_write(s, u >> 32);
stream_write(s, u >> 24);
stream_write(s, u >> 16);
stream_write(s, u >> 8);
stream_write(s, u & 0xff);
}
}
void msgpck_write_integer_i8(Stream * s, int8_t i) {
if((i < -32) || (i > 127)) {
stream_write(s, 0xd0);
stream_write(s, i);
} else {
stream_write(s, i);
}
}
void msgpck_write_integer_i16(Stream * s, int16_t i) {
if((i < -127) || (i > 254)) {
stream_write(s, 0xd1);
stream_write(s, i >> 8);
stream_write(s, i & 0xff);
} else {
msgpck_write_integer_i8(s, (int8_t) i);
}
}
void msgpck_write_integer_i32(Stream * s, int32_t i) {
if((i < -32768) || (i > 32767)) {
stream_write(s, 0xd2);
stream_write(s, (i >> 24)& 0xff);
stream_write(s, (i >> 16)& 0xff);
stream_write(s, (i >> 8)& 0xff);
stream_write(s, i & 0xff);
} else {
msgpck_write_integer_i16(s, (int16_t) i);
}
}
void msgpck_write_integer_i64(Stream * s, int64_t i) {
if((i < -2147483647) || (i > 2147483647)) {
stream_write(s, 0xd3);
stream_write(s, i >> 56);
stream_write(s, i >> 48);
stream_write(s, i >> 40);
stream_write(s, i >> 32);
stream_write(s, i >> 24);
stream_write(s, i >> 16);
stream_write(s, i >> 8);
stream_write(s, i & 0xff);
} else {
msgpck_write_integer_i32(s, (int32_t) i);
}
}
void msgpck_write_float(Stream *s, float f) {
union float_to_byte {
float f;
byte b[4];
} f2b;
f2b.f = f;
stream_write(s, 0xca);
stream_write(s, f2b.b[3]);
stream_write(s, f2b.b[2]);
stream_write(s, f2b.b[1]);
stream_write(s, f2b.b[0]);
}
void msgpck_write_string(Stream * s, char * str, uint32_t str_size) {
if(str_size > 65535) {
stream_write(s, 0xdb);
stream_write(s, (str_size >> 24) & 0xff);
stream_write(s, (str_size >> 16) & 0xff);
stream_write(s, (str_size >> 8) & 0xff);
stream_write(s, str_size & 0xff);
} else if(str_size > 255) {
stream_write(s, 0xda);
stream_write(s, str_size >> 8);
stream_write(s, str_size & 0xff);
} else if (str_size > 31) {
stream_write(s, 0xd9);
stream_write(s, str_size & 0xff);
} else {
stream_write(s, 0xa0 + str_size);
}
uint32_t i;
for(i=0;i<str_size;i++){
stream_write(s, str[i]);
}
}
void msgpck_write_bin(Stream * s, byte * b, uint32_t bin_size) {
if(bin_size > 65535) {
stream_write(s, 0xc6);
stream_write(s, (bin_size >> 24) & 0xff);
stream_write(s, (bin_size >> 16) & 0xff);
stream_write(s, (bin_size >> 8) & 0xff);
stream_write(s, bin_size & 0xff);
} else if(bin_size > 255) {
stream_write(s, 0xc5);
stream_write(s, (bin_size >> 8) & 0xff);
stream_write(s, bin_size & 0xff);
} else {
stream_write(s, 0xc4);
stream_write(s, bin_size & 0xff);
}
uint32_t i;
for(i=0;i<bin_size;i++){
stream_write(s, b[i]);
}
}
void msgpck_write_array_header(Stream * s, uint32_t ar_size) {
if(ar_size > 65535) {
stream_write(s, 0xdd);
stream_write(s, ar_size >> 24);
stream_write(s, ar_size >> 16);
stream_write(s, ar_size >> 8);
stream_write(s, ar_size & 0xff);
} else if (ar_size > 15) {
stream_write(s, 0xdc);
stream_write(s, ar_size >> 8);
stream_write(s, ar_size & 0xff);
} else {
stream_write(s, 0x90 + ar_size);
}
}
void msgpck_write_map_header(Stream * s, uint32_t map_size) {
if(map_size > 65535) {
stream_write(s, 0xde);
stream_write(s, map_size >> 24);
stream_write(s, map_size >> 16);
stream_write(s, map_size >> 8);
stream_write(s, map_size & 0xff);
} else if (map_size > 15) {
stream_write(s, 0xdf);
stream_write(s, map_size >> 8);
stream_write(s, map_size & 0xff);
} else {
stream_write(s, 0x80 + map_size);
}
}
void flush_buf(char * buf, uint16_t buf_size) {
uint16_t i;
for(i = 0; i < buf_size; i++) {
buf[i] = ' ';
}
buf[buf_size] = '\0';
}
// void print_string(Stream * output, char * str, uint16_t str_size) {
// uint16_t i;
// for(i = 0; i < str_size; i++) {
// output->write(str[i]);
// }
// }
// void print_bin(Stream * output, byte * str, uint16_t str_size) {
// uint16_t i;
// for(i = 0; i < str_size; i++) {
// output->write(" 0x");
// output->print(str[i], HEX);
// }
// }
// void msgpck_to_json(Stream * output, Stream * input, ssize_t BUFFER_SIZE) {
// uint8_t i;
// uint16_t buf_size = BUFFER_SIZE;
// char buf[BUFFER_SIZE+1];
// if(msgpck_map_next(input)) {
// uint32_t map_size;
// msgpck_read_map_size(input, &map_size);
// output->print(F("{"));
// for(i = 0; i < map_size; i++) {
// if(i != 0)
// output->print(F(", "));
// flush_buf( buf, buf_size);
// uint32_t r_size;
// msgpck_read_string(input, buf, buf_size, &r_size);
// output->print(F("\""));
// print_string(output, buf, r_size);
// output->print(F("\": "));
// msgpck_to_json(output, input, BUFFER_SIZE);
// }
// output->print(F("}"));
// } else if(msgpck_array_next(input)) {
// uint32_t array_size;
// msgpck_read_array_size(input, &array_size);
// output->print(F("["));
// for(i = 0; i < array_size; i++) {
// if(i != 0)
// output->print(F(", "));
// msgpck_to_json(output, input, BUFFER_SIZE);
// }
// output->print(F("]"));
// } else if (msgpck_nil_next(input)) {
// msgpck_read_nil(input);
// output->print(F("nil"));
// } else if(msgpck_bool_next(input)) {
// bool b;
// msgpck_read_bool(input, &b);
// if(b) {
// output->print(F("true"));
// } else {
// output->print(F("false"));
// }
// } else if(msgpck_integer_next(input)) {
// if(msgpck_signed_next(input)) {
// int32_t i = 0;
// uint8_t * p = (uint8_t *) &i;
// msgpck_read_integer(input, p, 4);
// output->print(i);
// } else {
// uint32_t u = 0;
// uint8_t * p = (uint8_t *) &u;
// msgpck_read_integer(input, p, 4);
// output->print(u);
// }
// } else if(msgpck_float_next(input)) {
// float f;
// msgpack_read_float(input, &f);
// output->print(f);
// } else if(msgpck_string_next(input)) {
// flush_buf( buf, buf_size);
// uint32_t r_size;
// msgpck_read_string(input, buf, buf_size, &r_size);
// output->print(F("\""));
// print_string(output, buf, r_size);
// output->print(F("\""));
// } else if(msgpck_bin_next(input)) {
// flush_buf( buf, buf_size);
// uint32_t r_size;
// msgpck_read_bin(input,(unsigned char *) buf, buf_size, &r_size);
// print_bin(output, (unsigned char *) buf, r_size);
// output->print(F("'"));
// }
// }