Indentation fix, cleanup.
[AROS.git] / compiler / arossupport / readstruct.c
blob93ff18879dc5168d101f1ea39dfdfb29844ba9e6
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Read a big endian structure from a streamhook
6 Lang: english
7 */
9 #include <string.h>
10 #include <exec/memory.h>
11 #include <proto/dos.h>
12 #include <proto/exec.h>
13 #include <aros/debug.h>
14 #include <utility/hooks.h>
16 struct ReadLevel
18 struct MinNode node;
19 const IPTR * sd;
20 UBYTE * s;
21 int pos;
24 /******************************************************************************
26 NAME */
27 #include <stdio.h>
28 #include <aros/bigendianio.h>
29 #include <proto/alib.h>
31 BOOL ReadStruct (
33 /* SYNOPSIS */
34 struct Hook * hook,
35 APTR * dataptr,
36 void * stream,
37 const IPTR * sd)
39 /* FUNCTION
40 Reads one big endian structure from a streamhook.
42 INPUTS
43 hook - Streamhook
44 dataptr - Put the data here. If NULL, a new memory block is allocated
45 stream - Read from this stream
46 sd - Description of the structure to be read. The first element
47 is the size of the structure.
49 RESULT
50 The function returns TRUE on success. On success, the value
51 read is written into dataptr. On failure, FALSE is returned and the
52 contents of dataptr are not changed.
54 NOTES
55 This function reads big endian values from a streamhook even on
56 little endian machines.
58 EXAMPLE
59 See below.
61 BUGS
63 SEE ALSO
64 ReadByte(), ReadWord(), ReadLong(), ReadFloat(), ReadDouble(),
65 ReadString(), ReadStruct(), WriteByte(), WriteWord(), WriteLong(),
66 WriteFloat(), WriteDouble(), WriteString(), WriteStruct()
68 HISTORY
70 ******************************************************************************/
72 struct MinList _list;
73 struct ReadLevel * curr;
74 BOOL pre_alloc = (*dataptr) ? TRUE : FALSE;
76 # define list ((struct List *)&_list)
78 NEWLIST(list);
80 if (!(curr = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
81 return FALSE;
83 AddTail (list, (struct Node *)curr);
85 curr->sd = sd;
86 curr->pos = 0;
87 curr->s = *dataptr;
89 # define DESC curr->sd[curr->pos]
90 # define IDESC curr->sd[curr->pos ++]
92 for (;;)
94 if (!curr->pos)
96 IPTR size = IDESC;
97 if (!curr->s && !(curr->s = AllocMem (size, MEMF_CLEAR)) )
98 goto error;
101 if (DESC == SDT_END)
102 break;
104 switch (IDESC)
106 case SDT_UBYTE: /* Read one 8bit byte */
107 if (!ReadByte (hook, (UBYTE *)(curr->s + IDESC), stream))
108 goto error;
110 break;
112 case SDT_UWORD: /* Read one 16bit word */
113 if (!ReadWord (hook, (UWORD *)(curr->s + IDESC), stream))
114 goto error;
116 break;
118 case SDT_ULONG: /* Read one 32bit long */
119 if (!ReadLong (hook, (ULONG *)(curr->s + IDESC), stream))
120 goto error;
122 break;
124 case SDT_FLOAT: /* Read one 32bit IEEE */
125 if (!ReadFloat (hook, (FLOAT *)(curr->s + IDESC), stream))
126 goto error;
128 break;
130 case SDT_DOUBLE: /* Read one 64bit IEEE */
131 if (!ReadDouble (hook, (DOUBLE *)(curr->s + IDESC), stream))
132 goto error;
134 break;
136 case SDT_STRING: { /* Read a string */
137 UBYTE valid_ptr;
138 STRPTR * sptr;
140 sptr = (STRPTR *)(curr->s + IDESC);
142 if (!ReadByte (hook, &valid_ptr, stream))
143 goto error;
145 if (valid_ptr)
147 if (!ReadString (hook, sptr, stream))
148 goto error;
150 else
152 *sptr = NULL;
155 break; }
157 case SDT_STRUCT: { /* Read a structure */
158 struct ReadLevel * next;
159 IPTR * desc;
160 APTR aptr;
162 aptr = (APTR)(curr->s + IDESC);
163 desc = (IPTR *)IDESC;
165 curr->pos -= 3; /* Go back to type */
167 if (!(next = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
168 goto error;
170 AddTail (list, (struct Node *)next);
171 next->sd = desc;
172 next->pos = 1;
173 next->s = aptr;
175 curr = next;
177 break; }
179 case SDT_PTR: { /* Follow a pointer */
180 struct ReadLevel * next;
182 UBYTE valid_ptr;
183 IPTR * desc;
184 APTR * aptr;
186 aptr = ((APTR *)(curr->s + IDESC));
187 desc = (IPTR *)IDESC;
189 if (!ReadByte (hook, &valid_ptr, stream))
190 goto error;
192 if (valid_ptr)
194 curr->pos -= 3;
196 if (!(next = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
197 goto error;
199 AddTail (list, (struct Node *)next);
200 next->sd = desc;
201 next->pos = 0;
203 curr = next;
205 else
207 *aptr = NULL;
210 break; }
212 case SDT_IGNORE: { /* Ignore x bytes */
213 struct BEIOM_Ignore ig = {BEIO_IGNORE, IDESC};
214 if (CallHookA (hook, stream, &ig) == EOF)
215 goto error;
217 break; }
219 case SDT_FILL_BYTE: { /* Fill x bytes */
220 IPTR offset;
221 UBYTE value;
222 IPTR count;
224 offset = IDESC;
225 value = IDESC;
226 count = IDESC;
228 memset (curr->s + offset, value, count);
230 break; }
232 case SDT_FILL_LONG: { /* Fill x longs */
233 ULONG * ulptr;
234 ULONG value;
235 IPTR count;
237 ulptr = (ULONG *)(curr->s + IDESC);
238 value = IDESC;
239 count = IDESC;
241 while (count --)
242 *ulptr ++ = value;
244 break; }
246 case SDT_IFILL_BYTE: { /* Fill x bytes */
247 IPTR offset;
248 UBYTE value;
249 IPTR count;
251 offset = IDESC;
252 value = IDESC;
253 count = IDESC;
255 struct BEIOM_Ignore ig = {BEIO_IGNORE, count};
257 if (CallHookA (hook, stream, &ig) == EOF)
258 goto error;
260 memset (curr->s + offset, value, count);
262 break; }
264 case SDT_IFILL_LONG: { /* Fill x longs */
265 ULONG * ulptr;
266 ULONG value;
267 IPTR count;
269 ulptr = (ULONG *)(curr->s + IDESC);
270 value = IDESC;
271 count = IDESC;
273 struct BEIOM_Ignore ig = {BEIO_IGNORE, count << 2};
275 if (CallHookA (hook, stream, &ig) == EOF)
276 goto error;
278 while (count --)
279 *ulptr ++ = value;
281 break; }
283 case SDT_SPECIAL: { /* Call user hook */
284 struct Hook * uhook;
285 struct SDData data;
287 data.sdd_Dest = ((APTR)(curr->s + IDESC));
288 data.sdd_Mode = SDV_SPECIALMODE_READ;
289 data.sdd_Stream = stream;
291 uhook = (struct Hook *)IDESC;
293 if (!CallHookA (uhook, hook, &data))
294 goto error;
296 break; }
298 default:
299 goto error;
301 } /* switch */
303 /* End of the description list ? */
304 if (DESC == SDT_END)
306 struct ReadLevel * last;
308 /* Remove the current level */
309 last = curr;
310 Remove ((struct Node *)last);
312 /* Get the last level */
313 if ((curr = (struct ReadLevel *)GetTail (list)))
315 switch (IDESC)
317 case SDT_STRUCT:
318 curr->pos += 2; /* Skip 2 parameters */
319 break;
321 case SDT_PTR: {
322 APTR * aptr;
324 aptr = ((APTR *)(curr->s + IDESC));
325 curr->pos ++; /* Skip description parameter */
328 Now put the result of the current level in the
329 struct of the previous level.
331 *aptr = last->s;
333 break; }
337 FreeMem (last, sizeof (struct ReadLevel));
339 else
341 curr = last;
344 } /* while */
346 *dataptr = curr->s;
348 FreeMem (curr, sizeof (struct ReadLevel));
350 return TRUE;
352 error:
353 curr = (struct ReadLevel *)GetHead (list);
355 if (curr && curr->s && !pre_alloc)
356 FreeStruct (curr->s, curr->sd);
358 while ((curr = (struct ReadLevel *)RemTail (list)))
359 FreeMem (curr, sizeof (struct ReadLevel));
361 return FALSE;
362 } /* ReadStruct */
364 #ifdef TEST
365 #include <stdio.h>
366 #include <dos/dos.h>
367 #include <aros/structdesc.h>
368 #include <proto/alib.h>
370 struct Level1
372 BYTE l1_Byte;
373 LONG l1_Long;
376 struct MainLevel
378 BYTE ml_Byte;
379 UBYTE ml_UByte;
380 WORD ml_Word;
381 UWORD ml_UWord;
382 LONG ml_Long;
383 ULONG ml_ULong;
384 FLOAT ml_Float;
385 DOUBLE ml_Double;
386 STRPTR ml_String;
387 struct Level1 ml_Level1;
389 BYTE * ml_BytePtr;
390 WORD * ml_WordPtr;
391 LONG * ml_LongPtr;
392 FLOAT * ml_FloatPtr;
393 DOUBLE * ml_DoublePtr;
394 STRPTR * ml_StringPtr;
395 struct Level1 * ml_Level1Ptr;
398 IPTR ByteDesc[] = { sizeof(UBYTE), SDM_UBYTE(0), SDM_END };
399 IPTR WordDesc[] = { sizeof(UWORD), SDM_UWORD(0), SDM_END };
400 IPTR LongDesc[] = { sizeof(ULONG), SDM_ULONG(0), SDM_END };
401 IPTR FloatDesc[] = { sizeof(FLOAT), SDM_FLOAT(0), SDM_END };
402 IPTR DoubleDesc[] = { sizeof(DOUBLE), SDM_DOUBLE(0), SDM_END };
403 IPTR StringDesc[] = { sizeof(STRPTR), SDM_STRING(0), SDM_END };
405 #define O(x) offsetof(struct Level1,x)
406 IPTR Level1Desc[] =
408 sizeof (struct Level1),
409 SDM_UBYTE(O(l1_Byte)),
410 SDM_ULONG(O(l1_Long)),
411 SDM_END
414 #undef O
415 #define O(x) offsetof(struct MainLevel,x)
416 IPTR MainDesc[] =
418 sizeof (struct MainLevel),
419 SDM_UBYTE(O(ml_Byte)),
420 SDM_UBYTE(O(ml_UByte)),
421 SDM_UWORD(O(ml_Word)),
422 SDM_UWORD(O(ml_UWord)),
423 SDM_ULONG(O(ml_Long)),
424 SDM_ULONG(O(ml_ULong)),
425 SDM_FLOAT(O(ml_Float)),
426 SDM_DOUBLE(O(ml_Double)),
427 SDM_STRING(O(ml_String)),
428 SDM_STRUCT(O(ml_Level1),Level1Desc),
430 SDM_PTR(O(ml_BytePtr),ByteDesc),
431 SDM_PTR(O(ml_WordPtr),WordDesc),
432 SDM_PTR(O(ml_LongPtr),LongDesc),
433 SDM_PTR(O(ml_FloatPtr),FloatDesc),
434 SDM_PTR(O(ml_DoublePtr),DoubleDesc),
435 SDM_PTR(O(ml_StringPtr),StringDesc),
436 SDM_PTR(O(ml_Level1Ptr),Level1Desc),
438 SDM_END
441 LONG dosstreamhook (struct Hook * hook, BPTR fh, ULONG * msg);
443 struct Hook dsh =
445 { NULL, NULL }, HookEntry, (void *)dosstreamhook, NULL
448 LONG dosstreamhook (struct Hook * hook, BPTR fh, ULONG * msg)
450 LONG rc;
452 switch (*msg)
454 case BEIO_READ:
455 rc = FGetC (fh);
456 break;
458 case BEIO_WRITE:
459 rc = FPutC (fh, ((struct BEIOM_Write *)msg)->Data);
460 break;
462 case BEIO_IGNORE:
463 Flush (fh);
465 rc = Seek (fh, ((struct BEIOM_Ignore *)msg)->Count, OFFSET_CURRENT);
466 break;
470 return rc;
471 } /* dosstreamhook */
473 int main (int argc, char ** argv)
475 struct MainLevel demo =
477 (BYTE)0x88, 0xFF,
478 (WORD)0x8844, 0xFF77,
479 (LONG)0x88442211, 0xFF773311,
480 1.5, 1.75,
481 "Hallo",
482 { (BYTE)0x88, (LONG)0x88442211 },
483 /* ... */
485 BYTE b = (BYTE)0x88;
486 WORD w = (WORD)0x8844;
487 LONG l = (LONG)0x88442211;
488 FLOAT f = 1.5;
489 DOUBLE d = 1.75;
490 STRPTR s = "Hallo";
491 struct Level1 l1 =
493 (BYTE)0x88, (LONG)0x88442211
495 BPTR fh;
496 struct MainLevel * readback;
498 demo.ml_BytePtr = &b;
499 demo.ml_WordPtr = &w;
500 demo.ml_LongPtr = &l;
501 demo.ml_FloatPtr = &f;
502 demo.ml_DoublePtr = &d;
503 demo.ml_StringPtr = &s;
504 demo.ml_Level1Ptr = &l1;
506 fh = Open ("writestruct.dat", MODE_NEWFILE);
508 if (!fh)
510 PrintFault (IoErr(), "Can't open file\n");
511 return 10;
515 This writes the following data stream:
517 0000 88 ml_Byte
518 0001 ff ml_Ubyte
519 0002 88 44 ml_Word
520 0004 ff 77 ml_UWord
521 0006 88 44 22 11 ml_Long
522 000a ff 77 33 11 ml_ULong
523 000e 3f c0 00 00 ml_Float
524 0012 3f fc 00 00 00 00 00 00 ml_Double
525 001a 01:48 61 6c 6c 6f 00 ml_String
526 0021 88 ml_Level1.l1_Byte
527 0022 88 44 22 11 ml_Level1.l1_Long
528 0026 01:88 ml_BytePtr
529 0028 01:88 44 ml_WordPtr
530 002b 01:88 44 22 11 ml_LongPtr
531 0030 01:3f c0 00 00 ml_FloatPtr
532 0035 01:3f fc 00 00 00 00 00 00 ml_DoublePtr
533 003e 01:01:48 61 6c 6c 6f 00 ml_StringPtr - Note two 01 !
534 0046 01:88 88 44 22 11 ml_Level1Ptr
537 if (!WriteStruct (&dsh, &demo, fh, MainDesc))
539 PrintFault (IoErr(), "Failed to write to file\n");
542 if (!Close (fh))
544 PrintFault (IoErr(), "Failed to close file\n");
547 /* Read the structure back */
548 fh = Open ("writestruct.dat", MODE_OLDFILE);
550 if (!fh)
552 PrintFault (IoErr(), "Can't open file for reading\n");
553 return 10;
556 if (!ReadStruct (&dsh, (APTR *)&readback, fh, MainDesc))
558 PrintFault (IoErr(), "Failed to read from file\n");
560 else
562 UBYTE * ptr;
563 int t;
565 ptr = (UBYTE *)readback;
566 t = 0;
568 kprintf ("readback = %p\n", readback);
570 kprintf ("%02X (88) %02X (FF)\n"
571 , (UBYTE)readback->ml_Byte
572 , readback->ml_UByte
574 kprintf ("%04X (8844) %04X (FF77)\n"
575 , (UWORD)readback->ml_Word
576 , readback->ml_UWord
578 kprintf ("%08lX (88442211) %08lX (FF773311)\n"
579 , readback->ml_Long
580 , readback->ml_ULong
582 kprintf ("%08lX (3FC00000) %08lX:%08lX (3FFC0000:00000000)\n"
583 , *(ULONG *)&readback->ml_Float
584 , ((ULONG *)&readback->ml_Double)[1]
585 , ((ULONG *)&readback->ml_Double)[0]
587 kprintf ("%s (Hallo)\n"
588 , readback->ml_String
590 kprintf ("{ %02X %08X } ({ 88 88442211 })\n"
591 , (UBYTE)readback->ml_Level1.l1_Byte
592 , readback->ml_Level1.l1_Long
594 kprintf ("%02X (88)\n"
595 , (UBYTE)*readback->ml_BytePtr
597 kprintf ("%04X (8844)\n"
598 , (UWORD)*readback->ml_WordPtr
600 kprintf ("%08lX (88442211)\n"
601 , *readback->ml_LongPtr
603 kprintf ("%08lX (3FC00000) %08lX:%08lX (3FFC0000:00000000)\n"
604 , *(ULONG *)readback->ml_FloatPtr
605 , ((ULONG *)readback->ml_DoublePtr)[1]
606 , ((ULONG *)readback->ml_DoublePtr)[0]
608 kprintf ("%s (Hallo)\n"
609 , *readback->ml_StringPtr
611 kprintf ("{ %02X %08X } ({ 88 88442211 })\n"
612 , (UBYTE)readback->ml_Level1Ptr->l1_Byte
613 , readback->ml_Level1Ptr->l1_Long
616 FreeStruct (readback, MainDesc);
619 if (!Close (fh))
621 PrintFault (IoErr(), "Failed to close file after reading\n");
624 return 0;
625 } /* main */
627 #endif /* TEST */