2 docCopyright("Steve Dekorte", 2004)
3 docLicense("BSD revised")
18 #define BSTREAM_IS_BIG_ENDIAN 1
20 BStream
*BStream_new(void)
23 BStream
*self
= (BStream
*)io_calloc(1, sizeof(BStream
));
24 self
->ba
= UArray_new();
27 self
->tmp
= UArray_new();
28 self
->errorBa
= UArray_new();
30 self
->typeBuf
= (unsigned char *)io_calloc(1, 512);
34 BStream
*BStream_clone(BStream
*self
)
36 BStream
*child
= BStream_new();
37 UArray_copy_(child
->ba
, self
->ba
);
38 child
->index
= self
->index
;
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
);
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
)
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);
78 UArray
*BStream_byteArray(BStream
*self
)
83 void BStream_empty(BStream
*self
)
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
);
107 static void reverseBytes(unsigned char *d
, size_t length
)
110 size_t b
= length
- 1;
114 unsigned char c
= d
[a
];
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));
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
];
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
);
220 uint32_t BStream_readUint32(BStream
*self
)
223 BStream_readNumber_size_(self
, (unsigned char *)(&v
), sizeof(uint32_t));
227 int32_t BStream_readInt32(BStream
*self
)
230 BStream_readNumber_size_(self
, (unsigned char *)(&v
), sizeof(int32_t));
234 #if !defined(__SYMBIAN32__)
235 int64_t BStream_readInt64(BStream
*self
)
238 BStream_readNumber_size_(self
, (unsigned char *)(&v
), sizeof(int64_t));
243 double BStream_readDouble(BStream
*self
)
246 BStream_readNumber_size_(self
, (unsigned char *)(&v
), sizeof(double));
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
;
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
);
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
)
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");
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);
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
);
342 #if sizeof(double) != 8
343 #error BStream expects doubles to be 64bit
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
);
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");
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");
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");
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
);
482 BStream_error_(self
, "unhandled pointer size");
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");
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
);
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
);
542 printf("%s%i ", BStreamTag_typeName(&t
), t
.byteCount
* 8);
546 BStream_readNumber_size_(self
, (unsigned char *)(&v
), t
.byteCount
);
550 printf("ERROR: byteCount out of range\n");
558 void BStream_show(BStream
*self
)
560 int pos
= self
->index
;
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 " : "");
578 if (t
.byteCount
== 1)
580 int size
= BStream_showInt(self
);
587 unsigned char *data
= BStream_readDataOfLength_(self
, size
);
588 printf(" '%s']\n", data
);
593 printf("ERROR: array element byteCount not 1\n");
599 if (t
.byteCount
> 0 && t
.byteCount
< 5)
601 BStream_readNumber_size_(self
, (unsigned char *)(&v
), t
.byteCount
);
605 printf("ERROR: byteCount out of range\n");
610 if (t.byteCount == 1)