PICKLE Reader Library API, version 1 This library is a very simple one, intended for use in interpreters that want to support reading PICKLE files. This library does not have functions to write or analyze PICKLE files, just to read them in the rather limited way that interpreters should want to. * Building To compile the library, you'll first have to adapt the pickle.h file to your machine. Uncomment the definition of either BIG_ENDIAN or LITTLE_ENDIAN, depending on whether integers are stored with the most significant byte or the least significant byte first. (Respectively.) Also, if the "long int" type is not 32 bits long, you'll have to change the typedef of pikLong to whatever signed integer type is 32 bits. The library checks these settings at run-time, so you'll get error codes if you set them wrong. See the list of result codes for pikCreateMap. Then compile pickle.c, either as a library or directly in your interpreter makefile. (If it complains that pikNative is not defined, you forgot to uncomment one of the _ENDIAN definitions.) Note that picklex.h and picklex.c are not part of the reader library. They are the editor library, which is used to write and analyze PICKLE files. * Use This is the idea: - You open the PICKLE file yourself, using fopen(), or whatever is appropriate. - Read the first four bytes of the file. Use pikIsPickleHeader to verify that it really is a PICKLE file. - Pass the file pointer to pikCreateMap. This reads the index map into memory, and returns a pikMapPtr, which is what you will use to refer to the PICKLE file in future library calls. - For each chunk you want to read, call pikFindChunk, which returns a pikChunkID. You can then pass the pikChunkID to pikLoadChunk in order to actually get at the chunk. pikLoadChunk will actually allocate memory and read in the chunk, if you want. If you don't want, it will just tell you where the chunk lies in the file, so that you can read it yourself. (This is handy if you already have interpreter routines which read the data, or if you want to read it in small pieces.) - Optionally, call pikUnloadChunk, to dispose of the memory used by a chunk which you allocated with pikLoadChunk. - When you're finished with the PICKLE file, call pikDestroyMap to destroy the index map and associated structures. The pikMapPtr becomes invalid. - You may then close the file, using fclose() or whatever. * Types pikLong: A signed 32-bit numeric value. pikType: A 32-bit value, which can be read as four characters. The first character is the MSB; the fourth is the LSB. (Note that pikTypes are endian-dependent, just as pikLongs are. You need not worry about this. The reader library handles all endianness problems when reading PICKLE files.) The pikMakeType macro can be used to create pikType constants. pikMapPtr: A 32-bit identifier, which refers to an open PICKLE file. You get this from pikCreateMap, and pass it to every other function that refers to that file. pikFormat: A 64-bit value which represents a PICKLE chunk format. This consists of a major format (name) and a minor format (version). pikChunkID: A 32-bit identifier, which refers to a particular chunk in a PICKLE file. You get this from pikFindChunk, and pass it to pikLoadChunk or pikUnloadChunk. pikChunk: A structure, which is used by pikLoadChunk to return data about a chunk. * Function Reference Most functions return a result code of type pikErr. The various result codes are defined in pickle.h. short pikIsPickleHeader(char *header) This function determines if a given file is a PICKLE file. header should point to a buffer containing at least the first four bytes of a file. The function examines those four bytes. If they are 'pikl' (hex values 70 69 6b 6c), the file appears to be a PICKLE file, and pikIsPickleHeader returns TRUE (1). Otherwise it returns FALSE (0). Result codes: TRUE or FALSE. pikType pikMakeType(char c1, char c2, char c3, char c4) This macro turns four characters into a pikType value. This is just for convenience. Since it is a macro, you can use it in compile-time constants. pikErr pikCreateMap(FILE *file, pikMapPtr *newmap) This function looks at an open PICKLE file, and creates an index map in memory. file must be a file which is already open for reading. (It may also be open for writing, if your operating system allows this, but you should not write to the file after calling pikCreateMap.) If pikCreateMap succeeds, the location pointed at by newmap will be filled in with a pikMapPtr value, which you will use in future calls to refer to the index map. If an error occurs, *newmap is left unchanged. Result codes: pikerr_None: The index map was successfully created. pikerr_NotAMap: The file is not a PICKLE file, or is of a version not recognized by the library. pikerr_CantRead: An error was encounted while trying to read from the file. pikerr_Memory: The library was unable to allocate enough memory to store the index map. pikerr_WrongSizeInts: When the library was compiled, pikLong was not defined to be a 32-bit value. You must edit pickle.h and recompile. pikerr_WrongEndian: When the library was compiled, BIG_ENDIAN was defined instead of LITTLE_ENDIAN, or vice versa. You must edit pickle.h and recompile. pikErr pikDestroyMap(pikMapPtr map) This function destroys an index map created with pikCreateMap. It also unloads any chunks loaded into memory with pikLoadChunk, so you should not rely on such pointers after you call pikDestroyMap. You must call pikDestroyMap before closing the open file that you created the map with. Result codes: pikerr_None: The index map was successfully destroyed. pikerr_NotAMap: map is not a valid index map. pikErr pikFindChunk(pikMapPtr map, pikType use, pikLong number, short numformats, pikFormat *formatlist, pikChunkID *idfound) This function finds a chunk which matches a given use and number. If numformats is 0 and formatlist is NULL, pikFindChunk will return any chunk which matches the use and number; if there is more than one, an arbitrary one is returned. You may also specify a list of formats in formatlist, setting numformats to the length of the list. In this case, pikFindChunk will return a chunk matching a format in the list; if there is more than one, pikFindChunk will return the one whose format is earliest in the list. The returned value is a pikChunkID, which is written into the location pointed at by idfound. The pikChunkID can then be passed to pikLoadChunk and pikUnloadChunk. If you do not care about the pikChunkID, but only want the result code, you may set idfound to NULL. Result codes: pikerr_None: A chunk was found, and *idfound has been set to its id. pikerr_NotFound: No chunk was found matching your requirements. In this case, *idfound is set to the special constant pik_NoChunk. pikerr_BadOption: One of the function arguments is invalid. pikerr_NotAMap: map is not a valid index map. pikErr pikLoadChunk(pikMapPtr map, pikChunkID id, short method, pikChunk *found) This function allows you to access a chunk which you have found with pikFindChunk. Information about the chunk is written into the pikChunk structure pointed to by found. The length of the chunk, in bytes, will be stored in found->length; the format of the chunk will be stored in found->format. The method argument describes how you want to access the chunk, and must be one of the following constants: pikmethod_FilePos: The position of the start of the chunk, measured in bytes from the start of the file, will be stored in found->data.startpos. You can use this information together with found->length to read the chunk data. pikmethod_Memory: The entire chunk will be loaded into memory, and a pointer to the start of the chunk will be stored in found->data.ptr. You should not write to this memory, or try to free() it. Further calls to pikLoadChunk with the same pikChunkID will not load multiple copies of the chunk; they will all return the same pointer. Use pikUnloadChunk to free this allocated memory. pikmethod_DontRead: None of the above. You can use this method when you only care about the length or format of the chunk. Result codes: pikerr_None: The function succeeded, and *found contains the information you requested. pikerr_CantRead: An error was encounted while trying to read from the file. (This can only occur with the pikmethod_Memory method.) pikerr_Memory: The library was unable to allocate enough memory to store the chunk. (This can only occur with the pikmethod_Memory method.) pikerr_BadOption: One of the function arguments is invalid. pikerr_NotAMap: map is not a valid index map. pikErr pikUnloadChunk(pikMapPtr map, pikChunkID id) This function deallocates any memory for the given chunk which was allocated by a call to pikLoadChunk with the pikmethod_Memory method. The pointer which was placed infound->data.ptr becomes invalid. It is safe to call this for a chunk which was never loaded (although pikerr_NotFound will be returned.) Result codes: pikerr_None: The memory was deallocated. pikerr_NotFound: pikLoadChunk has never allocated memory for this chunk. pikerr_BadOption: One of the function arguments is invalid. pikerr_NotAMap: map is not a valid index map.