LEX (File Format)/C example

From Custom Mario Kart
Jump to navigation Jump to search

This page shows example code in C for »LEX (File Format)« 



Structures

lex_header_t

typedef struct lex_header_t
{
    char	magic[4];	// always LEX_BIN_MAGIC
    u16		major_version;	// usually LEX_MAJOR_VERSION
    u16		minor_version;	// usually LEX_MINOR_VERSION
    u32		size;		// size of this file (header+streams)
    u32		element_off;	// offset of first lex_element_t, 32-bit aligned
}
__attribute__ ((packed)) lex_header_t;

lex_element_t

typedef struct lex_element_t
{
    u32		magic;		// identification of section
    uint	size;		// size of 'data' (this header excluded)
    u8		data[];		// section data, 32-bit aligned
}
__attribute__ ((packed)) lex_element_t;

Function Headers


typedef enumError (*lex_stream_func)
	( u32 magic, const u8 *data, uint size, cvp user_ptr );

enumError ScanLexFile
	( const void *data, uint data_size, lex_stream_func func, const void *user_ptr );

enumError ScanLexStream
	( const void *data, uint data_size, lex_stream_func func, const void *user_ptr );

Scanning Functions

ScanLexFile()

enumError ScanLexFile
	( const void *data, uint data_size, lex_stream_func func, const void *user_ptr )
{
    if ( !data || data_size < sizeof(lex_header_t) )
	return ERR_INVALID_DATA;

    const lex_header_t *hd = (lex_header_t*)data;
    if (memcmp(hd->magic,LEX_BIN_MAGIC,4))
	return ERR_INVALID_DATA;

    if ( ntohs(hd->major_version) != LEX_MAJOR_VERSION )
	return ERR_INVALID_VERSION;

    const uint size = ntohl(hd->size);
    const uint off  = ntohl(hd->stream_off);
    if ( (size&3) || size > data_size || (off&3) || off + 4 > size )
	return ERR_INVALID_DATA;

    return ScanLexElements((u8*)data+off,size-off,func,user_ptr);
}

ScanLexElements()

enumError ScanLexElements
	( const void *data, uint data_size, lex_stream_func func, const void *user_ptr )
{
    if ( !data || !data_size || (data_size&3) )
	return ERR_INVALID_DATA;

    enumError max_err = ERR_OK;

    uint off = 0;
    while ( off < data_size )
    {
	const lex_element_t *s = (lex_element_t*)( (u8*)data + off );

	const u32 magic = ntohl(s->magic);
	if (!magic)
	    break;

	const uint size = ntohl(s->size);
	off += sizeof(lex_element_t) + size;
	if ( !size || (size&3) || off > data_size )
	    return ERR_INVALID_DATA;

	if (func)
	{
	    const int err = func(magic,s->data,size,user_ptr);
	    if (err<0)
		return -err;
	    if ( max_err < err )
		 max_err = err;
	}
    }
    return max_err;
}