MBED port of https://github.com/ys1382/filagree . The only change is adding #define MBED

Dependents:   filagree_test

Committer:
yusufx
Date:
Wed May 30 21:13:01 2012 +0000
Revision:
0:1a89e28dea91

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yusufx 0:1a89e28dea91 1 /*
yusufx 0:1a89e28dea91 2 * serial.c
yusufx 0:1a89e28dea91 3 *
yusufx 0:1a89e28dea91 4 * stream serialization - serialies and deserializes byte_array and calls-back on each element
yusufx 0:1a89e28dea91 5 */
yusufx 0:1a89e28dea91 6
yusufx 0:1a89e28dea91 7 #include <stdint.h>
yusufx 0:1a89e28dea91 8 #include <stdio.h>
yusufx 0:1a89e28dea91 9 #include <stdlib.h>
yusufx 0:1a89e28dea91 10 #include <string.h>
yusufx 0:1a89e28dea91 11 #include <math.h>
yusufx 0:1a89e28dea91 12
yusufx 0:1a89e28dea91 13 #include "serial.h"
yusufx 0:1a89e28dea91 14 #include "struct.h"
yusufx 0:1a89e28dea91 15 #include "vm.h"
yusufx 0:1a89e28dea91 16 #include "util.h"
yusufx 0:1a89e28dea91 17
yusufx 0:1a89e28dea91 18 // functions ///////////////////////////////////////////////////////////////
yusufx 0:1a89e28dea91 19
yusufx 0:1a89e28dea91 20 // tells how many bytes are needed to encode this value
yusufx 0:1a89e28dea91 21 uint8_t encode_int_size(int32_t value)
yusufx 0:1a89e28dea91 22 {
yusufx 0:1a89e28dea91 23 uint8_t i;
yusufx 0:1a89e28dea91 24 value = (value >= 0 ? value : -value) >> 6;
yusufx 0:1a89e28dea91 25 for (i=1; value; i++, value >>=7);
yusufx 0:1a89e28dea91 26 return i;
yusufx 0:1a89e28dea91 27 }
yusufx 0:1a89e28dea91 28
yusufx 0:1a89e28dea91 29 struct byte_array *encode_int(struct byte_array *buf, int32_t value)
yusufx 0:1a89e28dea91 30 {
yusufx 0:1a89e28dea91 31 if (!buf)
yusufx 0:1a89e28dea91 32 buf = byte_array_new();
yusufx 0:1a89e28dea91 33 uint8_t growth = encode_int_size(value);
yusufx 0:1a89e28dea91 34 byte_array_resize(buf, buf->length + growth);
yusufx 0:1a89e28dea91 35 bool neg = value < 0;
yusufx 0:1a89e28dea91 36 value = abs(value);
yusufx 0:1a89e28dea91 37 uint8_t byte = (value & 0x3F) | ((value >= 0x40) ? 0x80 : 0) | (neg ? 0x40 : 0);
yusufx 0:1a89e28dea91 38 *buf->current++ = byte;
yusufx 0:1a89e28dea91 39 value >>= 6;
yusufx 0:1a89e28dea91 40 while (value) {
yusufx 0:1a89e28dea91 41 byte = (value & 0x7F) | ((value >= 0x80) ? 0x80 : 0);
yusufx 0:1a89e28dea91 42 *buf->current++ = byte;
yusufx 0:1a89e28dea91 43 value >>= 7;
yusufx 0:1a89e28dea91 44 }
yusufx 0:1a89e28dea91 45 return buf;
yusufx 0:1a89e28dea91 46 }
yusufx 0:1a89e28dea91 47
yusufx 0:1a89e28dea91 48 struct byte_array* serial_encode_int(struct byte_array* buf, int32_t key, int32_t value) {
yusufx 0:1a89e28dea91 49 if (!buf)
yusufx 0:1a89e28dea91 50 buf = byte_array_new();
yusufx 0:1a89e28dea91 51 if (key)
yusufx 0:1a89e28dea91 52 encode_int(buf, key<<2 | SERIAL_INT);
yusufx 0:1a89e28dea91 53 encode_int(buf, value);
yusufx 0:1a89e28dea91 54 return buf;
yusufx 0:1a89e28dea91 55 }
yusufx 0:1a89e28dea91 56
yusufx 0:1a89e28dea91 57 int32_t serial_decode_int(struct byte_array* buf)
yusufx 0:1a89e28dea91 58 {
yusufx 0:1a89e28dea91 59 bool neg = *buf->current & 0x40;
yusufx 0:1a89e28dea91 60 int32_t ret = *buf->current & 0x3F;
yusufx 0:1a89e28dea91 61 int bitpos = 6;
yusufx 0:1a89e28dea91 62 while ((*buf->current++ & 0x80) && (bitpos < (sizeof(int32_t)*8))) {
yusufx 0:1a89e28dea91 63 ret |= (*buf->current & 0x7F) << bitpos;
yusufx 0:1a89e28dea91 64 bitpos += 7;
yusufx 0:1a89e28dea91 65 }
yusufx 0:1a89e28dea91 66 return neg ? -ret : ret;
yusufx 0:1a89e28dea91 67 }
yusufx 0:1a89e28dea91 68
yusufx 0:1a89e28dea91 69 float serial_decode_float(struct byte_array* buf)
yusufx 0:1a89e28dea91 70 {
yusufx 0:1a89e28dea91 71 float f;
yusufx 0:1a89e28dea91 72 uint8_t *uf = (uint8_t*)&f;
yusufx 0:1a89e28dea91 73 for (int i=4; i; i--) {
yusufx 0:1a89e28dea91 74 *uf = *buf->current;
yusufx 0:1a89e28dea91 75 uf++;
yusufx 0:1a89e28dea91 76 buf->current++;
yusufx 0:1a89e28dea91 77 }
yusufx 0:1a89e28dea91 78 //DEBUGPRINT("serial_decode_float %f\n", f);
yusufx 0:1a89e28dea91 79 return f;
yusufx 0:1a89e28dea91 80 }
yusufx 0:1a89e28dea91 81
yusufx 0:1a89e28dea91 82 struct byte_array* serial_decode_string(struct byte_array* buf)
yusufx 0:1a89e28dea91 83 {
yusufx 0:1a89e28dea91 84 null_check(buf);
yusufx 0:1a89e28dea91 85 int32_t len = serial_decode_int(buf);
yusufx 0:1a89e28dea91 86 assert_message(len>=0, "negative malloc");
yusufx 0:1a89e28dea91 87 struct byte_array* ba = byte_array_new_size(len);
yusufx 0:1a89e28dea91 88 ba->data = ba->current = (uint8_t*)malloc(len);
yusufx 0:1a89e28dea91 89 null_check(ba->data);
yusufx 0:1a89e28dea91 90 memcpy(ba->data, buf->current, len);
yusufx 0:1a89e28dea91 91 buf->current += len;
yusufx 0:1a89e28dea91 92 return ba;
yusufx 0:1a89e28dea91 93 }
yusufx 0:1a89e28dea91 94
yusufx 0:1a89e28dea91 95 void serial_decode(struct byte_array* buf, serial_element se, const void* extra)
yusufx 0:1a89e28dea91 96 {
yusufx 0:1a89e28dea91 97 // DEBUGPRINT("serial_decode %d %x<%x?\n", buf->size, buf->current, buf->data + buf->size);
yusufx 0:1a89e28dea91 98 while (buf->current < buf->data + buf->length)
yusufx 0:1a89e28dea91 99 {
yusufx 0:1a89e28dea91 100 // get key and wire type
yusufx 0:1a89e28dea91 101 int32_t keyWire = serial_decode_int(buf);
yusufx 0:1a89e28dea91 102 struct key_value_pair pair = {
yusufx 0:1a89e28dea91 103 .key = keyWire >> 2,
yusufx 0:1a89e28dea91 104 .wire_type = (enum serial_type)(keyWire & 0x03)
yusufx 0:1a89e28dea91 105 };
yusufx 0:1a89e28dea91 106 // DEBUGPRINT("serial_decode %d:%d\n", pair.key, pair.wire_type);
yusufx 0:1a89e28dea91 107
yusufx 0:1a89e28dea91 108 // get data
yusufx 0:1a89e28dea91 109 switch(pair.wire_type) {
yusufx 0:1a89e28dea91 110 case SERIAL_INT: /* int */
yusufx 0:1a89e28dea91 111 pair.value.integer = serial_decode_int(buf);
yusufx 0:1a89e28dea91 112 break;
yusufx 0:1a89e28dea91 113 case SERIAL_FLOAT:
yusufx 0:1a89e28dea91 114 pair.value.floater = serial_decode_float(buf);
yusufx 0:1a89e28dea91 115 case SERIAL_STRING: /* bytes */
yusufx 0:1a89e28dea91 116 pair.value.bytes = serial_decode_string(buf);
yusufx 0:1a89e28dea91 117 break;
yusufx 0:1a89e28dea91 118 case SERIAL_ARRAY:
yusufx 0:1a89e28dea91 119 break;
yusufx 0:1a89e28dea91 120 default:
yusufx 0:1a89e28dea91 121 DEBUGPRINT("serial_decode ?\n");
yusufx 0:1a89e28dea91 122 break;
yusufx 0:1a89e28dea91 123 }
yusufx 0:1a89e28dea91 124 if (se(&pair, buf, extra)) {
yusufx 0:1a89e28dea91 125 // DEBUGPRINT("serial_decode: break\n");
yusufx 0:1a89e28dea91 126 break;
yusufx 0:1a89e28dea91 127 }
yusufx 0:1a89e28dea91 128 }
yusufx 0:1a89e28dea91 129 // DEBUGPRINT("serial_decode done\n");
yusufx 0:1a89e28dea91 130 }
yusufx 0:1a89e28dea91 131
yusufx 0:1a89e28dea91 132 // assume little endian
yusufx 0:1a89e28dea91 133 struct byte_array *encode_float(struct byte_array *buf, float f)
yusufx 0:1a89e28dea91 134 {
yusufx 0:1a89e28dea91 135 assert_message(sizeof(float)==4, "bad float size");
yusufx 0:1a89e28dea91 136 uint8_t *uf = (uint8_t*)&f;
yusufx 0:1a89e28dea91 137 for (int i=4; i; i--) {
yusufx 0:1a89e28dea91 138 byte_array_add_byte(buf, *uf);
yusufx 0:1a89e28dea91 139 uf++;
yusufx 0:1a89e28dea91 140 }
yusufx 0:1a89e28dea91 141 return buf;
yusufx 0:1a89e28dea91 142 }
yusufx 0:1a89e28dea91 143
yusufx 0:1a89e28dea91 144 struct byte_array* serial_encode_float(struct byte_array* buf, int32_t key, float value) {
yusufx 0:1a89e28dea91 145 if (!buf)
yusufx 0:1a89e28dea91 146 buf = byte_array_new();
yusufx 0:1a89e28dea91 147 if (key)
yusufx 0:1a89e28dea91 148 encode_int(buf, key<<2 | SERIAL_FLOAT);
yusufx 0:1a89e28dea91 149 encode_float(buf, value);
yusufx 0:1a89e28dea91 150 return buf;
yusufx 0:1a89e28dea91 151 }
yusufx 0:1a89e28dea91 152
yusufx 0:1a89e28dea91 153 uint8_t serial_encode_string_size(int32_t key, const struct byte_array* string) {
yusufx 0:1a89e28dea91 154 if (!string)
yusufx 0:1a89e28dea91 155 return 0;
yusufx 0:1a89e28dea91 156 return (key ? encode_int_size(key) : 0) +
yusufx 0:1a89e28dea91 157 encode_int_size(string->length) +
yusufx 0:1a89e28dea91 158 string->length;
yusufx 0:1a89e28dea91 159 }
yusufx 0:1a89e28dea91 160
yusufx 0:1a89e28dea91 161 struct byte_array* serial_encode_string(struct byte_array* buf, int32_t key, const struct byte_array* bytes)
yusufx 0:1a89e28dea91 162 {
yusufx 0:1a89e28dea91 163 if (!bytes)
yusufx 0:1a89e28dea91 164 return buf;
yusufx 0:1a89e28dea91 165 if (!buf)
yusufx 0:1a89e28dea91 166 buf = byte_array_new();
yusufx 0:1a89e28dea91 167
yusufx 0:1a89e28dea91 168 if (key)
yusufx 0:1a89e28dea91 169 encode_int(buf, key<<2 | SERIAL_STRING);
yusufx 0:1a89e28dea91 170 encode_int(buf, bytes->length);
yusufx 0:1a89e28dea91 171 byte_array_resize(buf, buf->length + bytes->length);
yusufx 0:1a89e28dea91 172 memcpy(buf->current, bytes->data, bytes->length);
yusufx 0:1a89e28dea91 173
yusufx 0:1a89e28dea91 174 buf->current = buf->data + buf->length;
yusufx 0:1a89e28dea91 175 return buf;
yusufx 0:1a89e28dea91 176 }
yusufx 0:1a89e28dea91 177
yusufx 0:1a89e28dea91 178 struct byte_array* serial_encode_array(struct byte_array* buf, int32_t key, int32_t count) {
yusufx 0:1a89e28dea91 179 if (!buf) buf = byte_array_new();
yusufx 0:1a89e28dea91 180 encode_int(buf, key<<2 | SERIAL_ARRAY);
yusufx 0:1a89e28dea91 181 encode_int(buf, count);
yusufx 0:1a89e28dea91 182 return buf;
yusufx 0:1a89e28dea91 183 }
yusufx 0:1a89e28dea91 184
yusufx 0:1a89e28dea91 185 #ifdef DEBUG
yusufx 0:1a89e28dea91 186
yusufx 0:1a89e28dea91 187 bool display_serial(const struct key_value_pair* kvp) {
yusufx 0:1a89e28dea91 188 DEBUGPRINT("serialElementDebug %d:\t", kvp->key);
yusufx 0:1a89e28dea91 189 char* str;
yusufx 0:1a89e28dea91 190
yusufx 0:1a89e28dea91 191 switch (kvp->wire_type) {
yusufx 0:1a89e28dea91 192 case SERIAL_ERROR:
yusufx 0:1a89e28dea91 193 DEBUGPRINT("error %d\n", kvp->value.serialError);
yusufx 0:1a89e28dea91 194 break;
yusufx 0:1a89e28dea91 195 case SERIAL_INT:
yusufx 0:1a89e28dea91 196 DEBUGPRINT("int %d\n", kvp->value.integer);
yusufx 0:1a89e28dea91 197 break;
yusufx 0:1a89e28dea91 198 case SERIAL_FLOAT:
yusufx 0:1a89e28dea91 199 DEBUGPRINT("float %f\n", kvp->value.floater)
yusufx 0:1a89e28dea91 200 case SERIAL_STRING:
yusufx 0:1a89e28dea91 201 str = (char*)malloc(kvp->value.bytes->length + 1);
yusufx 0:1a89e28dea91 202 memcpy(str, kvp->value.bytes->data, kvp->value.bytes->length);
yusufx 0:1a89e28dea91 203 str[kvp->value.bytes->length] = 0;
yusufx 0:1a89e28dea91 204 DEBUGPRINT("bytes %s\n", str);
yusufx 0:1a89e28dea91 205 break;
yusufx 0:1a89e28dea91 206 case SERIAL_ARRAY:
yusufx 0:1a89e28dea91 207 DEBUGPRINT("array\n");
yusufx 0:1a89e28dea91 208 break;
yusufx 0:1a89e28dea91 209 }
yusufx 0:1a89e28dea91 210 return true;
yusufx 0:1a89e28dea91 211 }
yusufx 0:1a89e28dea91 212
yusufx 0:1a89e28dea91 213 #endif // DEBUG