Check-in [25f6ecad04]

Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1 Hash:25f6ecad0414de989bb9251585df3a8c6bbb881c
Date: 2008-12-09 19:39:10
User: stephan
Comment:imported changes from c11n tree
Tags And Properties
Changes
hide diffs unified diffs patch

Changes to src/whclob.c

Old (87499aa26331a38f) New (d9e7955e3a226fc9)
1 #include <string.h> 1 #include <string.h>
2 #include <stdlib.h> 2 #include <stdlib.h>
3 #include <stdio.h> 3 #include <stdio.h>
4 #include <stdarg.h> 4 #include <stdarg.h>
5 5
115 hidden lines
121 else 121 else
122 { 122 {
123 whclob_appendf( dest, "=[NULL]", cb ); 123 whclob_appendf( dest, "=[NULL]", cb );
124 } 124 }
125 } 125 }
126 fappendf( stdout, "%s\n", whclob_buffer( dest ) ); | 126 fappendf( stderr, "%s\n", whclob_buffer( dest ) );
127 whclob_finalize( dest ); 127 whclob_finalize( dest );
128 } 128 }
129 129
130 130
131 long whclob_reset( whclob * cb ) 131 long whclob_reset( whclob * cb )
32 hidden lines
164 164
165 static long whclob_do_resize( whclob * cb, 165 static long whclob_do_resize( whclob * cb,
166 unsigned int sz, 166 unsigned int sz,
167 short usePolicyHint) 167 short usePolicyHint)
168 { 168 {
169 static const int fudge = 1; | 169 static const int fudge = 2;
170 char const * zOld = 0; 170 char const * zOld = 0;
171 long oldUsed = 0; 171 long oldUsed = 0;
172 long oldAlloc = 0; 172 long oldAlloc = 0;
173 long allocsize = 0; 173 long allocsize = 0;
174 char * pNew = 0; 174 char * pNew = 0;
78 hidden lines
253 char const * whclob_bufferc( whclob const * cb ) { return cb ? cb->aData : 0; } 253 char const * whclob_bufferc( whclob const * cb ) { return cb ? cb->aData : 0; }
254 254
255 long whclob_resize( whclob * cb, unsigned int sz ) 255 long whclob_resize( whclob * cb, unsigned int sz )
256 { 256 {
257 unsigned long ret = whclob_do_resize( cb, sz, 1 ); 257 unsigned long ret = whclob_do_resize( cb, sz, 1 );
258 if( ret >= sz ) | 258 if( sz && (ret >= sz) )
259 { 259 {
260 cb->nUsed = sz; 260 cb->nUsed = sz;
261 cb->aData[sz] = 0; 261 cb->aData[sz] = 0;
262 } 262 }
263 return ret; 263 return ret;
49 hidden lines
313 else 313 else
314 { 314 {
315 if( !n ) return whclob_rc.OK; 315 if( !n ) return whclob_rc.OK;
316 } 316 }
317 if( data && (n < 0) ) n = strlen( data ); 317 if( data && (n < 0) ) n = strlen( data );
> 318 #if 1
318 rc = whclob_reserve( *cb, n ); 319 rc = whclob_reserve( *cb, n );
> 320 //rc = whclob_resize( *cb, n );
319 if( rc < whclob_rc.OK ) 321 if( rc < whclob_rc.OK )
320 { 322 {
321 free( *cb ); 323 free( *cb );
322 *cb = 0; 324 *cb = 0;
323 return rc; 325 return rc;
324 } 326 }
325 if( data ) 327 if( data )
326 { 328 {
327 memcpy( (*cb)->aData, data, n ); 329 memcpy( (*cb)->aData, data, n );
328 } 330 }
> 331 #else
> 332 rc = whclob_append( *cb, data, n );
> 333 if( rc < whclob_rc.OK )
> 334 {
> 335 free( *cb );
> 336 *cb = 0;
> 337 return rc;
> 338 }
> 339 #endif
329 return whclob_rc.OK; 340 return whclob_rc.OK;
330 } 341 }
331 342
332 343
333 long whclob_seek( whclob * cb, long offset, int whence ) 344 long whclob_seek( whclob * cb, long offset, int whence )
117 hidden lines
451 462
452 463
453 long whclob_append( whclob * cb, char const * data, long dsize ) 464 long whclob_append( whclob * cb, char const * data, long dsize )
454 { 465 {
455 long old = cb->nUsed; 466 long old = cb->nUsed;
456 cb->nUsed += whclob_writeat( cb, cb->nUsed, data, dsize ); | 467 long rc = whclob_writeat( cb, cb->nUsed, data, dsize );
| 468 if( rc < whclob_rc.OK ) return rc;
| 469 cb->nUsed += rc;
| 470 //cb->aData[cb->nUsed] = 0;
| 471 whclob_null_terminate(cb);
457 return cb->nUsed - old; 472 return cb->nUsed - old;
458 } 473 }
459 474
460 long whclob_append_char_n( whclob * cb, char c, long n ) 475 long whclob_append_char_n( whclob * cb, char c, long n )
461 { 476 {
463 if( !cb || (n <= 0) ) return whclob_rc.RangeError; 478 if( !cb || (n <= 0) ) return whclob_rc.RangeError;
464 rc = whclob_reserve( cb, cb->nUsed + n ); 479 rc = whclob_reserve( cb, cb->nUsed + n );
465 if( rc < 0 ) return rc; 480 if( rc < 0 ) return rc;
466 memset( cb->aData + cb->nUsed, c, n ); 481 memset( cb->aData + cb->nUsed, c, n );
467 cb->nUsed += n; 482 cb->nUsed += n;
> 483 /* do we want to do a whclob_null_terminate() here? */
> 484 /* whclob_null_terminate(cb); */
468 return n; 485 return n;
469 } 486 }
470 487
471 488
472 long whclob_copy( whclob * src, whclob * dest ) 489 long whclob_copy( whclob * src, whclob * dest )
51 hidden lines
524 long whclob_truncate( whclob * cb, long pos, int memPolicy ) 541 long whclob_truncate( whclob * cb, long pos, int memPolicy )
525 { 542 {
526 long rc = 0; 543 long rc = 0;
527 if( ! cb ) return whclob_rc.UnexpectedNull; 544 if( ! cb ) return whclob_rc.UnexpectedNull;
528 /* if( cb->nUsed <= pos ) return whclob_rc.OK; */ 545 /* if( cb->nUsed <= pos ) return whclob_rc.OK; */
529 if( cb->nAlloc <= pos ) return whclob_rc.OK; | 546
530 cb->nUsed = pos; | 547 if( pos < cb->nAlloc )
531 rc = whclob_rc.OK; | 548 { /* adding a single \0 to the data isn't sufficient here. */
532 if( memPolicy > 0 ) | 549 memset( cb->aData + pos, 0, (cb->nAlloc-pos));
533 { | 550 }
534 rc = whclob_reserve( cb, cb->nUsed ); | 551
535 } | 552 if( cb->nAlloc <= pos )
536 else if( memPolicy < 0 ) | 553 {
| 554 //return whclob_rc.OK;
| 555 memPolicy = 1;
| 556 }
| 557 rc = whclob_rc.OK;
| 558 if( memPolicy > 0 )
| 559 {
| 560 rc = whclob_reserve( cb, pos );
| 561 }
| 562 else if( memPolicy < 0 )
| 563 {
| 564 #if 0
| 565 /* try a simple heuristic to calculate whether a
| 566 realloc is worth it... */
| 567 const long diff = (cb->nAlloc - pos);
| 568 const int rel = 4; /* ((diff) >= (cb->nAlloc/rel)) = do realloc */
| 569 const int abs = 512; /* (diff >= abs) = do realloc */
| 570 if(
| 571 ( diff >= abs )
| 572 ||
| 573 ((diff) >= (cb->nAlloc/rel) )
| 574 )
537 { 575 {
538 #if 1 | 576 /* rc = whclob_resize( cb, cb->nUsed ); */
539 /* try a simple heuristic to calculate whether a | 577 rc = whclob_do_resize( cb, pos, 0 );
540 realloc is worth it... */ |
541 const long diff = (cb->nAlloc - pos); |
542 const int rel = 4; /* ((diff) >= (cb->nAlloc/rel)) = do realloc */ |
543 const int abs = 512; /* (diff >= abs) = do realloc */ |
544 if( |
545 ( diff >= abs ) |
546 || |
547 ((diff) >= (cb->nAlloc/rel) ) |
548 ) |
549 { |
550 /* rc = whclob_resize( cb, cb->nUsed ); */ |
551 rc = whclob_do_resize( cb, cb->nUsed, 0 ); |
552 } |
553 #else |
554 MARKER("TRUNCATE alloc=%ld len=%ld\n", cb->nAlloc, cb->nUsed ); |
555 rc = whclob_resize( cb, cb->nUsed ); |
556 /* rc = whclob_do_resize( cb, cb->nUsed, 0 ); */ |
557 MARKER("TRUNCATED: alloc=%ld len=%ld, rc=%ld\n", cb->nAlloc, cb->nUsed, rc ); |
558 #endif |
559 } 578 }
560 whclob_null_terminate( cb ); | 579 #else
561 return rc; | 580 //MARKER("TRUNCATE alloc=%ld len=%ld\n", cb->nAlloc, cb->nUsed );
| 581 rc = whclob_resize( cb, pos );
| 582 /* rc = whclob_do_resize( cb, cb->nUsed, 0 ); */
| 583 //MARKER("TRUNCATED: alloc=%ld len=%ld, rc=%ld\n", cb->nAlloc, cb->nUsed, rc );
| 584 #endif
| 585 }
| 586 cb->nUsed = pos;
| 587 //whclob_null_terminate( cb );
| 588 return rc;
562 } 589 }
563 590
564 591
565 long whclob_memmove( whclob * cb, int start1, int n, int start2 ) 592 long whclob_memmove( whclob * cb, int start1, int n, int start2 )
566 { 593 {
574 hidden lines
1141 return whclob_size(dest) - oldUsed; 1168 return whclob_size(dest) - oldUsed;
1142 } 1169 }
1143 1170
1144 long whclob_importer_filename( whclob * dest, void * arg ) 1171 long whclob_importer_filename( whclob * dest, void * arg )
1145 { 1172 {
1146 char const * fname = (char *)arg; | 1173 char const * fname = (char const *)arg;
1147 FILE * fh = 0; 1174 FILE * fh = 0;
1148 long ret = 0; 1175 long ret = 0;
1149 if( ! fname ) return whclob_rc.ArgError; 1176 if( ! fname ) return whclob_rc.ArgError;
1150 fh = fopen( fname, "rb" ); 1177 fh = fopen( fname, "rb" );
1151 if( !fh ) return whclob_rc.IOError; | 1178 if( !fh )
1152 ret = whclob_import( dest, fh, whclob_importer_FILE ); | 1179 {
1153 fclose( fh ); | 1180 ret = whclob_rc.IOError;
| 1181 }
| 1182 else
| 1183 {
| 1184 ret = whclob_import( dest, fh, whclob_importer_FILE );
| 1185 fclose( fh );
| 1186 }
1154 return ret; 1187 return ret;
1155 } 1188 }
1156 1189
1157 long whclob_import_FILE( whclob * dest, FILE * fp ) 1190 long whclob_import_FILE( whclob * dest, FILE * fp )
1158 { 1191 {
5 hidden lines
1164 return whclob_import( dest, (void*)fn, whclob_importer_filename ); 1197 return whclob_import( dest, (void*)fn, whclob_importer_filename );
1165 /* i HATE that cast, but we know the importer won't change fn. */ 1198 /* i HATE that cast, but we know the importer won't change fn. */
1166 } 1199 }
1167 #endif /* WHCLOB_USE_FILE */ 1200 #endif /* WHCLOB_USE_FILE */
1168 1201
1169 #undef WHCLOB_USE_ZLIB | 1202 #if WHCLOB_USE_BASE64
| 1203 #include "s11n.net/c11n/detail/b64/cencode.h"
| 1204 #include "s11n.net/c11n/detail/b64/cdecode.h"
| 1205 long whclob_base64_enc( whclob const *cIn, whclob *cOut )
| 1206 {
| 1207 unsigned int szIn = whclob_size(cIn);
| 1208 unsigned int szOut = (unsigned int) ((szIn+1) * 1.4);
| 1209 long rc = 0;
| 1210 whclob * tmp = 0;
| 1211 if( ! cIn || !cOut || !szIn ) return whclob_rc.ArgError;
| 1212 if( szOut < (szIn-5) ) szOut = szIn + 5;
| 1213 if( cOut != cIn ) whclob_reset( cOut );
| 1214 rc = whclob_init( &tmp, 0, szOut );
| 1215 if( whclob_rc.OK != rc )
| 1216 {
| 1217 return rc;
| 1218 }
| 1219 base64_encodestate state;
| 1220 base64_init_encodestate( &state );
| 1221 char * outBuf = whclob_buffer(tmp);
| 1222 rc = base64_encode_block( whclob_bufferc(cIn), whclob_size(cIn), outBuf, &state );
| 1223 //MARKER("enc inSize=%ld, rc=%ld\n",whclob_size(cIn), rc);
| 1224 rc += base64_encode_blockend( outBuf+rc, &state);
| 1225 //MARKER("enc rc=%ld\n",rc);
| 1226 whclob_resize( tmp, rc );
| 1227 whclob_swap( cOut, tmp );
| 1228 whclob_finalize( tmp );
| 1229 return whclob_rc.OK;
| 1230 }
| 1231
| 1232 long whclob_base64_dec( whclob const *cIn, whclob *cOut )
| 1233 {
| 1234 unsigned int szIn = whclob_size(cIn);
| 1235 unsigned int szOut = szIn;
| 1236 long rc = 0;
| 1237 whclob * tmp = 0;
| 1238 if( ! cIn || !cOut || !szIn ) return whclob_rc.ArgError;
| 1239 if( cOut != cIn ) whclob_reset( cOut );
| 1240 rc = whclob_init( &tmp, 0, szOut );
| 1241 if( whclob_rc.OK != rc )
| 1242 {
| 1243 return rc;
| 1244 }
| 1245 base64_decodestate state;
| 1246 base64_init_decodestate( &state );
| 1247 rc = base64_decode_block( whclob_bufferc(cIn), whclob_size(cIn), whclob_buffer(tmp), &state );
| 1248 whclob_resize( tmp, rc );
| 1249 //MARKER("dec inSize=%ld, outSize=%ld, rc=%ld\n",whclob_size(cIn), whclob_size(tmp), rc);
| 1250 whclob_swap( cOut, tmp );
| 1251 whclob_finalize( tmp );
| 1252 return whclob_rc.OK;
| 1253 }
| 1254 #endif /* WHCLOB_USE_BASE64 */
| 1255
1170 #undef WHCLOB_DEBUG 1256 #undef WHCLOB_DEBUG

Changes to src/whclob.h

Old (3fa66dce60d55e54) New (ab740daaf1684872)
1 #ifndef WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ 1 #ifndef WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_
2 #define WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ 1 2 #define WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ 1
3 #include <stdarg.h> 3 #include <stdarg.h>
4 #include <stddef.h> 4 #include <stddef.h>
5 5
34 hidden lines
40 @code 40 @code
41 whclob * c; 41 whclob * c;
42 whclob_init( &c, 0, 0 ); 42 whclob_init( &c, 0, 0 );
43 whclob_appendf( c, "Hello, %s!", "world"); 43 whclob_appendf( c, "Hello, %s!", "world");
44 ... 44 ...
> 45 printf("%s\n",whclob_bufferc(c));
45 whclob_finalize( c ); 46 whclob_finalize( c );
46 @endcode 47 @endcode
47 48
48 You can dump a whclob to stdout with the whclob_export() API: 49 You can dump a whclob to stdout with the whclob_export() API:
49 50
51 52
52 But doing so with binary data is not recommended. 53 But doing so with binary data is not recommended.
53 54
54 Some example uses for clobs are: 55 Some example uses for clobs are:
55 56
56 - Copying strings. | 57 - Creating and copying strings.
57 - Buffering input or output. 58 - Buffering input or output.
58 - Easily reading a whole file (or other input source) into memory. 59 - Easily reading a whole file (or other input source) into memory.
59 60
60 @section whclob_sec_todo TODOs 61 @section whclob_sec_todo TODOs
61 62
62 - The read/write API is not complete. (Can't quite remember what's 63 - The read/write API is not complete. (Can't quite remember what's
63 missing, though.) 64 missing, though.)
> 65
> 66 - We really need to move from using 'long' to 'size_t' in many places.
> 67 In some places that's not practical because we need to have room for
> 68 negative error codes.
64 69
65 ************************************************************************/ 70 ************************************************************************/
66 71
67 72
68 /** @def WHCLOB_USE_FILE 73 /** @def WHCLOB_USE_FILE
3 hidden lines
72 objects from/to FILE handles. 77 objects from/to FILE handles.
73 */ 78 */
74 #if !defined(WHCLOB_USE_FILE) 79 #if !defined(WHCLOB_USE_FILE)
75 #define WHCLOB_USE_FILE 1 80 #define WHCLOB_USE_FILE 1
76 #endif 81 #endif
> 82 #if WHCLOB_USE_FILE
> 83 #include <stdio.h>
> 84 #endif
77 85
78 /** @def WHCLOB_USE_ZLIB 86 /** @def WHCLOB_USE_ZLIB
79 87
80 If whclob is built with WHCLOB_USE_ZLIB set to a true value then 88 If whclob is built with WHCLOB_USE_ZLIB set to a true value then
81 some routines are added which use zlib to de/compress whclob 89 some routines are added which use zlib to de/compress whclob
2 hidden lines
84 */ 92 */
85 #if !defined(WHCLOB_USE_ZLIB) 93 #if !defined(WHCLOB_USE_ZLIB)
86 #define WHCLOB_USE_ZLIB 0 94 #define WHCLOB_USE_ZLIB 0
87 #endif 95 #endif
88 96
89 #if WHCLOB_USE_FILE | 97 /** @def WHCLOB_USE_BASE64
90 #include <stdio.h> | 98
| 99 If whclob is built with WHCLOB_USE_BASE64 set to a true value then
| 100 an import/export API is included for importing/export whclob
| 101 objects from/to FILE handles.
| 102 */
| 103 #if !defined(WHCLOB_USE_BASE64)
| 104 #define WHCLOB_USE_BASE64 0
91 #endif 105 #endif
> 106
92 107
93 108
94 #ifdef __cplusplus 109 #ifdef __cplusplus
95 extern "C" { 110 extern "C" {
96 #endif 111 #endif
519 hidden lines
616 - whclob_rc.AllocError if a memory (re)allocation fails. 631 - whclob_rc.AllocError if a memory (re)allocation fails.
617 */ 632 */
618 long whclob_null_terminate( whclob * cb ); 633 long whclob_null_terminate( whclob * cb );
619 634
620 /** 635 /**
621 If whclob_size(cb) "used space" is currently less than pos then this | 636 "Chops" cb off at a given length. If the current used space is
622 function does nothing, otherwise cb is truncated to that length. | 637 smaller than pos then it will be padded with NULLs to make it fit.
| 638 It is is longer than pos then the clob will be reallocated (if
| 639 necessary) to fit the new space and any old data which is now
| 640 outside the used range will be zeroed out (this is necessary for
| 641 sane behaviour in some use cases). In any case, on success the new
| 642 position of the clob will be the given position.
623 643
624 If allocPolicy is 0 then the amount of memory allocated by cb is 644 If allocPolicy is 0 then the amount of memory allocated by cb is
625 not adjusted. If it is >0, whclob_reserve() will be called to try to | 645 not adjusted (unless (pos>whclob_size(cb)), in which case we have
626 shrink the allocated buffer (but this does not guaranty that the | 646 to expand the clob). If it is >0, whclob_reserve() will be called
627 allocated memory will actually be reduced). If (allocPolicy<0) then | 647 to try to reserve at least pos bytes. If (allocPolicy<0) then the
628 a simple heuristic is used to determine if a reallocation might | 648 allocated memory is shrunk to fit (if possible). If pos is past the
629 release a useful amount of memory. | 649 current end-of-data position then allocPolicy is forced to 1 so
| 650 that the buffer can be expanded (if needed).
630 651
631 Returns whclob_rc.OK on success or another value from whclob_rc | 652 Returns whclob_rc.OK or a positive value on success or a negative
632 on error. | 653 value from whclob_rc on error.
| 654
| 655 The two most common uses for this function:
| 656
| 657 - "Shrink-wrapping" the value (eliminating extra allocated space)
| 658
| 659 - Re-using a clob's buffer as a target for, e.g. fread(), by
| 660 reserving a certain amount of space then truncating it at position
| 661 0 but with an allocPolicy of >=0. This can save on allocations compared
| 662 to using, e.g. whclob_reset().
| 663
633 */ 664 */
634 long whclob_truncate( whclob * cb, long pos, int allocPolicy ); 665 long whclob_truncate( whclob * cb, long pos, int allocPolicy );
635 666
636 /* TODO???: whclob_trim() */ 667 /* TODO???: whclob_trim() */
637 668
278 hidden lines
916 whclob_uncompress(), but uses the zlib inflate() algorithm instead of 947 whclob_uncompress(), but uses the zlib inflate() algorithm instead of
917 the uncompress() algorithm. 948 the uncompress() algorithm.
918 */ 949 */
919 int whclob_inflate( whclob *cIn, whclob *cOut ); 950 int whclob_inflate( whclob *cIn, whclob *cOut );
920 #endif /* WHCLOB_USE_ZLIB */ 951 #endif /* WHCLOB_USE_ZLIB */
> 952
> 953 #if WHCLOB_USE_BASE64
> 954 /**
> 955 Encodes cIn's contents in base64 and sends it to cOut.
> 956 cIn may be the same as cOut. If cOut is not cIn then
> 957 it is cleared before encoding begins. On success, cOut is populated with
> 958 the encoded data and whclob_rc.OK is returned. On error:
> 959
> 960 - If (!cIn, !cOut, or !whclob_size(cIn)) then whclob_rc.ArgError
> 961 is returned and cOut is unmodified.
> 962
> 963 - On any other error, if (cIn!=cOut) then cOut will contain no
> 964 data, otherwise cIn/cOut will be unmodified. In these cases some
> 965 other error code from whclob_rc will be returned.
> 966 */
> 967 long whclob_base64_enc( whclob const *cIn, whclob *cOut );
> 968
> 969 /**
> 970 The converse of whclob_base64_enc(), with the same
> 971 conventions.
> 972 */
> 973 long whclob_base64_dec( whclob const *cIn, whclob *cOut );
> 974 #endif /* WHCLOB_USE_BASE64 */
> 975
921 976
922 #ifdef __cplusplus 977 #ifdef __cplusplus
923 } /* extern "C" */ 978 } /* extern "C" */
924 #endif 979 #endif
925 #endif /* WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ */ 980 #endif /* WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ */