473 lines
7.2 KiB
C
473 lines
7.2 KiB
C
|
/*
|
||
|
======================================================================
|
||
|
lwio.c
|
||
|
|
||
|
Functions for reading basic LWO2 data types.
|
||
|
|
||
|
Ernie Wright 17 Sep 00
|
||
|
====================================================================== */
|
||
|
|
||
|
#include "../picointernal.h"
|
||
|
#include "lwo2.h"
|
||
|
#include <limits.h>
|
||
|
#include "globaldefs.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
======================================================================
|
||
|
flen
|
||
|
|
||
|
This accumulates a count of the number of bytes read. Callers can set
|
||
|
it at the beginning of a sequence of reads and then retrieve it to get
|
||
|
the number of bytes actually read. If one of the I/O functions fails,
|
||
|
flen is set to an error code, after which the I/O functions ignore
|
||
|
read requests until flen is reset.
|
||
|
====================================================================== */
|
||
|
|
||
|
const int FLEN_ERROR = INT_MIN;
|
||
|
|
||
|
static int flen;
|
||
|
|
||
|
void set_flen( int i ) { flen = i; }
|
||
|
|
||
|
int get_flen( void ) { return flen; }
|
||
|
|
||
|
|
||
|
#if !GDEF_ARCH_ENDIAN_BIG
|
||
|
/*
|
||
|
=====================================================================
|
||
|
revbytes()
|
||
|
|
||
|
Reverses byte order in place.
|
||
|
|
||
|
INPUTS
|
||
|
bp bytes to reverse
|
||
|
elsize size of the underlying data type
|
||
|
elcount number of elements to swap
|
||
|
|
||
|
RESULTS
|
||
|
Reverses the byte order in each of elcount elements.
|
||
|
|
||
|
This only needs to be defined on little-endian platforms, most
|
||
|
notably Windows. lwo2.h replaces this with a #define on big-endian
|
||
|
platforms.
|
||
|
===================================================================== */
|
||
|
|
||
|
void revbytes( void *bp, int elsize, int elcount ){
|
||
|
register unsigned char *p, *q;
|
||
|
|
||
|
p = ( unsigned char * ) bp;
|
||
|
|
||
|
if ( elsize == 2 ) {
|
||
|
q = p + 1;
|
||
|
while ( elcount-- ) {
|
||
|
*p ^= *q;
|
||
|
*q ^= *p;
|
||
|
*p ^= *q;
|
||
|
p += 2;
|
||
|
q += 2;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
while ( elcount-- ) {
|
||
|
q = p + elsize - 1;
|
||
|
while ( p < q ) {
|
||
|
*p ^= *q;
|
||
|
*q ^= *p;
|
||
|
*p ^= *q;
|
||
|
++p;
|
||
|
--q;
|
||
|
}
|
||
|
p += elsize >> 1;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
void *getbytes( picoMemStream_t *fp, int size ){
|
||
|
void *data;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
if ( size < 0 ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
data = _pico_alloc( size );
|
||
|
if ( !data ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, data, size ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
_pico_free( data );
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
flen += size;
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
|
||
|
void skipbytes( picoMemStream_t *fp, int n ){
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return;
|
||
|
}
|
||
|
if ( _pico_memstream_seek( fp, n, PICO_SEEK_CUR ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
}
|
||
|
else{
|
||
|
flen += n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int getI1( picoMemStream_t *fp ){
|
||
|
int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
i = _pico_memstream_getc( fp );
|
||
|
if ( i < 0 ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
if ( i > 127 ) {
|
||
|
i -= 256;
|
||
|
}
|
||
|
flen += 1;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
short getI2( picoMemStream_t *fp ){
|
||
|
short i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, &i, 2 ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
revbytes( &i, 2, 1 );
|
||
|
flen += 2;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
int getI4( picoMemStream_t *fp ){
|
||
|
int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, &i, 4 ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
revbytes( &i, 4, 1 );
|
||
|
flen += 4;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned char getU1( picoMemStream_t *fp ){
|
||
|
int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
i = _pico_memstream_getc( fp );
|
||
|
if ( i < 0 ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
flen += 1;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned short getU2( picoMemStream_t *fp ){
|
||
|
unsigned short i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, &i, 2 ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
revbytes( &i, 2, 1 );
|
||
|
flen += 2;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned int getU4( picoMemStream_t *fp ){
|
||
|
unsigned int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, &i, 4 ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
revbytes( &i, 4, 1 );
|
||
|
flen += 4;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
int getVX( picoMemStream_t *fp ){
|
||
|
int i, c;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
c = _pico_memstream_getc( fp );
|
||
|
if ( c != 0xFF ) {
|
||
|
i = c << 8;
|
||
|
c = _pico_memstream_getc( fp );
|
||
|
i |= c;
|
||
|
flen += 2;
|
||
|
}
|
||
|
else {
|
||
|
c = _pico_memstream_getc( fp );
|
||
|
i = c << 16;
|
||
|
c = _pico_memstream_getc( fp );
|
||
|
i |= c << 8;
|
||
|
c = _pico_memstream_getc( fp );
|
||
|
i |= c;
|
||
|
flen += 4;
|
||
|
}
|
||
|
|
||
|
if ( _pico_memstream_error( fp ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0;
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
float getF4( picoMemStream_t *fp ){
|
||
|
float f;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0.0f;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, &f, 4 ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return 0.0f;
|
||
|
}
|
||
|
revbytes( &f, 4, 1 );
|
||
|
flen += 4;
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *getS0( picoMemStream_t *fp ){
|
||
|
char *s;
|
||
|
int i, c, len, pos;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pos = _pico_memstream_tell( fp );
|
||
|
for ( i = 1; ; i++ ) {
|
||
|
c = _pico_memstream_getc( fp );
|
||
|
if ( c <= 0 ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( c < 0 ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if ( i == 1 ) {
|
||
|
if ( _pico_memstream_seek( fp, pos + 2, PICO_SEEK_SET ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
}
|
||
|
else{
|
||
|
flen += 2;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
len = i + ( i & 1 );
|
||
|
s = _pico_alloc( len );
|
||
|
if ( !s ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if ( _pico_memstream_seek( fp, pos, PICO_SEEK_SET ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
if ( 1 != _pico_memstream_read( fp, s, len ) ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
flen += len;
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
int sgetI1( unsigned char **bp ){
|
||
|
int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
i = **bp;
|
||
|
if ( i > 127 ) {
|
||
|
i -= 256;
|
||
|
}
|
||
|
flen += 1;
|
||
|
( *bp )++;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
short sgetI2( unsigned char **bp ){
|
||
|
short i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
memcpy( &i, *bp, 2 );
|
||
|
revbytes( &i, 2, 1 );
|
||
|
flen += 2;
|
||
|
*bp += 2;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
int sgetI4( unsigned char **bp ){
|
||
|
int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
memcpy( &i, *bp, 4 );
|
||
|
revbytes( &i, 4, 1 );
|
||
|
flen += 4;
|
||
|
*bp += 4;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned char sgetU1( unsigned char **bp ){
|
||
|
unsigned char c;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
c = **bp;
|
||
|
flen += 1;
|
||
|
( *bp )++;
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned short sgetU2( unsigned char **bp ){
|
||
|
unsigned char *buf = *bp;
|
||
|
unsigned short i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
i = ( buf[ 0 ] << 8 ) | buf[ 1 ];
|
||
|
flen += 2;
|
||
|
*bp += 2;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned int sgetU4( unsigned char **bp ){
|
||
|
unsigned int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
memcpy( &i, *bp, 4 );
|
||
|
revbytes( &i, 4, 1 );
|
||
|
flen += 4;
|
||
|
*bp += 4;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
int sgetVX( unsigned char **bp ){
|
||
|
unsigned char *buf = *bp;
|
||
|
int i;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if ( buf[ 0 ] != 0xFF ) {
|
||
|
i = buf[ 0 ] << 8 | buf[ 1 ];
|
||
|
flen += 2;
|
||
|
*bp += 2;
|
||
|
}
|
||
|
else {
|
||
|
i = ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ];
|
||
|
flen += 4;
|
||
|
*bp += 4;
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
float sgetF4( unsigned char **bp ){
|
||
|
float f;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return 0.0f;
|
||
|
}
|
||
|
memcpy( &f, *bp, 4 );
|
||
|
revbytes( &f, 4, 1 );
|
||
|
flen += 4;
|
||
|
*bp += 4;
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *sgetS0( unsigned char **bp ){
|
||
|
char *s;
|
||
|
unsigned char *buf = *bp;
|
||
|
int len;
|
||
|
|
||
|
if ( flen == FLEN_ERROR ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
len = strlen( (const char *) buf ) + 1;
|
||
|
if ( len == 1 ) {
|
||
|
flen += 2;
|
||
|
*bp += 2;
|
||
|
return NULL;
|
||
|
}
|
||
|
len += len & 1;
|
||
|
s = _pico_alloc( len );
|
||
|
if ( !s ) {
|
||
|
flen = FLEN_ERROR;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
memcpy( s, buf, len );
|
||
|
flen += len;
|
||
|
*bp += len;
|
||
|
return s;
|
||
|
}
|