too much things to enumerate...

This commit is contained in:
Andre Leiradella 2016-06-14 21:37:09 -03:00
parent c2443374e4
commit 3bbe3424cd
13 changed files with 592 additions and 566 deletions

9
.gitignore vendored
View File

@ -2,6 +2,15 @@
*.exe
*.dll
*.so
*.png
*.tmx
*.tsx
*~
rl_version.c
boot_lua.h
bounce.h
sketch008.h
smile.h
GPATH
GRTAGS
GTAGS

View File

@ -4,7 +4,7 @@ DEFINES=-DOUTSIDE_SPEEX -DRANDOM_PREFIX=speex -DEXPORT= -DFIXED_POINT
#CFLAGS=-O3 --std=c99 -Wall $(INCLUDES) $(DEFINES) -fPIC
CFLAGS=-O0 -g --std=c99 -Wall $(INCLUDES) $(DEFINES) -fPIC
OBJS=rl_backgrnd.o rl_base64.o rl_config.o rl_image.o rl_imgdata.o rl_pack.o rl_rand.o rl_resample.o rl_sound.o rl_snddata.o rl_sprite.o rl_version.o rl_xml.o external/resample.o
OBJS=rl_backgrnd.o rl_base64.o rl_config.o rl_image.o rl_imgdata.o rl_pack.o rl_rand.o rl_resample.o rl_sound.o rl_snddata.o rl_sprite.o rl_tiled.o rl_version.o rl_xml.o external/resample.o
%.o: %.c
gcc $(CFLAGS) -c $< -o $@

View File

@ -7,7 +7,8 @@
//#define RL_BACKGRND_STRETCH 1
//#define RL_BACKGRND_EXPAND 2
#define RL_COLOR( r, g, b ) ( ( r * 32 / 256 ) << 11 | ( g * 64 / 256 ) << 5 | ( b * 32 / 256 ) )
#define RL_COLOR( r, g, b ) ( ( ( r ) * 32 / 256 ) << 11 | ( ( g ) * 64 / 256 ) << 5 | ( ( b ) * 32 / 256 ) )
#define RL_COLOR_2( rgb ) RL_COLOR( ( rgb >> 16 ) & 255, ( rgb >> 8 ) & 255, rgb & 255 )
int rl_backgrnd_create( int width, int height, int aspect );
void rl_backgrnd_destroy( void );

View File

@ -1,27 +1,27 @@
#include <rl_config.h>
static const rl_config_t config =
{
RL_VERSION_MAJOR,
RL_VERSION_MINOR,
RL_BACKGRND_MARGIN,
RL_MAX_SPRITES,
RL_BG_SAVE_SIZE,
RL_FRAME_RATE,
RL_SAMPLE_RATE,
RL_SAMPLES_PER_FRAME,
RL_RESAMPLER_QUALITY,
RL_MAX_VOICES,
RL_OGG_INCREMENT,
#ifdef RL_OGG_VORBIS
1,
#else
0,
#endif
RL_USERDATA_COUNT
};
const rl_config_t* rl_get_config( void )
{
return &config;
}
#include <rl_config.h>
static const rl_config_t config =
{
RL_VERSION_MAJOR,
RL_VERSION_MINOR,
RL_BACKGRND_MARGIN,
RL_MAX_SPRITES,
RL_BG_SAVE_SIZE,
RL_FRAME_RATE,
RL_SAMPLE_RATE,
RL_SAMPLES_PER_FRAME,
RL_RESAMPLER_QUALITY,
RL_MAX_VOICES,
RL_OGG_INCREMENT,
#ifdef RL_OGG_VORBIS
1,
#else
0,
#endif
RL_USERDATA_COUNT
};
const rl_config_t* rl_get_config( void )
{
return &config;
}

View File

@ -10,3 +10,16 @@ static inline uint32_t djb2( const char* str )
return hash;
}
static inline uint32_t djb2_length( const char* str, size_t length )
{
const unsigned char* aux = (const unsigned char*)str;
uint32_t hash = 5381;
while ( length-- )
{
hash = ( hash << 5 ) + hash + *aux++;
}
return hash;
}

View File

@ -5,6 +5,7 @@
#include <rl_imgdata.h>
#include <stdint.h>
#include <stdlib.h>
/*
An image with RLE-encoded pixels and per-pixel alpha of 0, 25, 50, 75 and 100%.

View File

@ -1,86 +1,86 @@
#include <rl_resample.h>
#include <stdlib.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
#include "external/speex_resampler.h"
/*---------------------------------------------------------------------------*/
#if RL_RESAMPLER_QUALITY < SPEEX_RESAMPLER_QUALITY_MIN || RL_RESAMPLER_QUALITY > SPEEX_RESAMPLER_QUALITY_MAX
#error Invalid quality value in RL_RESAMPLER_QUALITY
#endif
static char passthrough = 0;
rl_resampler_t* rl_resampler_create( unsigned in_freq )
{
if ( in_freq != RL_SAMPLE_RATE )
{
return (rl_resampler_t*)speex_resampler_init( 2, in_freq, RL_SAMPLE_RATE, RL_RESAMPLER_QUALITY, NULL );
}
return (rl_resampler_t*)&passthrough;
}
void rl_resampler_destroy( rl_resampler_t* resampler )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
speex_resampler_destroy( (SpeexResamplerState*)resampler );
}
}
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
spx_uint32_t in_rate, out_rate;
speex_resampler_get_rate( st, &in_rate, &out_rate );
return in_samples * out_rate / in_rate;
}
else
{
return in_samples;
}
}
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
spx_uint32_t in_rate, out_rate;
speex_resampler_get_rate( st, &in_rate, &out_rate );
return out_samples * in_rate / out_rate;
}
else
{
return out_samples;
}
}
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
spx_uint32_t in_len = in_samples;
spx_uint32_t out_len = out_samples;
int error = speex_resampler_process_int( (SpeexResamplerState*)resampler, 0, in_buffer, &in_len, out_buffer, &out_len );
return error == RESAMPLER_ERR_SUCCESS ? out_len : 0;
}
else
{
if ( in_samples > out_samples )
{
in_samples = out_samples;
}
memcpy( out_buffer, in_buffer, in_samples * sizeof( int16_t ) );
return in_samples;
}
}
#include <rl_resample.h>
#include <stdlib.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
#include "external/speex_resampler.h"
/*---------------------------------------------------------------------------*/
#if RL_RESAMPLER_QUALITY < SPEEX_RESAMPLER_QUALITY_MIN || RL_RESAMPLER_QUALITY > SPEEX_RESAMPLER_QUALITY_MAX
#error Invalid quality value in RL_RESAMPLER_QUALITY
#endif
static char passthrough = 0;
rl_resampler_t* rl_resampler_create( unsigned in_freq )
{
if ( in_freq != RL_SAMPLE_RATE )
{
return (rl_resampler_t*)speex_resampler_init( 2, in_freq, RL_SAMPLE_RATE, RL_RESAMPLER_QUALITY, NULL );
}
return (rl_resampler_t*)&passthrough;
}
void rl_resampler_destroy( rl_resampler_t* resampler )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
speex_resampler_destroy( (SpeexResamplerState*)resampler );
}
}
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
spx_uint32_t in_rate, out_rate;
speex_resampler_get_rate( st, &in_rate, &out_rate );
return in_samples * out_rate / in_rate;
}
else
{
return in_samples;
}
}
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
spx_uint32_t in_rate, out_rate;
speex_resampler_get_rate( st, &in_rate, &out_rate );
return out_samples * in_rate / out_rate;
}
else
{
return out_samples;
}
}
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples )
{
if ( resampler != (rl_resampler_t*)&passthrough )
{
spx_uint32_t in_len = in_samples;
spx_uint32_t out_len = out_samples;
int error = speex_resampler_process_int( (SpeexResamplerState*)resampler, 0, in_buffer, &in_len, out_buffer, &out_len );
return error == RESAMPLER_ERR_SUCCESS ? out_len : 0;
}
else
{
if ( in_samples > out_samples )
{
in_samples = out_samples;
}
memcpy( out_buffer, in_buffer, in_samples * sizeof( int16_t ) );
return in_samples;
}
}

View File

@ -1,23 +1,23 @@
#ifndef RL_RESAMPLE_H
#define RL_RESAMPLE_H
#include <rl_userdata.h>
#include <rl_imgdata.h>
#include <stdint.h>
typedef void rl_resampler_t;
/* Creates a resampler. */
rl_resampler_t* rl_resampler_create( unsigned in_freq );
/* Destroys a resampler. */
void rl_resampler_destroy( rl_resampler_t* resampler );
/* Returns how much samples an output buffer must have to resample an input buffer with this number of samples. */
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples );
/* Returns how much samples an input buffer must have to fill an output buffer with this number of samples. */
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples );
/* Resamples the input buffer into the output buffer. */
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples );
#endif /* RL_RESAMPLE_H */
#ifndef RL_RESAMPLE_H
#define RL_RESAMPLE_H
#include <rl_userdata.h>
#include <rl_imgdata.h>
#include <stdint.h>
typedef void rl_resampler_t;
/* Creates a resampler. */
rl_resampler_t* rl_resampler_create( unsigned in_freq );
/* Destroys a resampler. */
void rl_resampler_destroy( rl_resampler_t* resampler );
/* Returns how much samples an output buffer must have to resample an input buffer with this number of samples. */
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples );
/* Returns how much samples an input buffer must have to fill an output buffer with this number of samples. */
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples );
/* Resamples the input buffer into the output buffer. */
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples );
#endif /* RL_RESAMPLE_H */

View File

@ -1,225 +1,225 @@
#include <rl_snddata.h>
#include <rl_resample.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <rl_endian.inl>
typedef struct
{
/* header */
char chunkid[ 4 ];
uint32_t chunksize;
char format[ 4 ];
/* fmt */
char subchunk1id[ 4 ];
uint32_t subchunk1size;
uint16_t audioformat;
uint16_t numchannels;
uint32_t samplerate;
uint32_t byterate;
uint16_t blockalign;
uint16_t bitspersample;
/* data */
char subchunk2id[ 4 ];
uint32_t subchunk2size;
uint8_t data[ 0 ];
}
wave_t;
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size )
{
const wave_t* wave = (const wave_t*)data;
if ( wave->chunkid[ 0 ] != 'R' || wave->chunkid[ 1 ] != 'I' || wave->chunkid[ 2 ] != 'F' || wave->chunkid[ 3 ] != 'F' )
{
return -1;
}
if ( wave->format[ 0 ] != 'W' || wave->format[ 1 ] != 'A' || wave->format[ 2 ] != 'V' || wave->format[ 3 ] != 'E' )
{
return -1;
}
if ( wave->subchunk1id[ 0 ] != 'f' || wave->subchunk1id[ 1 ] != 'm' || wave->subchunk1id[ 2 ] != 't' || wave->subchunk1id[ 3 ] != ' ' )
{
return -1;
}
if ( wave->subchunk2id[ 0 ] != 'd' || wave->subchunk2id[ 1 ] != 'a' || wave->subchunk2id[ 2 ] != 't' || wave->subchunk2id[ 3 ] != 'a' )
{
return -1;
}
snddata->bps = le16( wave->bitspersample );
snddata->channels = le16( wave->numchannels );
snddata->freq = le32( wave->samplerate );
if ( le16( wave->audioformat ) != 1 )
{
return -1;
}
if ( snddata->channels != 1 && snddata->channels != 2 )
{
return -1;
}
if ( snddata->bps != 8 && snddata->bps != 16 )
{
return -1;
}
snddata->size = le32( wave->subchunk2size );
snddata->samples = malloc( snddata->size );
if ( snddata->samples )
{
memcpy( (void*)snddata->samples, (void*)wave->data, snddata->size );
return 0;
}
return -1;
}
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata )
{
int16_t* out_buffer;
size_t in_samples;
if ( snddata->bps == 8 )
{
if ( snddata->channels == 1 )
{
/* 8 bps, mono. */
in_samples = snddata->size;
*out_samples = in_samples * 2;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint8_t* begin = (const uint8_t*)snddata->samples;
const uint8_t* end = begin + in_samples;
while ( begin < end )
{
int sample = *begin++;
sample = sample * 65792 / 256 - 32768;
*samples++ = sample;
*samples++ = sample;
}
}
else
{
/* 8 bps, stereo. */
in_samples = snddata->size;
*out_samples = in_samples;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint8_t* begin = (const uint8_t*)snddata->samples;
const uint8_t* end = begin + in_samples;
while ( begin < end )
{
int sample = *begin++;
sample = sample * 65792 / 256 - 32768;
*samples++ = sample;
}
}
}
else
{
if ( snddata->channels == 1 )
{
/* 16 bps, mono. */
in_samples = snddata->size / 2;
*out_samples = in_samples * 2;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint16_t* begin = (const uint16_t*)snddata->samples;
const uint16_t* end = begin + in_samples;
while ( begin < end )
{
int16_t sample = le16( *begin++ );
*samples++ = sample;
*samples++ = sample;
}
}
else
{
/* 16 bps, stereo. */
in_samples = snddata->size / 2;
*out_samples = in_samples;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint16_t* begin = (const uint16_t*)snddata->samples;
const uint16_t* end = begin + in_samples;
while ( begin < end )
{
*samples++ = le16( *begin++ );
}
}
}
if ( snddata->freq != RL_SAMPLE_RATE )
{
rl_resampler_t* resampler = rl_resampler_create( snddata->freq );
if ( !resampler )
{
free( out_buffer );
return NULL;
}
size_t new_samples = rl_resampler_out_samples( resampler, *out_samples );
int16_t* new_buffer = (int16_t*)malloc( new_samples * sizeof( int16_t ) );
if ( !new_buffer )
{
rl_resampler_destroy( resampler );
free( out_buffer );
return NULL;
}
if ( rl_resampler_resample( resampler, out_buffer, *out_samples, new_buffer, new_samples ) != new_samples )
{
free( new_buffer );
rl_resampler_destroy( resampler );
free( out_buffer );
return NULL;
}
free( out_buffer );
out_buffer = new_buffer;
*out_samples = new_samples;
}
return out_buffer;
}
#include <rl_snddata.h>
#include <rl_resample.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <rl_endian.inl>
typedef struct
{
/* header */
char chunkid[ 4 ];
uint32_t chunksize;
char format[ 4 ];
/* fmt */
char subchunk1id[ 4 ];
uint32_t subchunk1size;
uint16_t audioformat;
uint16_t numchannels;
uint32_t samplerate;
uint32_t byterate;
uint16_t blockalign;
uint16_t bitspersample;
/* data */
char subchunk2id[ 4 ];
uint32_t subchunk2size;
uint8_t data[ 0 ];
}
wave_t;
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size )
{
const wave_t* wave = (const wave_t*)data;
if ( wave->chunkid[ 0 ] != 'R' || wave->chunkid[ 1 ] != 'I' || wave->chunkid[ 2 ] != 'F' || wave->chunkid[ 3 ] != 'F' )
{
return -1;
}
if ( wave->format[ 0 ] != 'W' || wave->format[ 1 ] != 'A' || wave->format[ 2 ] != 'V' || wave->format[ 3 ] != 'E' )
{
return -1;
}
if ( wave->subchunk1id[ 0 ] != 'f' || wave->subchunk1id[ 1 ] != 'm' || wave->subchunk1id[ 2 ] != 't' || wave->subchunk1id[ 3 ] != ' ' )
{
return -1;
}
if ( wave->subchunk2id[ 0 ] != 'd' || wave->subchunk2id[ 1 ] != 'a' || wave->subchunk2id[ 2 ] != 't' || wave->subchunk2id[ 3 ] != 'a' )
{
return -1;
}
snddata->bps = le16( wave->bitspersample );
snddata->channels = le16( wave->numchannels );
snddata->freq = le32( wave->samplerate );
if ( le16( wave->audioformat ) != 1 )
{
return -1;
}
if ( snddata->channels != 1 && snddata->channels != 2 )
{
return -1;
}
if ( snddata->bps != 8 && snddata->bps != 16 )
{
return -1;
}
snddata->size = le32( wave->subchunk2size );
snddata->samples = malloc( snddata->size );
if ( snddata->samples )
{
memcpy( (void*)snddata->samples, (void*)wave->data, snddata->size );
return 0;
}
return -1;
}
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata )
{
int16_t* out_buffer;
size_t in_samples;
if ( snddata->bps == 8 )
{
if ( snddata->channels == 1 )
{
/* 8 bps, mono. */
in_samples = snddata->size;
*out_samples = in_samples * 2;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint8_t* begin = (const uint8_t*)snddata->samples;
const uint8_t* end = begin + in_samples;
while ( begin < end )
{
int sample = *begin++;
sample = sample * 65792 / 256 - 32768;
*samples++ = sample;
*samples++ = sample;
}
}
else
{
/* 8 bps, stereo. */
in_samples = snddata->size;
*out_samples = in_samples;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint8_t* begin = (const uint8_t*)snddata->samples;
const uint8_t* end = begin + in_samples;
while ( begin < end )
{
int sample = *begin++;
sample = sample * 65792 / 256 - 32768;
*samples++ = sample;
}
}
}
else
{
if ( snddata->channels == 1 )
{
/* 16 bps, mono. */
in_samples = snddata->size / 2;
*out_samples = in_samples * 2;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint16_t* begin = (const uint16_t*)snddata->samples;
const uint16_t* end = begin + in_samples;
while ( begin < end )
{
int16_t sample = le16( *begin++ );
*samples++ = sample;
*samples++ = sample;
}
}
else
{
/* 16 bps, stereo. */
in_samples = snddata->size / 2;
*out_samples = in_samples;
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
if ( !out_buffer )
{
return NULL;
}
int16_t* samples = out_buffer;
const uint16_t* begin = (const uint16_t*)snddata->samples;
const uint16_t* end = begin + in_samples;
while ( begin < end )
{
*samples++ = le16( *begin++ );
}
}
}
if ( snddata->freq != RL_SAMPLE_RATE )
{
rl_resampler_t* resampler = rl_resampler_create( snddata->freq );
if ( !resampler )
{
free( out_buffer );
return NULL;
}
size_t new_samples = rl_resampler_out_samples( resampler, *out_samples );
int16_t* new_buffer = (int16_t*)malloc( new_samples * sizeof( int16_t ) );
if ( !new_buffer )
{
rl_resampler_destroy( resampler );
free( out_buffer );
return NULL;
}
if ( rl_resampler_resample( resampler, out_buffer, *out_samples, new_buffer, new_samples ) != new_samples )
{
free( new_buffer );
rl_resampler_destroy( resampler );
free( out_buffer );
return NULL;
}
free( out_buffer );
out_buffer = new_buffer;
*out_samples = new_samples;
}
return out_buffer;
}

View File

@ -1,27 +1,28 @@
#ifndef RL_SNDDATA_H
#define RL_SNDDATA_H
#include <rl_userdata.h>
#include <stddef.h>
#include <stdint.h>
typedef struct
{
rl_userdata_t ud;
int bps; /* bits per sample */
int channels; /* number of channels */
int freq; /* frequency */
size_t size;
const void* samples;
}
rl_snddata_t;
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size );
#define rl_snddata_destroy( snddata ) do { free( (void*)( snddata )->samples ); } while ( 0 )
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata );
#endif /* RL_SNDDATA_H */
#ifndef RL_SNDDATA_H
#define RL_SNDDATA_H
#include <rl_userdata.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct
{
rl_userdata_t ud;
int bps; /* bits per sample */
int channels; /* number of channels */
int freq; /* frequency */
size_t size;
const void* samples;
}
rl_snddata_t;
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size );
#define rl_snddata_destroy( snddata ) do { free( (void*)( snddata )->samples ); } while ( 0 )
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata );
#endif /* RL_SNDDATA_H */

View File

@ -6,6 +6,7 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
/* Reasons passed to the stop callback. */
#define RL_SOUND_FINISHED 0

View File

@ -1,152 +1,152 @@
#include <rl_xml.h>
#include <string.h>
#include <ctype.h>
static inline void skip_to_tag( const char** xml )
{
const char* aux = *xml;
while ( *aux != '<' && *aux )
{
aux++;
}
*xml = aux;
}
static inline void skip_name( const char** xml )
{
const char* aux = *xml;
while ( !isspace( *aux ) && *aux != '>' && *aux != '=' && *aux )
{
aux++;
}
*xml = aux;
}
static inline void skip_spaces( const char** xml )
{
const char* aux = *xml;
while ( isspace( *aux ) )
{
aux++;
}
*xml = aux;
}
#define CHECK( stmt ) do { int res = stmt; if ( res ) return res; } while ( 0 )
static int parse( const char* xml, const char* end, rl_xmlhandlers_t* handlers )
{
CHECK( handlers->start_document( handlers ) );
do
{
const char* text = xml;
skip_to_tag( &xml );
if ( xml != text )
{
CHECK( handlers->characters( handlers, text, xml - text ) );
}
if ( *xml != '<' )
{
goto out;
}
if ( xml[ 1 ] == '/' )
{
const char* name = xml += 2;
skip_name( &xml );
CHECK( handlers->end_element( handlers, name, xml - name ) );
skip_spaces( &xml );
if ( *xml != '>' )
{
goto out;
}
xml++;
}
else if ( xml[ 1 ] == '?' )
{
xml = strstr( xml + 2, "?>" );
if ( !xml )
{
goto out;
}
xml += 2;
}
else
{
const char* name = ++xml;
skip_name( &xml );
size_t name_length = xml - name;
CHECK( handlers->start_element( handlers, name, name_length ) );
skip_spaces( &xml );
while ( *xml != '>' && *xml != '/' )
{
const char* key = xml;
skip_name( &xml );
size_t key_length = xml - key;
skip_spaces( &xml );
if ( *xml != '=' )
{
goto out;
}
xml++;
skip_spaces( &xml );
char quote = *xml++;
const char* value = xml;
xml = strchr( xml, quote );
if ( !xml )
{
goto out;
}
CHECK( handlers->attribute( handlers, key, key_length, value, xml - value ) );
xml++;
skip_spaces( &xml );
}
if ( *xml == '/' )
{
CHECK( handlers->end_element( handlers, name, name_length ) );
xml++;
skip_spaces( &xml );
if ( *xml != '>' )
{
goto out;
}
}
xml++;
}
}
while ( *xml );
out:
return handlers->end_document( handlers );
}
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers )
{
return parse( xml, xml + length, handlers );
}
#include <rl_xml.h>
#include <string.h>
#include <ctype.h>
static inline void skip_to_tag( const char** xml )
{
const char* aux = *xml;
while ( *aux != '<' && *aux )
{
aux++;
}
*xml = aux;
}
static inline void skip_name( const char** xml )
{
const char* aux = *xml;
while ( !isspace( *aux ) && *aux != '>' && *aux != '=' && *aux )
{
aux++;
}
*xml = aux;
}
static inline void skip_spaces( const char** xml )
{
const char* aux = *xml;
while ( isspace( *aux ) )
{
aux++;
}
*xml = aux;
}
#define CHECK( stmt ) do { int res = stmt; if ( res ) return res; } while ( 0 )
static int parse( const char* xml, const char* end, rl_xmlhandlers_t* handlers )
{
CHECK( handlers->start_document( handlers ) );
do
{
const char* text = xml;
skip_to_tag( &xml );
if ( xml != text )
{
CHECK( handlers->characters( handlers, text, xml - text ) );
}
if ( *xml != '<' )
{
goto out;
}
if ( xml[ 1 ] == '/' )
{
const char* name = xml += 2;
skip_name( &xml );
CHECK( handlers->end_element( handlers, name, xml - name ) );
skip_spaces( &xml );
if ( *xml != '>' )
{
goto out;
}
xml++;
}
else if ( xml[ 1 ] == '?' )
{
xml = strstr( xml + 2, "?>" );
if ( !xml )
{
goto out;
}
xml += 2;
}
else
{
const char* name = ++xml;
skip_name( &xml );
size_t name_length = xml - name;
CHECK( handlers->start_element( handlers, name, name_length ) );
skip_spaces( &xml );
while ( *xml != '>' && *xml != '/' )
{
const char* key = xml;
skip_name( &xml );
size_t key_length = xml - key;
skip_spaces( &xml );
if ( *xml != '=' )
{
goto out;
}
xml++;
skip_spaces( &xml );
char quote = *xml++;
const char* value = xml;
xml = strchr( xml, quote );
if ( !xml )
{
goto out;
}
CHECK( handlers->attribute( handlers, key, key_length, value, xml - value ) );
xml++;
skip_spaces( &xml );
}
if ( *xml == '/' )
{
CHECK( handlers->end_element( handlers, name, name_length ) );
xml++;
skip_spaces( &xml );
if ( *xml != '>' )
{
goto out;
}
}
xml++;
}
}
while ( *xml );
out:
return handlers->end_document( handlers );
}
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers )
{
return parse( xml, xml + length, handlers );
}

View File

@ -1,24 +1,24 @@
#ifndef RL_XML_H
#define RL_XML_H
#include <rl_userdata.h>
#include <stddef.h>
typedef struct rl_xmlhandlers_t rl_xmlhandlers_t;
struct rl_xmlhandlers_t
{
rl_userdata_t ud;
int ( *start_document )( rl_xmlhandlers_t* handlers );
int ( *end_document )( rl_xmlhandlers_t* handlers );
int ( *start_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
int ( *end_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
int ( *attribute )( rl_xmlhandlers_t* handlers, const char* key, size_t key_length, const char* value, size_t value_length );
int ( *characters )( rl_xmlhandlers_t* handlers, const char* text, size_t length );
};
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers );
#endif /* RL_XML_H */
#ifndef RL_XML_H
#define RL_XML_H
#include <rl_userdata.h>
#include <stddef.h>
typedef struct rl_xmlhandlers_t rl_xmlhandlers_t;
struct rl_xmlhandlers_t
{
rl_userdata_t ud;
int ( *start_document )( rl_xmlhandlers_t* handlers );
int ( *end_document )( rl_xmlhandlers_t* handlers );
int ( *start_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
int ( *end_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
int ( *attribute )( rl_xmlhandlers_t* handlers, const char* key, size_t key_length, const char* value, size_t value_length );
int ( *characters )( rl_xmlhandlers_t* handlers, const char* text, size_t length );
};
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers );
#endif /* RL_XML_H */