1 #ifndef __MICRO_IFF_H__ 2 #define __MICRO_IFF_H__ 3 #include <stdint.h> 4 #include <stdio.h> 5 6 typedef int32_t IFFP; /* Status code result from an IFF procedure */ 7 /* LONG, because must be type compatable with ID for GetChunkHdr.*/ 8 /* Note that the error codes below are not legal IDs.*/ 9 #define IFF_OKAY 0L /* Keep going...*/ 10 #define END_MARK -1L /* As if there was a chunk at end of group.*/ 11 #define IFF_DONE -2L /* clientProc returns this when it has READ enough. 12 * It means return thru all levels. File is Okay.*/ 13 #define DOS_ERROR -3L 14 #define NOT_IFF -4L /* not an IFF file.*/ 15 #define NO_FILE -5L /* Tried to open file, DOS didn't find it.*/ 16 #define CLIENT_ERROR -6L /* Client made invalid request, for instance, write 17 * a negative size chunk.*/ 18 #define BAD_FORM -7L /* A client read proc complains about FORM semantics; 19 * e.g. valid IFF, but missing a required chunk.*/ 20 #define SHORT_CHUNK -8L /* Client asked to IFFReadBytes more bytes than left 21 * in the chunk. Could be client bug or bad form.*/ 22 #define BAD_IFF -9L /* mal-formed IFF file. [TBD] Expand this into a 23 * range of error codes.*/ 24 #define LAST_ERROR BAD_IFF 25 26 // Flags for calling the group find function 27 #define IFF_FIND_REWIND 1 //!< rewind before searching 28 29 /*! \brief Four-character IDentifier builder.*/ 30 #define MakeID(a,b,c,d) ( (int32_t)(a)<<24L | (int32_t)(b)<<16L | (c)<<8 | (d) ) 31 /* Standard group IDs. A chunk with one of these IDs contains a 32 SubTypeID followed by zero or more chunks.*/ 33 #define FORM MakeID('F','O','R','M') 34 #define PROP MakeID('P','R','O','P') 35 #define LIST MakeID('L','I','S','T') 36 #define CAT MakeID('C','A','T',' ') 37 #define FILLER MakeID(' ',' ',' ',' ') 38 #define JUNK MakeID('J', 'U', 'N', 'K') 39 40 typedef int32_t ID; /*! \brief An ID is four printable ASCII chars 41 * but stored as a int32_t for efficient copy 42 * & compare.*/ 43 44 typedef struct Uiff_CTX { 45 FILE *f; 46 void *last_data; //!< last data was read here 47 ID grID; //!<group id, eg FORM 48 ID grsID; //!<group sub id, eg FORM ILBM 49 long grbgn; //!<beginning position of group *data* in file 50 long grend; //!<begin + grsz 51 int32_t grsz; //!<group size 52 53 ID ckID; //!<id of current chunk, eg BMHD 54 long ckbgn; //!<beginning of chunk *data* 55 long ckend; 56 int32_t cksz; //!<chunk size of current chunk 57 } uiff_ctx_t; 58 59 /*! \brief find a chunk in a file 60 * 61 * File is positioned on data. If ckID is zero then the next available 62 * chunk is found. 63 * 64 * \param ckID id of the chunk to be found 65 * \return chunk size 66 */ 67 int32_t uiff_find_chunk(FILE *inf, long length, ID ckID); 68 69 /*! \brief find a group in a file 70 * 71 * File is positioned on data. If ckID is zero then any of the default 72 * group chunks (FORM, LIST, CAT, PROP) is found. 73 * 74 * \param ckID id of the group chunk, e.g. FORM, etc. 75 * \param subID subid of the group, e.g. ILBM, etc. 76 * \return chunk size 77 */ 78 int32_t uiff_find_group(FILE *inf, long length, ID ckID, ID subID); 79 80 /*! \brief group predicate 81 * 82 */ 83 int uiff_group_p(FILE *inf, ID grID, ID ckID); 84 85 /*! \brief read chunk to allocated memory 86 * 87 * Chunk is read within current context. 88 */ 89 void *uiff_reada_chunk_ctx(uiff_ctx_t *inf); 90 91 /*! \brief read a 32-bit big endian integer from file 92 * 93 * \param inf input file 94 * \return unsigned integer 32 bit 95 */ 96 uint32_t read32(FILE *inf); 97 98 /*! \brief read a 16-bit big endian integer from file 99 * 100 * \param inf input file 101 * \return unsigned integer 16 bit 102 */ 103 uint16_t read16(FILE *inf); 104 105 uiff_ctx_t *uiff_new_ctx(FILE *f, uiff_ctx_t *ctx); 106 107 /* \brief Get a context from a file only for true IFF files. 108 * 109 * This will rewind the file, check if it is an IFF file, and it will 110 * return a context with the stream positioned into the main group. 111 * 112 * \param f a file which is rewound and checked 113 * \param grID the group the file shall have, set to zero if any valid IFF file 114 * \param subID Which type of IFF file (ILBM, etc.)? Set to zero if any. 115 */ 116 uiff_ctx_t *uiff_from_file(FILE *f, ID grID, ID subID); 117 118 /*! \brief close an iff context and underlying file 119 * 120 * \param ctx uiff context 121 * \return IFF_OKAY on success 122 */ 123 int32_t uiff_close(uiff_ctx_t *ctx); 124 125 /*! \brief Find a group chunk 126 * 127 * If the ckID for the group is equal to zero any type of grouping 128 * chunk is found. 129 * 130 * \param ctx iff context 131 * \param flags currently only rewind 132 * \param ckID id of the grouping chunk 133 * \param subID sub id of the group 134 * \return size of the group, is , is < 0 on error 135 */ 136 int32_t uiff_find_group_ctx(uiff_ctx_t *ctx, unsigned flags, ID ckID, ID subID); 137 138 /*! \brief find a chunk in a group 139 * 140 * If the ckID for the chunk is equal to zero any type of chunk is 141 * found. 142 * 143 * \param ctx iff context 144 * \param ckID id of the chunk 145 * \return size of the group, <0 on error 146 */ 147 int32_t uiff_find_chunk_ctx(uiff_ctx_t *ctx, ID ckID); 148 149 /*! \brief find a chunk in a group with flags 150 * 151 * If the ckID for the chunk is equal to zero any type of chunk is 152 * found. 153 * 154 * Currently only IFF_FIND_REWIND is supported. 155 * 156 * \param ctx iff context 157 * \param ckID id of the chunk 158 * \return size of the group, <0 on error 159 */ 160 int32_t uiff_find_chunk_wflags(uiff_ctx_t *ctx, ID ckID, unsigned flags); 161 162 163 /*! \brief skip to end of chunk 164 * 165 * Will skip to the end of the current chunk. 166 * 167 * \param ctx micro iff context 168 * \return number of bytes skipped or error if < 0 169 */ 170 int32_t uiff_skip(uiff_ctx_t *ctx); 171 172 /*! \brief rewind to the beginning of the group 173 */ 174 void uiff_rewind_group(uiff_ctx_t *ctx); 175 #endif 176