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 ----------------------------------------------------------------------------- */
36 * - fix p->curLine for parser routines. increased twice
41 #include "picointernal.h"
45 /* function pointers */
46 void *( *_pico_ptr_malloc )( size_t ) = malloc;
47 void ( *_pico_ptr_free )( void* ) = free;
48 void ( *_pico_ptr_load_file )( const char*, unsigned char**, int* ) = NULL;
49 void ( *_pico_ptr_free_file )( void* ) = NULL;
50 void ( *_pico_ptr_print )( int, const char* ) = NULL;
60 * kludged memory allocation wrapper
62 void *_pico_alloc( size_t size ){
65 /* some sanity checks */
69 if ( _pico_ptr_malloc == NULL ) {
74 ptr = _pico_ptr_malloc( size );
79 /* zero out allocated memory */
82 /* return pointer to allocated memory */
87 * _pico_calloc wrapper
89 void *_pico_calloc( size_t num, size_t size ){
92 /* some sanity checks */
93 if ( num == 0 || size == 0 ) {
96 if ( _pico_ptr_malloc == NULL ) {
100 /* allocate memory */
101 ptr = _pico_ptr_malloc( num * size );
106 /* zero out allocated memory */
107 memset( ptr,0,num * size );
109 /* return pointer to allocated memory */
114 * memory reallocation wrapper (note: only grows,
115 * but never shrinks or frees)
117 void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize ){
124 if ( newSize < oldSize ) {
127 if ( _pico_ptr_malloc == NULL ) {
131 /* allocate new pointer */
132 ptr2 = _pico_alloc( newSize );
133 if ( ptr2 == NULL ) {
138 if ( *ptr != NULL ) {
139 memcpy( ptr2, *ptr, oldSize );
143 /* fix up and return */
148 /* _pico_clone_alloc:
149 * handy function for quick string allocation/copy. it clones
150 * the given string and returns a pointer to the new allocated
151 * clone (which must be freed by caller of course) or returns
152 * NULL on memory alloc or param errors. if 'size' is -1 the
153 * length of the input string is used, otherwise 'size' is used
154 * as custom clone size (the string is cropped to fit into mem
157 char *_pico_clone_alloc( const char *str ){
165 /* allocate memory */
166 cloned = _pico_alloc( strlen( str ) + 1 );
167 if ( cloned == NULL ) {
171 /* copy input string to cloned string */
172 strcpy( cloned, str );
174 /* return ptr to cloned string */
179 * wrapper around the free function pointer
181 void _pico_free( void *ptr ){
186 if ( _pico_ptr_free == NULL ) {
190 /* free the allocated memory */
191 _pico_ptr_free( ptr );
195 * wrapper around the loadfile function pointer
197 void _pico_load_file( const char *name, unsigned char **buffer, int *bufSize ){
199 if ( name == NULL ) {
203 if ( _pico_ptr_load_file == NULL ) {
207 /* do the actual call to read in the file; */
208 /* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
209 _pico_ptr_load_file( name,buffer,bufSize );
213 * wrapper around the file free function pointer
215 void _pico_free_file( void *buffer ){
217 if ( buffer == NULL ) {
221 /* use default free */
222 if ( _pico_ptr_free_file == NULL ) {
226 /* free the allocated file */
227 _pico_ptr_free_file( buffer );
231 * wrapper around the print function pointer -sea
233 void _pico_printf( int level, const char *format, ... ){
238 if ( format == NULL ) {
241 if ( _pico_ptr_print == NULL ) {
246 va_start( argptr,format );
247 vsprintf( str,format,argptr );
250 /* remove linefeeds */
251 if ( str[ strlen( str ) - 1 ] == '\n' ) {
252 str[ strlen( str ) - 1 ] = '\0';
255 /* do the actual call */
256 _pico_ptr_print( level,str );
259 /* _pico_first_token:
260 * trims everything after the first whitespace-delimited token
263 void _pico_first_token( char *str ){
264 if ( !str || !*str ) {
267 while ( *str && !isspace( *str ) )
273 * left trims the given string -sea
275 char *_pico_strltrim( char *str ){
276 char *str1 = str, *str2 = str;
278 while ( isspace( *str2 ) ) str2++;
280 while ( *str2 != '\0' ) /* fix: ydnar */
287 * right trims the given string -sea
289 char *_pico_strrtrim( char *str ){
296 if ( allspace && !isspace( *str1 ) ) {
306 while ( ( isspace( *str1 ) ) && ( str1 >= str ) )
314 * pico internal string-to-lower routine.
316 char *_pico_strlwr( char *str ){
318 for ( cp = str; *cp; ++cp )
320 if ( 'A' <= *cp && *cp <= 'Z' ) {
321 *cp += ( 'a' - 'A' );
328 * counts how often the given char appears in str. -sea
330 int _pico_strchcount( char *str, int ch ){
332 while ( *str++ ) if ( *str == ch ) {
338 void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs ){
340 for ( i = 0; i < 3; i++ )
347 void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs ){
349 for ( i = 0; i < 3; i++ )
352 if ( value < mins[i] ) {
355 if ( value > maxs[i] ) {
361 void _pico_zero_vec( picoVec3_t vec ){
362 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
365 void _pico_zero_vec2( picoVec2_t vec ){
366 vec[ 0 ] = vec[ 1 ] = 0;
369 void _pico_zero_vec4( picoVec4_t vec ){
370 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
373 void _pico_set_vec( picoVec3_t v, float a, float b, float c ){
379 void _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d ){
386 void _pico_copy_vec( picoVec3_t src, picoVec3_t dest ){
387 dest[ 0 ] = src[ 0 ];
388 dest[ 1 ] = src[ 1 ];
389 dest[ 2 ] = src[ 2 ];
392 void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest ){
393 dest[ 0 ] = src[ 0 ];
394 dest[ 1 ] = src[ 1 ];
397 void _pico_copy_vec4( picoVec4_t src, picoVec4_t dest ){
398 dest[ 0 ] = src[ 0 ];
399 dest[ 1 ] = src[ 1 ];
400 dest[ 2 ] = src[ 2 ];
401 dest[ 3 ] = src[ 3 ];
405 picoVec_t _pico_normalize_vec( picoVec3_t vec ){
408 len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
413 vec[ 0 ] *= (picoVec_t) ilen;
414 vec[ 1 ] *= (picoVec_t) ilen;
415 vec[ 2 ] *= (picoVec_t) ilen;
416 return (picoVec_t) len;
419 void _pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
420 dest[ 0 ] = a[ 0 ] + b[ 0 ];
421 dest[ 1 ] = a[ 1 ] + b[ 1 ];
422 dest[ 2 ] = a[ 2 ] + b[ 2 ];
425 void _pico_subtract_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_scale_vec( picoVec3_t v, float scale, picoVec3_t dest ){
432 dest[ 0 ] = v[ 0 ] * scale;
433 dest[ 1 ] = v[ 1 ] * scale;
434 dest[ 2 ] = v[ 2 ] * scale;
437 void _pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest ){
438 dest[ 0 ] = v[ 0 ] * scale;
439 dest[ 1 ] = v[ 1 ] * scale;
440 dest[ 2 ] = v[ 2 ] * scale;
441 dest[ 3 ] = v[ 3 ] * scale;
444 picoVec_t _pico_dot_vec( picoVec3_t a, picoVec3_t b ){
445 return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
448 void _pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest ){
449 dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
450 dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
451 dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
454 picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c ){
457 _pico_subtract_vec( b, a, ba );
458 _pico_subtract_vec( c, a, ca );
459 _pico_cross_vec( ca, ba, plane );
460 plane[ 3 ] = _pico_dot_vec( a, plane );
461 return _pico_normalize_vec( plane );
464 /* separate from _pico_set_vec4 */
465 void _pico_set_color( picoColor_t c, int r, int g, int b, int a ){
472 void _pico_copy_color( picoColor_t src, picoColor_t dest ){
473 dest[ 0 ] = src[ 0 ];
474 dest[ 1 ] = src[ 1 ];
475 dest[ 2 ] = src[ 2 ];
476 dest[ 3 ] = src[ 3 ];
479 #ifdef __BIG_ENDIAN__
481 int _pico_big_long( int src ) { return src; }
482 short _pico_big_short( short src ) { return src; }
483 float _pico_big_float( float src ) { return src; }
485 int _pico_little_long( int src ){
486 return ( ( src & 0xFF000000 ) >> 24 ) |
487 ( ( src & 0x00FF0000 ) >> 8 ) |
488 ( ( src & 0x0000FF00 ) << 8 ) |
489 ( ( src & 0x000000FF ) << 24 );
492 short _pico_little_short( short src ){
493 return ( ( src & 0xFF00 ) >> 8 ) |
494 ( ( src & 0x00FF ) << 8 );
497 float _pico_little_float( float src ){
498 floatSwapUnion in,out;
500 out.c[ 0 ] = in.c[ 3 ];
501 out.c[ 1 ] = in.c[ 2 ];
502 out.c[ 2 ] = in.c[ 1 ];
503 out.c[ 3 ] = in.c[ 0 ];
506 #else /*__BIG_ENDIAN__*/
508 int _pico_little_long( int src ) { return src; }
509 short _pico_little_short( short src ) { return src; }
510 float _pico_little_float( float src ) { return src; }
512 int _pico_big_long( int src ){
513 return ( ( src & 0xFF000000 ) >> 24 ) |
514 ( ( src & 0x00FF0000 ) >> 8 ) |
515 ( ( src & 0x0000FF00 ) << 8 ) |
516 ( ( src & 0x000000FF ) << 24 );
519 short _pico_big_short( short src ){
520 return ( ( src & 0xFF00 ) >> 8 ) |
521 ( ( src & 0x00FF ) << 8 );
524 float _pico_big_float( float src ){
525 floatSwapUnion in,out;
527 out.c[ 0 ] = in.c[ 3 ];
528 out.c[ 1 ] = in.c[ 2 ];
529 out.c[ 2 ] = in.c[ 1 ];
530 out.c[ 3 ] = in.c[ 0 ];
533 #endif /*__BIG_ENDIAN__*/
536 * case-insensitive strstr. -sea
538 const char *_pico_stristr( const char *str, const char *substr ){
539 const size_t sublen = strlen( substr );
542 if ( !_pico_strnicmp( str,substr,sublen ) ) {
555 changes dos \ style path separators to /
558 void _pico_unixify( char *path ){
559 if ( path == NULL ) {
564 if ( *path == '\\' ) {
572 * removes file name portion from given file path and converts
573 * the directory separators to un*x style. returns 1 on success
574 * or 0 when 'destSize' was exceeded. -sea
576 int _pico_nofname( const char *path, char *dest, int destSize ){
580 while ( ( *dest = *path ) != '\0' )
582 if ( *dest == '/' || *dest == '\\' ) {
598 * returns ptr to filename portion in given path or an empty
599 * string otherwise. given 'path' is not altered. -sea
601 const char *_pico_nopath( const char *path ){
603 src = path + ( strlen( path ) - 1 );
605 if ( path == NULL ) {
608 if ( !strchr( path,'/' ) && !strchr( path,'\\' ) ) {
612 while ( ( src-- ) != path )
614 if ( *src == '/' || *src == '\\' ) {
622 * sets/changes the file extension for the given filename
623 * or filepath's filename portion. the given 'path' *is*
624 * altered. leave 'ext' empty to remove extension. -sea
626 char *_pico_setfext( char *path, const char *ext ){
630 src = path + ( strlen( path ) - 1 );
635 if ( strlen( ext ) < 1 ) {
638 if ( strlen( path ) < 1 ) {
642 while ( ( src-- ) != path )
644 if ( *src == '/' || *src == '\\' ) {
662 * extracts one line from the given buffer and stores it in dest.
663 * returns -1 on error or the length of the line on success. i've
664 * removed string trimming here. this can be done manually by the
667 int _pico_getline( char *buf, int bufsize, char *dest, int destsize ){
671 if ( dest == NULL || destsize < 1 ) {
674 memset( dest,0,destsize );
677 if ( buf == NULL || bufsize < 1 ) {
682 for ( pos = 0; pos < bufsize && pos < destsize; pos++ )
684 if ( buf[pos] == '\n' ) {
687 dest[pos] = buf[pos];
689 /* terminate dest and return */
694 /* _pico_parse_skip_white:
695 * skips white spaces in current pico parser, sets *hasLFs
696 * to 1 if linefeeds were skipped, and either returns the
697 * parser's cursor pointer or NULL on error. -sea
699 void _pico_parse_skip_white( picoParser_t *p, int *hasLFs ){
701 if ( p == NULL || p->cursor == NULL ) {
705 /* skin white spaces */
709 if ( p->cursor < p->buffer ||
710 p->cursor >= p->max ) {
713 /* break for chars other than white spaces */
714 if ( *p->cursor > 0x20 ) {
717 if ( *p->cursor == 0x00 ) {
721 /* a bit of linefeed handling */
722 if ( *p->cursor == '\n' ) {
726 /* go to next character */
732 * allocates a new ascii parser object.
734 picoParser_t *_pico_new_parser( const picoByte_t *buffer, int bufSize ){
738 if ( buffer == NULL || bufSize <= 0 ) {
742 /* allocate reader */
743 p = _pico_alloc( sizeof( picoParser_t ) );
747 memset( p,0,sizeof( picoParser_t ) );
749 /* allocate token space */
752 p->token = _pico_alloc( p->tokenMax );
753 if ( p->token == NULL ) {
758 p->buffer = (const char *) buffer;
759 p->cursor = (const char *) buffer;
760 p->bufSize = bufSize;
761 p->max = p->buffer + bufSize;
762 p->curLine = 1; /* sea: new */
764 /* return ptr to parser */
768 /* _pico_free_parser:
769 * frees an existing pico parser object.
771 void _pico_free_parser( picoParser_t *p ){
777 /* free the parser */
778 if ( p->token != NULL ) {
779 _pico_free( p->token );
785 * reads the next token from given pico parser object. if param
786 * 'allowLFs' is 1 it will read beyond linefeeds and return 0 when
787 * the EOF is reached. if 'allowLFs' is 0 it will return 0 when
788 * the EOL is reached. if 'handleQuoted' is 1 the parser function
789 * will handle "quoted" strings and return the data between the
790 * quotes as token. returns 0 on end/error or 1 on success. -sea
792 int _pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted ){
797 if ( p == NULL || p->buffer == NULL ||
798 p->cursor < p->buffer ||
799 p->cursor >= p->max ) {
802 /* clear parser token */
804 p->token[ 0 ] = '\0';
807 /* skip whitespaces */
808 while ( p->cursor < p->max && *p->cursor <= 32 )
810 if ( *p->cursor == '\n' ) {
816 /* return if we're not allowed to go beyond lfs */
817 if ( ( hasLFs > 0 ) && !allowLFs ) {
821 /* get next quoted string */
822 if ( *p->cursor == '\"' && handleQuoted ) {
824 while ( p->cursor < p->max && *p->cursor )
826 if ( *p->cursor == '\\' ) {
827 if ( *( p->cursor + 1 ) == '"' ) {
830 p->token[ p->tokenSize++ ] = *p->cursor++;
833 else if ( *p->cursor == '\"' ) {
837 else if ( *p->cursor == '\n' ) {
840 p->token[ p->tokenSize++ ] = *p->cursor++;
842 /* terminate token */
843 p->token[ p->tokenSize ] = '\0';
846 /* otherwise get next word */
847 while ( p->cursor < p->max && *p->cursor > 32 )
849 if ( *p->cursor == '\n' ) {
852 p->token[ p->tokenSize++ ] = *p->cursor++;
854 /* terminate token */
855 p->token[ p->tokenSize ] = '\0';
859 /* _pico_parse_first:
860 * reads the first token from the next line and returns
861 * a pointer to it. returns NULL on EOL or EOF. -sea
863 char *_pico_parse_first( picoParser_t *p ){
869 /* try to read next token (with lfs & quots) */
870 if ( !_pico_parse_ex( p,1,1 ) ) {
874 /* return ptr to the token string */
879 * reads the next token from the parser and returns a pointer
880 * to it. quoted strings are handled as usual. returns NULL
881 * on EOL or EOF. -sea
883 char *_pico_parse( picoParser_t *p, int allowLFs ){
889 /* try to read next token (with quots) */
890 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
894 /* return ptr to the token string */
898 /* _pico_parse_skip_rest:
899 * skips the rest of the current line in parser.
901 void _pico_parse_skip_rest( picoParser_t *p ){
902 while ( _pico_parse_ex( p,0,0 ) ) ;
905 /* _pico_parse_skip_braced:
906 * parses/skips over a braced section. returns 1 on success
907 * or 0 on error (when there was no closing bracket and the
908 * end of buffer was reached or when the opening bracket was
911 int _pico_parse_skip_braced( picoParser_t *p ){
920 /* set the initial level for parsing */
923 /* skip braced section */
926 /* read next token (lfs allowed) */
927 if ( !_pico_parse_ex( p,1,1 ) ) {
928 /* end of parser buffer reached */
931 /* first token must be an opening bracket */
932 if ( firstToken && p->token[0] != '{' ) {
933 /* opening bracket missing */
936 /* we only check this once */
940 if ( p->token[1] == '\0' ) {
941 if ( p->token[0] == '{' ) {
944 if ( p->token[0] == '}' ) {
948 /* break if we're back at our starting level */
953 /* successfully skipped braced section */
957 int _pico_parse_check( picoParser_t *p, int allowLFs, char *str ){
958 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
961 if ( !strcmp( p->token,str ) ) {
967 int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str ){
968 if ( !_pico_parse_ex( p,allowLFs,1 ) ) {
971 if ( !_pico_stricmp( p->token,str ) ) {
977 int _pico_parse_int( picoParser_t *p, int *out ){
981 if ( p == NULL || out == NULL ) {
985 /* get token and turn it into an integer */
987 token = _pico_parse( p,0 );
988 if ( token == NULL ) {
991 *out = atoi( token );
997 int _pico_parse_int_def( picoParser_t *p, int *out, int def ){
1001 if ( p == NULL || out == NULL ) {
1005 /* get token and turn it into an integer */
1007 token = _pico_parse( p,0 );
1008 if ( token == NULL ) {
1011 *out = atoi( token );
1017 int _pico_parse_float( picoParser_t *p, float *out ){
1021 if ( p == NULL || out == NULL ) {
1025 /* get token and turn it into a float */
1027 token = _pico_parse( p,0 );
1028 if ( token == NULL ) {
1031 *out = (float) atof( token );
1037 int _pico_parse_float_def( picoParser_t *p, float *out, float def ){
1041 if ( p == NULL || out == NULL ) {
1045 /* get token and turn it into a float */
1047 token = _pico_parse( p,0 );
1048 if ( token == NULL ) {
1051 *out = (float) atof( token );
1057 int _pico_parse_vec( picoParser_t *p, picoVec3_t out ){
1062 if ( p == NULL || out == NULL ) {
1066 /* zero out outination vector */
1067 _pico_zero_vec( out );
1069 /* parse three vector components */
1070 for ( i = 0; i < 3; i++ )
1072 token = _pico_parse( p,0 );
1073 if ( token == NULL ) {
1074 _pico_zero_vec( out );
1077 out[ i ] = (float) atof( token );
1083 int _pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def ){
1088 if ( p == NULL || out == NULL ) {
1092 /* assign default vector value */
1093 _pico_copy_vec( def,out );
1095 /* parse three vector components */
1096 for ( i = 0; i < 3; i++ )
1098 token = _pico_parse( p,0 );
1099 if ( token == NULL ) {
1100 _pico_copy_vec( def,out );
1103 out[ i ] = (float) atof( token );
1109 int _pico_parse_vec2( picoParser_t *p, picoVec2_t out ){
1114 if ( p == NULL || out == NULL ) {
1118 /* zero out outination vector */
1119 _pico_zero_vec2( out );
1121 /* parse two vector components */
1122 for ( i = 0; i < 2; i++ )
1124 token = _pico_parse( p,0 );
1125 if ( token == NULL ) {
1126 _pico_zero_vec2( out );
1129 out[ i ] = (float) atof( token );
1135 int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def ){
1140 if ( p == NULL || out == NULL ) {
1144 /* assign default vector value */
1145 _pico_copy_vec2( def,out );
1147 /* parse two vector components */
1148 for ( i = 0; i < 2; i++ )
1150 token = _pico_parse( p,0 );
1151 if ( token == NULL ) {
1152 _pico_copy_vec2( def,out );
1155 out[ i ] = (float) atof( token );
1161 int _pico_parse_vec4( picoParser_t *p, picoVec4_t out ){
1166 if ( p == NULL || out == NULL ) {
1170 /* zero out outination vector */
1171 _pico_zero_vec4( out );
1173 /* parse four vector components */
1174 for ( i = 0; i < 4; i++ )
1176 token = _pico_parse( p,0 );
1177 if ( token == NULL ) {
1178 _pico_zero_vec4( out );
1181 out[ i ] = (float) atof( token );
1187 int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def ){
1192 if ( p == NULL || out == NULL ) {
1196 /* assign default vector value */
1197 _pico_copy_vec4( def,out );
1199 /* parse four vector components */
1200 for ( i = 0; i < 4; i++ )
1202 token = _pico_parse( p,0 );
1203 if ( token == NULL ) {
1204 _pico_copy_vec4( def,out );
1207 out[ i ] = (float) atof( token );
1213 /* _pico_new_memstream:
1214 * allocates a new memorystream object.
1216 picoMemStream_t *_pico_new_memstream( const picoByte_t *buffer, int bufSize ){
1220 if ( buffer == NULL || bufSize <= 0 ) {
1224 /* allocate stream */
1225 s = _pico_alloc( sizeof( picoMemStream_t ) );
1229 memset( s,0,sizeof( picoMemStream_t ) );
1234 s->bufSize = bufSize;
1237 /* return ptr to stream */
1241 /* _pico_free_memstream:
1242 * frees an existing pico memorystream object.
1244 void _pico_free_memstream( picoMemStream_t *s ){
1250 /* free the stream */
1254 /* _pico_memstream_read:
1255 * reads data from a pico memorystream into a buffer.
1257 int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len ){
1261 if ( s == NULL || buffer == NULL ) {
1265 if ( s->curPos + len > s->buffer + s->bufSize ) {
1266 s->flag |= PICO_IOEOF;
1267 len = s->buffer + s->bufSize - s->curPos;
1272 memcpy( buffer, s->curPos, len );
1277 /* _pico_memstream_read:
1278 * reads a character from a pico memorystream
1280 int _pico_memstream_getc( picoMemStream_t *s ){
1288 /* read the character */
1289 if ( _pico_memstream_read( s, &c, 1 ) == 0 ) {
1296 /* _pico_memstream_seek:
1297 * sets the current read position to a different location
1299 int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin ){
1307 if ( origin == PICO_SEEK_SET ) {
1308 s->curPos = s->buffer + offset;
1309 overflow = s->curPos - ( s->buffer + s->bufSize );
1310 if ( overflow > 0 ) {
1311 s->curPos = s->buffer + s->bufSize;
1312 return offset - overflow;
1316 else if ( origin == PICO_SEEK_CUR ) {
1317 s->curPos += offset;
1318 overflow = s->curPos - ( s->buffer + s->bufSize );
1319 if ( overflow > 0 ) {
1320 s->curPos = s->buffer + s->bufSize;
1321 return offset - overflow;
1325 else if ( origin == PICO_SEEK_END ) {
1326 s->curPos = ( s->buffer + s->bufSize ) - offset;
1327 overflow = s->buffer - s->curPos;
1328 if ( overflow > 0 ) {
1329 s->curPos = s->buffer;
1330 return offset - overflow;
1338 /* _pico_memstream_tell:
1339 * returns the current read position in the pico memorystream
1341 long _pico_memstream_tell( picoMemStream_t *s ){
1347 return s->curPos - s->buffer;