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

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: writestruct.c,v 1.9 1997/02/07 14:22:38 digulla Exp $
  4.  
  5.     Desc: Write a big endian structure to 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 WriteLevel
  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 WriteStruct (
  32.  
  33. /*  SYNOPSIS */
  34.     BPTR         fh,
  35.     APTR         data,
  36.     const IPTR * sd)
  37.  
  38. /*  FUNCTION
  39.     Writes one big endian structure to a file.
  40.  
  41.     INPUTS
  42.     fh - Write to this file
  43.     sd - Description of the structure to be written. The first element
  44.         is the size of the structure.
  45.     data - Address of the structure
  46.  
  47.     RESULT
  48.     The function returns TRUE on success and FALSE otherwise. In error,
  49.     you can examine IoErr() to find out what was wrong.
  50.  
  51.     NOTES
  52.     This function writes big endian values to a file even on little
  53.     endian machines.
  54.  
  55.     EXAMPLE
  56.     See below.
  57.  
  58.     BUGS
  59.  
  60.     INTERNALS
  61.     The function uses the Write*()-functions to write data into
  62.     the file.
  63.  
  64.     Pointers are written as <valid><data structure>, where valid is
  65.     a byte with the values 1 (then the full data structure follows)
  66.     or 0 (then nothing follows and the pointer will be intialized as
  67.     NULL when the structure is read back).
  68.  
  69.     SEE ALSO
  70.     Open(), Close(), ReadByte(), ReadWord(), ReadLong(), ReadFloat(),
  71.     ReadString(), ReadStruct(), WriteByte(), WriteWord(), WriteLong(),
  72.     WriteFloat(), WriteDouble(), WriteString()
  73.  
  74.     HISTORY
  75.     28.11.96 digulla created
  76.  
  77. ******************************************************************************/
  78. {
  79.     struct MinList    _list;
  80.     struct WriteLevel * curr;
  81.  
  82. #   define list     ((struct List *)&_list)
  83.  
  84.     NEWLIST(list);
  85.  
  86.     if (!(curr = AllocMem (sizeof (struct WriteLevel), MEMF_ANY)) )
  87.     return FALSE;
  88.  
  89.     AddTail (list, (struct Node *)curr);
  90.  
  91.     curr->sd  = sd;
  92.     curr->pos = 1; /* Ignore size */
  93.     curr->s   = data;
  94.  
  95. #   define DESC     (curr->sd[curr->pos])
  96. #   define IDESC    (curr->sd[curr->pos ++])
  97.  
  98.     while (DESC != SDT_END)
  99.     {
  100.     switch (IDESC)
  101.     {
  102.     case SDT_UBYTE:      /* Write one  8bit byte */
  103.         if (!WriteByte (fh, *((UBYTE *)(curr->s + IDESC))))
  104.         goto error;
  105.  
  106.         break;
  107.  
  108.     case SDT_UWORD:      /* Write one 16bit word */
  109.         if (!WriteWord (fh, *((UWORD *)(curr->s + IDESC))))
  110.         goto error;
  111.  
  112.         break;
  113.  
  114.     case SDT_ULONG:      /* Write one 32bit long */
  115.         if (!WriteLong (fh, *((ULONG *)(curr->s + IDESC))))
  116.         goto error;
  117.  
  118.         break;
  119.  
  120.     case SDT_FLOAT:      /* Write one 32bit IEEE */
  121.         if (!WriteFloat (fh, *((FLOAT *)(curr->s + IDESC))))
  122.         goto error;
  123.  
  124.         break;
  125.  
  126.     case SDT_DOUBLE:     /* Write one 64bit IEEE */
  127.         if (!WriteDouble (fh, *((DOUBLE *)(curr->s + IDESC))))
  128.         goto error;
  129.  
  130.         break;
  131.  
  132.     case SDT_STRING: {   /* Write a string */
  133.         STRPTR str;
  134.  
  135.         str = *((STRPTR *)(curr->s + IDESC));
  136.  
  137.         if (str)
  138.         {
  139.         if (!WriteByte (fh, 1))
  140.             goto error;
  141.  
  142.         if (!WriteString (fh, str))
  143.             goto error;
  144.         }
  145.         else
  146.         {
  147.         if (!WriteByte (fh, 0))
  148.             goto error;
  149.  
  150.         curr->pos ++;
  151.         }
  152.  
  153.         break; }
  154.  
  155.     case SDT_STRUCT: {    /* Write a structure */
  156.         struct WriteLevel * next;
  157.  
  158.         IPTR * desc;
  159.         APTR   ptr;
  160.  
  161.         ptr  = (APTR)(curr->s + IDESC);
  162.         desc = (IPTR *)IDESC;
  163.  
  164.         if (!(next = AllocMem (sizeof (struct WriteLevel), MEMF_ANY)) )
  165.         goto error;
  166.  
  167.         AddTail (list, (struct Node *)next);
  168.         next->sd  = desc;
  169.         next->pos = 1; /* Ignore size */
  170.         next->s   = ptr;
  171.  
  172.         curr = next;
  173.  
  174.         break; }
  175.  
  176.     case SDT_PTR: {       /* Follow a pointer */
  177.         struct WriteLevel * next;
  178.  
  179.         IPTR * desc;
  180.         APTR   ptr;
  181.  
  182.         ptr  = *((APTR *)(curr->s + IDESC));
  183.         desc = (IPTR *)IDESC;
  184.  
  185.         if (ptr)
  186.         {
  187.         if (!WriteByte (fh, 1))
  188.             goto error;
  189.  
  190.         if (!(next = AllocMem (sizeof (struct WriteLevel), MEMF_ANY)) )
  191.             goto error;
  192.  
  193.         AddTail (list, (struct Node *)next);
  194.         next->sd  = desc;
  195.         next->pos = 1;
  196.         next->s   = ptr;
  197.  
  198.         curr = next;
  199.         }
  200.         else
  201.         {
  202.         if (!WriteByte (fh, 0))
  203.             goto error;
  204.  
  205.         curr->pos ++;
  206.         }
  207.  
  208.         break; }
  209.  
  210.     case SDT_IGNORE: {   /* Ignore x bytes */
  211.         ULONG count;
  212.  
  213.         count = IDESC;
  214.  
  215.         while (count --)
  216.         {
  217.         if (FPutC (fh, 0) == EOF)
  218.             goto error;
  219.         }
  220.  
  221.         break; }
  222.  
  223.     case SDT_FILL_BYTE:   /* Fill x bytes */
  224.     case SDT_FILL_LONG:   /* Fill x longs */
  225.         /* ignore */
  226.         break;
  227.  
  228.     case SDT_IFILL_BYTE: { /* Fill x bytes */
  229.         IPTR  offset;
  230.         UBYTE value;
  231.         IPTR  count;
  232.  
  233.         offset = IDESC;
  234.         value  = IDESC;
  235.         count  = IDESC;
  236.  
  237.         while (count --)
  238.         {
  239.         if (FPutC (fh, 0) == EOF)
  240.             goto error;
  241.         }
  242.  
  243.         break; }
  244.  
  245.     case SDT_IFILL_LONG: { /* Fill x longs */
  246.         IPTR  offset;
  247.         UBYTE value;
  248.         IPTR  count;
  249.  
  250.         offset = IDESC;
  251.         value  = IDESC;
  252.         count  = IDESC;
  253.  
  254.         while (count --)
  255.         {
  256.         if (!WriteLong (fh, 0L))
  257.             goto error;
  258.         }
  259.  
  260.         break; }
  261.  
  262.     case SDT_SPECIAL: {   /* Call user hook */
  263.         struct Hook * hook;
  264.         struct SDData data;
  265.  
  266.         data.sdd_Dest = ((APTR)(curr->s + IDESC));
  267.         data.sdd_Mode = SDV_SPECIALMODE_WRITE;
  268.  
  269.         hook = (struct Hook *)IDESC;
  270.  
  271.         CallHookA (hook, fh, &data);
  272.  
  273.         break; }
  274.  
  275.     default:
  276.         goto error;
  277.  
  278.     } /* switch */
  279.  
  280.     /* End of the description list ? */
  281.     if (DESC == SDT_END)
  282.     {
  283.         struct WriteLevel * last;
  284.  
  285.         /* Remove the current level */
  286.         last = curr;
  287.         Remove ((struct Node *)last);
  288.  
  289.         /* Get the last level */
  290.         if ((curr = GetTail (list)))
  291.         {
  292.         FreeMem (last, sizeof (struct WriteLevel));
  293.         }
  294.         else
  295.         {
  296.         curr = last;
  297.         }
  298.     }
  299.     } /* while */
  300.  
  301.     FreeMem (curr, sizeof (struct WriteLevel));
  302.  
  303.     return TRUE;
  304.  
  305. error:
  306.  
  307.     while ((curr = (struct WriteLevel *)RemTail (list)))
  308.     FreeMem (curr, sizeof (struct WriteLevel));
  309.  
  310.     return FALSE;
  311. } /* WriteStruct */
  312.  
  313. #ifdef TEST
  314. #include <stdio.h>
  315. #include <dos/dos.h>
  316. #include <aros/structdesc.h>
  317. #include <proto/alib.h>
  318.  
  319. struct Level1
  320. {
  321.     BYTE l1_Byte;
  322.     LONG l1_Long;
  323. };
  324.  
  325. struct MainLevel
  326. {
  327.     BYTE   ml_Byte;
  328.     UBYTE  ml_UByte;
  329.     WORD   ml_Word;
  330.     UWORD  ml_UWord;
  331.     LONG   ml_Long;
  332.     ULONG  ml_ULong;
  333.     FLOAT  ml_Float;
  334.     DOUBLE ml_Double;
  335.     STRPTR ml_String;
  336.     struct Level1 ml_Level1;
  337.  
  338.     BYTE   * ml_BytePtr;
  339.     WORD   * ml_WordPtr;
  340.     LONG   * ml_LongPtr;
  341.     FLOAT  * ml_FloatPtr;
  342.     DOUBLE * ml_DoublePtr;
  343.     STRPTR * ml_StringPtr;
  344.     struct Level1 * ml_Level1Ptr;
  345. };
  346.  
  347. IPTR ByteDesc[]   = { sizeof(UBYTE),  SDM_UBYTE(0),  SDM_END };
  348. IPTR WordDesc[]   = { sizeof(UWORD),  SDM_UWORD(0),  SDM_END };
  349. IPTR LongDesc[]   = { sizeof(ULONG),  SDM_ULONG(0),  SDM_END };
  350. IPTR FloatDesc[]  = { sizeof(FLOAT),  SDM_FLOAT(0),  SDM_END };
  351. IPTR DoubleDesc[] = { sizeof(DOUBLE), SDM_DOUBLE(0), SDM_END };
  352. IPTR StringDesc[] = { sizeof(STRPTR), SDM_STRING(0), SDM_END };
  353.  
  354. #define O(x)        offsetof(struct Level1,x)
  355. IPTR Level1Desc[] =
  356. {
  357.     sizeof (struct Level1),
  358.     SDM_UBYTE(O(l1_Byte)),
  359.     SDM_ULONG(O(l1_Long)),
  360.     SDM_END
  361. };
  362.  
  363. #undef O
  364. #define O(x)        offsetof(struct MainLevel,x)
  365. IPTR MainDesc[] =
  366. {
  367.     sizeof (struct MainLevel),
  368.     SDM_UBYTE(O(ml_Byte)),
  369.     SDM_UBYTE(O(ml_UByte)),
  370.     SDM_UWORD(O(ml_Word)),
  371.     SDM_UWORD(O(ml_UWord)),
  372.     SDM_ULONG(O(ml_Long)),
  373.     SDM_ULONG(O(ml_ULong)),
  374.     SDM_FLOAT(O(ml_Float)),
  375.     SDM_DOUBLE(O(ml_Double)),
  376.     SDM_STRING(O(ml_String)),
  377.     SDM_STRUCT(O(ml_Level1),Level1Desc),
  378.  
  379.     SDM_PTR(O(ml_BytePtr),ByteDesc),
  380.     SDM_PTR(O(ml_WordPtr),WordDesc),
  381.     SDM_PTR(O(ml_LongPtr),LongDesc),
  382.     SDM_PTR(O(ml_FloatPtr),FloatDesc),
  383.     SDM_PTR(O(ml_DoublePtr),DoubleDesc),
  384.     SDM_PTR(O(ml_StringPtr),StringDesc),
  385.     SDM_PTR(O(ml_Level1Ptr),Level1Desc),
  386.  
  387.     SDM_END
  388. };
  389.  
  390. int main (int argc, char ** argv)
  391. {
  392.     struct MainLevel demo =
  393.     {
  394.     (BYTE)0x88,       0xFF,
  395.     (WORD)0x8844,     0xFF77,
  396.     (LONG)0x88442211, 0xFF773311,
  397.     1.5, 1.75,
  398.     "Hallo",
  399.     { (BYTE)0x88, (LONG)0x88442211 },
  400.     /* ... */
  401.     };
  402.     BYTE b = (BYTE)0x88;
  403.     WORD w = (WORD)0x8844;
  404.     LONG l = (LONG)0x88442211;
  405.     FLOAT f = 1.5;
  406.     DOUBLE d = 1.75;
  407.     STRPTR s = "Hallo";
  408.     struct Level1 l1 =
  409.     {
  410.     (BYTE)0x88, (LONG)0x88442211
  411.     };
  412.     BPTR fh;
  413.  
  414.     demo.ml_BytePtr = &b;
  415.     demo.ml_WordPtr = &w;
  416.     demo.ml_LongPtr = &l;
  417.     demo.ml_FloatPtr = &f;
  418.     demo.ml_DoublePtr = &d;
  419.     demo.ml_StringPtr = &s;
  420.     demo.ml_Level1Ptr = &l1;
  421.  
  422.     fh = Open ("writestruct.dat", MODE_NEWFILE);
  423.  
  424.     if (!fh)
  425.     {
  426.     PrintFault (IoErr(), "Can't open file\n");
  427.     return 10;
  428.     }
  429.  
  430.     /*
  431.     This writes the following data stream:
  432.  
  433.         0000 88                ml_Byte
  434.         0001 ff                ml_Ubyte
  435.         0002 88 44                ml_Word
  436.         0004 ff 77                ml_UWord
  437.         0006 88 44 22 11            ml_Long
  438.         000a ff 77 33 11            ml_ULong
  439.         000e 3f c0 00 00            ml_Float
  440.         0012 3f fc 00 00 00 00 00 00    ml_Double
  441.         001a 01:48 61 6c 6c 6f 00        ml_String
  442.         0021 88                ml_Level1.l1_Byte
  443.         0022 88 44 22 11            ml_Level1.l1_Long
  444.         0026 01:88                ml_BytePtr
  445.         0028 01:88 44            ml_WordPtr
  446.         002b 01:88 44 22 11         ml_LongPtr
  447.         0030 01:3f c0 00 00         ml_FloatPtr
  448.         0035 01:3f fc 00 00 00 00 00 00 ml_DoublePtr
  449.         003e 01:01:48 61 6c 6c 6f 00    ml_StringPtr - Note two 01 !
  450.         0046 01:88 88 44 22 11        ml_Level1Ptr
  451.     */
  452.  
  453.     if (!WriteStruct (fh, &demo, MainDesc))
  454.     {
  455.     PrintFault (IoErr(), "Failed to write to file\n");
  456.     }
  457.  
  458.     if (!Close (fh))
  459.     {
  460.     PrintFault (IoErr(), "Failed to close file\n");
  461.     }
  462.  
  463.     return 0;
  464. } /* main */
  465.  
  466. #endif /* TEST */
  467.