1 /* -----------------------------------------------------------------------------
5 Copyright (c) 2002, Randy Reddig & seaw0lf
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
11 Redistributions of source code must retain the above copyright notice, this list
12 of conditions and the following disclaimer.
14 Redistributions in binary form must reproduce the above copyright notice, this
15 list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
18 Neither the names of the copyright holders nor the names of its contributors may
19 be used to endorse or promote products derived from this software without
20 specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ----------------------------------------------------------------------------- */
38 #define PICOINTERNAL_C
43 * - fix p->curLine for parser routines. increased twice
48 #include "picointernal.h"
52 /* function pointers */
53 void *( *_pico_ptr_malloc )( size_t ) = malloc;
54 void ( *_pico_ptr_free )( void* ) = free;
55 void ( *_pico_ptr_load_file )( char*, unsigned char**, int* ) = NULL;
56 void ( *_pico_ptr_free_file )( void* ) = NULL;
57 void ( *_pico_ptr_print )( int, const char* ) = NULL;
67 * kludged memory allocation wrapper
69 void *_pico_alloc( size_t size ){
72 /* some sanity checks */
76 if ( _pico_ptr_malloc == NULL ) {
81 ptr = _pico_ptr_malloc( size );
86 /* zero out allocated memory */
89 /* return pointer to allocated memory */
94 * _pico_calloc wrapper
96 void *_pico_calloc( size_t num, size_t size ){
99 /* some sanity checks */
100 if ( num == 0 || size == 0 ) {
103 if ( _pico_ptr_malloc == NULL ) {
107 /* allocate memory */
108 ptr = _pico_ptr_malloc( num * size );
113 /* zero out allocated memory */
114 memset( ptr,0,num * size );
116 /* return pointer to allocated memory */
121 * memory reallocation wrapper (note: only grows,
122 * but never shrinks or frees)
124 void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize ){
131 if ( newSize < oldSize ) {
134 if ( _pico_ptr_malloc == NULL ) {
138 /* allocate new pointer */
139 ptr2 = _pico_alloc( newSize );
140 if ( ptr2 == NULL ) {
145 if ( *ptr != NULL ) {
146 memcpy( ptr2, *ptr, oldSize );
150 /* fix up and return */
155 /* _pico_clone_alloc:
156 * handy function for quick string allocation/copy. it clones
157 * the given string and returns a pointer to the new allocated
158 * clone (which must be freed by caller of course) or returns
159 * NULL on memory alloc or param errors. if 'size' is -1 the
160 * length of the input string is used, otherwise 'size' is used
161 * as custom clone size (the string is cropped to fit into mem
164 char *_pico_clone_alloc( char *str, int size ){
173 /* set real size of cloned string */
174 cloneSize = ( size < 0 ) ? strlen( str ) : size;
176 /* allocate memory */
177 cloned = _pico_alloc( cloneSize + 1 ); /* bugfix! */
178 if ( cloned == NULL ) {
182 /* zero out memory allocated by cloned string */
183 memset( cloned,0,cloneSize );
185 /* copy input string to cloned string */
186 if ( cloneSize < strlen( str ) ) {
187 memcpy( cloned,str,cloneSize );
188 cloned[ cloneSize ] = '\0';
191 strcpy( cloned,str );
193 /* return ptr to cloned string */
198 * wrapper around the free function pointer
200 void _pico_free( void *ptr ){
205 if ( _pico_ptr_free == NULL ) {
209 /* free the allocated memory */
210 _pico_ptr_free( ptr );
214 * wrapper around the loadfile function pointer
216 void _pico_load_file( char *name, unsigned char **buffer, int *bufSize ){
218 if ( name == NULL ) {
222 if ( _pico_ptr_load_file == NULL ) {
226 /* do the actual call to read in the file; */
227 /* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
228 _pico_ptr_load_file( name,buffer,bufSize );
232 * wrapper around the file free function pointer
234 void _pico_free_file( void *buffer ){
236 if ( buffer == NULL ) {
240 /* use default free */
241 if ( _pico_ptr_free_file == NULL ) {
245 /* free the allocated file */
246 _pico_ptr_free_file( buffer );
250 * wrapper around the print function pointer -sea
252 void _pico_printf( int level, const char *format, ... ){
257 if ( format == NULL ) {
260 if ( _pico_ptr_print == NULL ) {
265 va_start( argptr,format );
266 vsprintf( str,format,argptr );
269 /* remove linefeeds */
270 if ( str[ strlen( str ) - 1 ] == '\n' ) {
271 str[ strlen( str ) - 1 ] = '\0';
274 /* do the actual call */
275 _pico_ptr_print( level,str );
279 * left trims the given string -sea
281 char *_pico_strltrim( char *str ){
282 char *str1 = str, *str2 = str;
284 while ( isspace( *str2 ) ) str2++;
286 while ( *str2 != '\0' ) /* fix: ydnar */
293 * right trims the given string -sea
295 char *_pico_strrtrim( char *str ){
302 if ( allspace && !isspace( *str1 ) ) {
312 while ( ( isspace( *str1 ) ) && ( str1 >= str ) )
320 * pico internal string-to-lower routine.
322 char *_pico_strlwr( char *str ){
324 for ( cp = str; *cp; ++cp )
326 if ( 'A' <= *cp && *cp <= 'Z' ) {
327 *cp += ( 'a' - 'A' );
334 * counts how often the given char appears in str. -sea
336 int _pico_strchcount( char *str, int ch ){
338 while ( *str++ ) if ( *str == ch ) {
344 void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs ){
346 for ( i = 0; i < 3; i++ )
353 void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs ){
355 for ( i = 0; i < 3; i++ )
358 if ( value < mins[i] ) {
361 if ( value > maxs[i] ) {
367 void _pico_zero_vec( picoVec3_t vec ){
368 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
371 void _pico_zero_vec2( picoVec2_t vec ){
372 vec[ 0 ] = vec[ 1 ] = 0;
375 void _pico_zero_vec4( picoVec4_t vec ){
376 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
379 void _pico_set_vec( picoVec3_t v, float a, float b, float c ){
385 void _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d ){
392 void _pico_copy_vec( picoVec3_t src, picoVec3_t dest ){
393 dest[ 0 ] = src[ 0 ];
394 dest[ 1 ] = src[ 1 ];
395 dest[ 2 ] = src[ 2 ];
398 void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest ){
399 dest[ 0 ] = src[ 0 ];
400 dest[ 1 ] = src[ 1 ];
403 void _pico_copy_vec4( picoVec4_t src, picoVec4_t dest ){
404 dest[ 0 ] = src[ 0 ];
405 dest[ 1 ] = src[ 1 ];
406 dest[ 2 ] = src[ 2 ];
407 dest[ 3 ] = src[ 3 ];
411 picoVec_t _pico_normalize_vec( picoVec3_t vec ){
414 len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
419 vec[ 0 ] *= (picoVec_t) ilen;
420 vec[ 1 ] *= (picoVec_t) ilen;
421 vec[ 2 ] *= (picoVec_t) ilen;
422 return (picoVec_t) len;
425 void _pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
426 dest[ 0 ] = a[ 0 ] + b[ 0 ];
427 dest[ 1 ] = a[ 1 ] + b[ 1 ];
428 dest[ 2 ] = a[ 2 ] + b[ 2 ];
431 void _pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
432 dest[ 0 ] = a[ 0 ] - b[ 0 ];
433 dest[ 1 ] = a[ 1 ] - b[ 1 ];
434 dest[ 2 ] = a[ 2 ] - b[ 2 ];
437 void _pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest ){
438 dest[ 0 ] = v[ 0 ] * scale;
439 dest[ 1 ] = v[ 1 ] * scale;
440 dest[ 2 ] = v[ 2 ] * scale;
443 void _pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest ){
444 dest[ 0 ] = v[ 0 ] * scale;
445 dest[ 1 ] = v[ 1 ] * scale;
446 dest[ 2 ] = v[ 2 ] * scale;
447 dest[ 3 ] = v[ 3 ] * scale;
450 picoVec_t _pico_dot_vec( picoVec3_t a, picoVec3_t b ){
451 return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
454 void _pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
455 dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
456 dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
457 dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
460 picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c ){
463 _pico_subtract_vec( b, a, ba );
464 _pico_subtract_vec( c, a, ca );
465 _pico_cross_vec( ca, ba, plane );
466 plane[ 3 ] = _pico_dot_vec( a, plane );
467 return _pico_normalize_vec( plane );
470 /* separate from _pico_set_vec4 */
471 void _pico_set_color( picoColor_t c, int r, int g, int b, int a ){
478 void _pico_copy_color( picoColor_t src, picoColor_t dest ){
479 dest[ 0 ] = src[ 0 ];
480 dest[ 1 ] = src[ 1 ];
481 dest[ 2 ] = src[ 2 ];
482 dest[ 3 ] = src[ 3 ];
485 #ifdef __BIG_ENDIAN__
487 int _pico_big_long( int src ) { return src; }
488 short _pico_big_short( short src ) { return src; }
489 float _pico_big_float( float src ) { return src; }
491 int _pico_little_long( int src ){
492 return ( ( src & 0xFF000000 ) >> 24 ) |
493 ( ( src & 0x00FF0000 ) >> 8 ) |
494 ( ( src & 0x0000FF00 ) << 8 ) |
495 ( ( src & 0x000000FF ) << 24 );
498 short _pico_little_short( short src ){
499 return ( ( src & 0xFF00 ) >> 8 ) |
500 ( ( src & 0x00FF ) << 8 );
503 float _pico_little_float( float src ){
504 floatSwapUnion in,out;
506 out.c[ 0 ] = in.c[ 3 ];
507 out.c[ 1 ] = in.c[ 2 ];
508 out.c[ 2 ] = in.c[ 1 ];
509 out.c[ 3 ] = in.c[ 0 ];
512 #else /*__BIG_ENDIAN__*/
514 int _pico_little_long( int src ) { return src; }
515 short _pico_little_short( short src ) { return src; }
516 float _pico_little_float( float src ) { return src; }
518 int _pico_big_long( int src ){
519 return ( ( src & 0xFF000000 ) >> 24 ) |
520 ( ( src & 0x00FF0000 ) >> 8 ) |
521 ( ( src & 0x0000FF00 ) << 8 ) |
522 ( ( src & 0x000000FF ) << 24 );
525 short _pico_big_short( short src ){
526 return ( ( src & 0xFF00 ) >> 8 ) |
527 ( ( src & 0x00FF ) << 8 );
530 float _pico_big_float( float src ){
531 floatSwapUnion in,out;
533 out.c[ 0 ] = in.c[ 3 ];
534 out.c[ 1 ] = in.c[ 2 ];
535 out.c[ 2 ] = in.c[ 1 ];
536 out.c[ 3 ] = in.c[ 0 ];
539 #endif /*__BIG_ENDIAN__*/
542 * case-insensitive strstr. -sea
544 char *_pico_stristr( char *str, const char *substr ){
545 const int sublen = strlen( substr );
548 if ( !_pico_strnicmp( str,substr,sublen ) ) {
561 changes dos \ style path separators to /
564 void _pico_unixify( char *path ){
565 if ( path == NULL ) {
570 if ( *path == '\\' ) {
578 * removes file name portion from given file path and converts
579 * the directory separators to un*x style. returns 1 on success
580 * or 0 when 'destSize' was exceeded. -sea
582 int _pico_nofname( const char *path, char *dest, int destSize ){
586 while ( ( *dest = *path ) != '\0' )
588 if ( *dest == '/' || *dest == '\\' ) {
604 * returns ptr to filename portion in given path or an empty
605 * string otherwise. given 'path' is not altered. -sea
607 char *_pico_nopath( const char *path ){
609 src = (char *)path + ( strlen( path ) - 1 );
611 if ( path == NULL ) {
614 if ( !strchr( (char *)path,'/' ) && !strchr( (char *)path,'\\' ) ) {
615 return ( (char *)path );
618 while ( ( src-- ) != path )
620 if ( *src == '/' || *src == '\\' ) {
628 * sets/changes the file extension for the given filename
629 * or filepath's filename portion. the given 'path' *is*
630 * altered. leave 'ext' empty to remove extension. -sea
632 char *_pico_setfext( char *path, const char *ext ){
636 src = path + ( strlen( path ) - 1 );
641 if ( strlen( ext ) < 1 ) {
644 if ( strlen( path ) < 1 ) {
648 while ( ( src-- ) != path )
650 if ( *src == '/' || *src == '\\' ) {
668 * extracts one line from the given buffer and stores it in dest.
669 * returns -1 on error or the length of the line on success. i've
670 * removed string trimming here. this can be done manually by the
673 int _pico_getline( char *buf, int bufsize, char *dest, int destsize ){
677 if ( dest == NULL || destsize < 1 ) {
680 memset( dest,0,destsize );
683 if ( buf == NULL || bufsize < 1 ) {
688 for ( pos = 0; pos < bufsize && pos < destsize; pos++ )
690 if ( buf[pos] == '\n' ) {
693 dest[pos] = buf[pos];
695 /* terminate dest and return */
700 /* _pico_parse_skip_white:
701 * skips white spaces in current pico parser, sets *hasLFs
702 * to 1 if linefeeds were skipped, and either returns the
703 * parser's cursor pointer or NULL on error. -sea
705 void _pico_parse_skip_white( picoParser_t *p, int *hasLFs ){
707 if ( p == NULL || p->cursor == NULL ) {
711 /* skin white spaces */
715 if ( p->cursor < p->buffer ||
716 p->cursor >= p->max ) {
719 /* break for chars other than white spaces */
720 if ( *p->cursor > 0x20 ) {
723 if ( *p->cursor == 0x00 ) {
727 /* a bit of linefeed handling */
728 if ( *p->cursor == '\n' ) {
732 /* go to next character */
738 * allocates a new ascii parser object.
740 picoParser_t *_pico_new_parser( picoByte_t *buffer, int bufSize ){
744 if ( buffer == NULL || bufSize <= 0 ) {
748 /* allocate reader */
749 p = _pico_alloc( sizeof( picoParser_t ) );
753 memset( p,0,sizeof( picoParser_t ) );
755 /* allocate token space */
758 p->token = _pico_alloc( p->tokenMax );
759 if ( p->token == NULL ) {
766 p->bufSize = bufSize;
767 p->max = p->buffer + bufSize;
768 p->curLine = 1; /* sea: new */
770 /* return ptr to parser */
774 /* _pico_free_parser:
775 * frees an existing pico parser object.
777 void _pico_free_parser( picoParser_t *p ){
783 /* free the parser */
784 if ( p->token != NULL ) {
785 _pico_free( p->token );
791 * reads the next token from given pico parser object. if param
792 * 'allowLFs' is 1 it will read beyond linefeeds and return 0 when
793 * the EOF is reached. if 'allowLFs' is 0 it will return 0 when
794 * the EOL is reached. if 'handleQuoted' is 1 the parser function
795 * will handle "quoted" strings and return the data between the
796 * quotes as token. returns 0 on end/error or 1 on success. -sea
798 int _pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted ){
803 if ( p == NULL || p->buffer == NULL ||
804 p->cursor < p->buffer ||
805 p->cursor >= p->max ) {
808 /* clear parser token */
810 p->token[ 0 ] = '\0';
813 /* skip whitespaces */
814 while ( p->cursor < p->max && *p->cursor <= 32 )
816 if ( *p->cursor == '\n' ) {
822 /* return if we're not allowed to go beyond lfs */
823 if ( ( hasLFs > 0 ) && !allowLFs ) {
827 /* get next quoted string */
828 if ( *p->cursor == '\"' && handleQuoted ) {
830 while ( p->cursor < p->max && *p->cursor )
832 if ( *p->cursor == '\\' ) {
833 if ( *( p->cursor + 1 ) == '"' ) {
836 p->token[ p->tokenSize++ ] = *p->cursor++;
839 else if ( *p->cursor == '\"' ) {
843 else if ( *p->cursor == '\n' ) {
846 p->token[ p->tokenSize++ ] = *p->cursor++;
848 /* terminate token */
849 p->token[ p->tokenSize ] = '\0';
852 /* otherwise get next word */
853 while ( p->cursor < p->max && *p->cursor > 32 )
855 if ( *p->cursor == '\n' ) {
858 p->token[ p->tokenSize++ ] = *p->cursor++;
860 /* terminate token */
861 p->token[ p->tokenSize ] = '\0';
865 /* _pico_parse_first:
866 * reads the first token from the next line and returns
867 * a pointer to it. returns NULL on EOL or EOF. -sea
869 char *_pico_parse_first( picoParser_t *p ){
875 /* try to read next token (with lfs & quots) */
876 if ( !_pico_parse_ex( p,1,1 ) ) {
880 /* return ptr to the token string */
885 * reads the next token from the parser and returns a pointer
886 * to it. quoted strings are handled as usual. returns NULL
887 * on EOL or EOF. -sea
889 char *_pico_parse( picoParser_t *p, int allowLFs ){
895 /* try to read next token (with quots) */
896 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
900 /* return ptr to the token string */
904 /* _pico_parse_skip_rest:
905 * skips the rest of the current line in parser.
907 void _pico_parse_skip_rest( picoParser_t *p ){
908 while ( _pico_parse_ex( p,0,0 ) ) ;
911 /* _pico_parse_skip_braced:
912 * parses/skips over a braced section. returns 1 on success
913 * or 0 on error (when there was no closing bracket and the
914 * end of buffer was reached or when the opening bracket was
917 int _pico_parse_skip_braced( picoParser_t *p ){
926 /* set the initial level for parsing */
929 /* skip braced section */
932 /* read next token (lfs allowed) */
933 if ( !_pico_parse_ex( p,1,1 ) ) {
934 /* end of parser buffer reached */
937 /* first token must be an opening bracket */
938 if ( firstToken && p->token[0] != '{' ) {
939 /* opening bracket missing */
942 /* we only check this once */
946 if ( p->token[1] == '\0' ) {
947 if ( p->token[0] == '{' ) {
950 if ( p->token[0] == '}' ) {
954 /* break if we're back at our starting level */
959 /* successfully skipped braced section */
963 int _pico_parse_check( picoParser_t *p, int allowLFs, char *str ){
964 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
967 if ( !strcmp( p->token,str ) ) {
973 int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str ){
974 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
977 if ( !_pico_stricmp( p->token,str ) ) {
983 int _pico_parse_int( picoParser_t *p, int *out ){
987 if ( p == NULL || out == NULL ) {
991 /* get token and turn it into an integer */
993 token = _pico_parse( p,0 );
994 if ( token == NULL ) {
997 *out = atoi( token );
1003 int _pico_parse_int_def( picoParser_t *p, int *out, int def ){
1007 if ( p == NULL || out == NULL ) {
1011 /* get token and turn it into an integer */
1013 token = _pico_parse( p,0 );
1014 if ( token == NULL ) {
1017 *out = atoi( token );
1023 int _pico_parse_float( picoParser_t *p, float *out ){
1027 if ( p == NULL || out == NULL ) {
1031 /* get token and turn it into a float */
1033 token = _pico_parse( p,0 );
1034 if ( token == NULL ) {
1037 *out = (float) atof( token );
1043 int _pico_parse_float_def( picoParser_t *p, float *out, float def ){
1047 if ( p == NULL || out == NULL ) {
1051 /* get token and turn it into a float */
1053 token = _pico_parse( p,0 );
1054 if ( token == NULL ) {
1057 *out = (float) atof( token );
1063 int _pico_parse_vec( picoParser_t *p, picoVec3_t out ){
1068 if ( p == NULL || out == NULL ) {
1072 /* zero out outination vector */
1073 _pico_zero_vec( out );
1075 /* parse three vector components */
1076 for ( i = 0; i < 3; i++ )
1078 token = _pico_parse( p,0 );
1079 if ( token == NULL ) {
1080 _pico_zero_vec( out );
1083 out[ i ] = (float) atof( token );
1089 int _pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def ){
1094 if ( p == NULL || out == NULL ) {
1098 /* assign default vector value */
1099 _pico_copy_vec( def,out );
1101 /* parse three vector components */
1102 for ( i = 0; i < 3; i++ )
1104 token = _pico_parse( p,0 );
1105 if ( token == NULL ) {
1106 _pico_copy_vec( def,out );
1109 out[ i ] = (float) atof( token );
1115 int _pico_parse_vec2( picoParser_t *p, picoVec2_t out ){
1120 if ( p == NULL || out == NULL ) {
1124 /* zero out outination vector */
1125 _pico_zero_vec2( out );
1127 /* parse two vector components */
1128 for ( i = 0; i < 2; i++ )
1130 token = _pico_parse( p,0 );
1131 if ( token == NULL ) {
1132 _pico_zero_vec2( out );
1135 out[ i ] = (float) atof( token );
1141 int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def ){
1146 if ( p == NULL || out == NULL ) {
1150 /* assign default vector value */
1151 _pico_copy_vec2( def,out );
1153 /* parse two vector components */
1154 for ( i = 0; i < 2; i++ )
1156 token = _pico_parse( p,0 );
1157 if ( token == NULL ) {
1158 _pico_copy_vec2( def,out );
1161 out[ i ] = (float) atof( token );
1167 int _pico_parse_vec4( picoParser_t *p, picoVec4_t out ){
1172 if ( p == NULL || out == NULL ) {
1176 /* zero out outination vector */
1177 _pico_zero_vec4( out );
1179 /* parse four vector components */
1180 for ( i = 0; i < 4; i++ )
1182 token = _pico_parse( p,0 );
1183 if ( token == NULL ) {
1184 _pico_zero_vec4( out );
1187 out[ i ] = (float) atof( token );
1193 int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def ){
1198 if ( p == NULL || out == NULL ) {
1202 /* assign default vector value */
1203 _pico_copy_vec4( def,out );
1205 /* parse four vector components */
1206 for ( i = 0; i < 4; i++ )
1208 token = _pico_parse( p,0 );
1209 if ( token == NULL ) {
1210 _pico_copy_vec4( def,out );
1213 out[ i ] = (float) atof( token );
1219 /* _pico_new_memstream:
1220 * allocates a new memorystream object.
1222 picoMemStream_t *_pico_new_memstream( picoByte_t *buffer, int bufSize ){
1226 if ( buffer == NULL || bufSize <= 0 ) {
1230 /* allocate stream */
1231 s = _pico_alloc( sizeof( picoMemStream_t ) );
1235 memset( s,0,sizeof( picoMemStream_t ) );
1240 s->bufSize = bufSize;
1243 /* return ptr to stream */
1247 /* _pico_free_memstream:
1248 * frees an existing pico memorystream object.
1250 void _pico_free_memstream( picoMemStream_t *s ){
1256 /* free the stream */
1260 /* _pico_memstream_read:
1261 * reads data from a pico memorystream into a buffer.
1263 int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len ){
1267 if ( s == NULL || buffer == NULL ) {
1271 if ( s->curPos + len > s->buffer + s->bufSize ) {
1272 s->flag |= PICO_IOEOF;
1273 len = s->buffer + s->bufSize - s->curPos;
1278 memcpy( buffer, s->curPos, len );
1283 /* _pico_memstream_read:
1284 * reads a character from a pico memorystream
1286 int _pico_memstream_getc( picoMemStream_t *s ){
1294 /* read the character */
1295 if ( _pico_memstream_read( s, &c, 1 ) == 0 ) {
1302 /* _pico_memstream_seek:
1303 * sets the current read position to a different location
1305 int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin ){
1313 if ( origin == PICO_SEEK_SET ) {
1314 s->curPos = s->buffer + offset;
1315 overflow = s->curPos - ( s->buffer + s->bufSize );
1316 if ( overflow > 0 ) {
1317 s->curPos = s->buffer + s->bufSize;
1318 return offset - overflow;
1322 else if ( origin == PICO_SEEK_CUR ) {
1323 s->curPos += offset;
1324 overflow = s->curPos - ( s->buffer + s->bufSize );
1325 if ( overflow > 0 ) {
1326 s->curPos = s->buffer + s->bufSize;
1327 return offset - overflow;
1331 else if ( origin == PICO_SEEK_END ) {
1332 s->curPos = ( s->buffer + s->bufSize ) - offset;
1333 overflow = s->buffer - s->curPos;
1334 if ( overflow > 0 ) {
1335 s->curPos = s->buffer;
1336 return offset - overflow;
1344 /* _pico_memstream_tell:
1345 * returns the current read position in the pico memorystream
1347 long _pico_memstream_tell( picoMemStream_t *s ){
1353 return s->curPos - s->buffer;