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 )( const 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( const char *str ){
172 /* allocate memory */
173 cloned = _pico_alloc( strlen( str ) + 1 );
174 if ( cloned == NULL ) {
178 /* copy input string to cloned string */
179 strcpy( cloned, str );
181 /* return ptr to cloned string */
186 * wrapper around the free function pointer
188 void _pico_free( void *ptr ){
193 if ( _pico_ptr_free == NULL ) {
197 /* free the allocated memory */
198 _pico_ptr_free( ptr );
202 * wrapper around the loadfile function pointer
204 void _pico_load_file( const char *name, unsigned char **buffer, int *bufSize ){
206 if ( name == NULL ) {
210 if ( _pico_ptr_load_file == NULL ) {
214 /* do the actual call to read in the file; */
215 /* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
216 _pico_ptr_load_file( name,buffer,bufSize );
220 * wrapper around the file free function pointer
222 void _pico_free_file( void *buffer ){
224 if ( buffer == NULL ) {
228 /* use default free */
229 if ( _pico_ptr_free_file == NULL ) {
233 /* free the allocated file */
234 _pico_ptr_free_file( buffer );
238 * wrapper around the print function pointer -sea
240 void _pico_printf( int level, const char *format, ... ){
245 if ( format == NULL ) {
248 if ( _pico_ptr_print == NULL ) {
253 va_start( argptr,format );
254 vsprintf( str,format,argptr );
257 /* remove linefeeds */
258 if ( str[ strlen( str ) - 1 ] == '\n' ) {
259 str[ strlen( str ) - 1 ] = '\0';
262 /* do the actual call */
263 _pico_ptr_print( level,str );
266 /* _pico_first_token:
267 * trims everything after the first whitespace-delimited token
270 void _pico_first_token( char *str ){
271 if ( !str || !*str ) {
274 while ( *str && !isspace( *str ) )
280 * left trims the given string -sea
282 char *_pico_strltrim( char *str ){
283 char *str1 = str, *str2 = str;
285 while ( isspace( *str2 ) ) str2++;
287 while ( *str2 != '\0' ) /* fix: ydnar */
294 * right trims the given string -sea
296 char *_pico_strrtrim( char *str ){
303 if ( allspace && !isspace( *str1 ) ) {
313 while ( ( isspace( *str1 ) ) && ( str1 >= str ) )
321 * pico internal string-to-lower routine.
323 char *_pico_strlwr( char *str ){
325 for ( cp = str; *cp; ++cp )
327 if ( 'A' <= *cp && *cp <= 'Z' ) {
328 *cp += ( 'a' - 'A' );
335 * counts how often the given char appears in str. -sea
337 int _pico_strchcount( char *str, int ch ){
339 while ( *str++ ) if ( *str == ch ) {
345 void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs ){
347 for ( i = 0; i < 3; i++ )
354 void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs ){
356 for ( i = 0; i < 3; i++ )
359 if ( value < mins[i] ) {
362 if ( value > maxs[i] ) {
368 void _pico_zero_vec( picoVec3_t vec ){
369 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
372 void _pico_zero_vec2( picoVec2_t vec ){
373 vec[ 0 ] = vec[ 1 ] = 0;
376 void _pico_zero_vec4( picoVec4_t vec ){
377 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
380 void _pico_set_vec( picoVec3_t v, float a, float b, float c ){
386 void _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d ){
393 void _pico_copy_vec( picoVec3_t src, picoVec3_t dest ){
394 dest[ 0 ] = src[ 0 ];
395 dest[ 1 ] = src[ 1 ];
396 dest[ 2 ] = src[ 2 ];
399 void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest ){
400 dest[ 0 ] = src[ 0 ];
401 dest[ 1 ] = src[ 1 ];
404 void _pico_copy_vec4( picoVec4_t src, picoVec4_t dest ){
405 dest[ 0 ] = src[ 0 ];
406 dest[ 1 ] = src[ 1 ];
407 dest[ 2 ] = src[ 2 ];
408 dest[ 3 ] = src[ 3 ];
412 picoVec_t _pico_normalize_vec( picoVec3_t vec ){
415 len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
420 vec[ 0 ] *= (picoVec_t) ilen;
421 vec[ 1 ] *= (picoVec_t) ilen;
422 vec[ 2 ] *= (picoVec_t) ilen;
423 return (picoVec_t) len;
426 void _pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
427 dest[ 0 ] = a[ 0 ] + b[ 0 ];
428 dest[ 1 ] = a[ 1 ] + b[ 1 ];
429 dest[ 2 ] = a[ 2 ] + b[ 2 ];
432 void _pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
433 dest[ 0 ] = a[ 0 ] - b[ 0 ];
434 dest[ 1 ] = a[ 1 ] - b[ 1 ];
435 dest[ 2 ] = a[ 2 ] - b[ 2 ];
438 void _pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest ){
439 dest[ 0 ] = v[ 0 ] * scale;
440 dest[ 1 ] = v[ 1 ] * scale;
441 dest[ 2 ] = v[ 2 ] * scale;
444 void _pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest ){
445 dest[ 0 ] = v[ 0 ] * scale;
446 dest[ 1 ] = v[ 1 ] * scale;
447 dest[ 2 ] = v[ 2 ] * scale;
448 dest[ 3 ] = v[ 3 ] * scale;
451 picoVec_t _pico_dot_vec( picoVec3_t a, picoVec3_t b ){
452 return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
455 void _pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
456 dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
457 dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
458 dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
461 picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c ){
464 _pico_subtract_vec( b, a, ba );
465 _pico_subtract_vec( c, a, ca );
466 _pico_cross_vec( ca, ba, plane );
467 plane[ 3 ] = _pico_dot_vec( a, plane );
468 return _pico_normalize_vec( plane );
471 /* separate from _pico_set_vec4 */
472 void _pico_set_color( picoColor_t c, int r, int g, int b, int a ){
479 void _pico_copy_color( picoColor_t src, picoColor_t dest ){
480 dest[ 0 ] = src[ 0 ];
481 dest[ 1 ] = src[ 1 ];
482 dest[ 2 ] = src[ 2 ];
483 dest[ 3 ] = src[ 3 ];
486 #ifdef __BIG_ENDIAN__
488 int _pico_big_long( int src ) { return src; }
489 short _pico_big_short( short src ) { return src; }
490 float _pico_big_float( float src ) { return src; }
492 int _pico_little_long( int src ){
493 return ( ( src & 0xFF000000 ) >> 24 ) |
494 ( ( src & 0x00FF0000 ) >> 8 ) |
495 ( ( src & 0x0000FF00 ) << 8 ) |
496 ( ( src & 0x000000FF ) << 24 );
499 short _pico_little_short( short src ){
500 return ( ( src & 0xFF00 ) >> 8 ) |
501 ( ( src & 0x00FF ) << 8 );
504 float _pico_little_float( float src ){
505 floatSwapUnion in,out;
507 out.c[ 0 ] = in.c[ 3 ];
508 out.c[ 1 ] = in.c[ 2 ];
509 out.c[ 2 ] = in.c[ 1 ];
510 out.c[ 3 ] = in.c[ 0 ];
513 #else /*__BIG_ENDIAN__*/
515 int _pico_little_long( int src ) { return src; }
516 short _pico_little_short( short src ) { return src; }
517 float _pico_little_float( float src ) { return src; }
519 int _pico_big_long( int src ){
520 return ( ( src & 0xFF000000 ) >> 24 ) |
521 ( ( src & 0x00FF0000 ) >> 8 ) |
522 ( ( src & 0x0000FF00 ) << 8 ) |
523 ( ( src & 0x000000FF ) << 24 );
526 short _pico_big_short( short src ){
527 return ( ( src & 0xFF00 ) >> 8 ) |
528 ( ( src & 0x00FF ) << 8 );
531 float _pico_big_float( float src ){
532 floatSwapUnion in,out;
534 out.c[ 0 ] = in.c[ 3 ];
535 out.c[ 1 ] = in.c[ 2 ];
536 out.c[ 2 ] = in.c[ 1 ];
537 out.c[ 3 ] = in.c[ 0 ];
540 #endif /*__BIG_ENDIAN__*/
543 * case-insensitive strstr. -sea
545 const char *_pico_stristr( const char *str, const char *substr ){
546 const size_t sublen = strlen( substr );
549 if ( !_pico_strnicmp( str,substr,sublen ) ) {
562 changes dos \ style path separators to /
565 void _pico_unixify( char *path ){
566 if ( path == NULL ) {
571 if ( *path == '\\' ) {
579 * removes file name portion from given file path and converts
580 * the directory separators to un*x style. returns 1 on success
581 * or 0 when 'destSize' was exceeded. -sea
583 int _pico_nofname( const char *path, char *dest, int destSize ){
587 while ( ( *dest = *path ) != '\0' )
589 if ( *dest == '/' || *dest == '\\' ) {
605 * returns ptr to filename portion in given path or an empty
606 * string otherwise. given 'path' is not altered. -sea
608 const char *_pico_nopath( const char *path ){
609 if ( path == NULL ) {
613 src = path + ( strlen( path ) - 1 );
615 if ( !strchr( path,'/' ) && !strchr( path,'\\' ) ) {
619 while ( ( src-- ) != path )
621 if ( *src == '/' || *src == '\\' ) {
629 * sets/changes the file extension for the given filename
630 * or filepath's filename portion. the given 'path' *is*
631 * altered. leave 'ext' empty to remove extension. -sea
633 char *_pico_setfext( char *path, const char *ext ){
637 src = path + ( strlen( path ) - 1 );
642 if ( strlen( ext ) < 1 ) {
645 if ( strlen( path ) < 1 ) {
649 while ( ( src-- ) != path )
651 if ( *src == '/' || *src == '\\' ) {
669 * extracts one line from the given buffer and stores it in dest.
670 * returns -1 on error or the length of the line on success. i've
671 * removed string trimming here. this can be done manually by the
674 int _pico_getline( char *buf, int bufsize, char *dest, int destsize ){
678 if ( dest == NULL || destsize < 1 ) {
681 memset( dest,0,destsize );
684 if ( buf == NULL || bufsize < 1 ) {
689 for ( pos = 0; pos < bufsize && pos < destsize; pos++ )
691 if ( buf[pos] == '\n' ) {
694 dest[pos] = buf[pos];
696 /* terminate dest and return */
701 /* _pico_parse_skip_white:
702 * skips white spaces in current pico parser, sets *hasLFs
703 * to 1 if linefeeds were skipped, and either returns the
704 * parser's cursor pointer or NULL on error. -sea
706 void _pico_parse_skip_white( picoParser_t *p, int *hasLFs ){
708 if ( p == NULL || p->cursor == NULL ) {
712 /* skin white spaces */
716 if ( p->cursor < p->buffer ||
717 p->cursor >= p->max ) {
720 /* break for chars other than white spaces */
721 if ( *p->cursor > 0x20 ) {
724 if ( *p->cursor == 0x00 ) {
728 /* a bit of linefeed handling */
729 if ( *p->cursor == '\n' ) {
733 /* go to next character */
739 * allocates a new ascii parser object.
741 picoParser_t *_pico_new_parser( const picoByte_t *buffer, int bufSize ){
745 if ( buffer == NULL || bufSize <= 0 ) {
749 /* allocate reader */
750 p = _pico_alloc( sizeof( picoParser_t ) );
754 memset( p,0,sizeof( picoParser_t ) );
756 /* allocate token space */
759 p->token = _pico_alloc( p->tokenMax );
760 if ( p->token == NULL ) {
765 p->buffer = (const char *) buffer;
766 p->cursor = (const char *) buffer;
767 p->bufSize = bufSize;
768 p->max = p->buffer + bufSize;
769 p->curLine = 1; /* sea: new */
771 /* return ptr to parser */
775 /* _pico_free_parser:
776 * frees an existing pico parser object.
778 void _pico_free_parser( picoParser_t *p ){
784 /* free the parser */
785 if ( p->token != NULL ) {
786 _pico_free( p->token );
792 * reads the next token from given pico parser object. if param
793 * 'allowLFs' is 1 it will read beyond linefeeds and return 0 when
794 * the EOF is reached. if 'allowLFs' is 0 it will return 0 when
795 * the EOL is reached. if 'handleQuoted' is 1 the parser function
796 * will handle "quoted" strings and return the data between the
797 * quotes as token. returns 0 on end/error or 1 on success. -sea
799 int _pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted ){
804 if ( p == NULL || p->buffer == NULL ||
805 p->cursor < p->buffer ||
806 p->cursor >= p->max ) {
809 /* clear parser token */
811 p->token[ 0 ] = '\0';
814 /* skip whitespaces */
815 while ( p->cursor < p->max && *p->cursor <= 32 )
817 if ( *p->cursor == '\n' ) {
823 /* return if we're not allowed to go beyond lfs */
824 if ( ( hasLFs > 0 ) && !allowLFs ) {
828 /* get next quoted string */
829 if ( *p->cursor == '\"' && handleQuoted ) {
831 while ( p->cursor < p->max && *p->cursor )
833 if ( *p->cursor == '\\' ) {
834 if ( *( p->cursor + 1 ) == '"' ) {
837 p->token[ p->tokenSize++ ] = *p->cursor++;
840 else if ( *p->cursor == '\"' ) {
844 else if ( *p->cursor == '\n' ) {
847 p->token[ p->tokenSize++ ] = *p->cursor++;
849 /* terminate token */
850 p->token[ p->tokenSize ] = '\0';
853 /* otherwise get next word */
854 while ( p->cursor < p->max && *p->cursor > 32 )
856 if ( *p->cursor == '\n' ) {
859 p->token[ p->tokenSize++ ] = *p->cursor++;
861 /* terminate token */
862 p->token[ p->tokenSize ] = '\0';
866 /* _pico_parse_first:
867 * reads the first token from the next line and returns
868 * a pointer to it. returns NULL on EOL or EOF. -sea
870 char *_pico_parse_first( picoParser_t *p ){
876 /* try to read next token (with lfs & quots) */
877 if ( !_pico_parse_ex( p,1,1 ) ) {
881 /* return ptr to the token string */
886 * reads the next token from the parser and returns a pointer
887 * to it. quoted strings are handled as usual. returns NULL
888 * on EOL or EOF. -sea
890 char *_pico_parse( picoParser_t *p, int allowLFs ){
896 /* try to read next token (with quots) */
897 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
901 /* return ptr to the token string */
905 /* _pico_parse_skip_rest:
906 * skips the rest of the current line in parser.
908 void _pico_parse_skip_rest( picoParser_t *p ){
909 while ( _pico_parse_ex( p,0,0 ) ) ;
912 /* _pico_parse_skip_braced:
913 * parses/skips over a braced section. returns 1 on success
914 * or 0 on error (when there was no closing bracket and the
915 * end of buffer was reached or when the opening bracket was
918 int _pico_parse_skip_braced( picoParser_t *p ){
927 /* set the initial level for parsing */
930 /* skip braced section */
933 /* read next token (lfs allowed) */
934 if ( !_pico_parse_ex( p,1,1 ) ) {
935 /* end of parser buffer reached */
938 /* first token must be an opening bracket */
939 if ( firstToken && p->token[0] != '{' ) {
940 /* opening bracket missing */
943 /* we only check this once */
947 if ( p->token[1] == '\0' ) {
948 if ( p->token[0] == '{' ) {
951 if ( p->token[0] == '}' ) {
955 /* break if we're back at our starting level */
960 /* successfully skipped braced section */
964 int _pico_parse_check( picoParser_t *p, int allowLFs, char *str ){
965 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
968 if ( !strcmp( p->token,str ) ) {
974 int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str ){
975 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
978 if ( !_pico_stricmp( p->token,str ) ) {
984 int _pico_parse_int( picoParser_t *p, int *out ){
988 if ( p == NULL || out == NULL ) {
992 /* get token and turn it into an integer */
994 token = _pico_parse( p,0 );
995 if ( token == NULL ) {
998 *out = atoi( token );
1004 int _pico_parse_int_def( picoParser_t *p, int *out, int def ){
1008 if ( p == NULL || out == NULL ) {
1012 /* get token and turn it into an integer */
1014 token = _pico_parse( p,0 );
1015 if ( token == NULL ) {
1018 *out = atoi( token );
1024 int _pico_parse_float( picoParser_t *p, float *out ){
1028 if ( p == NULL || out == NULL ) {
1032 /* get token and turn it into a float */
1034 token = _pico_parse( p,0 );
1035 if ( token == NULL ) {
1038 *out = (float) atof( token );
1044 int _pico_parse_float_def( picoParser_t *p, float *out, float def ){
1048 if ( p == NULL || out == NULL ) {
1052 /* get token and turn it into a float */
1054 token = _pico_parse( p,0 );
1055 if ( token == NULL ) {
1058 *out = (float) atof( token );
1064 int _pico_parse_vec( picoParser_t *p, picoVec3_t out ){
1069 if ( p == NULL || out == NULL ) {
1073 /* zero out outination vector */
1074 _pico_zero_vec( out );
1076 /* parse three vector components */
1077 for ( i = 0; i < 3; i++ )
1079 token = _pico_parse( p,0 );
1080 if ( token == NULL ) {
1081 _pico_zero_vec( out );
1084 out[ i ] = (float) atof( token );
1090 int _pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def ){
1095 if ( p == NULL || out == NULL ) {
1099 /* assign default vector value */
1100 _pico_copy_vec( def,out );
1102 /* parse three vector components */
1103 for ( i = 0; i < 3; i++ )
1105 token = _pico_parse( p,0 );
1106 if ( token == NULL ) {
1107 _pico_copy_vec( def,out );
1110 out[ i ] = (float) atof( token );
1116 int _pico_parse_vec2( picoParser_t *p, picoVec2_t out ){
1121 if ( p == NULL || out == NULL ) {
1125 /* zero out outination vector */
1126 _pico_zero_vec2( out );
1128 /* parse two vector components */
1129 for ( i = 0; i < 2; i++ )
1131 token = _pico_parse( p,0 );
1132 if ( token == NULL ) {
1133 _pico_zero_vec2( out );
1136 out[ i ] = (float) atof( token );
1142 int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def ){
1147 if ( p == NULL || out == NULL ) {
1151 /* assign default vector value */
1152 _pico_copy_vec2( def,out );
1154 /* parse two vector components */
1155 for ( i = 0; i < 2; i++ )
1157 token = _pico_parse( p,0 );
1158 if ( token == NULL ) {
1159 _pico_copy_vec2( def,out );
1162 out[ i ] = (float) atof( token );
1168 int _pico_parse_vec4( picoParser_t *p, picoVec4_t out ){
1173 if ( p == NULL || out == NULL ) {
1177 /* zero out outination vector */
1178 _pico_zero_vec4( out );
1180 /* parse four vector components */
1181 for ( i = 0; i < 4; i++ )
1183 token = _pico_parse( p,0 );
1184 if ( token == NULL ) {
1185 _pico_zero_vec4( out );
1188 out[ i ] = (float) atof( token );
1194 int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def ){
1199 if ( p == NULL || out == NULL ) {
1203 /* assign default vector value */
1204 _pico_copy_vec4( def,out );
1206 /* parse four vector components */
1207 for ( i = 0; i < 4; i++ )
1209 token = _pico_parse( p,0 );
1210 if ( token == NULL ) {
1211 _pico_copy_vec4( def,out );
1214 out[ i ] = (float) atof( token );
1220 /* _pico_new_memstream:
1221 * allocates a new memorystream object.
1223 picoMemStream_t *_pico_new_memstream( const picoByte_t *buffer, int bufSize ){
1227 if ( buffer == NULL || bufSize <= 0 ) {
1231 /* allocate stream */
1232 s = _pico_alloc( sizeof( picoMemStream_t ) );
1236 memset( s,0,sizeof( picoMemStream_t ) );
1241 s->bufSize = bufSize;
1244 /* return ptr to stream */
1248 /* _pico_free_memstream:
1249 * frees an existing pico memorystream object.
1251 void _pico_free_memstream( picoMemStream_t *s ){
1257 /* free the stream */
1261 /* _pico_memstream_read:
1262 * reads data from a pico memorystream into a buffer.
1264 int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len ){
1268 if ( s == NULL || buffer == NULL ) {
1272 if ( s->curPos + len > s->buffer + s->bufSize ) {
1273 s->flag |= PICO_IOEOF;
1274 len = s->buffer + s->bufSize - s->curPos;
1279 memcpy( buffer, s->curPos, len );
1284 /* _pico_memstream_read:
1285 * reads a character from a pico memorystream
1287 int _pico_memstream_getc( picoMemStream_t *s ){
1295 /* read the character */
1296 if ( _pico_memstream_read( s, &c, 1 ) == 0 ) {
1303 /* _pico_memstream_seek:
1304 * sets the current read position to a different location
1306 int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin ){
1314 if ( origin == PICO_SEEK_SET ) {
1315 s->curPos = s->buffer + offset;
1316 overflow = s->curPos - ( s->buffer + s->bufSize );
1317 if ( overflow > 0 ) {
1318 s->curPos = s->buffer + s->bufSize;
1319 return offset - overflow;
1323 else if ( origin == PICO_SEEK_CUR ) {
1324 s->curPos += offset;
1325 overflow = s->curPos - ( s->buffer + s->bufSize );
1326 if ( overflow > 0 ) {
1327 s->curPos = s->buffer + s->bufSize;
1328 return offset - overflow;
1332 else if ( origin == PICO_SEEK_END ) {
1333 s->curPos = ( s->buffer + s->bufSize ) - offset;
1334 overflow = s->buffer - s->curPos;
1335 if ( overflow > 0 ) {
1336 s->curPos = s->buffer;
1337 return offset - overflow;
1345 /* _pico_memstream_tell:
1346 * returns the current read position in the pico memorystream
1348 long _pico_memstream_tell( picoMemStream_t *s ){
1354 return s->curPos - s->buffer;