parent
c388bc2a46
commit
48ccbe5123
|
@ -13,6 +13,10 @@ These routines are used for Eet Library interaction
|
|||
@author Carsten Haitzler <raster@rasterman.com>
|
||||
@date 2000-2002
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@section intro What is Eet?
|
||||
|
||||
It is a tiny library designed to write an arbitary set of chunks of data
|
||||
|
@ -21,13 +25,160 @@ and allow fast random-access reading of the file later on. It does not
|
|||
do zip as a zip itself has more complexity than is needed, and it was much
|
||||
simpler to impliment this once here.
|
||||
|
||||
Eet is extremely fast, small and simple. Eet files can be very small and
|
||||
highly compressed, making them very optimal for just sending across the
|
||||
internet without having to archive, compress or decompress and install them.
|
||||
They allow for lightning-fast random-acess reads once created, making them
|
||||
perfect for storing data that is written once (or rarely) and read many
|
||||
times, but the program does not want to have to read it all in at once.
|
||||
|
||||
It also can encode and decode data structures in memory, as well as image
|
||||
data for saving to eet files or sending across the network to other
|
||||
data for saving to Eet files or sending across the network to other
|
||||
machines, or just writing to arbitary files on the system. All data is
|
||||
encoded in a platform independant way and can be written and read by any
|
||||
architecture.
|
||||
|
||||
@todo Complete documentation of API
|
||||
@todo Add fixed and variable array encode/decode support
|
||||
|
||||
|
||||
|
||||
|
||||
@section example A simple example on using Eet
|
||||
|
||||
Here is a simple example on how to use Eet to save a series of strings to a
|
||||
file and load them again. The advantage of using Eet over just fprintf() and
|
||||
fscanf() is that not only can these entries be strings, they need no special
|
||||
parsing to handle delimiter characters or escaping, they can be binary data,
|
||||
image data, data structures containing integers, strings, other data
|
||||
structures, linked lists and much more, without the programmer having to
|
||||
worry about parsing, and best of all, Eet is very fast.
|
||||
|
||||
@code
|
||||
#include <Eet.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Eet_File *ef;
|
||||
int i;
|
||||
char buf[32];
|
||||
char *ret;
|
||||
int size;
|
||||
char **entries =
|
||||
{
|
||||
"Entry 1",
|
||||
"Big text string here compared to others",
|
||||
"Eet is cool"
|
||||
};
|
||||
|
||||
// blindly open an file for output and write strings with their NUL char
|
||||
ef = eet_open("test.eet", EET_FILE_MODE_WRITE);
|
||||
eet_write(ef, "Entry 1", entries[0], strlen(entries[0]) + 1, 0);
|
||||
eet_write(ef, "Entry 2", entries[1], strlen(entries[1]) + 1, 1);
|
||||
eet_write(ef, "Entry 3", entries[2], strlen(entries[2]) + 1, 0);
|
||||
eet_close(ef);
|
||||
|
||||
// open the file again and blindly get the entries we wrote
|
||||
ef = eet_open("test.eet", EET_FILE_MODE_READ);
|
||||
ret = eet_read(ef, "Entry 1", &size);
|
||||
printf("%s\n", ret);
|
||||
ret = eet_read(ef, "Entry 2", &size);
|
||||
printf("%s\n", ret);
|
||||
ret = eet_read(ef, "Entry 3", &size);
|
||||
printf("%s\n", ret);
|
||||
eet_close(ef);
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@section format What does an Eet file look like?
|
||||
|
||||
The file format is very simple. There is a directory block at the start of
|
||||
the file listing entries and offsets into the file where they are stored,
|
||||
their sizes, compression flags etc. followed by all the entry data strung one
|
||||
element after the other.
|
||||
|
||||
All Eet files start with t a 4 byte magic number. It is written using network
|
||||
byte-order (big endian, or from most significant byte first to least
|
||||
significant byte last) and is 0x1ee7ff00 (or byte by byte 0:1e 1:e7 2:ff
|
||||
3:00). The next 4 bytes are an integer (in big endian notation) indicating
|
||||
how many entries are stored in the Eet file. 0 indicates it is empty. This is
|
||||
a signed integer and thus values less than 0 are invalid, limiting the number
|
||||
of entries in an Eet file to 0x7fffffff entries at most. The next 4 bytes is
|
||||
the size of the directory table, in bytes, encoded in big-endian format. This
|
||||
is a signed integer and cannot be less than 0.
|
||||
|
||||
The directory table for the file follows immediately, with a continuous list
|
||||
of all entries in the Eet file, their offset in the file etc. The order of
|
||||
these entries is not important, but convention would have them be from first
|
||||
to last entry in the file. Each directory entry consiste of 5 integers, one
|
||||
after the other, each stored as a signed, big endian integer. The first is
|
||||
the offset in the file that the data for this entry is stored at (based from
|
||||
the very start of the file, not relative to the end of the directory block).
|
||||
The second integer holds flags for the entry. currently only the least
|
||||
significant bit (bit 0) holds any useful information, and it is set to 1 if
|
||||
the entry is compressed using zlib compression calls, or 0 if it is not
|
||||
compressed. The next integer is the size of the entry in bytes stored in the
|
||||
file. The next integer is the size of the data when decompressed (if it was
|
||||
compressed) in bytes. This may be the same as the previous integer if the
|
||||
entry was not compressed. The final integer is the number of bytes used by
|
||||
the string identifier for the entry, without the NUL byte terminator, which
|
||||
is not stored. The next series of bytes is the string name of the entry, with
|
||||
the number of bytes being the same as specified in the last integer above.
|
||||
This list of entries continues until there are no more entries left to list.
|
||||
To read an entry from an Eet file, simply find the appropriate entry in the
|
||||
directory table, find it's offset and size, and read it into memory. If it is
|
||||
compressed, decompress it using zlib and then use that data.
|
||||
|
||||
Here is a data map of an Eet file. All integers are encoded using big-endian
|
||||
notation (most significant byte first) and are signed. There is no alignment
|
||||
of data, so all data types follow immediately on, one after the other. All
|
||||
compressed data is compressed using the zlib compress2() function, and
|
||||
decompressed using the zlib uncompress() function. Please see zlib
|
||||
documentation for more information as to the encoding of compressed data.
|
||||
|
||||
@verbatim
|
||||
HEADER:
|
||||
[INT] Magic number (0x1ee7ff00)
|
||||
[INT] Number of entries in the directory table
|
||||
[INT] The size of the directory table, in bytes
|
||||
|
||||
DIRECTORY TABLE ENTRIES (as many as specified in the header):
|
||||
[INT] Offest from file start at which entry is stored (in bytes)
|
||||
[INT] Entry flags (1 = compressed, 0 = not compressed)
|
||||
[INT] Size of data chunk in file (in bytes)
|
||||
[INT] Size of the data chunk once decompressed (or the same as above, if not)
|
||||
[INT] The length of the string itendifier, in bytes, without NUL terminator
|
||||
[STR] Series of bytes for the string identifier, no NUL terminator
|
||||
... more directory entries
|
||||
|
||||
DATA STORED, ONE AFTER ANOTHER:
|
||||
[DAT] DATA ENTRY 1...
|
||||
[DAT] DATA ENTRY 2...
|
||||
[DAT] DATA ENTRY 3...
|
||||
... more data chunks
|
||||
@endverbatim
|
||||
|
||||
The contents of each entry in an Eet file has no defined format as such. It
|
||||
is an opaque chunk of data, that is up to the application to deocde, unless
|
||||
it is an image, ecoded by Eet, or a data structure encoded by Eet. The data
|
||||
itself for these entries can be encoded and decoded by Eet with extra helper
|
||||
functions in Eet. eet_data_image_read() and eet_data_image_write() are used
|
||||
to handle reading and writing image data from a known Eet file entry name.
|
||||
eet_data_read() and eet_data_write() are used to decode and encode program
|
||||
data structures from an Eet file, making the loading and saving of program
|
||||
information stored in data structures a simple 1 function call process.
|
||||
|
||||
Please see src/lib/eet_data.c for information on the format of these
|
||||
specially encoded data entries in an Eet file (for now).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@todo Add hash table, fixed and variable array encode/decode support.
|
||||
@todo Document data format for images and data structures.
|
||||
|
||||
*/
|
||||
|
|
|
@ -328,8 +328,10 @@ extern "C" {
|
|||
* @param func_list_next The function to get the next list node.
|
||||
* @param func_list_append The function to append a member to a list.
|
||||
* @param func_list_data The function to get the data from a list node.
|
||||
* @param func_list_free The function to free an entire linked list.
|
||||
* @param func_hash_foreach The function to iterate through all hash table entries.
|
||||
* @param func_hash_add The function to add a member to a hash table.
|
||||
* @param func_hash_free The function to free an entire hash table.
|
||||
* @return A new empty data descriptor.
|
||||
*
|
||||
* This function creates a new data descriptore and returns a handle to the
|
||||
|
@ -529,7 +531,7 @@ extern "C" {
|
|||
* likes. Eet can handle members being added or deleted from the data in
|
||||
* storage and safely zero-fills unfilled members if they were not found
|
||||
* in the data. It checks sizes and headers whenever it reads data, allowing
|
||||
* the programmer ot not worry about corrupt data.
|
||||
* the programmer to not worry about corrupt data.
|
||||
*
|
||||
* Once a data structure has been described by the programmer with the
|
||||
* fields they wish to save or load, storing or retrieving a data structure
|
||||
|
@ -555,25 +557,75 @@ extern "C" {
|
|||
int eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, char *name, void *data, int compress);
|
||||
|
||||
/**
|
||||
* To be documented.
|
||||
* Decode a data structure from an arbitary location in memory.
|
||||
* @param edd The data descriptor to use when decoding.
|
||||
* @param data_in The pointer to the data to decode into a struct.
|
||||
* @param size_in The size of the data pointed to in bytes.
|
||||
* @return NULL on failure, or a valid decoded struct pointer on success.
|
||||
*
|
||||
* FIXME: To be fixed.
|
||||
* This function will decode a data structure that has been encoded using
|
||||
* eet_data_descriptor_encode(), and return a data structure with all its
|
||||
* elements filled out, if successful, or NULL on failure.
|
||||
*
|
||||
* The data to be decoded is stored at the memory pointed to by @p data_in,
|
||||
* and is described by the descriptor pointed to by @p edd. The data size is
|
||||
* passed in as the value to @p size_in, ande must be greater than 0 to
|
||||
* succeed.
|
||||
*
|
||||
* This function is useful for decoding data structures delivered to the
|
||||
* application by means other than an eet file, such as an IPC or socket
|
||||
* connection, raw files, shared memory etc.
|
||||
*
|
||||
* Please see eet_data_read() for more information.
|
||||
*
|
||||
*/
|
||||
void *eet_data_descriptor_decode(Eet_Data_Descriptor *edd, void *data_in, int size_in);
|
||||
|
||||
/**
|
||||
* To be documented.
|
||||
* Encode a dsata struct to memory and return that encoded data.
|
||||
* @param edd The data descriptor to use when encoding.
|
||||
* @param data_in The pointer to the struct to encode into data.
|
||||
* @param size_ret A pointer to the an int to be filled with the decoded size.
|
||||
* @return NULL on failure, or a valid encoded data chunk on success.
|
||||
*
|
||||
* FIXME: To be fixed.
|
||||
* This function takes a data structutre in memory and encodes it into a
|
||||
* serialised chunk of data that can be decoded again by
|
||||
* eet_data_descriptor_decode(). This is useful for being able to transmit
|
||||
* data structures across sockets, pipes, IPC or shared file mechanisms,
|
||||
* without having to worry about memory space, machine type, endianess etc.
|
||||
*
|
||||
* The parameter @p edd must point to a valid data descriptor, and
|
||||
* @p data_in must point to the right data structure to encode. If not, the
|
||||
* encoding may fail.
|
||||
*
|
||||
* On success a non NULL valid pointer is returned and what @p size_ret
|
||||
* points to is set to the size of this decoded data, in bytes. When the
|
||||
* encoded data is no longer needed, call free() on it. On failure NULL is
|
||||
* returned and what @p size_ret points to is set to 0.
|
||||
*
|
||||
* Please see eet_data_write() for more information.
|
||||
*
|
||||
*/
|
||||
void *eet_data_descriptor_encode(Eet_Data_Descriptor *edd, void *data_in, int *size_ret);
|
||||
|
||||
/**
|
||||
* To be documented.
|
||||
* Add a basic data element to a data descriptor.
|
||||
* @param edd The data descriptor to add the type to.
|
||||
* @param struct_type The type of the struct.
|
||||
* @param name The string name to use to encode/decode this member.
|
||||
* @param member The struct member itself to be encoded.
|
||||
* @param type The type of the member to encode.
|
||||
*
|
||||
* FIXME: To be fixed.
|
||||
* This macro is a convenience macro provided to add a member to the data
|
||||
* descriptor @p edd. The type of the structure is provided as the
|
||||
* @p struct_type parameter (for example: struct my_struct). The @p name
|
||||
* parameter defines a string that will be used to uniquely name that
|
||||
* member of the struct (it is suggested to use the struct member itself).
|
||||
* The @p member parameter is the actual struct member itself (for
|
||||
* example: values), and @p type is the basic data type of the member which
|
||||
* must be one of: EET_T_CHAR, EET_T_SHORT, EET_T_INT, EET_T_LONG_LONG,
|
||||
* EET_T_FLOAT, EET_T_DOUBLE, EET_T_UCHAR, EET_T_USHORT, EET_T_UINT,
|
||||
* EET_T_ULONG_LONG or EET_T_STRING.
|
||||
*
|
||||
*/
|
||||
#define EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct_type, name, member, type) \
|
||||
|
@ -586,9 +638,18 @@ extern "C" {
|
|||
}
|
||||
|
||||
/**
|
||||
* To be documented.
|
||||
* Add a sub-element type to a data descriptor
|
||||
* @param edd The data descriptor to add the type to.
|
||||
* @param struct_type The type of the struct.
|
||||
* @param name The string name to use to encode/decode this member.
|
||||
* @param member The struct member itself to be encoded.
|
||||
* @param subtype The type of sub-type struct to add.
|
||||
*
|
||||
* FIXME: To be fixed.
|
||||
* This macro lets you easily add a sub-type (a struct that's pointed to
|
||||
* by this one). All the parameters are the same as for
|
||||
* EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the exception.
|
||||
* This must be the data descriptor of the struct that is pointed to by
|
||||
* this element.
|
||||
*
|
||||
*/
|
||||
#define EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct_type, name, member, subtype) \
|
||||
|
@ -601,9 +662,17 @@ extern "C" {
|
|||
}
|
||||
|
||||
/**
|
||||
* To be documented.
|
||||
* Add a linked list type to a data descriptor
|
||||
* @param edd The data descriptor to add the type to.
|
||||
* @param struct_type The type of the struct.
|
||||
* @param name The string name to use to encode/decode this member.
|
||||
* @param member The struct member itself to be encoded.
|
||||
* @param subtype The type of linked list member to add.
|
||||
*
|
||||
* FIXME: To be fixed.
|
||||
* This macro lets you easily add a linked list of other data types. All the
|
||||
* parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the
|
||||
* @p subtype being the exception. This must be the data descriptor of the
|
||||
* element that is in each member of the linked list to be stored.
|
||||
*
|
||||
*/
|
||||
#define EET_DATA_DESCRIPTOR_ADD_LIST(edd, struct_type, name, member, subtype) \
|
||||
|
|
Loading…
Reference in New Issue