Sample: cleaning up Inheritance
[io/quag.git] / libs / basekit / source / BStream.c
blobfb9939ce64e5d0e3e72e9b13b800b2b14823be3b
1 /*
2 docCopyright("Steve Dekorte", 2004)
3 docLicense("BSD revised")
4 */
6 #include "Base.h"
8 //#define BStream_C
9 #include "BStream.h"
10 //#undef BStream_C
12 #include <string.h>
13 #include <ctype.h>
14 #include <stdlib.h>
15 #include <math.h>
16 #include <limits.h>
18 #define BSTREAM_IS_BIG_ENDIAN 1
20 BStream *BStream_new(void)
22 int flipEndian;
23 BStream *self = (BStream *)io_calloc(1, sizeof(BStream));
24 self->ba = UArray_new();
25 self->index = 0;
26 self->ownsUArray = 1;
27 self->tmp = UArray_new();
28 self->errorBa = UArray_new();
29 flipEndian = 0;
30 self->typeBuf = (unsigned char *)io_calloc(1, 512);
31 return self;
34 BStream *BStream_clone(BStream *self)
36 BStream *child = BStream_new();
37 UArray_copy_(child->ba, self->ba);
38 child->index = self->index;
39 return child;
42 void BStream_free(BStream *self)
44 if (self->ownsUArray) UArray_free(self->ba);
45 UArray_free(self->tmp);
46 UArray_free(self->errorBa);
47 io_free(self->typeBuf);
48 io_free(self);
51 void BStream_error_(BStream *self, const char *s)
53 UArray_setCString_(self->errorBa, s);
56 char *BStream_error(BStream *self)
58 return (char *)UArray_bytes(self->errorBa);
61 void BStream_setUArray_(BStream *self, UArray *ba)
63 if (self->ownsUArray)
65 UArray_free(ba);
66 self->ownsUArray = 0;
68 self->ba = ba;
69 self->index = 0;
72 void BStream_setData_length_(BStream *self, unsigned char *data, size_t length)
74 UArray_setData_type_size_copy_(self->ba, data, CTYPE_uint8_t, length, 1);
75 self->index = 0;
78 UArray *BStream_byteArray(BStream *self)
80 return self->ba;
83 void BStream_empty(BStream *self)
85 self->index = 0;
86 UArray_setSize_(self->ba, 0);
89 int BStream_isEmpty(BStream *self)
91 return UArray_size(self->ba) == 0;
94 // writing --------------------------------------
96 void BStream_writeByte_(BStream *self, unsigned char v)
98 BStream_writeUint8_(self, v);
101 void BStream_writeUint8_(BStream *self, uint8_t v)
103 UArray_appendLong_(self->ba, v);
104 self->index ++;
107 static void reverseBytes(unsigned char *d, size_t length)
109 size_t a = 0;
110 size_t b = length - 1;
112 while ( a < b)
114 unsigned char c = d[a];
116 d[a] = d[b];
117 d[b] = c;
118 a ++;
119 b --;
123 void BStream_writeNumber_size_(BStream *self, unsigned char *v, size_t length)
125 memcpy(self->typeBuf, v, length);
127 if (self->flipEndian)
129 reverseBytes(self->typeBuf, length);
132 UArray_appendBytes_size_(self->ba, (unsigned char *)self->typeBuf, length);
133 self->index += length;
136 void BStream_writeData_length_(BStream *self, const unsigned char *data, size_t length)
138 UArray_appendBytes_size_(self->ba, (unsigned char *)data, length);
139 self->index += length;
142 void BStream_writeInt32_(BStream *self, int32_t v)
144 BStream_writeNumber_size_(self, (unsigned char *)(&v), sizeof(int32_t));
147 void BStream_writeUint32_(BStream *self, uint32_t v)
149 BStream_writeNumber_size_(self, (unsigned char *)(&v), sizeof(uint32_t));
152 #if !defined(__SYMBIAN32__)
153 void BStream_writeInt64_(BStream *self, int64_t v)
155 BStream_writeNumber_size_(self, (unsigned char *)(&v), sizeof(int64_t));
157 #endif
159 void BStream_writeDouble_(BStream *self, double v)
161 BStream_writeNumber_size_(self, (unsigned char *)(&v), sizeof(double));
164 void BStream_writeCString_(BStream *self, const char *s)
166 int length = strlen(s);
167 BStream_writeInt32_(self, length);
168 BStream_writeData_length_(self, (unsigned char *)s, length);
171 void BStream_writeUArray_(BStream *self, UArray *ba)
173 BStream_writeInt32_(self, UArray_size(ba));
174 UArray_append_(self->ba, ba);
175 self->index += UArray_size(ba);
178 // reading --------------------------------------
180 unsigned char BStream_readByte(BStream *self)
182 return BStream_readUint8(self);
185 uint8_t BStream_readUint8(BStream *self)
187 if (self->index < UArray_size(self->ba))
189 unsigned char b = UArray_bytes(self->ba)[self->index];
190 self->index ++;
191 return b;
194 return 0;
197 void BStream_readNumber_size_(BStream *self, unsigned char *v, int size)
199 if (self->index + size <= UArray_size(self->ba))
201 const uint8_t *b = UArray_bytes(self->ba);
202 memcpy(v, b + self->index, size);
204 if (self->flipEndian)
206 reverseBytes(v, size);
209 self->index += size;
210 return;
213 while (size--)
215 *v = 0;
216 v ++;
220 uint32_t BStream_readUint32(BStream *self)
222 uint32_t v;
223 BStream_readNumber_size_(self, (unsigned char *)(&v), sizeof(uint32_t));
224 return v;
227 int32_t BStream_readInt32(BStream *self)
229 int32_t v;
230 BStream_readNumber_size_(self, (unsigned char *)(&v), sizeof(int32_t));
231 return v;
234 #if !defined(__SYMBIAN32__)
235 int64_t BStream_readInt64(BStream *self)
237 int64_t v;
238 BStream_readNumber_size_(self, (unsigned char *)(&v), sizeof(int64_t));
239 return v;
241 #endif
243 double BStream_readDouble(BStream *self)
245 double v;
246 BStream_readNumber_size_(self, (unsigned char *)(&v), sizeof(double));
247 return v;
250 unsigned char *BStream_readDataOfLength_(BStream *self, size_t length)
252 if (self->index + length <= UArray_size(self->ba))
254 unsigned char *b = (unsigned char *)UArray_bytes(self->ba) + self->index;
255 self->index += length;
256 return b;
259 return NULL;
262 void BStream_readUArray_(BStream *self, UArray *b)
264 size_t size = BStream_readInt32(self);
265 unsigned char *data = BStream_readDataOfLength_(self, size);
266 UArray_setData_type_size_copy_(b, data, CTYPE_uint8_t, size, 1);
269 UArray *BStream_readUArray(BStream *self)
271 BStream_readUArray_(self, self->tmp);
272 return self->tmp;
275 const char *BStream_readCString(BStream *self)
277 BStream_readUArray_(self, self->tmp);
278 return (const char *)UArray_bytes(self->tmp);
281 // tagged writing --------------------------------------
283 void BStream_writeTag(BStream *self, unsigned int t, unsigned int b, unsigned int a)
285 BStreamTag tag;
286 tag.isArray = a;
287 tag.type = t;
288 tag.byteCount = b;
291 unsigned char c = BStreamTag_asUnsignedChar(&tag);
292 BStreamTag tag2 = BStreamTag_FromUnsignedChar(c);
294 if (tag2.isArray != tag.isArray ||
295 tag2.type != tag.type ||
296 tag2.byteCount != tag.byteCount)
298 printf("tags don't match\n");
299 exit(-1);
302 BStream_writeUint8_(self, c);
306 void BStream_writeTaggedUint8_(BStream *self, uint8_t v)
308 BStream_writeTag(self, BSTREAM_UNSIGNED_INT, 1, 0);
309 BStream_writeUint8_(self, v);
312 void BStream_writeTaggedUint32_(BStream *self, uint32_t v)
314 BStream_writeTag(self, BSTREAM_UNSIGNED_INT, 4, 0);
315 BStream_writeUint32_(self, v);
318 void BStream_writeTaggedInt32_(BStream *self, int32_t v)
321 if (v =< MAX_INT && v -128)
323 BStream_writeTag(self, BSTREAM_SIGNED_INT, 1, 0);
324 BStream_writeInt8_(self, (int8_t)v);
326 else
329 BStream_writeTag(self, BSTREAM_SIGNED_INT, 4, 0);
330 BStream_writeInt32_(self, v);
333 #if !defined(__SYMBIAN32__)
334 void BStream_writeTaggedInt64_(BStream *self, int64_t v)
336 BStream_writeTag(self, BSTREAM_SIGNED_INT, 8, 0);
337 BStream_writeInt64_(self, v);
339 #endif
342 #if sizeof(double) != 8
343 #error BStream expects doubles to be 64bit
344 #endif
347 void BStream_writeTaggedDouble_(BStream *self, double v)
349 BStream_writeTag(self, BSTREAM_FLOAT, 8, 0);
350 BStream_writeDouble_(self, v);
353 void BStream_writeTaggedData_length_(BStream *self, const unsigned char *data, size_t length)
355 BStream_writeTag(self, BSTREAM_UNSIGNED_INT, 1, 1);
356 BStream_writeTaggedInt32_(self, length);
357 UArray_appendBytes_size_(self->ba, (unsigned char *)data, length);
358 self->index += length;
361 void BStream_writeTaggedCString_(BStream *self, const char *s)
363 BStream_writeTaggedData_length_(self, (unsigned char *)s, strlen(s));
366 void BStream_writeTaggedUArray_(BStream *self, UArray *ba)
368 BStream_writeTaggedData_length_(self, UArray_bytes(ba), UArray_size(ba));
371 // reading --------------------------------------
373 int BStream_readTag(BStream *self, unsigned int t, unsigned int b, unsigned int a)
375 unsigned char c = BStream_readUint8(self);
376 BStreamTag readTag = BStreamTag_FromUnsignedChar(c);
377 BStreamTag expectedTag = BStreamTag_TagArray_type_byteCount_(a, t, b);
379 if (!BStreamTag_isEqual_(&readTag, &expectedTag))
381 printf("BStream error: read:\n ");
382 BStreamTag_print(&readTag);
383 printf(" but expected:\n ");
384 BStreamTag_print(&expectedTag);
385 printf("\n");
386 BStream_show(self);
387 printf("\n");
388 return -1;
391 return 0;
395 unsigned char BStream_readTaggedByte(BStream *self)
397 BStream_readTag(self, BSTREAM_UNSIGNED_INT, 1, 0);
398 return BStream_readByte(self);
401 int BStream_readTaggedInt(BStream *self)
403 BStream_readTag(self, BSTREAM_SIGNED_INT, 4, 0);
404 return BStream_readInt32(self);
408 uint8_t BStream_readTaggedUint8(BStream *self)
410 return BStream_readTaggedInt32(self);
413 uint32_t BStream_readTaggedUint32(BStream *self)
415 unsigned char c = BStream_readByte(self);
416 BStreamTag t = BStreamTag_FromUnsignedChar(c);
418 if (t.type == BSTREAM_UNSIGNED_INT && t.byteCount == 1)
419 { return (uint32_t)BStream_readUint8(self); }
421 if (t.type == BSTREAM_UNSIGNED_INT && t.byteCount == 4)
422 { return (uint32_t)BStream_readUint32(self); }
424 BStream_error_(self, "unhandled int type/size combination");
425 return 0;
428 int32_t BStream_readTaggedInt32(BStream *self)
430 unsigned char c = BStream_readByte(self);
431 BStreamTag t = BStreamTag_FromUnsignedChar(c);
433 if (t.type == BSTREAM_UNSIGNED_INT && t.byteCount == 1)
435 return (int32_t)BStream_readUint8(self);
438 if (t.type == BSTREAM_SIGNED_INT && t.byteCount == 4)
440 return (int32_t)BStream_readInt32(self);
443 if (t.type == BSTREAM_SIGNED_INT && t.byteCount == 8)
445 return (int32_t)BStream_readInt64(self);
449 BStream_error_(self, "unhandled int type/size combination");
451 return 0;
454 intptr_t BStream_readTaggedPointer(BStream *self)
456 unsigned char c = BStream_readByte(self);
457 BStreamTag t = BStreamTag_FromUnsignedChar(c);
459 if (t.type == BSTREAM_POINTER)
461 BStream_error_(self, "expected pointer");
462 return 0;
465 if (t.byteCount == 1)
467 return (intptr_t)BStream_readUint8(self);
470 if (t.byteCount == 4)
472 return (intptr_t)BStream_readInt32(self);
475 #if !defined(__SYMBIAN32__)
476 if (t.byteCount == 8)
478 return (intptr_t)BStream_readInt64(self);
480 #endif
482 BStream_error_(self, "unhandled pointer size");
483 return 0;
486 double BStream_readTaggedDouble(BStream *self)
488 unsigned char c = BStream_readByte(self);
489 BStreamTag t = BStreamTag_FromUnsignedChar(c);
491 if (t.type == BSTREAM_FLOAT && t.byteCount == 4)
493 return BStream_readFloat(self);
496 if (t.type == BSTREAM_FLOAT && t.byteCount == 8)
498 return BStream_readDouble(self);
501 BStream_error_(self, "unhandled float type/size combination");
502 return 0;
505 void BStream_readTaggedUArray_(BStream *self, UArray *b)
507 BStream_readTag(self, BSTREAM_UNSIGNED_INT, 1, 1);
509 size_t size = BStream_readTaggedInt32(self);
510 unsigned char *data = BStream_readDataOfLength_(self, size);
511 UArray_setData_type_size_copy_(b, data, CTYPE_uint8_t, size, 1);
515 UArray *BStream_readTaggedUArray(BStream *self)
517 BStream_readTaggedUArray_(self, self->tmp);
518 return self->tmp;
521 const char *BStream_readTaggedCString(BStream *self)
523 BStream_readTag(self, BSTREAM_UNSIGNED_INT, 1, 1);
526 size_t size = BStream_readTaggedInt32(self);
527 return (char *)BStream_readDataOfLength_(self, size);
531 int BStream_atEnd(BStream *self)
533 return self->index >= UArray_size(self->ba);
536 int BStream_showInt(BStream *self)
538 unsigned char c = BStream_readUint8(self);
539 BStreamTag t = BStreamTag_FromUnsignedChar(c);
540 int v = 0;
542 printf("%s%i ", BStreamTag_typeName(&t), t.byteCount * 8);
544 if (t.byteCount < 5)
546 BStream_readNumber_size_(self, (unsigned char *)(&v), t.byteCount);
548 else
550 printf("ERROR: byteCount out of range\n");
551 exit(-1);
554 printf("%i", v);
555 return v;
558 void BStream_show(BStream *self)
560 int pos = self->index;
561 int v = 0;
563 self->index = 0;
565 while (!BStream_atEnd(self))
567 unsigned char c = BStream_readUint8(self);
568 BStreamTag t = BStreamTag_FromUnsignedChar(c);
570 /*printf("isArray:%i type:%s byteCount:%i value:", t.isArray, BStreamTag_typeName(t), t.byteCount);*/
571 printf(" %s%i %s", BStreamTag_typeName(&t), t.byteCount * 8, t.isArray ? "array " : "");
572 fflush(stdout);
574 if (t.isArray)
576 printf("[");
578 if (t.byteCount == 1)
580 int size = BStream_showInt(self);
581 if (size == 0)
583 printf(" '']\n");
585 else
587 unsigned char *data = BStream_readDataOfLength_(self, size);
588 printf(" '%s']\n", data);
591 else
593 printf("ERROR: array element byteCount not 1\n");
594 exit(-1);
597 else
599 if (t.byteCount > 0 && t.byteCount < 5)
601 BStream_readNumber_size_(self, (unsigned char *)(&v), t.byteCount);
603 else
605 printf("ERROR: byteCount out of range\n");
606 exit(1);
610 if (t.byteCount == 1)
612 printf("%c\n", v);
614 else
617 printf("%i\n", v);
618 /*}*/
621 self->index = pos;