home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / compiler / aros / readstruct.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-07  |  11.9 KB  |  594 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: readstruct.c,v 1.9 1997/02/07 14:22:37 digulla Exp $
  4.  
  5.     Desc: Read a big endian structure from a file
  6.     Lang: english
  7. */
  8. #define AROS_ALMOST_COMPATIBLE
  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>
  15.  
  16. struct ReadLevel
  17. {
  18.     struct MinNode   node;
  19.     const IPTR       * sd;
  20.     UBYTE       * s;
  21.     int          pos;
  22. };
  23.  
  24. /******************************************************************************
  25.  
  26.     NAME */
  27. #include <stdio.h>
  28. #include <aros/structdesc.h>
  29. #include <proto/alib.h>
  30.  
  31.     BOOL ReadStruct (
  32.  
  33. /*  SYNOPSIS */
  34.     BPTR         fh,
  35.     APTR       * dataptr,
  36.     const IPTR * sd)
  37.  
  38. /*  FUNCTION
  39.     Reads one big endian structure from a file.
  40.  
  41.     INPUTS
  42.     fh - Read from this file
  43.     sd - Description of the structure to be read. The first element
  44.         is the size of the structure.
  45.     data - Put the data here
  46.  
  47.     RESULT
  48.     The function returns TRUE on success. On success, the value
  49.     read is written into dataptr. On failure, FALSE is returned and the
  50.     contents of dataptr are not changed.
  51.  
  52.     NOTES
  53.     This function reads big endian values from a file even on little
  54.     endian machines.
  55.  
  56.     EXAMPLE
  57.     See below.
  58.  
  59.     BUGS
  60.  
  61.     SEE ALSO
  62.     Open(), Close(), ReadByte(), ReadWord(), ReadLong(),
  63.     ReadFloat(), ReadString(), WriteByte(), WriteWord(), WriteLong(),
  64.     WriteFloat(), WriteDouble(), WriteString(), WriteStruct()
  65.  
  66.     HISTORY
  67.     14.09.93    ada created
  68.  
  69. ******************************************************************************/
  70. {
  71.     struct MinList     _list;
  72.     struct ReadLevel * curr;
  73.  
  74. #   define list     ((struct List *)&_list)
  75.  
  76.     NEWLIST(list);
  77.  
  78.     if (!(curr = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
  79.     return FALSE;
  80.  
  81.     AddTail (list, (struct Node *)curr);
  82.  
  83.     curr->sd  = sd;
  84.     curr->pos = 0;
  85.     curr->s   = NULL;
  86.  
  87. #   define DESC     curr->sd[curr->pos]
  88. #   define IDESC    curr->sd[curr->pos ++]
  89.  
  90.     for (;;)
  91.     {
  92.     if (!curr->pos)
  93.     {
  94.         if (!(curr->s = AllocMem (IDESC, MEMF_CLEAR)) )
  95.         goto error;
  96.     }
  97.  
  98.     if (DESC == SDT_END)
  99.         break;
  100.  
  101.     switch (IDESC)
  102.     {
  103.     case SDT_UBYTE:      /* Read one  8bit byte */
  104.         if (!ReadByte (fh, (UBYTE *)(curr->s + IDESC)))
  105.         goto error;
  106.  
  107.         break;
  108.  
  109.     case SDT_UWORD:      /* Read one 16bit word */
  110.         if (!ReadWord (fh, (UWORD *)(curr->s + IDESC)))
  111.         goto error;
  112.  
  113.         break;
  114.  
  115.     case SDT_ULONG:      /* Read one 32bit long */
  116.         if (!ReadLong (fh, (ULONG *)(curr->s + IDESC)))
  117.         goto error;
  118.  
  119.         break;
  120.  
  121.     case SDT_FLOAT:      /* Read one 32bit IEEE */
  122.         if (!ReadFloat (fh, (FLOAT *)(curr->s + IDESC)))
  123.         goto error;
  124.  
  125.         break;
  126.  
  127.     case SDT_DOUBLE:     /* Read one 64bit IEEE */
  128.         if (!ReadDouble (fh, (DOUBLE *)(curr->s + IDESC)))
  129.         goto error;
  130.  
  131.         break;
  132.  
  133.     case SDT_STRING: {   /* Read a string */
  134.         UBYTE    valid_ptr;
  135.         STRPTR * sptr;
  136.  
  137.         sptr = (STRPTR *)(curr->s + IDESC);
  138.  
  139.         if (!ReadByte (fh, &valid_ptr))
  140.         goto error;
  141.  
  142.         if (valid_ptr)
  143.         {
  144.         if (!ReadString (fh, sptr))
  145.             goto error;
  146.         }
  147.         else
  148.         {
  149.         *sptr = NULL;
  150.         }
  151.  
  152.         break; }
  153.  
  154.     case SDT_STRUCT: {    /* Read a structure */
  155.         struct ReadLevel * next;
  156.         IPTR * desc;
  157.         APTR   aptr;
  158.  
  159.         aptr = (APTR)(curr->s + IDESC);
  160.         desc = (IPTR *)IDESC;
  161.  
  162.         curr->pos -= 3; /* Go back to type */
  163.  
  164.         if (!(next = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
  165.         goto error;
  166.  
  167.         AddTail (list, (struct Node *)next);
  168.         next->sd  = desc;
  169.         next->pos = 1;
  170.         next->s   = aptr;
  171.  
  172.         curr = next;
  173.  
  174.         break; }
  175.  
  176.     case SDT_PTR: {    /* Follow a pointer */
  177.         struct ReadLevel * next;
  178.  
  179.         UBYTE  valid_ptr;
  180.         IPTR * desc;
  181.         APTR * aptr;
  182.  
  183.         aptr = ((APTR *)(curr->s + IDESC));
  184.         desc = (IPTR *)IDESC;
  185.  
  186.         if (!ReadByte (fh, &valid_ptr))
  187.         goto error;
  188.  
  189.         if (valid_ptr)
  190.         {
  191.         curr->pos -= 3;
  192.  
  193.         if (!(next = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
  194.             goto error;
  195.  
  196.         AddTail (list, (struct Node *)next);
  197.         next->sd  = desc;
  198.         next->pos = 0;
  199.  
  200.         curr = next;
  201.         }
  202.         else
  203.         {
  204.         *aptr = NULL;
  205.         }
  206.  
  207.         break; }
  208.  
  209.     case SDT_IGNORE:     /* Ignore x bytes */
  210.         Flush (fh);
  211.  
  212.         if (Seek (fh, IDESC, OFFSET_CURRENT) == EOF)
  213.         goto error;
  214.  
  215.         break;
  216.  
  217.     case SDT_FILL_BYTE: { /* Fill x bytes */
  218.         IPTR  offset;
  219.         UBYTE value;
  220.         IPTR  count;
  221.  
  222.         offset = IDESC;
  223.         value  = IDESC;
  224.         count  = IDESC;
  225.  
  226.         memset (curr->s + offset, value, count);
  227.  
  228.         break; }
  229.  
  230.     case SDT_FILL_LONG: { /* Fill x longs */
  231.         ULONG * ulptr;
  232.         ULONG   value;
  233.         IPTR    count;
  234.  
  235.         ulptr = (ULONG *)(curr->s + IDESC);
  236.         value = IDESC;
  237.         count = IDESC;
  238.  
  239.         while (count --)
  240.         *ulptr ++ = value;
  241.  
  242.         break; }
  243.  
  244.     case SDT_IFILL_BYTE: { /* Fill x bytes */
  245.         IPTR  offset;
  246.         UBYTE value;
  247.         IPTR  count;
  248.  
  249.         offset = IDESC;
  250.         value  = IDESC;
  251.         count  = IDESC;
  252.  
  253.         Flush (fh);
  254.  
  255.         if (Seek (fh, count, OFFSET_CURRENT) == EOF)
  256.         goto error;
  257.  
  258.         memset (curr->s + offset, value, count);
  259.  
  260.         break; }
  261.  
  262.     case SDT_IFILL_LONG: { /* Fill x longs */
  263.         ULONG * ulptr;
  264.         ULONG   value;
  265.         IPTR    count;
  266.  
  267.         ulptr = (ULONG *)(curr->s + IDESC);
  268.         value = IDESC;
  269.         count = IDESC;
  270.  
  271.         Flush (fh);
  272.  
  273.         if (Seek (fh, count<<2, OFFSET_CURRENT) == EOF)
  274.         goto error;
  275.  
  276.         while (count --)
  277.         *ulptr ++ = value;
  278.  
  279.         break; }
  280.  
  281.     case SDT_SPECIAL: {   /* Call user hook */
  282.         struct Hook * hook;
  283.         struct SDData data;
  284.  
  285.         data.sdd_Dest = ((APTR)(curr->s + IDESC));
  286.         data.sdd_Mode = SDV_SPECIALMODE_READ;
  287.  
  288.         hook = (struct Hook *)IDESC;
  289.  
  290.         CallHookA (hook, fh, &data);
  291.  
  292.         break; }
  293.  
  294.     default:
  295.         goto error;
  296.  
  297.     } /* switch */
  298.  
  299.     /* End of the description list ? */
  300.     if (DESC == SDT_END)
  301.     {
  302.         struct ReadLevel * last;
  303.  
  304.         /* Remove the current level */
  305.         last = curr;
  306.         Remove ((struct Node *)last);
  307.  
  308.         /* Get the last level */
  309.         if ((curr = GetTail (list)))
  310.         {
  311.         switch (IDESC)
  312.         {
  313.         case SDT_STRUCT:
  314.             curr->pos += 2; /* Skip 2 parameters */
  315.             break;
  316.  
  317.         case SDT_PTR: {
  318.             APTR * aptr;
  319.  
  320.             aptr  = ((APTR *)(curr->s + IDESC));
  321.             curr->pos ++; /* Skip description parameter */
  322.  
  323.             /*
  324.             Now put the result of the current level in the
  325.             struct of the previous level.
  326.             */
  327.             *aptr = last->s;
  328.  
  329.             break; }
  330.  
  331.         }
  332.  
  333.         FreeMem (last, sizeof (struct ReadLevel));
  334.         }
  335.         else
  336.         {
  337.         curr = last;
  338.         }
  339.     }
  340.     } /* while */
  341.  
  342.     *dataptr = curr->s;
  343.  
  344.     FreeMem (curr, sizeof (struct ReadLevel));
  345.  
  346.     return TRUE;
  347.  
  348. error:
  349.     curr = GetHead (list);
  350.  
  351.     /* TODO
  352.     if (curr && curr->s)
  353.     FreeStruct (curr->s, curr->sd); */
  354.  
  355.     while ((curr = (struct ReadLevel *)RemTail (list)))
  356.     FreeMem (curr, sizeof (struct ReadLevel));
  357.  
  358.     return FALSE;
  359. } /* ReadStruct */
  360.  
  361. #ifdef TEST
  362. #include <stdio.h>
  363. #include <dos/dos.h>
  364. #include <aros/structdesc.h>
  365. #include <proto/alib.h>
  366.  
  367. struct Level1
  368. {
  369.     BYTE l1_Byte;
  370.     LONG l1_Long;
  371. };
  372.  
  373. struct MainLevel
  374. {
  375.     BYTE   ml_Byte;
  376.     UBYTE  ml_UByte;
  377.     WORD   ml_Word;
  378.     UWORD  ml_UWord;
  379.     LONG   ml_Long;
  380.     ULONG  ml_ULong;
  381.     FLOAT  ml_Float;
  382.     DOUBLE ml_Double;
  383.     STRPTR ml_String;
  384.     struct Level1 ml_Level1;
  385.  
  386.     BYTE   * ml_BytePtr;
  387.     WORD   * ml_WordPtr;
  388.     LONG   * ml_LongPtr;
  389.     FLOAT  * ml_FloatPtr;
  390.     DOUBLE * ml_DoublePtr;
  391.     STRPTR * ml_StringPtr;
  392.     struct Level1 * ml_Level1Ptr;
  393. };
  394.  
  395. IPTR ByteDesc[]   = { sizeof(UBYTE),  SDM_UBYTE(0),  SDM_END };
  396. IPTR WordDesc[]   = { sizeof(UWORD),  SDM_UWORD(0),  SDM_END };
  397. IPTR LongDesc[]   = { sizeof(ULONG),  SDM_ULONG(0),  SDM_END };
  398. IPTR FloatDesc[]  = { sizeof(FLOAT),  SDM_FLOAT(0),  SDM_END };
  399. IPTR DoubleDesc[] = { sizeof(DOUBLE), SDM_DOUBLE(0), SDM_END };
  400. IPTR StringDesc[] = { sizeof(STRPTR), SDM_STRING(0), SDM_END };
  401.  
  402. #define O(x)        offsetof(struct Level1,x)
  403. IPTR Level1Desc[] =
  404. {
  405.     sizeof (struct Level1),
  406.     SDM_UBYTE(O(l1_Byte)),
  407.     SDM_ULONG(O(l1_Long)),
  408.     SDM_END
  409. };
  410.  
  411. #undef O
  412. #define O(x)        offsetof(struct MainLevel,x)
  413. IPTR MainDesc[] =
  414. {
  415.     sizeof (struct MainLevel),
  416.     SDM_UBYTE(O(ml_Byte)),
  417.     SDM_UBYTE(O(ml_UByte)),
  418.     SDM_UWORD(O(ml_Word)),
  419.     SDM_UWORD(O(ml_UWord)),
  420.     SDM_ULONG(O(ml_Long)),
  421.     SDM_ULONG(O(ml_ULong)),
  422.     SDM_FLOAT(O(ml_Float)),
  423.     SDM_DOUBLE(O(ml_Double)),
  424.     SDM_STRING(O(ml_String)),
  425.     SDM_STRUCT(O(ml_Level1),Level1Desc),
  426.  
  427.     SDM_PTR(O(ml_BytePtr),ByteDesc),
  428.     SDM_PTR(O(ml_WordPtr),WordDesc),
  429.     SDM_PTR(O(ml_LongPtr),LongDesc),
  430.     SDM_PTR(O(ml_FloatPtr),FloatDesc),
  431.     SDM_PTR(O(ml_DoublePtr),DoubleDesc),
  432.     SDM_PTR(O(ml_StringPtr),StringDesc),
  433.     SDM_PTR(O(ml_Level1Ptr),Level1Desc),
  434.  
  435.     SDM_END
  436. };
  437.  
  438. int main (int argc, char ** argv)
  439. {
  440.     struct MainLevel demo =
  441.     {
  442.     (BYTE)0x88,       0xFF,
  443.     (WORD)0x8844,     0xFF77,
  444.     (LONG)0x88442211, 0xFF773311,
  445.     1.5, 1.75,
  446.     "Hallo",
  447.     { (BYTE)0x88, (LONG)0x88442211 },
  448.     /* ... */
  449.     };
  450.     BYTE b = (BYTE)0x88;
  451.     WORD w = (WORD)0x8844;
  452.     LONG l = (LONG)0x88442211;
  453.     FLOAT f = 1.5;
  454.     DOUBLE d = 1.75;
  455.     STRPTR s = "Hallo";
  456.     struct Level1 l1 =
  457.     {
  458.     (BYTE)0x88, (LONG)0x88442211
  459.     };
  460.     BPTR fh;
  461.     struct MainLevel * readback;
  462.  
  463.     demo.ml_BytePtr = &b;
  464.     demo.ml_WordPtr = &w;
  465.     demo.ml_LongPtr = &l;
  466.     demo.ml_FloatPtr = &f;
  467.     demo.ml_DoublePtr = &d;
  468.     demo.ml_StringPtr = &s;
  469.     demo.ml_Level1Ptr = &l1;
  470.  
  471.     fh = Open ("writestruct.dat", MODE_NEWFILE);
  472.  
  473.     if (!fh)
  474.     {
  475.     PrintFault (IoErr(), "Can't open file\n");
  476.     return 10;
  477.     }
  478.  
  479.     /*
  480.     This writes the following data stream:
  481.  
  482.         0000 88                ml_Byte
  483.         0001 ff                ml_Ubyte
  484.         0002 88 44                ml_Word
  485.         0004 ff 77                ml_UWord
  486.         0006 88 44 22 11            ml_Long
  487.         000a ff 77 33 11            ml_ULong
  488.         000e 3f c0 00 00            ml_Float
  489.         0012 3f fc 00 00 00 00 00 00    ml_Double
  490.         001a 01:48 61 6c 6c 6f 00        ml_String
  491.         0021 88                ml_Level1.l1_Byte
  492.         0022 88 44 22 11            ml_Level1.l1_Long
  493.         0026 01:88                ml_BytePtr
  494.         0028 01:88 44            ml_WordPtr
  495.         002b 01:88 44 22 11         ml_LongPtr
  496.         0030 01:3f c0 00 00         ml_FloatPtr
  497.         0035 01:3f fc 00 00 00 00 00 00 ml_DoublePtr
  498.         003e 01:01:48 61 6c 6c 6f 00    ml_StringPtr - Note two 01 !
  499.         0046 01:88 88 44 22 11        ml_Level1Ptr
  500.     */
  501.  
  502.     if (!WriteStruct (fh, &demo, MainDesc))
  503.     {
  504.     PrintFault (IoErr(), "Failed to write to file\n");
  505.     }
  506.  
  507.     if (!Close (fh))
  508.     {
  509.     PrintFault (IoErr(), "Failed to close file\n");
  510.     }
  511.  
  512.     /* Read the structure back */
  513.     fh = Open ("writestruct.dat", MODE_OLDFILE);
  514.  
  515.     if (!fh)
  516.     {
  517.     PrintFault (IoErr(), "Can't open file for reading\n");
  518.     return 10;
  519.     }
  520.  
  521.     if (!ReadStruct (fh, (APTR *)&readback, MainDesc))
  522.     {
  523.     PrintFault (IoErr(), "Failed to read from file\n");
  524.     }
  525.     else
  526.     {
  527.     UBYTE * ptr;
  528.     int t;
  529.  
  530.     ptr = (UBYTE *)readback;
  531.     t = 0;
  532.  
  533.     kprintf ("readback = %p\n", readback);
  534.  
  535.     kprintf ("%02x (88) %02x (FF)\n"
  536.         , (UBYTE)readback->ml_Byte
  537.         , readback->ml_UByte
  538.     );
  539.     kprintf ("%04x (8844) %04x (FF77)\n"
  540.         , (UWORD)readback->ml_Word
  541.         , readback->ml_UWord
  542.     );
  543.     kprintf ("%08lx (88442211) %08lx (FF773311)\n"
  544.         , readback->ml_Long
  545.         , readback->ml_ULong
  546.     );
  547.     kprintf ("%08lx (3FC00000) %08lx:%08lx (3FFC0000:00000000)\n"
  548.         , *(ULONG *)&readback->ml_Float
  549.         , ((ULONG *)&readback->ml_Double)[1]
  550.         , ((ULONG *)&readback->ml_Double)[0]
  551.     );
  552.     kprintf ("%s (Hallo)\n"
  553.         , readback->ml_String
  554.     );
  555.     kprintf ("{ %02x %08x } ({ 88 88442211 })\n"
  556.         , (UBYTE)readback->ml_Level1.l1_Byte
  557.         , readback->ml_Level1.l1_Long
  558.     );
  559.     kprintf ("%02x (88)\n"
  560.         , (UBYTE)*readback->ml_BytePtr
  561.     );
  562.     kprintf ("%04x (8844)\n"
  563.         , (UWORD)*readback->ml_WordPtr
  564.     );
  565.     kprintf ("%08lx (88442211)\n"
  566.         , *readback->ml_LongPtr
  567.     );
  568.     kprintf ("%08lx (3FC00000) %08lx:%08lx (3FFC0000:00000000)\n"
  569.         , *(ULONG *)readback->ml_FloatPtr
  570.         , ((ULONG *)readback->ml_DoublePtr)[1]
  571.         , ((ULONG *)readback->ml_DoublePtr)[0]
  572.     );
  573.     kprintf ("%s (Hallo)\n"
  574.         , *readback->ml_StringPtr
  575.     );
  576.     kprintf ("{ %02x %08x } ({ 88 88442211 })\n"
  577.         , (UBYTE)readback->ml_Level1Ptr->l1_Byte
  578.         , readback->ml_Level1Ptr->l1_Long
  579.     );
  580.  
  581.     FreeStruct (readback, MainDesc);
  582.     }
  583.  
  584.     if (!Close (fh))
  585.     {
  586.     PrintFault (IoErr(), "Failed to close file after reading\n");
  587.     }
  588.  
  589.     return 0;
  590. } /* main */
  591.  
  592. #endif /* TEST */
  593.  
  594.