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( char *str, int size )
164 if (str == NULL) return NULL;
166 /* set real size of cloned string */
167 cloneSize = (size < 0) ? strlen(str) : size;
169 /* allocate memory */
170 cloned = _pico_alloc( cloneSize+1 ); /* bugfix! */
174 /* zero out memory allocated by cloned string */
175 memset( cloned,0,cloneSize );
177 /* copy input string to cloned string */
178 if (cloneSize < strlen( str )) {
179 memcpy( cloned,str,cloneSize );
180 cloned[ cloneSize ] = '\0';
182 strcpy( cloned,str );
184 /* return ptr to cloned string */
189 * wrapper around the free function pointer
191 void _pico_free( void *ptr )
196 if (_pico_ptr_free == NULL)
199 /* free the allocated memory */
200 _pico_ptr_free( ptr );
204 * wrapper around the loadfile function pointer
206 void _pico_load_file( char *name, unsigned char **buffer, int *bufSize )
214 if (_pico_ptr_load_file == NULL)
219 /* do the actual call to read in the file; */
220 /* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
221 _pico_ptr_load_file( name,buffer,bufSize );
225 * wrapper around the file free function pointer
227 void _pico_free_file( void *buffer )
233 /* use default free */
234 if( _pico_ptr_free_file == NULL )
239 /* free the allocated file */
240 _pico_ptr_free_file( buffer );
244 * wrapper around the print function pointer -sea
246 void _pico_printf( int level, const char *format, ...)
254 if (_pico_ptr_print == NULL)
258 va_start( argptr,format );
259 vsprintf( str,format,argptr );
262 /* remove linefeeds */
263 if (str[ strlen(str)-1 ] == '\n')
264 str[ strlen(str)-1 ] = '\0';
266 /* do the actual call */
267 _pico_ptr_print( level,str );
271 * left trims the given string -sea
273 char *_pico_strltrim( char *str )
275 char *str1 = str, *str2 = str;
277 while (isspace(*str2)) str2++;
279 while( *str2 != '\0' ) /* fix: ydnar */
285 * right trims the given string -sea
287 char *_pico_strrtrim( char *str )
296 if (allspace && !isspace(*str1)) allspace = 0;
299 if (allspace) *str = '\0';
302 while ((isspace(*str1)) && (str1 >= str))
310 * pico internal string-to-lower routine.
312 char *_pico_strlwr( char *str )
315 for (cp=str; *cp; ++cp)
317 if ('A' <= *cp && *cp <= 'Z')
326 * counts how often the given char appears in str. -sea
328 int _pico_strchcount( char *str, int ch )
331 while (*str++) if (*str == ch) count++;
335 void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs )
345 void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs )
351 if (value < mins[i]) mins[i] = value;
352 if (value > maxs[i]) maxs[i] = value;
356 void _pico_zero_vec( picoVec3_t vec )
358 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
361 void _pico_zero_vec2( picoVec2_t vec )
363 vec[ 0 ] = vec[ 1 ] = 0;
366 void _pico_zero_vec4( picoVec4_t vec )
368 vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
371 void _pico_set_vec( picoVec3_t v, float a, float b, float c )
378 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 )
388 dest[ 0 ] = src[ 0 ];
389 dest[ 1 ] = src[ 1 ];
390 dest[ 2 ] = src[ 2 ];
393 void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest )
395 dest[ 0 ] = src[ 0 ];
396 dest[ 1 ] = src[ 1 ];
399 void _pico_copy_vec4( picoVec4_t src, picoVec4_t dest )
401 dest[ 0 ] = src[ 0 ];
402 dest[ 1 ] = src[ 1 ];
403 dest[ 2 ] = src[ 2 ];
404 dest[ 3 ] = src[ 3 ];
408 picoVec_t _pico_normalize_vec( picoVec3_t vec )
412 len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
413 if( len == 0.0 ) return 0.0;
415 vec[ 0 ] *= (picoVec_t) ilen;
416 vec[ 1 ] *= (picoVec_t) ilen;
417 vec[ 2 ] *= (picoVec_t) ilen;
418 return (picoVec_t) len;
421 void _pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
423 dest[ 0 ] = a[ 0 ] + b[ 0 ];
424 dest[ 1 ] = a[ 1 ] + b[ 1 ];
425 dest[ 2 ] = a[ 2 ] + b[ 2 ];
428 void _pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
430 dest[ 0 ] = a[ 0 ] - b[ 0 ];
431 dest[ 1 ] = a[ 1 ] - b[ 1 ];
432 dest[ 2 ] = a[ 2 ] - b[ 2 ];
435 void _pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest )
437 dest[ 0 ] = v[ 0 ] * scale;
438 dest[ 1 ] = v[ 1 ] * scale;
439 dest[ 2 ] = v[ 2 ] * scale;
442 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 )
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 )
457 dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
458 dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
459 dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
462 picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c )
466 _pico_subtract_vec( b, a, ba );
467 _pico_subtract_vec( c, a, ca );
468 _pico_cross_vec( ca, ba, plane );
469 plane[ 3 ] = _pico_dot_vec( a, plane );
470 return _pico_normalize_vec( plane );
473 /* separate from _pico_set_vec4 */
474 void _pico_set_color( picoColor_t c, int r, int g, int b, int a )
482 void _pico_copy_color( picoColor_t src, picoColor_t dest )
484 dest[ 0 ] = src[ 0 ];
485 dest[ 1 ] = src[ 1 ];
486 dest[ 2 ] = src[ 2 ];
487 dest[ 3 ] = src[ 3 ];
490 #ifdef __BIG_ENDIAN__
492 int _pico_big_long ( int src ) { return src; }
493 short _pico_big_short( short src ) { return src; }
494 float _pico_big_float( float src ) { return src; }
496 int _pico_little_long( int src )
498 return ((src & 0xFF000000) >> 24) |
499 ((src & 0x00FF0000) >> 8) |
500 ((src & 0x0000FF00) << 8) |
501 ((src & 0x000000FF) << 24);
504 short _pico_little_short( short src )
506 return ((src & 0xFF00) >> 8) |
507 ((src & 0x00FF) << 8);
510 float _pico_little_float( float src )
512 floatSwapUnion in,out;
514 out.c[ 0 ] = in.c[ 3 ];
515 out.c[ 1 ] = in.c[ 2 ];
516 out.c[ 2 ] = in.c[ 1 ];
517 out.c[ 3 ] = in.c[ 0 ];
520 #else /*__BIG_ENDIAN__*/
522 int _pico_little_long ( int src ) { return src; }
523 short _pico_little_short( short src ) { return src; }
524 float _pico_little_float( float src ) { return src; }
526 int _pico_big_long( int src )
528 return ((src & 0xFF000000) >> 24) |
529 ((src & 0x00FF0000) >> 8) |
530 ((src & 0x0000FF00) << 8) |
531 ((src & 0x000000FF) << 24);
534 short _pico_big_short( short src )
536 return ((src & 0xFF00) >> 8) |
537 ((src & 0x00FF) << 8);
540 float _pico_big_float( float src )
542 floatSwapUnion in,out;
544 out.c[ 0 ] = in.c[ 3 ];
545 out.c[ 1 ] = in.c[ 2 ];
546 out.c[ 2 ] = in.c[ 1 ];
547 out.c[ 3 ] = in.c[ 0 ];
550 #endif /*__BIG_ENDIAN__*/
553 * case-insensitive strstr. -sea
555 char *_pico_stristr( char *str, const char *substr )
557 const int sublen = strlen(substr);
560 if (!_pico_strnicmp(str,substr,sublen)) break;
563 if (!(*str)) str = NULL;
569 changes dos \ style path separators to /
572 void _pico_unixify( char *path )
585 * removes file name portion from given file path and converts
586 * the directory separators to un*x style. returns 1 on success
587 * or 0 when 'destSize' was exceeded. -sea
589 int _pico_nofname( const char *path, char *dest, int destSize )
594 while ((*dest = *path) != '\0')
596 if (*dest == '/' || *dest == '\\')
614 * returns ptr to filename portion in given path or an empty
615 * string otherwise. given 'path' is not altered. -sea
617 char *_pico_nopath( const char *path )
620 src = (char *)path + (strlen(path) - 1);
622 if (path == NULL) return (char *)"";
623 if (!strchr((char *)path,'/') && !strchr((char *)path,'\\'))
624 return ((char *)path);
626 while ((src--) != path)
628 if (*src == '/' || *src == '\\')
635 * sets/changes the file extension for the given filename
636 * or filepath's filename portion. the given 'path' *is*
637 * altered. leave 'ext' empty to remove extension. -sea
639 char *_pico_setfext( char *path, const char *ext )
644 src = path + (strlen(path) - 1);
646 if (ext == NULL) ext = "";
647 if (strlen(ext ) < 1) remfext = 1;
648 if (strlen(path) < 1)
651 while ((src--) != path)
653 if (*src == '/' || *src == '\\')
672 * extracts one line from the given buffer and stores it in dest.
673 * returns -1 on error or the length of the line on success. i've
674 * removed string trimming here. this can be done manually by the
677 int _pico_getline( char *buf, int bufsize, char *dest, int destsize )
682 if (dest == NULL || destsize < 1) return -1;
683 memset( dest,0,destsize );
686 if (buf == NULL || bufsize < 1)
690 for (pos=0; pos<bufsize && pos<destsize; pos++)
692 if (buf[pos] == '\n') { pos++; break; }
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 )
708 if (p == NULL || p->cursor == NULL)
711 /* skin white spaces */
715 if (p->cursor < p->buffer ||
720 /* break for chars other than white spaces */
721 if (*p->cursor > 0x20) break;
722 if (*p->cursor == 0x00) return;
724 /* a bit of linefeed handling */
725 if (*p->cursor == '\n')
730 /* go to next character */
736 * allocates a new ascii parser object.
738 picoParser_t *_pico_new_parser( picoByte_t *buffer, int bufSize )
743 if( buffer == NULL || bufSize <= 0 )
746 /* allocate reader */
747 p = _pico_alloc( sizeof(picoParser_t) );
748 if (p == NULL) return NULL;
749 memset( p,0,sizeof(picoParser_t) );
751 /* allocate token space */
754 p->token = _pico_alloc( p->tokenMax );
755 if( p->token == NULL )
763 p->bufSize = bufSize;
764 p->max = p->buffer + bufSize;
765 p->curLine = 1; /* sea: new */
767 /* return ptr to parser */
771 /* _pico_free_parser:
772 * frees an existing pico parser object.
774 void _pico_free_parser( picoParser_t *p )
777 if (p == NULL) return;
779 /* free the parser */
780 if (p->token != NULL)
782 _pico_free( p->token );
788 * reads the next token from given pico parser object. if param
789 * 'allowLFs' is 1 it will read beyond linefeeds and return 0 when
790 * the EOF is reached. if 'allowLFs' is 0 it will return 0 when
791 * the EOL is reached. if 'handleQuoted' is 1 the parser function
792 * will handle "quoted" strings and return the data between the
793 * quotes as token. returns 0 on end/error or 1 on success. -sea
795 int _pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted )
801 if( p == NULL || p->buffer == NULL ||
802 p->cursor < p->buffer ||
803 p->cursor >= p->max )
807 /* clear parser token */
809 p->token[ 0 ] = '\0';
812 /* skip whitespaces */
813 while( p->cursor < p->max && *p->cursor <= 32 )
815 if (*p->cursor == '\n')
822 /* return if we're not allowed to go beyond lfs */
823 if ((hasLFs > 0) && !allowLFs)
828 /* get next quoted string */
829 if (*p->cursor == '\"' && handleQuoted)
832 while (p->cursor < p->max && *p->cursor)
834 if (*p->cursor == '\\')
836 if (*(p->cursor+1) == '"')
840 p->token[ p->tokenSize++ ] = *p->cursor++;
843 else if (*p->cursor == '\"')
848 else if (*p->cursor == '\n')
852 p->token[ p->tokenSize++ ] = *p->cursor++;
854 /* terminate token */
855 p->token[ p->tokenSize ] = '\0';
858 /* otherwise get next word */
859 while( p->cursor < p->max && *p->cursor > 32 )
861 if (*p->cursor == '\n')
865 p->token[ p->tokenSize++ ] = *p->cursor++;
867 /* terminate token */
868 p->token[ p->tokenSize ] = '\0';
872 /* _pico_parse_first:
873 * reads the first token from the next line and returns
874 * a pointer to it. returns NULL on EOL or EOF. -sea
876 char *_pico_parse_first( picoParser_t *p )
879 if (p == NULL) return NULL;
881 /* try to read next token (with lfs & quots) */
882 if (!_pico_parse_ex( p,1,1 ))
885 /* return ptr to the token string */
890 * reads the next token from the parser and returns a pointer
891 * to it. quoted strings are handled as usual. returns NULL
892 * on EOL or EOF. -sea
894 char *_pico_parse( picoParser_t *p, int allowLFs )
897 if (p == NULL) return NULL;
899 /* try to read next token (with quots) */
900 if (!_pico_parse_ex( p,allowLFs,1 ))
903 /* return ptr to the token string */
907 /* _pico_parse_skip_rest:
908 * skips the rest of the current line in parser.
910 void _pico_parse_skip_rest( picoParser_t *p )
912 while( _pico_parse_ex( p,0,0 ) ) ;
915 /* _pico_parse_skip_braced:
916 * parses/skips over a braced section. returns 1 on success
917 * or 0 on error (when there was no closing bracket and the
918 * end of buffer was reached or when the opening bracket was
921 int _pico_parse_skip_braced( picoParser_t *p )
927 if (p == NULL) return 0;
929 /* set the initial level for parsing */
932 /* skip braced section */
935 /* read next token (lfs allowed) */
936 if (!_pico_parse_ex( p,1,1 ))
938 /* end of parser buffer reached */
941 /* first token must be an opening bracket */
942 if (firstToken && p->token[0] != '{')
944 /* opening bracket missing */
947 /* we only check this once */
951 if (p->token[1] == '\0')
953 if (p->token[0] == '{') level++;
954 if (p->token[0] == '}') level--;
956 /* break if we're back at our starting level */
957 if (level == 0) break;
959 /* successfully skipped braced section */
963 int _pico_parse_check( picoParser_t *p, int allowLFs, char *str )
965 if (!_pico_parse_ex( p,allowLFs,1 ))
967 if (!strcmp(p->token,str))
972 int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str )
974 if (!_pico_parse_ex( p,allowLFs,1 ))
976 if (!_pico_stricmp(p->token,str))
981 int _pico_parse_int( picoParser_t *p, int *out )
986 if (p == NULL || out == NULL)
989 /* get token and turn it into an integer */
991 token = _pico_parse( p,0 );
992 if (token == NULL) return 0;
993 *out = atoi( token );
999 int _pico_parse_int_def( picoParser_t *p, int *out, int def )
1004 if (p == NULL || out == NULL)
1007 /* get token and turn it into an integer */
1009 token = _pico_parse( p,0 );
1010 if (token == NULL) return 0;
1011 *out = atoi( token );
1017 int _pico_parse_float( picoParser_t *p, float *out )
1022 if (p == NULL || out == NULL)
1025 /* get token and turn it into a float */
1027 token = _pico_parse( p,0 );
1028 if (token == NULL) return 0;
1029 *out = (float) atof( token );
1035 int _pico_parse_float_def( picoParser_t *p, float *out, float def )
1040 if (p == NULL || out == NULL)
1043 /* get token and turn it into a float */
1045 token = _pico_parse( p,0 );
1046 if (token == NULL) return 0;
1047 *out = (float) atof( token );
1053 int _pico_parse_vec( picoParser_t *p, picoVec3_t out )
1059 if (p == NULL || out == NULL)
1062 /* zero out outination vector */
1063 _pico_zero_vec( out );
1065 /* parse three vector components */
1068 token = _pico_parse( p,0 );
1071 _pico_zero_vec( out );
1074 out[ i ] = (float) atof( token );
1080 int _pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def )
1086 if (p == NULL || out == NULL)
1089 /* assign default vector value */
1090 _pico_copy_vec( def,out );
1092 /* parse three vector components */
1095 token = _pico_parse( p,0 );
1098 _pico_copy_vec( def,out );
1101 out[ i ] = (float) atof( token );
1107 int _pico_parse_vec2( picoParser_t *p, picoVec2_t out )
1113 if (p == NULL || out == NULL)
1116 /* zero out outination vector */
1117 _pico_zero_vec2( out );
1119 /* parse two vector components */
1122 token = _pico_parse( p,0 );
1125 _pico_zero_vec2( out );
1128 out[ i ] = (float) atof( token );
1134 int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def )
1140 if (p == NULL || out == NULL)
1143 /* assign default vector value */
1144 _pico_copy_vec2( def,out );
1146 /* parse two vector components */
1149 token = _pico_parse( p,0 );
1152 _pico_copy_vec2( def,out );
1155 out[ i ] = (float) atof( token );
1161 int _pico_parse_vec4( picoParser_t *p, picoVec4_t out )
1167 if (p == NULL || out == NULL)
1170 /* zero out outination vector */
1171 _pico_zero_vec4( out );
1173 /* parse four vector components */
1176 token = _pico_parse( p,0 );
1179 _pico_zero_vec4( out );
1182 out[ i ] = (float) atof( token );
1188 int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def )
1194 if (p == NULL || out == NULL)
1197 /* assign default vector value */
1198 _pico_copy_vec4( def,out );
1200 /* parse four vector components */
1203 token = _pico_parse( p,0 );
1206 _pico_copy_vec4( def,out );
1209 out[ i ] = (float) atof( token );
1215 /* _pico_new_memstream:
1216 * allocates a new memorystream object.
1218 picoMemStream_t *_pico_new_memstream( picoByte_t *buffer, int bufSize )
1223 if( buffer == NULL || bufSize <= 0 )
1226 /* allocate stream */
1227 s = _pico_alloc( sizeof(picoMemStream_t) );
1228 if (s == NULL) return NULL;
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 )
1247 if (s == NULL) return;
1249 /* free the stream */
1253 /* _pico_memstream_read:
1254 * reads data from a pico memorystream into a buffer.
1256 int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len )
1261 if (s == NULL || buffer == NULL)
1264 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)
1295 /* _pico_memstream_seek:
1296 * sets the current read position to a different location
1298 int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin )
1306 if (origin == PICO_SEEK_SET)
1308 s->curPos = s->buffer + offset;
1309 overflow = s->curPos - ( s->buffer + s->bufSize );
1312 s->curPos = s->buffer + s->bufSize;
1313 return offset - overflow;
1317 else if (origin == PICO_SEEK_CUR)
1319 s->curPos += offset;
1320 overflow = s->curPos - ( s->buffer + s->bufSize );
1323 s->curPos = s->buffer + s->bufSize;
1324 return offset - overflow;
1328 else if (origin == PICO_SEEK_END)
1330 s->curPos = ( s->buffer + s->bufSize ) - offset;
1331 overflow = s->buffer - s->curPos;
1334 s->curPos = s->buffer;
1335 return offset - overflow;
1343 /* _pico_memstream_tell:
1344 * returns the current read position in the pico memorystream
1346 long _pico_memstream_tell( picoMemStream_t *s )
1352 return s->curPos - s->buffer;