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 )
73 /* some sanity checks */
76 if (_pico_ptr_malloc == NULL)
80 ptr = _pico_ptr_malloc(size);
84 /* zero out allocated memory */
87 /* return pointer to allocated memory */
92 * _pico_calloc wrapper
94 void *_pico_calloc( size_t num, size_t size )
98 /* some sanity checks */
99 if( num == 0 || size == 0 )
101 if (_pico_ptr_malloc == NULL)
104 /* allocate memory */
105 ptr = _pico_ptr_malloc(num*size);
109 /* zero out allocated memory */
110 memset(ptr,0,num*size);
112 /* return pointer to allocated memory */
117 * memory reallocation wrapper (note: only grows,
118 * but never shrinks or frees)
120 void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize )
127 if( newSize < oldSize )
129 if (_pico_ptr_malloc == NULL)
132 /* allocate new pointer */
133 ptr2 = _pico_alloc( newSize );
140 memcpy( ptr2, *ptr, oldSize );
144 /* fix up and return */
149 /* _pico_clone_alloc:
150 * handy function for quick string allocation/copy. it clones
151 * the given string and returns a pointer to the new allocated
152 * clone (which must be freed by caller of course) or returns
153 * NULL on memory alloc or param errors. if 'size' is -1 the
154 * length of the input string is used, otherwise 'size' is used
155 * as custom clone size (the string is cropped to fit into mem
158 char *_pico_clone_alloc( const char *str )
166 /* allocate memory */
167 cloned = _pico_alloc( strlen(str) + 1 );
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)
189 /* free the allocated memory */
190 _pico_ptr_free( ptr );
194 * wrapper around the loadfile function pointer
196 void _pico_load_file( char *name, unsigned char **buffer, int *bufSize )
204 if (_pico_ptr_load_file == NULL)
209 /* do the actual call to read in the file; */
210 /* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
211 _pico_ptr_load_file( name,buffer,bufSize );
215 * wrapper around the file free function pointer
217 void _pico_free_file( void *buffer )
223 /* use default free */
224 if( _pico_ptr_free_file == NULL )
229 /* free the allocated file */
230 _pico_ptr_free_file( buffer );
234 * wrapper around the print function pointer -sea
236 void _pico_printf( int level, const char *format, ...)
244 if (_pico_ptr_print == NULL)
248 va_start( argptr,format );
249 vsprintf( str,format,argptr );
252 /* remove linefeeds */
253 if (str[ strlen(str)-1 ] == '\n')
254 str[ strlen(str)-1 ] = '\0';
256 /* do the actual call */
257 _pico_ptr_print( level,str );
260 /* _pico_first_token:
261 * trims everything after the first whitespace-delimited token
264 void _pico_first_token( char *str )
268 while( *str && !isspace( *str ) )
274 * left trims the given string -sea
276 char *_pico_strltrim( char *str )
278 char *str1 = str, *str2 = str;
280 while (isspace(*str2)) str2++;
282 while( *str2 != '\0' ) /* fix: ydnar */
288 * right trims the given string -sea
290 char *_pico_strrtrim( char *str )
299 if (allspace && !isspace(*str1)) allspace = 0;
302 if (allspace) *str = '\0';
305 while ((isspace(*str1)) && (str1 >= str))
313 * pico internal string-to-lower routine.
315 char *_pico_strlwr( char *str )
318 for (cp=str; *cp; ++cp)
320 if ('A' <= *cp && *cp <= 'Z')
329 * counts how often the given char appears in str. -sea
331 int _pico_strchcount( char *str, int ch )
334 while (*str++) if (*str == ch) count++;
338 void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs )
348 void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs )
354 if (value < mins[i]) mins[i] = value;
355 if (value > maxs[i]) maxs[i] = value;
359 void _pico_zero_vec( picoVec3_t vec )
361 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
364 void _pico_zero_vec2( picoVec2_t vec )
366 vec[ 0 ] = vec[ 1 ] = 0;
369 void _pico_zero_vec4( picoVec4_t vec )
371 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
374 void _pico_set_vec( picoVec3_t v, float a, float b, float c )
381 void _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d )
389 void _pico_copy_vec( picoVec3_t src, picoVec3_t dest )
391 dest[ 0 ] = src[ 0 ];
392 dest[ 1 ] = src[ 1 ];
393 dest[ 2 ] = src[ 2 ];
396 void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest )
398 dest[ 0 ] = src[ 0 ];
399 dest[ 1 ] = src[ 1 ];
402 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 )
415 len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
416 if( len == 0.0 ) return 0.0;
418 vec[ 0 ] *= (picoVec_t) ilen;
419 vec[ 1 ] *= (picoVec_t) ilen;
420 vec[ 2 ] *= (picoVec_t) ilen;
421 return (picoVec_t) len;
424 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 )
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 )
440 dest[ 0 ] = v[ 0 ] * scale;
441 dest[ 1 ] = v[ 1 ] * scale;
442 dest[ 2 ] = v[ 2 ] * scale;
445 void _pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest )
447 dest[ 0 ] = v[ 0 ] * scale;
448 dest[ 1 ] = v[ 1 ] * scale;
449 dest[ 2 ] = v[ 2 ] * scale;
450 dest[ 3 ] = v[ 3 ] * scale;
453 picoVec_t _pico_dot_vec( picoVec3_t a, picoVec3_t b )
455 return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
458 void _pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
460 dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
461 dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
462 dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
465 picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c )
469 _pico_subtract_vec( b, a, ba );
470 _pico_subtract_vec( c, a, ca );
471 _pico_cross_vec( ca, ba, plane );
472 plane[ 3 ] = _pico_dot_vec( a, plane );
473 return _pico_normalize_vec( plane );
476 /* separate from _pico_set_vec4 */
477 void _pico_set_color( picoColor_t c, int r, int g, int b, int a )
485 void _pico_copy_color( picoColor_t src, picoColor_t dest )
487 dest[ 0 ] = src[ 0 ];
488 dest[ 1 ] = src[ 1 ];
489 dest[ 2 ] = src[ 2 ];
490 dest[ 3 ] = src[ 3 ];
493 #ifdef __BIG_ENDIAN__
495 int _pico_big_long ( int src ) { return src; }
496 short _pico_big_short( short src ) { return src; }
497 float _pico_big_float( float src ) { return src; }
499 int _pico_little_long( int src )
501 return ((src & 0xFF000000) >> 24) |
502 ((src & 0x00FF0000) >> 8) |
503 ((src & 0x0000FF00) << 8) |
504 ((src & 0x000000FF) << 24);
507 short _pico_little_short( short src )
509 return ((src & 0xFF00) >> 8) |
510 ((src & 0x00FF) << 8);
513 float _pico_little_float( float src )
515 floatSwapUnion in,out;
517 out.c[ 0 ] = in.c[ 3 ];
518 out.c[ 1 ] = in.c[ 2 ];
519 out.c[ 2 ] = in.c[ 1 ];
520 out.c[ 3 ] = in.c[ 0 ];
523 #else /*__BIG_ENDIAN__*/
525 int _pico_little_long ( int src ) { return src; }
526 short _pico_little_short( short src ) { return src; }
527 float _pico_little_float( float src ) { return src; }
529 int _pico_big_long( int src )
531 return ((src & 0xFF000000) >> 24) |
532 ((src & 0x00FF0000) >> 8) |
533 ((src & 0x0000FF00) << 8) |
534 ((src & 0x000000FF) << 24);
537 short _pico_big_short( short src )
539 return ((src & 0xFF00) >> 8) |
540 ((src & 0x00FF) << 8);
543 float _pico_big_float( float src )
545 floatSwapUnion in,out;
547 out.c[ 0 ] = in.c[ 3 ];
548 out.c[ 1 ] = in.c[ 2 ];
549 out.c[ 2 ] = in.c[ 1 ];
550 out.c[ 3 ] = in.c[ 0 ];
553 #endif /*__BIG_ENDIAN__*/
556 * case-insensitive strstr. -sea
558 char *_pico_stristr( char *str, const char *substr )
560 const size_t sublen = strlen(substr);
563 if (!_pico_strnicmp(str,substr,sublen)) break;
566 if (!(*str)) str = NULL;
572 changes dos \ style path separators to /
575 void _pico_unixify( char *path )
588 * removes file name portion from given file path and converts
589 * the directory separators to un*x style. returns 1 on success
590 * or 0 when 'destSize' was exceeded. -sea
592 int _pico_nofname( const char *path, char *dest, int destSize )
597 while ((*dest = *path) != '\0')
599 if (*dest == '/' || *dest == '\\')
617 * returns ptr to filename portion in given path or an empty
618 * string otherwise. given 'path' is not altered. -sea
620 const char *_pico_nopath( const char *path )
623 src = path + (strlen(path) - 1);
625 if (path == NULL) return "";
626 if (!strchr(path,'/') && !strchr(path,'\\'))
629 while ((src--) != path)
631 if (*src == '/' || *src == '\\')
638 * sets/changes the file extension for the given filename
639 * or filepath's filename portion. the given 'path' *is*
640 * altered. leave 'ext' empty to remove extension. -sea
642 char *_pico_setfext( char *path, const char *ext )
647 src = path + (strlen(path) - 1);
649 if (ext == NULL) ext = "";
650 if (strlen(ext ) < 1) remfext = 1;
651 if (strlen(path) < 1)
654 while ((src--) != path)
656 if (*src == '/' || *src == '\\')
675 * extracts one line from the given buffer and stores it in dest.
676 * returns -1 on error or the length of the line on success. i've
677 * removed string trimming here. this can be done manually by the
680 int _pico_getline( char *buf, int bufsize, char *dest, int destsize )
685 if (dest == NULL || destsize < 1) return -1;
686 memset( dest,0,destsize );
689 if (buf == NULL || bufsize < 1)
693 for (pos=0; pos<bufsize && pos<destsize; pos++)
695 if (buf[pos] == '\n') { pos++; break; }
696 dest[pos] = buf[pos];
698 /* terminate dest and return */
703 /* _pico_parse_skip_white:
704 * skips white spaces in current pico parser, sets *hasLFs
705 * to 1 if linefeeds were skipped, and either returns the
706 * parser's cursor pointer or NULL on error. -sea
708 void _pico_parse_skip_white( picoParser_t *p, int *hasLFs )
711 if (p == NULL || p->cursor == NULL)
714 /* skin white spaces */
718 if (p->cursor < p->buffer ||
723 /* break for chars other than white spaces */
724 if (*p->cursor > 0x20) break;
725 if (*p->cursor == 0x00) return;
727 /* a bit of linefeed handling */
728 if (*p->cursor == '\n')
733 /* go to next character */
739 * allocates a new ascii parser object.
741 picoParser_t *_pico_new_parser( picoByte_t *buffer, int bufSize )
746 if( buffer == NULL || bufSize <= 0 )
749 /* allocate reader */
750 p = _pico_alloc( sizeof(picoParser_t) );
751 if (p == NULL) return NULL;
752 memset( p,0,sizeof(picoParser_t) );
754 /* allocate token space */
757 p->token = _pico_alloc( p->tokenMax );
758 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 )
780 if (p == NULL) return;
782 /* free the parser */
783 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 )
804 if( p == NULL || p->buffer == NULL ||
805 p->cursor < p->buffer ||
806 p->cursor >= p->max )
810 /* clear parser token */
812 p->token[ 0 ] = '\0';
815 /* skip whitespaces */
816 while( p->cursor < p->max && *p->cursor <= 32 )
818 if (*p->cursor == '\n')
825 /* return if we're not allowed to go beyond lfs */
826 if ((hasLFs > 0) && !allowLFs)
831 /* get next quoted string */
832 if (*p->cursor == '\"' && handleQuoted)
835 while (p->cursor < p->max && *p->cursor)
837 if (*p->cursor == '\\')
839 if (*(p->cursor+1) == '"')
843 p->token[ p->tokenSize++ ] = *p->cursor++;
846 else if (*p->cursor == '\"')
851 else if (*p->cursor == '\n')
855 p->token[ p->tokenSize++ ] = *p->cursor++;
857 /* terminate token */
858 p->token[ p->tokenSize ] = '\0';
861 /* otherwise get next word */
862 while( p->cursor < p->max && *p->cursor > 32 )
864 if (*p->cursor == '\n')
868 p->token[ p->tokenSize++ ] = *p->cursor++;
870 /* terminate token */
871 p->token[ p->tokenSize ] = '\0';
875 /* _pico_parse_first:
876 * reads the first token from the next line and returns
877 * a pointer to it. returns NULL on EOL or EOF. -sea
879 char *_pico_parse_first( picoParser_t *p )
882 if (p == NULL) return NULL;
884 /* try to read next token (with lfs & quots) */
885 if (!_pico_parse_ex( p,1,1 ))
888 /* return ptr to the token string */
893 * reads the next token from the parser and returns a pointer
894 * to it. quoted strings are handled as usual. returns NULL
895 * on EOL or EOF. -sea
897 char *_pico_parse( picoParser_t *p, int allowLFs )
900 if (p == NULL) return NULL;
902 /* try to read next token (with quots) */
903 if (!_pico_parse_ex( p,allowLFs,1 ))
906 /* return ptr to the token string */
910 /* _pico_parse_skip_rest:
911 * skips the rest of the current line in parser.
913 void _pico_parse_skip_rest( picoParser_t *p )
915 while( _pico_parse_ex( p,0,0 ) ) ;
918 /* _pico_parse_skip_braced:
919 * parses/skips over a braced section. returns 1 on success
920 * or 0 on error (when there was no closing bracket and the
921 * end of buffer was reached or when the opening bracket was
924 int _pico_parse_skip_braced( picoParser_t *p )
930 if (p == NULL) return 0;
932 /* set the initial level for parsing */
935 /* skip braced section */
938 /* read next token (lfs allowed) */
939 if (!_pico_parse_ex( p,1,1 ))
941 /* end of parser buffer reached */
944 /* first token must be an opening bracket */
945 if (firstToken && p->token[0] != '{')
947 /* opening bracket missing */
950 /* we only check this once */
954 if (p->token[1] == '\0')
956 if (p->token[0] == '{') level++;
957 if (p->token[0] == '}') level--;
959 /* break if we're back at our starting level */
960 if (level == 0) break;
962 /* successfully skipped braced section */
966 int _pico_parse_check( picoParser_t *p, int allowLFs, char *str )
968 if (!_pico_parse_ex( p,allowLFs,1 ))
970 if (!strcmp(p->token,str))
975 int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str )
977 if (!_pico_parse_ex( p,allowLFs,1 ))
979 if (!_pico_stricmp(p->token,str))
984 int _pico_parse_int( picoParser_t *p, int *out )
989 if (p == NULL || out == NULL)
992 /* get token and turn it into an integer */
994 token = _pico_parse( p,0 );
995 if (token == NULL) return 0;
996 *out = atoi( token );
1002 int _pico_parse_int_def( picoParser_t *p, int *out, int def )
1007 if (p == NULL || out == NULL)
1010 /* get token and turn it into an integer */
1012 token = _pico_parse( p,0 );
1013 if (token == NULL) return 0;
1014 *out = atoi( token );
1020 int _pico_parse_float( picoParser_t *p, float *out )
1025 if (p == NULL || out == NULL)
1028 /* get token and turn it into a float */
1030 token = _pico_parse( p,0 );
1031 if (token == NULL) return 0;
1032 *out = (float) atof( token );
1038 int _pico_parse_float_def( picoParser_t *p, float *out, float def )
1043 if (p == NULL || out == NULL)
1046 /* get token and turn it into a float */
1048 token = _pico_parse( p,0 );
1049 if (token == NULL) return 0;
1050 *out = (float) atof( token );
1056 int _pico_parse_vec( picoParser_t *p, picoVec3_t out )
1062 if (p == NULL || out == NULL)
1065 /* zero out outination vector */
1066 _pico_zero_vec( out );
1068 /* parse three vector components */
1071 token = _pico_parse( p,0 );
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 )
1089 if (p == NULL || out == NULL)
1092 /* assign default vector value */
1093 _pico_copy_vec( def,out );
1095 /* parse three vector components */
1098 token = _pico_parse( p,0 );
1101 _pico_copy_vec( def,out );
1104 out[ i ] = (float) atof( token );
1110 int _pico_parse_vec2( picoParser_t *p, picoVec2_t out )
1116 if (p == NULL || out == NULL)
1119 /* zero out outination vector */
1120 _pico_zero_vec2( out );
1122 /* parse two vector components */
1125 token = _pico_parse( p,0 );
1128 _pico_zero_vec2( out );
1131 out[ i ] = (float) atof( token );
1137 int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def )
1143 if (p == NULL || out == NULL)
1146 /* assign default vector value */
1147 _pico_copy_vec2( def,out );
1149 /* parse two vector components */
1152 token = _pico_parse( p,0 );
1155 _pico_copy_vec2( def,out );
1158 out[ i ] = (float) atof( token );
1164 int _pico_parse_vec4( picoParser_t *p, picoVec4_t out )
1170 if (p == NULL || out == NULL)
1173 /* zero out outination vector */
1174 _pico_zero_vec4( out );
1176 /* parse four vector components */
1179 token = _pico_parse( p,0 );
1182 _pico_zero_vec4( out );
1185 out[ i ] = (float) atof( token );
1191 int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def )
1197 if (p == NULL || out == NULL)
1200 /* assign default vector value */
1201 _pico_copy_vec4( def,out );
1203 /* parse four vector components */
1206 token = _pico_parse( p,0 );
1209 _pico_copy_vec4( def,out );
1212 out[ i ] = (float) atof( token );
1218 /* _pico_new_memstream:
1219 * allocates a new memorystream object.
1221 picoMemStream_t *_pico_new_memstream( picoByte_t *buffer, int bufSize )
1226 if( buffer == NULL || bufSize <= 0 )
1229 /* allocate stream */
1230 s = _pico_alloc( sizeof(picoMemStream_t) );
1231 if (s == NULL) return NULL;
1232 memset( s,0,sizeof(picoMemStream_t) );
1237 s->bufSize = bufSize;
1240 /* return ptr to stream */
1244 /* _pico_free_memstream:
1245 * frees an existing pico memorystream object.
1247 void _pico_free_memstream( picoMemStream_t *s )
1250 if (s == NULL) return;
1252 /* free the stream */
1256 /* _pico_memstream_read:
1257 * reads data from a pico memorystream into a buffer.
1259 int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len )
1264 if (s == NULL || buffer == NULL)
1267 if (s->curPos + len > s->buffer + s->bufSize)
1269 s->flag |= PICO_IOEOF;
1270 len = s->buffer + s->bufSize - s->curPos;
1275 memcpy( buffer, s->curPos, len );
1280 /* _pico_memstream_read:
1281 * reads a character from a pico memorystream
1283 int _pico_memstream_getc( picoMemStream_t *s )
1291 /* read the character */
1292 if (_pico_memstream_read( s, &c, 1) == 0)
1298 /* _pico_memstream_seek:
1299 * sets the current read position to a different location
1301 int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin )
1309 if (origin == PICO_SEEK_SET)
1311 s->curPos = s->buffer + offset;
1312 overflow = s->curPos - ( s->buffer + s->bufSize );
1315 s->curPos = s->buffer + s->bufSize;
1316 return offset - overflow;
1320 else if (origin == PICO_SEEK_CUR)
1322 s->curPos += offset;
1323 overflow = s->curPos - ( s->buffer + s->bufSize );
1326 s->curPos = s->buffer + s->bufSize;
1327 return offset - overflow;
1331 else if (origin == PICO_SEEK_END)
1333 s->curPos = ( s->buffer + s->bufSize ) - offset;
1334 overflow = s->buffer - s->curPos;
1337 s->curPos = s->buffer;
1338 return offset - overflow;
1346 /* _pico_memstream_tell:
1347 * returns the current read position in the pico memorystream
1349 long _pico_memstream_tell( picoMemStream_t *s )
1355 return s->curPos - s->buffer;