Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| SHA1 Hash: | 4111861b47ffcd6b6057369a6f064bf044e67775 |
|---|---|
| Date: | 2008-11-14 14:15:56 |
| User: | stephan |
| Comment: | s/whclob/memblob/g |
Changes
Changes to include/s11n.net/c11n/c11n.h
| Old (6edd5438695ea732) | New (b3be28219ec53288) | |||
|---|---|---|---|---|
| 1 | #ifndef S11N_NET_C11N_H_INCLUDED | 1 | #ifndef S11N_NET_C11N_H_INCLUDED | |
| 2 | #define S11N_NET_C11N_H_INCLUDED 1 | 2 | #define S11N_NET_C11N_H_INCLUDED 1 | |
| 3 | 3 | |||
| 4 | /** @page c11n_page_main c11n: generic serialization library for C | 4 | /** @page c11n_page_main c11n: generic serialization library for C | |
| 5 | 5 | |||
| 166 hidden lines | ||||
| 172 | 172 | |||
| 173 | - All functions and types in the core c11n API start with <tt>c11n_</tt>. | 173 | - All functions and types in the core c11n API start with <tt>c11n_</tt>. | |
| 174 | It may use some utility types which are delivered with c11n but do not | 174 | It may use some utility types which are delivered with c11n but do not | |
| 175 | really belong to the c11n API. Those routines may have their own naming | 175 | really belong to the c11n API. Those routines may have their own naming | |
| 176 | conventions (e.g. the <tt>vappendf()</tt> family of functions and | 176 | conventions (e.g. the <tt>vappendf()</tt> family of functions and | |
| 177 | the <tt>whclob</tt> API.). | | | 177 | the <tt>memblob</tt> API.). |
| 178 | 178 | |||
| 179 | - Functions which related to a specific data type normally have that | 179 | - Functions which related to a specific data type normally have that | |
| 180 | type's name as a prefix. e.g. The functions related to c11n_node | 180 | type's name as a prefix. e.g. The functions related to c11n_node | |
| 181 | are called c11n_node_something(). | 181 | are called c11n_node_something(). | |
| 182 | 182 | |||
| 1608 hidden lines | ||||
| 1791 | #ifdef __cplusplus | 1791 | #ifdef __cplusplus | |
| 1792 | } /* extern "C" */ | 1792 | } /* extern "C" */ | |
| 1793 | #endif | 1793 | #endif | |
| 1794 | 1794 | |||
| 1795 | #endif /* S11N_NET_C11N_H_INCLUDED */ | 1795 | #endif /* S11N_NET_C11N_H_INCLUDED */ | |
Deleted include/s11n.net/c11n/detail/whclob.h
| Old (2b0b5649e2f46674) | New () | |||
|---|---|---|---|---|
| 1 | #ifndef WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ | < | ||
| 2 | #define WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ 1 | < | ||
| 3 | #include <stdarg.h> | < | ||
| 4 | #include <stddef.h> | < | ||
| 5 | < | |||
| 6 | /*! @page whclob_page_main whclob: dynamic char array utilities | < | ||
| 7 | < | |||
| 8 | @section whclob_sec_about About whclob | < | ||
| 9 | < | |||
| 10 | The whclob API encapsulates behaviours related to creating, appending, | < | ||
| 11 | reading, writing, and freeing C-style blobs (stored in memory as char | < | ||
| 12 | arrays). | < | ||
| 13 | < | |||
| 14 | It is primarily intended to act as an output buffer for binary or | < | ||
| 15 | string data. It provides, for example, printf-like functionality which | < | ||
| 16 | makes use of the dynamic resize features blobs to simplify the | < | ||
| 17 | creation and ownership management of dynamic C-style strings. | < | ||
| 18 | < | |||
| 19 | whclob is heavily inspired and influenced by code in the Fossil source | < | ||
| 20 | tree (http://www.fossil-scm.org) written by D. Richard Hipp. In that | < | ||
| 21 | tree, blobs are used to store files in memory and to provide output | < | ||
| 22 | buffering support for the built-in web/cgi servers. | < | ||
| 23 | < | |||
| 24 | Rather than being a fork of Dr. Hipp's code, this is a | < | ||
| 25 | reimplementation done solely for licensing reasons - his code is GPL | < | ||
| 26 | and this is Public Domain. | < | ||
| 27 | < | |||
| 28 | Much of the heavy lifting of this API is done by the vappendf API | < | ||
| 29 | (see: \ref vappendf_page_main). | < | ||
| 30 | < | |||
| 31 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | < | ||
| 32 | < | |||
| 33 | @section whclob_sec_usage Usage | < | ||
| 34 | < | |||
| 35 | A whclob object must be initialized via whclob_init() (or equivalent) | < | ||
| 36 | and finalized via whclob_finalize(). Between those two calls, any | < | ||
| 37 | number of other clob-API functions may be used (unless documented | < | ||
| 38 | otherwise). As an example: | < | ||
| 39 | < | |||
| 40 | @code | < | ||
| 41 | whclob * c; | < | ||
| 42 | whclob_init( &c, 0, 0 ); | < | ||
| 43 | whclob_appendf( c, "Hello, %s!", "world"); | < | ||
| 44 | ... | < | ||
| 45 | printf("%s\n",whclob_bufferc(c)); | < | ||
| 46 | whclob_finalize( c ); | < | ||
| 47 | @endcode | < | ||
| 48 | < | |||
| 49 | You can dump a whclob to stdout with the whclob_export() API: | < | ||
| 50 | < | |||
| 51 | whclob_export( c, stdout, whclob_exporter_FILE ); | < | ||
| 52 | < | |||
| 53 | But doing so with binary data is not recommended. | < | ||
| 54 | < | |||
| 55 | Some example uses for clobs are: | < | ||
| 56 | < | |||
| 57 | - Creating and copying strings. | < | ||
| 58 | - Buffering input or output. | < | ||
| 59 | - Easily reading a whole file (or other input source) into memory. | < | ||
| 60 | < | |||
| 61 | @section whclob_sec_todo TODOs | < | ||
| 62 | < | |||
| 63 | - The read/write API is not complete. (Can't quite remember what's | < | ||
| 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. | < | ||
| 69 | < | |||
| 70 | ************************************************************************/ | < | ||
| 71 | < | |||
| 72 | < | |||
| 73 | /** @def WHCLOB_USE_FILE | < | ||
| 74 | < | |||
| 75 | If whclob is built with WHCLOB_USE_FILE set to a true value then | < | ||
| 76 | an import/export API is included for importing/export whclob | < | ||
| 77 | objects from/to FILE handles. | < | ||
| 78 | */ | < | ||
| 79 | #if !defined(WHCLOB_USE_FILE) | < | ||
| 80 | #define WHCLOB_USE_FILE 1 | < | ||
| 81 | #endif | < | ||
| 82 | #if WHCLOB_USE_FILE | < | ||
| 83 | #include <stdio.h> | < | ||
| 84 | #endif | < | ||
| 85 | < | |||
| 86 | /** @def WHCLOB_USE_ZLIB | < | ||
| 87 | < | |||
| 88 | If whclob is built with WHCLOB_USE_ZLIB set to a true value then | < | ||
| 89 | some routines are added which use zlib to de/compress whclob | < | ||
| 90 | objects in memory. Enabling this requires that the client link | < | ||
| 91 | with zlib (e.g. with the -lz linker argument). | < | ||
| 92 | */ | < | ||
| 93 | #if !defined(WHCLOB_USE_ZLIB) | < | ||
| 94 | #define WHCLOB_USE_ZLIB 0 | < | ||
| 95 | #endif | < | ||
| 96 | < | |||
| 97 | /** @def WHCLOB_USE_BASE64 | < | ||
| 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 1 | < | ||
| 105 | #endif | < | ||
| 106 | < | |||
| 107 | < | |||
| 108 | < | |||
| 109 | #ifdef __cplusplus | < | ||
| 110 | extern "C" { | < | ||
| 111 | #endif | < | ||
| 112 | < | |||
| 113 | /** | < | ||
| 114 | whclob_rc_t holds status codes for the clob API. | < | ||
| 115 | Their values must be unique negative integers, with | < | ||
| 116 | the exception of OK, which must be 0. | < | ||
| 117 | < | |||
| 118 | Many functions in the clob API return 0 or a positive | < | ||
| 119 | number on success and one of these codes on error. | < | ||
| 120 | < | |||
| 121 | The are accessed like: whclob_rc.AllocError. This is | < | ||
| 122 | unconventional, but the intention is so that debuggers can get an | < | ||
| 123 | actual symbol name. It also provides a namespace for | < | ||
| 124 | our enum-like values. | < | ||
| 125 | */ | < | ||
| 126 | struct whclob_rc_t | < | ||
| 127 | { | < | ||
| 128 | /** The success status code. Must have the value 0. */ | < | ||
| 129 | const long OK; | < | ||
| 130 | /** Generic error code. */ | < | ||
| 131 | const long Err; | < | ||
| 132 | /** Signals that an allocation or reallocation failed. */ | < | ||
| 133 | const long AllocError; | < | ||
| 134 | /** Signals that a null was passed or received where | < | ||
| 135 | one was not expected. */ | < | ||
| 136 | const long UnexpectedNull; | < | ||
| 137 | /** Signals that some value was out of range. */ | < | ||
| 138 | const long RangeError; | < | ||
| 139 | /** Signals an I/O error of some sort. */ | < | ||
| 140 | const long IOError; | < | ||
| 141 | /** Signals some sort of argument-type error (e.g. (void *) args). */ | < | ||
| 142 | const long ArgError; | < | ||
| 143 | }; | < | ||
| 144 | typedef struct whclob_rc_t whclob_rc_t; | < | ||
| 145 | < | |||
| 146 | /** | < | ||
| 147 | The official way to get the clob status code values | < | ||
| 148 | is via the whclob_rc object. | < | ||
| 149 | */ | < | ||
| 150 | extern const whclob_rc_t whclob_rc; | < | ||
| 151 | < | |||
| 152 | /** | < | ||
| 153 | @struct whclob | < | ||
| 154 | < | |||
| 155 | The whclob type (an opaque struct) holds data relating to in-memory | < | ||
| 156 | blobs allocated by malloc(). A whclob holds (and owns) a | < | ||
| 157 | varying-length character array for storing arbitrary binary data. | < | ||
| 158 | < | |||
| 159 | Note that because client code cannot see the whclob implementation, | < | ||
| 160 | they cannot create whclob objects on the stack. The proper way | < | ||
| 161 | to create, initialize, and free whclob objects is: | < | ||
| 162 | < | |||
| 163 | \code | < | ||
| 164 | whclob * c; | < | ||
| 165 | if( whclob_rc.OK != whclob_init(&c,0,0) ) { ... error ... } | < | ||
| 166 | ... | < | ||
| 167 | whclob_finalize( c ); | < | ||
| 168 | \endcode | < | ||
| 169 | < | |||
| 170 | Or to use the whclob_new() convenience function: | < | ||
| 171 | < | |||
| 172 | \code | < | ||
| 173 | whclob * c = whclob_new(); | < | ||
| 174 | if( !c ) { ... OOM ... } | < | ||
| 175 | ... | < | ||
| 176 | whclob_finalize( c ); | < | ||
| 177 | \endcode | < | ||
| 178 | < | |||
| 179 | */ | < | ||
| 180 | struct whclob; | < | ||
| 181 | typedef struct whclob whclob; | < | ||
| 182 | < | |||
| 183 | < | |||
| 184 | /** | < | ||
| 185 | Allocates a new whclob object and assigns (*cb) to it. It initializes | < | ||
| 186 | the object as described below. On error it assigns (*cb) to 0. | < | ||
| 187 | < | |||
| 188 | It is only legal to call this on fresh, uninitialized whclob | < | ||
| 189 | pointer. A clob is considered to be "uninitialized" just after | < | ||
| 190 | declaration (before it is assigned to) and after whclob_finalize() has | < | ||
| 191 | been called on it. | < | ||
| 192 | < | |||
| 193 | To avoid memory leaks, for each successful call to whclob_init() you | < | ||
| 194 | must have a matching call to whclob_finalize(). If this function | < | ||
| 195 | fails then (*cb) is set to 0, so there is no need to call | < | ||
| 196 | whclob_finalize() (but it is still safe (but a no-op) to do so, for | < | ||
| 197 | the cases where doing so may simplify error handling). | < | ||
| 198 | < | |||
| 199 | Interpretation of the 'data' and 'n' arguments: | < | ||
| 200 | < | |||
| 201 | - If data is null and n is less than 1 then cb is initialized | < | ||
| 202 | to a zero-length string. | < | ||
| 203 | < | |||
| 204 | - If data is non-null and n is less than 0 then strlen(data) is used | < | ||
| 205 | to calculate n. | < | ||
| 206 | < | |||
| 207 | - If data is non-null and n is greater than 0 then the first n | < | ||
| 208 | bytes of data are copied and data is assumed to be at least that | < | ||
| 209 | long. | < | ||
| 210 | < | |||
| 211 | - If data is 0 and n is positive then n bytes are reserved and | < | ||
| 212 | zeroed. | < | ||
| 213 | < | |||
| 214 | RETURNS: | < | ||
| 215 | < | |||
| 216 | If this function returns whclob_rc.OK then (*cb) points to a new whclob | < | ||
| 217 | object. On error it returns one of the negative integers defined in | < | ||
| 218 | whclob_rc: | < | ||
| 219 | < | |||
| 220 | - whclob_rc.UnexpectedNull if (!cb). | < | ||
| 221 | < | |||
| 222 | - whclob_rc.AllocError if allocation of the new whclob fails. | < | ||
| 223 | < | |||
| 224 | USAGE NOTES: | < | ||
| 225 | < | |||
| 226 | Calling whclob_finalize(0) has no ill effects (other than an | < | ||
| 227 | ignorable error code), so algorithms may be organized a call | < | ||
| 228 | whclob_finalize() regardless of whether whclob_init() succeeds or | < | ||
| 229 | fails. It is anticipated that this may simplify some error-handling | < | ||
| 230 | cases. | < | ||
| 231 | */ | < | ||
| 232 | long whclob_init( whclob ** cb, char const * data, long n ); | < | ||
| 233 | < | |||
| 234 | /** | < | ||
| 235 | A simplified form of whclob_init() which allocates a new, empty whclob | < | ||
| 236 | of the given size and returns it. The caller owns it and must finalize it with | < | ||
| 237 | whclob_finalize(). On error (out of memory) it returns 0. | < | ||
| 238 | */ | < | ||
| 239 | whclob * whclob_new_n( size_t reserved ); | < | ||
| 240 | < | |||
| 241 | /** | < | ||
| 242 | Equivalent to whclob_new_n(0). | < | ||
| 243 | */ | < | ||
| 244 | whclob * whclob_new(); | < | ||
| 245 | < | |||
| 246 | /** | < | ||
| 247 | See whclob_set_alloc_policy() and | < | ||
| 248 | See whclob_set_default_alloc_policy(). | < | ||
| 249 | */ | < | ||
| 250 | typedef long (*whclob_alloc_policy_t)( long ); | < | ||
| 251 | < | |||
| 252 | /** | < | ||
| 253 | Sets the current allocation size determination policy and returns | < | ||
| 254 | the previous one (so you may politely reset it when yours goes out | < | ||
| 255 | of scope). | < | ||
| 256 | < | |||
| 257 | When the framework wants to (re)allocate memory it will call the | < | ||
| 258 | current policy function and pass it the suggested amount of memory | < | ||
| 259 | it wants to reallocate. The policy may return that number as-is or | < | ||
| 260 | adjust it upwards (e.g. *= 1.5) (never downwards) and return that | < | ||
| 261 | number, which the reallocation will then use. If a smaller number | < | ||
| 262 | is returned it will be ignored. | < | ||
| 263 | < | |||
| 264 | Note that the policy only specifies a requested size, not where the | < | ||
| 265 | memory will come from. The memory will always be pulled from | < | ||
| 266 | malloc(). Likewise, the cleanup routines always use free() to | < | ||
| 267 | delete the memory. | < | ||
| 268 | < | |||
| 269 | The intention is to allow clients to who know they will append | < | ||
| 270 | blobs a lot to increase the size of the allocs to reduce the number | < | ||
| 271 | of potential reallocations. | < | ||
| 272 | < | |||
| 273 | Be aware that the reallocation internals may allocate slightly more | < | ||
| 274 | memory than requested, e.g. to unsure that the blob always has a | < | ||
| 275 | trailing null character. | < | ||
| 276 | < | |||
| 277 | If passed 0 it will use a default policy, which simply returns the | < | ||
| 278 | value passed to it. You can fetch the current policy, if you like, | < | ||
| 279 | by passing 0 to this function, then passing that return value | < | ||
| 280 | back to this function. | < | ||
| 281 | */ | < | ||
| 282 | whclob_alloc_policy_t whclob_set_default_alloc_policy( whclob_alloc_policy_t ); | < | ||
| 283 | < | |||
| 284 | /** | < | ||
| 285 | Works just like whclob_set_default_alloc_policy() except that it | < | ||
| 286 | applies only to cb and takes precedence over | < | ||
| 287 | whclob_set_default_alloc_policy(). | < | ||
| 288 | */ | < | ||
| 289 | whclob_alloc_policy_t whclob_set_alloc_policy( whclob * cb, whclob_alloc_policy_t ); | < | ||
| 290 | < | |||
| 291 | < | |||
| 292 | /** | < | ||
| 293 | Free the resources, if any, associated with cb and zeroes out the | < | ||
| 294 | freed memory. After calling this, whclob_buffer(cb) will be an empty | < | ||
| 295 | string and both whclob_size(cb) and whclob_capacity(cb) will be 0. | < | ||
| 296 | < | |||
| 297 | It is illegal to pass a whclob which was not initialized by | < | ||
| 298 | whclob_init() (or equivalent). Doing so results in undefined | < | ||
| 299 | behaviour. | < | ||
| 300 | < | |||
| 301 | Note that this function does not actually free the cb pointer | < | ||
| 302 | itself. After this function returns, cb can be re-used by any clob | < | ||
| 303 | API which is append-friendly (e.g. not whclob_char_filln()). | < | ||
| 304 | < | |||
| 305 | On success it returns whclob_rc.OK. On error it returns: | < | ||
| 306 | < | |||
| 307 | - whclob_rc.UnexpectedNull if (!cb). | < | ||
| 308 | */ | < | ||
| 309 | long whclob_reset( whclob * cb ); | < | ||
| 310 | < | |||
| 311 | /** | < | ||
| 312 | whclob_finalize() works just like whclob_reset(), plus it | < | ||
| 313 | deallocates cb by calling free(). After calling this, cb is invalid | < | ||
| 314 | until/unless it is passed to whclob_init() again. | < | ||
| 315 | < | |||
| 316 | Returns whclob_rc.OK on success and whclob_rc.UnexpectedNull if | < | ||
| 317 | (!cb). | < | ||
| 318 | */ | < | ||
| 319 | long whclob_finalize( whclob * cb ); | < | ||
| 320 | < | |||
| 321 | /** | < | ||
| 322 | Force's cb's cursor and used counter to be in bounds of the | < | ||
| 323 | actual allocated memory. They are moved forwards or backwards, | < | ||
| 324 | as necessary, to bring them into bounds. | < | ||
| 325 | */ | < | ||
| 326 | void whclob_force_in_bounds( whclob * cb ); | < | ||
| 327 | < | |||
| 328 | /** | < | ||
| 329 | Tries to reserve at least sz bytes of memory for the native blob | < | ||
| 330 | associated with cb. It will not shrink the blob, only grow it or | < | ||
| 331 | leave it alone, with one exception: if sz is 0 then the effect is | < | ||
| 332 | the same as whclob_reset(). | < | ||
| 333 | < | |||
| 334 | This function may invalidate any old pointers obtained via | < | ||
| 335 | whclob_buffer(). | < | ||
| 336 | < | |||
| 337 | Note that shrinking a clob may cause the internal position | < | ||
| 338 | cursor (used by the read/write API) to move backwards to the | < | ||
| 339 | new logical EOF. | < | ||
| 340 | < | |||
| 341 | If cb is "const" (points to a blob but has an allocated size of 0) | < | ||
| 342 | then calling this with a non-zero sz will cause sz bytes of the | < | ||
| 343 | referenced blob data to be deeply copied to cb. | < | ||
| 344 | < | |||
| 345 | On success it returns the number of bytes allocated to cb. The | < | ||
| 346 | number may be larger than sz, due to internal details of this API | < | ||
| 347 | and the implementation of the current allocation policy (see | < | ||
| 348 | whclob_set_default_alloc_policy()). | < | ||
| 349 | < | |||
| 350 | On error it returns one of the negative numbers specified | < | ||
| 351 | by whclob_rc: | < | ||
| 352 | < | |||
| 353 | - whclob_rc.AllocError = (re)allocation failed. | < | ||
| 354 | < | |||
| 355 | - whclob_rc.UnexpectedNull = cb parameter was 0. | < | ||
| 356 | < | |||
| 357 | */ | < | ||
| 358 | long whclob_reserve( whclob * cb, unsigned int sz ); | < | ||
| 359 | < | |||
| 360 | /** | < | ||
| 361 | Works like whclob_reserve(), but marks all memory | < | ||
| 362 | in the clob as used. This means that appending | < | ||
| 363 | will start from sz, rather than from whatever | < | ||
| 364 | the end previously was. It returns the same values | < | ||
| 365 | as whclob_reserve(). | < | ||
| 366 | */ | < | ||
| 367 | long whclob_resize( whclob * cb, unsigned int sz ); | < | ||
| 368 | < | |||
| 369 | /** | < | ||
| 370 | Returns the number of "used" bytes in cb. Appending to a clob will | < | ||
| 371 | start after the last "used" byte. Note that clobs may (and normally do) | < | ||
| 372 | have more memory allocated to them than is "used". | < | ||
| 373 | < | |||
| 374 | Returns 0 or greater (the size of cb) on success and | < | ||
| 375 | whclob_rc.UnexpectedNull if (!cb). | < | ||
| 376 | */ | < | ||
| 377 | long whclob_size( whclob const * cb ); | < | ||
| 378 | < | |||
| 379 | /** | < | ||
| 380 | Returns the current allocated capacity of cb, or | < | ||
| 381 | whclob_rc.UnexpectedNull if (!cb). | < | ||
| 382 | < | |||
| 383 | The capacity will always be equal to or greater than whclob_size(cb). | < | ||
| 384 | */ | < | ||
| 385 | long whclob_capacity( whclob const * cb ); | < | ||
| 386 | < | |||
| 387 | /** | < | ||
| 388 | Returns a pointer to cb's buffer (may be 0). The buffer is owned by | < | ||
| 389 | cb. | < | ||
| 390 | < | |||
| 391 | Do not keep ahold of the returned pointer for longer than | < | ||
| 392 | necessary, as any operations which change cb may invalidate that | < | ||
| 393 | pointer. | < | ||
| 394 | < | |||
| 395 | Do not generically depend on the returned array being a | < | ||
| 396 | null-terminated string, as cb can hold arbitrary data. Use | < | ||
| 397 | whclob_size(sb) to get the length of the data. | < | ||
| 398 | */ | < | ||
| 399 | char * whclob_buffer( whclob * cb ); | < | ||
| 400 | < | |||
| 401 | /** | < | ||
| 402 | A variant of whclob_buffer() for places where a const is needed. | < | ||
| 403 | */ | < | ||
| 404 | char const * whclob_bufferc( whclob const * cb ); | < | ||
| 405 | < | |||
| 406 | /** | < | ||
| 407 | Gives up cb's control of any allocated memory and returns it to the | < | ||
| 408 | caller, who takes over ownership. | < | ||
| 409 | < | |||
| 410 | If a blob is storing binary data then there is no way to know the | < | ||
| 411 | size of the returned buffer. Thus if you need its length, be sure | < | ||
| 412 | to call whclob_size(cb) before calling this. | < | ||
| 413 | < | |||
| 414 | This function effectively does whclob_reset(cb) but does not finalize | < | ||
| 415 | cb. Thus after calling this function cb is still a valid object for | < | ||
| 416 | purposes of the other whclob_xxx() functions. | < | ||
| 417 | */ | < | ||
| 418 | char * whclob_take_buffer( whclob * cb ); | < | ||
| 419 | < | |||
| 420 | /** | < | ||
| 421 | Flags for whclob_seek(), they are identical in nature to SEEK_SET, | < | ||
| 422 | SEEK_CUR, and SEEK_END used by the conventional fseek() C function. | < | ||
| 423 | < | |||
| 424 | WHCLOB_SEEK_SET: moves the cursor to absolute position (offset). | < | ||
| 425 | < | |||
| 426 | WHCLOB_SEEK_CUR: moves the cursor to (cursor + offset). | < | ||
| 427 | < | |||
| 428 | WHCLOB_SEEK_END: moves the cursor to relative postition (end - | < | ||
| 429 | offset), where 'end' is the index 1 after the last character of the | < | ||
| 430 | USED portion of the blob. e.g. the end of "abcd" is at position 4. | < | ||
| 431 | */ | < | ||
| 432 | enum WHClobSeekWhence { WHCLOB_SEEK_SET = 0, | < | ||
| 433 | WHCLOB_SEEK_CUR = 1, | < | ||
| 434 | WHCLOB_SEEK_END = -1 | < | ||
| 435 | }; | < | ||
| 436 | < | |||
| 437 | /** | < | ||
| 438 | Similar to the standard fseek(), whclob_seek() moves the blob's | < | ||
| 439 | cursor to its (current pos + offset), relative to whence, which | < | ||
| 440 | must be one of of the ClobSeekFlags values. Once the seek is | < | ||
| 441 | complete, the cursor is bumped back into bounds (or at EOF). The | < | ||
| 442 | return value is the new cursor position within the blob. | < | ||
| 443 | < | |||
| 444 | Note that when using WHCLOB_SEEK_END, only a negative offset makes | < | ||
| 445 | sense, as a positive offset is out of bounds. | < | ||
| 446 | < | |||
| 447 | The return value is a positive integer on success, indicting the | < | ||
| 448 | new position within the blob. On error a negative number is | < | ||
| 449 | returned: | < | ||
| 450 | < | |||
| 451 | - whclob_rc.RangeError = the 'whence' value is unknown. | < | ||
| 452 | < | |||
| 453 | */ | < | ||
| 454 | long whclob_seek( whclob * cb, long offset, int whence ); | < | ||
| 455 | < | |||
| 456 | /** | < | ||
| 457 | Moves cb's cursor back to the begining of the blob. | < | ||
| 458 | */ | < | ||
| 459 | void whclob_rewind( whclob * cb ); | < | ||
| 460 | < | |||
| 461 | /** Returns whclob_rc.OK if pos is within the used bounds of cb, | < | ||
| 462 | else returns whclob_rc.RangeError. | < | ||
| 463 | */ | < | ||
| 464 | long whclob_pos_in_bounds( whclob * cb, long pos ); | < | ||
| 465 | < | |||
| 466 | < | |||
| 467 | /** | < | ||
| 468 | Fills the pointed-to memory with char specified by c, starting at | < | ||
| 469 | blob offset specified by startPos and copying the next n bytes. It ignores | < | ||
| 470 | the "used" space boundary and fills any allocated space. It does | < | ||
| 471 | not change the size of the allocated memory block or its used-space | < | ||
| 472 | count. | < | ||
| 473 | < | |||
| 474 | On success it returns the number of zeroes which it fills | < | ||
| 475 | in. Normally this is n, but if (startPos + n) would overflow, the | < | ||
| 476 | blob is filled to the end and that (smaller) length is returned. | < | ||
| 477 | < | |||
| 478 | On failure it returns one of the values defined in whclob_rc: | < | ||
| 479 | < | |||
| 480 | - whclob_rc.Err if cb does not contain a blob, or points | < | ||
| 481 | to a blob but does not own it. | < | ||
| 482 | < | |||
| 483 | - whclob_rc.RangeError if startPos is out of bounds or n <= 0. | < | ||
| 484 | */ | < | ||
| 485 | long whclob_char_filln( whclob * cb, char c, long startPos, long n ); | < | ||
| 486 | < | |||
| 487 | /** | < | ||
| 488 | Same as whclob_char_filln( cb, '\\0', 0, whclob_size( cb ) ); | < | ||
| 489 | */ | < | ||
| 490 | long whclob_zero_fill( whclob * cb ); | < | ||
| 491 | < | |||
| 492 | < | |||
| 493 | /** | < | ||
| 494 | Appends the first dsize bytes of data to cb's blob, exanding the | < | ||
| 495 | blob as needed. If dsize is -1 then strlen(data) is used to | < | ||
| 496 | calculate the length. If dsize is 0 an error code is returned (see | < | ||
| 497 | below). This does not modify cb's internal position cursor. | < | ||
| 498 | < | |||
| 499 | If cb does not currently own the blob it points to then this | < | ||
| 500 | function may cause it to create a copy of that object, and append | < | ||
| 501 | to that copy. This may or may not be expensive, depending on the | < | ||
| 502 | size of the copy. | < | ||
| 503 | < | |||
| 504 | Unlike whclob_appendf(), this function is safe for use with binary | < | ||
| 505 | data, but only if dsize is explicitly set. Otherwise it will only | < | ||
| 506 | append up to the first null character in data. | < | ||
| 507 | < | |||
| 508 | On success a positive integer is returned, the number of bytes by | < | ||
| 509 | which the blob extended. On failure, one of the negative values | < | ||
| 510 | defined in whclob_rc is returned: | < | ||
| 511 | < | |||
| 512 | - whclob_rc.AllocError if a memory (re)allocation fails. | < | ||
| 513 | < | |||
| 514 | - whclob_rc.RangeError if dsize is 0. | < | ||
| 515 | */ | < | ||
| 516 | long whclob_append( whclob * cb, char const * data, long dsize ); | < | ||
| 517 | < | |||
| 518 | /** | < | ||
| 519 | Appends n copies of ch to cb and returns the number added. If n is less | < | ||
| 520 | than 1 then whclob_rc.RangeError is returned and cb is not modified. | < | ||
| 521 | */ | < | ||
| 522 | long whclob_append_char_n( whclob * cb, char ch, const long n ); | < | ||
| 523 | < | |||
| 524 | /** | < | ||
| 525 | Makes a deep copy of src, placing it into dest. | < | ||
| 526 | < | |||
| 527 | Neither src nor dest may be 0. dest is deallocated before the copy | < | ||
| 528 | happens. | < | ||
| 529 | < | |||
| 530 | Returns one of the values defined in whclob_rc: | < | ||
| 531 | < | |||
| 532 | - whclob_rc.RangeError if (src==dest). | < | ||
| 533 | < | |||
| 534 | - whclob_rc.AllocError if a memory (re)allocation fails. | < | ||
| 535 | < | |||
| 536 | - whclob_rc.OK on success. | < | ||
| 537 | */ | < | ||
| 538 | long whclob_copy( whclob * src, whclob * dest ); | < | ||
| 539 | < | |||
| 540 | < | |||
| 541 | < | |||
| 542 | /** | < | ||
| 543 | Like printf, but output is appended to the end of cb, expanding it | < | ||
| 544 | as necessary. It also imlements a couple extension conversions, to | < | ||
| 545 | be documented in the docs for vappendf(). | < | ||
| 546 | < | |||
| 547 | Return value: if the number is >= 0 then it is the size by which | < | ||
| 548 | the target blob grew as a result of the printf (i.e. the number of | < | ||
| 549 | bytes printf added to it). If the return value is negative then it | < | ||
| 550 | is an error code from whclob_rc. | < | ||
| 551 | < | |||
| 552 | This function is not safe for binary data - if fmt contains | < | ||
| 553 | any null characters the processing will stop. | < | ||
| 554 | < | |||
| 555 | For the list of non-standard format specifiers, see | < | ||
| 556 | the documentation for vappendf(). | < | ||
| 557 | */ | < | ||
| 558 | long whclob_vappendf( whclob * cb, char const * fmt, va_list vargs ); | < | ||
| 559 | < | |||
| 560 | < | |||
| 561 | /** | < | ||
| 562 | See whclob_vappendf(whclob*,char const *,va_list). This is identical | < | ||
| 563 | except that it takes an elipses list instead of va_list. | < | ||
| 564 | */ | < | ||
| 565 | long whclob_appendf( whclob * cb, const char * fmt, ... ); | < | ||
| 566 | < | |||
| 567 | < | |||
| 568 | < | |||
| 569 | /** | < | ||
| 570 | Reads up to n bytes from src, starting at startPos, and copies them | < | ||
| 571 | to dest. This does not advance cb's internal cursor. | < | ||
| 572 | < | |||
| 573 | On success the return value is the number of bytes read, which may | < | ||
| 574 | be less than n (or 0 on EOF). | < | ||
| 575 | < | |||
| 576 | On error it returns one of the negative values defined | < | ||
| 577 | in whclob_rc: | < | ||
| 578 | < | |||
| 579 | - whclob_rc.UnexpectedNull if src or dest are null | < | ||
| 580 | < | |||
| 581 | - whclob_rc.RangeError if n is less than 1 or if startPos is out of | < | ||
| 582 | src's bounds. | < | ||
| 583 | */ | < | ||
| 584 | long whclob_copy_slice( whclob * src, whclob * dest, long startPos, long n ); | < | ||
| 585 | < | |||
| 586 | /** | < | ||
| 587 | Reads up to n bytes from src, starting at the current | < | ||
| 588 | cursor position (whclob_tell()). Reading advances | < | ||
| 589 | the cursor. | < | ||
| 590 | < | |||
| 591 | The return value is the number of bytes read, which | < | ||
| 592 | may be less than n (or 0 on EOF). | < | ||
| 593 | */ | < | ||
| 594 | long whclob_read( whclob * src, whclob * dest, long n ); | < | ||
| 595 | < | |||
| 596 | /** | < | ||
| 597 | Returns the current position of cb's internal cursor, analogous to | < | ||
| 598 | the standard ftell() function. | < | ||
| 599 | */ | < | ||
| 600 | long whclob_tell( whclob const * cb ); | < | ||
| 601 | < | |||
| 602 | /** | < | ||
| 603 | This function is just like whclob_append() but it starts writing | < | ||
| 604 | at the position returned by whclob_tell(cb). Writing advances | < | ||
| 605 | the internal cursor. It returns the number of bytes written. | < | ||
| 606 | < | |||
| 607 | If dsize is -1 then strlen(data) is used for dsize. | < | ||
| 608 | < | |||
| 609 | On success it returns the number of bytes written. On failure it | < | ||
| 610 | returns a negative integer error code defined in whclob_rc: | < | ||
| 611 | < | |||
| 612 | - whclob_rc.AllocationError if memory could not be allocated. | < | ||
| 613 | < | |||
| 614 | - whclob_rc.RangeError if dsize is 0. | < | ||
| 615 | < | |||
| 616 | - whclob_rc.UnexpectedNull if data is 0. | < | ||
| 617 | */ | < | ||
| 618 | long whclob_write( whclob * cb, char const * data, long dsize ); | < | ||
| 619 | < | |||
| 620 | < | |||
| 621 | < | |||
| 622 | /** | < | ||
| 623 | This function ensures that the one-past-the-last item in the blob | < | ||
| 624 | to 0. The "used" size of cb does not change. | < | ||
| 625 | < | |||
| 626 | On success it returns whclob_rc.OK. On failure it returns one of the | < | ||
| 627 | negitive integer values defined in whclob_rc: | < | ||
| 628 | < | |||
| 629 | - whclob_rc.Err if cb does not own a pointer to an underlying blob. | < | ||
| 630 | < | |||
| 631 | - whclob_rc.AllocError if a memory (re)allocation fails. | < | ||
| 632 | */ | < | ||
| 633 | long whclob_null_terminate( whclob * cb ); | < | ||
| 634 | < | |||
| 635 | /** | < | ||
| 636 | "Chops" cb off at a given length. If the current used space is | < | ||
| 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. | < | ||
| 643 | < | |||
| 644 | If allocPolicy is 0 then the amount of memory allocated by cb is | < | ||
| 645 | not adjusted (unless (pos>whclob_size(cb)), in which case we have | < | ||
| 646 | to expand the clob). If it is >0, whclob_reserve() will be called | < | ||
| 647 | to try to reserve at least pos bytes. If (allocPolicy<0) then the | < | ||
| 648 | allocated memory is shrunk to fit (if possible). If pos is past the | < | ||
| 649 | current end-of-data position then allocPolicy is forced to 1 so | < | ||
| 650 | that the buffer can be expanded (if needed). | < | ||
| 651 | < | |||
| 652 | Returns whclob_rc.OK or a positive value on success or a negative | < | ||
| 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 | < | |||
| 664 | */ | < | ||
| 665 | long whclob_truncate( whclob * cb, long pos, int allocPolicy ); | < | ||
| 666 | < | |||
| 667 | /* TODO???: whclob_trim() */ | < | ||
| 668 | < | |||
| 669 | < | |||
| 670 | /** | < | ||
| 671 | whclob_exporter is a generic interface to exporting whclob objects | < | ||
| 672 | (e.g. to arbitrary streams). | < | ||
| 673 | < | |||
| 674 | Policy for implementations: | < | ||
| 675 | < | |||
| 676 | - Take a (char const *) data pointer and "export" n bytes of it, | < | ||
| 677 | where the meaning of "export" is implementation-specified. | < | ||
| 678 | < | |||
| 679 | - The 'arg' argument is an implementation-specific pointer. This API | < | ||
| 680 | does not use it, but passes it on so that client code can use it, e.g. | < | ||
| 681 | to accumulate or export data (e.g. by passing an output stream handle). | < | ||
| 682 | < | |||
| 683 | - On success it must return 0 or greater. Ideally it should return the | < | ||
| 684 | exact number of bytes processed, but that might not be feasible for | < | ||
| 685 | some implementations. In those cases, returning n is the best approach. | < | ||
| 686 | < | |||
| 687 | - On failure it must return a negative number, prefferably one of those | < | ||
| 688 | defined by whclob_rc. | < | ||
| 689 | */ | < | ||
| 690 | typedef long (*whclob_exporter)( void * arg, char const * data, long n ); | < | ||
| 691 | < | |||
| 692 | /** | < | ||
| 693 | whclob_export() is a generic interface for exporting blobs to | < | ||
| 694 | "external representations". | < | ||
| 695 | < | |||
| 696 | It calls pf( arg, ... ) one time to export cb's data using whatever | < | ||
| 697 | approach pf implements. The return value is that of calling pf. | < | ||
| 698 | */ | < | ||
| 699 | long whclob_export( whclob const * cb, void * arg, whclob_exporter pf ); | < | ||
| 700 | < | |||
| 701 | /** | < | ||
| 702 | whclob_importer is the import counterpart of whclob_exporter. It | < | ||
| 703 | defines an interface for callbacks which can provide a blob with | < | ||
| 704 | data. | < | ||
| 705 | < | |||
| 706 | Note that for input it is not generically possible to | < | ||
| 707 | get the length of the data before starting. Thus this | < | ||
| 708 | API takes a whclob object, which it can append to, whereas | < | ||
| 709 | the whclob_exporter functions take raw data pointers as | < | ||
| 710 | sources. | < | ||
| 711 | < | |||
| 712 | target must be an initialized whclob. It is appended to, | < | ||
| 713 | not overwritten. It is expanded as necessary. | < | ||
| 714 | < | |||
| 715 | Return value is the number of bytes appended to the target, or a | < | ||
| 716 | negative number on error (preferably one of the whclob_rc error | < | ||
| 717 | codes). | < | ||
| 718 | */ | < | ||
| 719 | typedef long (*whclob_importer)( whclob * target, void * arg ); | < | ||
| 720 | < | |||
| 721 | /** | < | ||
| 722 | Returns the same as pf( arg, dest ). | < | ||
| 723 | */ | < | ||
| 724 | long whclob_import( whclob * dest, void * arg, whclob_importer pf ); | < | ||
| 725 | < | |||
| 726 | /** | < | ||
| 727 | Moves a block of memory within cb, starting at start1, moving n | < | ||
| 728 | bytes to the position starting at start2. All points and ranges | < | ||
| 729 | must be in the whclob_size() range. start2 may be less than start1 | < | ||
| 730 | but they may not be equal. A value of less than 1 for n is not | < | ||
| 731 | currently supported, though it should be to support backwards | < | ||
| 732 | movement of memory. | < | ||
| 733 | < | |||
| 734 | Memory which is "moved" gets filled with the specified filler char | < | ||
| 735 | after its contents are copied to its new location. | < | ||
| 736 | < | |||
| 737 | This function does not change the size of cb. | < | ||
| 738 | < | |||
| 739 | On success it returns the number of bytes moved (n) | < | ||
| 740 | and on failure it returns: | < | ||
| 741 | < | |||
| 742 | - whclob_rc.RangeError if any values or ranges are out of bounds | < | ||
| 743 | < | |||
| 744 | - whclob_rc.UnexpectedNull if cb is null. | < | ||
| 745 | */ | < | ||
| 746 | long whclob_memmove_fill( whclob * cb, char const filler, int start1, int n, int start2 ); | < | ||
| 747 | < | |||
| 748 | /** | < | ||
| 749 | A convenience form of whclob_memmove_fill(cb,0,start1,n,start2). | < | ||
| 750 | */ | < | ||
| 751 | long whclob_memmove( whclob * cb, int start1, int n, int start2 ); | < | ||
| 752 | < | |||
| 753 | /** | < | ||
| 754 | Swaps the contents of n bytes between two blobs. start1 is relative | < | ||
| 755 | to cb1 and start2 is relative to cb2. | < | ||
| 756 | < | |||
| 757 | On success it returns the number of bytes swapped. On error it returns | < | ||
| 758 | one of: | < | ||
| 759 | < | |||
| 760 | - whclob_rc.UnexpectedNull if (!cb1) or (!cb2). | < | ||
| 761 | < | |||
| 762 | - whclob_rc.RangeError if start1 and n are not within cb1's bounds | < | ||
| 763 | or start2 and n are not within cb2's bounds. | < | ||
| 764 | < | |||
| 765 | This is a linear operation (based on the value of n). If you want | < | ||
| 766 | to swap the entire contents of two clobs, you can do so in constant | < | ||
| 767 | time by using whclob_swap() instead of this routine. | < | ||
| 768 | */ | < | ||
| 769 | long whclob_memswap( whclob * cb1, int start1, int n, whclob * cb2, int start2 ); | < | ||
| 770 | < | |||
| 771 | < | |||
| 772 | /** | < | ||
| 773 | Efficiently swaps the contents of blobs c1 and c2, which must | < | ||
| 774 | both be initialized clobs. | < | ||
| 775 | < | |||
| 776 | Returns whclob_rc.OK on success or whclob_rc.UnexpectedNull | < | ||
| 777 | if either c1 or c2 are null. | < | ||
| 778 | */ | < | ||
| 779 | long whclob_swap( whclob * c1, whclob * c2 ); | < | ||
| 780 | < | |||
| 781 | /** | < | ||
| 782 | Copies the contents of src to the dest, which | < | ||
| 783 | must be an UNINITIALIZED whclob object. | < | ||
| 784 | < | |||
| 785 | Returns whclob_rc.OK on success or, on error: | < | ||
| 786 | < | |||
| 787 | - whclob_rc.AllocError | < | ||
| 788 | < | |||
| 789 | - whclob_rc.UnexpectedNull if src is null. | < | ||
| 790 | < | |||
| 791 | Example usage: | < | ||
| 792 | < | |||
| 793 | \code | < | ||
| 794 | < | |||
| 795 | whclob * orig; | < | ||
| 796 | whclob_init( &orig ); | < | ||
| 797 | whclob_appendf( orig, "Hi, world." ); | < | ||
| 798 | whclob * clone; | < | ||
| 799 | whclob_clone( orig, &clone ); | < | ||
| 800 | < | |||
| 801 | \endcode | < | ||
| 802 | < | |||
| 803 | Note the pointer-to-pointer parameter for whclob_init() | < | ||
| 804 | and the second parameter to whclob_clone(). | < | ||
| 805 | < | |||
| 806 | */ | < | ||
| 807 | long whclob_clone( whclob * src, whclob ** dest ); | < | ||
| 808 | < | |||
| 809 | /** | < | ||
| 810 | Works more or less like sprintf(), but supports the printf | < | ||
| 811 | specifiers accepted by whclob_appendf() and can automatically | < | ||
| 812 | extends the string as necessary. The caller owns the returned | < | ||
| 813 | null-terminated string and must free it using free(). | < | ||
| 814 | */ | < | ||
| 815 | char * whclob_vmprintf( char const * fmt, va_list vargs ); | < | ||
| 816 | < | |||
| 817 | /** | < | ||
| 818 | Functionally identical to whclob_vmprintf() but takes | < | ||
| 819 | a (...) ellipses list instead of a va_list. | < | ||
| 820 | */ | < | ||
| 821 | char * whclob_mprintf( char const * fmt, ... ); | < | ||
| 822 | < | |||
| 823 | < | |||
| 824 | #if WHCLOB_USE_FILE | < | ||
| 825 | /** @implements whclob_exporter | < | ||
| 826 | < | |||
| 827 | This is a sample whclob_exporter for use with whclob_export. | < | ||
| 828 | It is used like this: | < | ||
| 829 | < | |||
| 830 | whclob_export( clob, an_open_FILE_handle, whclob_exporter_FILE ); | < | ||
| 831 | < | |||
| 832 | The second argument to whclob_export must be an open (FILE*). | < | ||
| 833 | < | |||
| 834 | Returns n on success and a negative number on error. | < | ||
| 835 | < | |||
| 836 | The file handle is not closed by this routine. | < | ||
| 837 | */ | < | ||
| 838 | long whclob_exporter_FILE( void * fh, char const * data, long n ); | < | ||
| 839 | < | |||
| 840 | /** | < | ||
| 841 | Like whclob_exporter_FILE(), but expects arg to be a (char const *) | < | ||
| 842 | filename. Returns the same as the equivalent whclob_exporter_FILE() | < | ||
| 843 | unless arg cannot be opened as a file, in which case | < | ||
| 844 | whclob_rc.IOError is returned. | < | ||
| 845 | */ | < | ||
| 846 | long whclob_exporter_filename( void * arg, char const * data, long n ); | < | ||
| 847 | < | |||
| 848 | /** | < | ||
| 849 | A whclob_importer implementation for whclob_import. It expects | < | ||
| 850 | arg to be an open (FILE*). The target is appended with the | < | ||
| 851 | contents of the file. On error, a negative number is returned. | < | ||
| 852 | On success, the number of bytes added to the target. | < | ||
| 853 | < | |||
| 854 | If arg is not a (FILE*) then whclob_rc.ArgError is returned. | < | ||
| 855 | < | |||
| 856 | The file handle is not closed by this routine. | < | ||
| 857 | */ | < | ||
| 858 | long whclob_importer_FILE( whclob * target, void * arg ); | < | ||
| 859 | < | |||
| 860 | /** | < | ||
| 861 | A whclob_importer implementation similar to whclob_importer_FILE(), but | < | ||
| 862 | expects arg to be a (char const *) filename. Returns the same as | < | ||
| 863 | the equivalent whclob_importer_FILE() call unless arg cannot be | < | ||
| 864 | opened as a file, in which case whclob_rc.IOError is returned. | < | ||
| 865 | */ | < | ||
| 866 | long whclob_importer_filename( whclob * target, void * arg ); | < | ||
| 867 | < | |||
| 868 | /** | < | ||
| 869 | Sends cb's blob to the given file handle, which must have been | < | ||
| 870 | previously opened. Returns the number of bytes written on success | < | ||
| 871 | or a negative number (probably whclob_rc.IOError) on error. | < | ||
| 872 | < | |||
| 873 | The file handle is not closed by this routine. | < | ||
| 874 | */ | < | ||
| 875 | long whclob_export_FILE( whclob const * cb, FILE * dest ); | < | ||
| 876 | < | |||
| 877 | /** | < | ||
| 878 | Identical to whclob_export_to_FILE() but takes a file | < | ||
| 879 | name. | < | ||
| 880 | */ | < | ||
| 881 | long whclob_export_filename( whclob const * cb, char const * dest ); | < | ||
| 882 | < | |||
| 883 | /** | < | ||
| 884 | The read counterpart of whclob_export_FILE(), appends all data | < | ||
| 885 | from src to cb. Return value is as for whclob_import(). | < | ||
| 886 | */ | < | ||
| 887 | long whclob_import_FILE( whclob * cb, FILE * src ); | < | ||
| 888 | < | |||
| 889 | /** | < | ||
| 890 | Identical to whclob_import_FILE() but takes a file | < | ||
| 891 | name. | < | ||
| 892 | */ | < | ||
| 893 | long whclob_import_filename( whclob * dest, char const * src ); | < | ||
| 894 | #endif /* WHCLOB_USE_FILE */ | < | ||
| 895 | < | |||
| 896 | #if WHCLOB_USE_ZLIB | < | ||
| 897 | /** | < | ||
| 898 | Compresses the contents of src to dest using the zlib compress() | < | ||
| 899 | function. dest may be either the same as src or an initialized | < | ||
| 900 | clob. If dest is not src then this function will clear dest's | < | ||
| 901 | contents whether or not this routine succeeds. If (dest==src) | < | ||
| 902 | then src is only modified if this routine succeeds. | < | ||
| 903 | < | |||
| 904 | Returns whclob_rc.OK on success, some other value on error: | < | ||
| 905 | < | |||
| 906 | - whclob_rc.IOError: compression failed | < | ||
| 907 | < | |||
| 908 | - whclob_rc.AllocError = a (re)allocation failed. | < | ||
| 909 | < | |||
| 910 | Note that the compressed data is compressed using zlib but contains | < | ||
| 911 | its own header, so it will not be usable by tools like gunzip. | < | ||
| 912 | */ | < | ||
| 913 | int whclob_compress( whclob * src, whclob * dest ); | < | ||
| 914 | < | |||
| 915 | /** | < | ||
| 916 | The converse of whclob_compress(), src is expected to be clob containing | < | ||
| 917 | data compressed with whclob_compress(). dest must be an initialized clob. | < | ||
| 918 | If dest is not the same as src then dest will be reset whether not | < | ||
| 919 | this routine succeeds. If (dest==src) then it is only modified | < | ||
| 920 | if this routine succeeds. | < | ||
| 921 | < | |||
| 922 | Returns whclob_rc.OK on success, some other value on error: | < | ||
| 923 | < | |||
| 924 | - whclob_rc.RangeError: source does not appear to contain any | < | ||
| 925 | compressed data or data was written by a different version of this | < | ||
| 926 | API. | < | ||
| 927 | < | |||
| 928 | - whclob_rc.ArgError: input is too small to contain the compression | < | ||
| 929 | header. | < | ||
| 930 | < | |||
| 931 | - whclob_rc.IOError: decompression failed | < | ||
| 932 | < | |||
| 933 | - whclob_rc.AllocError = a (re)allocation failed. | < | ||
| 934 | < | |||
| 935 | */ | < | ||
| 936 | int whclob_uncompress( whclob * src, whclob * dest ); | < | ||
| 937 | < | |||
| 938 | < | |||
| 939 | /** | < | ||
| 940 | Works equivalently to whclob_compress(), but uses the zlib deflate() | < | ||
| 941 | algorithm instead of the compress() algorithm. | < | ||
| 942 | */ | < | ||
| 943 | int whclob_deflate( whclob *cIn, whclob *cOut ); | < | ||
| 944 | < | |||
| 945 | /** | < | ||
| 946 | The converse of whclob_deflate(), this works equivalently to | < | ||
| 947 | whclob_uncompress(), but uses the zlib inflate() algorithm instead of | < | ||
| 948 | the uncompress() algorithm. | < | ||
| 949 | */ | < | ||
| 950 | int whclob_inflate( whclob *cIn, whclob *cOut ); | < | ||
| 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 | < | |||
| 976 | < | |||
| 977 | #ifdef __cplusplus | < | ||
| 978 | } /* extern "C" */ | < | ||
| 979 | #endif | < | ||
| 980 | #endif /* WANDERINGHORSE_NET_WHCLOB_H_INCLUDED_ */ | < | ||
Changes to include/s11n.net/c11n/io/c11n_io.h
| Old (836884ee4f81529a) | New (2df8e7de086cd98b) | |||
|---|---|---|---|---|
| 1 | #ifndef S11N_NET_C11N_IO_H_INCLUDED | 1 | #ifndef S11N_NET_C11N_IO_H_INCLUDED | |
| 2 | #define S11N_NET_C11N_IO_H_INCLUDED 1 | 2 | #define S11N_NET_C11N_IO_H_INCLUDED 1 | |
| 3 | /* | 3 | /* | |
| 4 | This file contains declarations and documentation for the generic | 4 | This file contains declarations and documentation for the generic | |
| 5 | i/o routines for c11n. The core does not know about this API and no | 5 | i/o routines for c11n. The core does not know about this API and no | |
| 307 hidden lines | ||||
| 313 | member, as documented in c11n_stream_api. Ownership of the underlying | 313 | member, as documented in c11n_stream_api. Ownership of the underlying | |
| 314 | native stream is defined by the factory function which creates | 314 | native stream is defined by the factory function which creates | |
| 315 | the stream. | 315 | the stream. | |
| 316 | 316 | |||
| 317 | For examples of creating concrete implementations of this type, | 317 | For examples of creating concrete implementations of this type, | |
| 318 | see the files c11n_stream_FILE.c and c11n_stream_whclob.c. | | | 318 | see the files c11n_stream_FILE.c and c11n_stream_memblob.c. |
| 319 | */ | 319 | */ | |
| 320 | struct c11n_stream | 320 | struct c11n_stream | |
| 321 | { | 321 | { | |
| 322 | /** | 322 | /** | |
| 323 | The api object represents the public API of this class. | 323 | The api object represents the public API of this class. | |
| 490 hidden lines | ||||
| 814 | strings containing backslash escapes in them. | 814 | strings containing backslash escapes in them. | |
| 815 | */ | 815 | */ | |
| 816 | size_t esc_len; | 816 | size_t esc_len; | |
| 817 | } c11n_string_escape_info; | 817 | } c11n_string_escape_info; | |
| 818 | 818 | |||
| 819 | struct whclob; // Provided by whclob.h | | | 819 | struct memblob; // Provided by memblob.h |
| 820 | 820 | |||
| 821 | /** | 821 | /** | |
| 822 | c11n_io_escape_string() is a generic string escaping/unescaping | 822 | c11n_io_escape_string() is a generic string escaping/unescaping | |
| 823 | routine. It scans the first inlen characters of input for entries | 823 | routine. It scans the first inlen characters of input for entries | |
| 824 | from the given table. On a match, it "replaces" the original with | 824 | from the given table. On a match, it "replaces" the original with | |
| 29 hidden lines | ||||
| 854 | {"&",1,"&",5}, | 854 | {"&",1,"&",5}, | |
| 855 | {"<",1,"<",4}, | 855 | {"<",1,"<",4}, | |
| 856 | {">",1,">",4}, | 856 | {">",1,">",4}, | |
| 857 | {0,0,0,0} | 857 | {0,0,0,0} | |
| 858 | }; | 858 | }; | |
| 859 | whclob * dest = whclob_new(); | | | 859 | memblob * dest = memblob_new(); |
| 860 | c11n_io_escape_str( input, inlen, escapes, true, dest ); | 860 | c11n_io_escape_str( input, inlen, escapes, true, dest ); | |
| 861 | printf("%s\n", whclob_bufferc(dest) ); // A%20B%20<C> | | | 861 | printf("%s\n", memblob_bufferc(dest) ); // A%20B%20<C> |
| 862 | whclob_finalize(dest); | | | 862 | memblob_finalize(dest); |
| 863 | @endcode | 863 | @endcode | |
| 864 | */ | 864 | */ | |
| 865 | size_t c11n_io_escape_string( c11n_const_string_t input, size_t inlen, | 865 | size_t c11n_io_escape_string( c11n_const_string_t input, size_t inlen, | |
| 866 | c11n_string_escape_info const * table, | 866 | c11n_string_escape_info const * table, | |
| 867 | bool doEscape, | 867 | bool doEscape, | |
| 868 | struct whclob * target ); | | | 868 | struct memblob * target ); |
| 869 | 869 | |||
| 870 | 870 | |||
| 871 | /** | 871 | /** | |
| 872 | Consumes stream to the first \\n character. It appends that data, minus the newline, | 872 | Consumes stream to the first \\n character. It appends that data, minus the newline, | |
| 873 | to dest. Returns the number of characters appended to dest, or 0 at EOF or on a read | 873 | to dest. Returns the number of characters appended to dest, or 0 at EOF or on a read | |
| 874 | error. | 874 | error. | |
| 875 | 875 | |||
| 876 | Note that the stream is consumed and the trailing newline character | 876 | Note that the stream is consumed and the trailing newline character | |
| 877 | (if any) is effectively lost. | 877 | (if any) is effectively lost. | |
| 878 | */ | 878 | */ | |
| 879 | size_t c11n_stream_readln_membuf(c11n_stream * stream, struct whclob * dest ); | | | 879 | size_t c11n_stream_readln_membuf(c11n_stream * stream, struct memblob * dest ); |
| 880 | 880 | |||
| 881 | /** | 881 | /** | |
| 882 | Functionally identical to c11n_stream_readln_membuf() except that the | 882 | Functionally identical to c11n_stream_readln_membuf() except that the | |
| 883 | line is returned as a null-termined string which the caller must | 883 | line is returned as a null-termined string which the caller must | |
| 884 | clean up using free(). On error or EOF 0 is returned. | 884 | clean up using free(). On error or EOF 0 is returned. | |
| 3 hidden lines | ||||
| 888 | #ifdef __cplusplus | 888 | #ifdef __cplusplus | |
| 889 | } /* extern "C" */ | 889 | } /* extern "C" */ | |
| 890 | #endif | 890 | #endif | |
| 891 | 891 | |||
| 892 | #endif // S11N_NET_C11N_IO_H_INCLUDED | 892 | #endif // S11N_NET_C11N_IO_H_INCLUDED | |
Added include/s11n.net/c11n/io/c11n_stream_memblob.h
| Old () | New (08275c48f0dba287) | |||
|---|---|---|---|---|
| > | 1 | #if !defined(_S11N_NET_C11N_STREAM_MEMBLOB_H_INCLUDED_) | ||
| > | 2 | #define _S11N_NET_C11N_STREAM_MEMBLOB_H_INCLUDED_ 1 | ||
| > | 3 | |||
| > | 4 | #include "c11n_io.h" | ||
| > | 5 | #ifdef __cplusplus | ||
| > | 6 | extern "C" { | ||
| > | 7 | #endif | ||
| > | 8 | |||
| > | 9 | /** Provided by memblob.h */ | ||
| > | 10 | struct memblob; | ||
| > | 11 | |||
| > | 12 | /** | ||
| > | 13 | Creates a stream which uses memblob object as its i/o | ||
| > | 14 | source/destination, thus providing an in-memory i/o buffer. The | ||
| > | 15 | clob parameter is of type memblob, which is defined in the | ||
| > | 16 | memblob API (see: @ref memblob_page_main). | ||
| > | 17 | |||
| > | 18 | It supports both read and write modes, but be aware of the | ||
| > | 19 | cursor semantics of the memblob API before trying to use it for | ||
| > | 20 | both. It is safest (and most predictable) to use it for only | ||
| > | 21 | reading or writing, not both. | ||
| > | 22 | |||
| > | 23 | The returned stream object must be destroyed by calling | ||
| > | 24 | stream->api->destroy(stream). | ||
| > | 25 | |||
| > | 26 | Requirements of the clob object are: | ||
| > | 27 | |||
| > | 28 | - It is owned by the caller. Calling stream->api->destroy(stream) | ||
| > | 29 | does not modify the clob (but does destroy the stream object). | ||
| > | 30 | |||
| > | 31 | - When the stream is written to, the data is appended to the current | ||
| > | 32 | cursor position of clob, growing the clob as needed. | ||
| > | 33 | |||
| > | 34 | - When the stream is read, the data is read from the current | ||
| > | 35 | cursor position of clob. It will not, of course, read past | ||
| > | 36 | the logical EOF. | ||
| > | 37 | |||
| > | 38 | In other words: | ||
| > | 39 | |||
| > | 40 | If stream->api->read() is called then the source clob must be | ||
| > | 41 | pre-populated by the caller so that we have something to read | ||
| > | 42 | out. That data is then copied to the stream->api->read() | ||
| > | 43 | destination pointer. If stream->api->write() is called, the data | ||
| > | 44 | from that source will be appended to the clob using | ||
| > | 45 | memblob_append(). | ||
| > | 46 | |||
| > | 47 | Behaviour is undefined if calls to stream->api->read(), | ||
| > | 48 | stream->api->write(), and/or the memblob API are inter-mixed, | ||
| > | 49 | with the exception that it is safe to use memblob_rewind() | ||
| > | 50 | to re-set an input buffer to its begining position. | ||
| > | 51 | |||
| > | 52 | When using output clob-streams to buffer any significant | ||
| > | 53 | amount of data, it is a good idea to initialize the clob | ||
| > | 54 | to some reasonable buffer size, e.g. using either memblob_init() | ||
| > | 55 | or memblob_reserve(). | ||
| > | 56 | */ | ||
| > | 57 | c11n_stream * c11n_stream_for_memblob( struct memblob * clob ); | ||
| > | 58 | |||
| > | 59 | /** | ||
| > | 60 | Reads at most max bytes from src and appends them to dest. Returns | ||
| > | 61 | the number of bytes read, or 0 if any arguments are 0, if 0 bytes | ||
| > | 62 | are read, or if dest needs to grow and a re-allocation fails. | ||
| > | 63 | */ | ||
| > | 64 | size_t c11n_stream_buffer_read( c11n_stream * src, struct memblob * dest, size_t max ); | ||
| > | 65 | |||
| > | 66 | |||
| > | 67 | #ifdef __cplusplus | ||
| > | 68 | } /* extern "C" */ | ||
| > | 69 | #endif | ||
| > | 70 | #endif /* _S11N_NET_C11N_STREAM_MEMBLOB_H_INCLUDED_ */ | ||
Deleted include/s11n.net/c11n/io/c11n_stream_whclob.h
| Old (b57814d48905a293) | New () | |||
|---|---|---|---|---|
| 1 | #if !defined(_S11N_NET_C11N_STREAM_WHCLOB_H_INCLUDED_) | < | ||
| 2 | #define _S11N_NET_C11N_STREAM_WHCLOB_H_INCLUDED_ 1 | < | ||
| 3 | < | |||
| 4 | #include "c11n_io.h" | < | ||
| 5 | #ifdef __cplusplus | < | ||
| 6 | extern "C" { | < | ||
| 7 | #endif | < | ||
| 8 | < | |||
| 9 | /** Provided by whclob.h */ | < | ||
| 10 | struct whclob; | < | ||
| 11 | < | |||
| 12 | /** | < | ||
| 13 | Creates a stream which uses whclob object as its i/o | < | ||
| 14 | source/destination, thus providing an in-memory i/o buffer. The | < | ||
| 15 | clob parameter is of type whclob, which is defined in the | < | ||
| 16 | whclob API (see: @ref whclob_page_main). | < | ||
| 17 | < | |||
| 18 | It supports both read and write modes, but be aware of the | < | ||
| 19 | cursor semantics of the whclob API before trying to use it for | < | ||
| 20 | both. It is safest (and most predictable) to use it for only | < | ||
| 21 | reading or writing, not both. | < | ||
| 22 | < | |||
| 23 | The returned stream object must be destroyed by calling | < | ||
| 24 | stream->api->destroy(stream). | < | ||
| 25 | < | |||
| 26 | Requirements of the clob object are: | < | ||
| 27 | < | |||
| 28 | - It is owned by the caller. Calling stream->api->destroy(stream) | < | ||
| 29 | does not modify the clob (but does destroy the stream object). | < | ||
| 30 | < | |||
| 31 | - When the stream is written to, the data is appended to the current | < | ||
| 32 | cursor position of clob, growing the clob as needed. | < | ||
| 33 | < | |||
| 34 | - When the stream is read, the data is read from the current | < | ||
| 35 | cursor position of clob. It will not, of course, read past | < | ||
| 36 | the logical EOF. | < | ||
| 37 | < | |||
| 38 | In other words: | < | ||
| 39 | < | |||
| 40 | If stream->api->read() is called then the source clob must be | < | ||
| 41 | pre-populated by the caller so that we have something to read | < | ||
| 42 | out. That data is then copied to the stream->api->read() | < | ||
| 43 | destination pointer. If stream->api->write() is called, the data | < | ||
| 44 | from that source will be appended to the clob using | < | ||
| 45 | whclob_append(). | < | ||
| 46 | < | |||
| 47 | Behaviour is undefined if calls to stream->api->read(), | < | ||
| 48 | stream->api->write(), and/or the whclob API are inter-mixed, | < | ||
| 49 | with the exception that it is safe to use whclob_rewind() | < | ||
| 50 | to re-set an input buffer to its begining position. | < | ||
| 51 | < | |||
| 52 | When using output clob-streams to buffer any significant | < | ||
| 53 | amount of data, it is a good idea to initialize the clob | < | ||
| 54 | to some reasonable buffer size, e.g. using either whclob_init() | < | ||
| 55 | or whclob_reserve(). | < | ||
| 56 | */ | < | ||
| 57 | c11n_stream * c11n_stream_for_whclob( struct whclob * clob ); | < | ||
| 58 | < | |||
| 59 | /** | < | ||
| 60 | Reads at most max bytes from src and appends them to dest. Returns | < | ||
| 61 | the number of bytes read, or 0 if any arguments are 0, if 0 bytes | < | ||
| 62 | are read, or if dest needs to grow and a re-allocation fails. | < | ||
| 63 | */ | < | ||
| 64 | size_t c11n_stream_buffer_read( c11n_stream * src, struct whclob * dest, size_t max ); | < | ||
| 65 | < | |||
| 66 | < | |||
| 67 | #ifdef __cplusplus | < | ||
| 68 | } /* extern "C" */ | < | ||
| 69 | #endif | < | ||
| 70 | #endif /* _S11N_NET_C11N_STREAM_WHCLOB_H_INCLUDED_ */ | < | ||
Changes to src/Makefile
| Old (32cc1aaa4916df68) | New (7db471d71f7f96e9) | |||
|---|---|---|---|---|
| 1 | #!/usr/bin/make -f | 1 | #!/usr/bin/make -f | |
| 2 | # Requires GNU Make 3.80+! | 2 | # Requires GNU Make 3.80+! | |
| 3 | default: all | 3 | default: all | |
| 4 | 4 | |||
| 5 | ifeq (1,$(TCC)) | 5 | ifeq (1,$(TCC)) | |
| 97 hidden lines | ||||
| 103 | $(call ShakeNMake.CALL.RULES.LIBS,libwhgc) | 103 | $(call ShakeNMake.CALL.RULES.LIBS,libwhgc) | |
| 104 | $(libwhgc.LIB): $(libwhhash.LIB) | 104 | $(libwhgc.LIB): $(libwhhash.LIB) | |
| 105 | 105 | |||
| 106 | ######################################################################## | 106 | ######################################################################## | |
| 107 | # Clob lib | 107 | # Clob lib | |
| 108 | WHCLOB_OBJ := whclob.o vappendf.o cencode.o cdecode.o | | | 108 | MEMBLOB_OBJ := memblob.o vappendf.o cencode.o cdecode.o |
| 109 | libwhclob.LIB.OBJECTS = $(WHCLOB_OBJ) | | | 109 | libmemblob.LIB.OBJECTS = $(MEMBLOB_OBJ) |
| 110 | $(call ShakeNMake.CALL.RULES.LIBS,libwhclob) | | | 110 | $(call ShakeNMake.CALL.RULES.LIBS,libmemblob) |
| 111 | libs: $(libwhclob.LIB) | | | 111 | libs: $(libmemblob.LIB) |
| 112 | 112 | |||
| 113 | ######################################################################## | 113 | ######################################################################## | |
| 114 | # Reference counting lib | 114 | # Reference counting lib | |
| 115 | #WHRC_OBJ := whrc.o | 115 | #WHRC_OBJ := whrc.o | |
| 116 | #libwhrc.LIB.OBJECTS = $(WHRC_OBJ) $(libwhhash.LIB) | 116 | #libwhrc.LIB.OBJECTS = $(WHRC_OBJ) $(libwhhash.LIB) | |
| 118 | #libs: $(libwhrc.LIB) | 118 | #libs: $(libwhrc.LIB) | |
| 119 | 119 | |||
| 120 | 120 | |||
| 121 | ######################################################################## | 121 | ######################################################################## | |
| 122 | # c11n lib: | 122 | # c11n lib: | |
| 123 | libc11n.LIB.EXTRALIBS := $(libwhclob.LIB) | | | 123 | libc11n.LIB.EXTRALIBS := $(libmemblob.LIB) |
| 124 | libc11n.LIB.EXTRAOBJ := $(libwhclob.LIB.OBJECTS) $(libwhhash.LIB.OBJECTS) | | | 124 | libc11n.LIB.EXTRAOBJ := $(libmemblob.LIB.OBJECTS) $(libwhhash.LIB.OBJECTS) |
| 125 | # libc11n.DLL.EXTRAOBJ := $(libc11n.LIB.EXTRAOBJ) | 125 | # libc11n.DLL.EXTRAOBJ := $(libc11n.LIB.EXTRAOBJ) | |
| 126 | # libc11n.DLL.LDFLAGS := -L. -lwhclob -L. -lwhhash | | | 126 | # libc11n.DLL.LDFLAGS := -L. -lmemblob -L. -lwhhash |
| 127 | # $(libwhgc.LIB) $(libwhhash.LIB) | 127 | # $(libwhgc.LIB) $(libwhhash.LIB) | |
| 128 | libc11n.LIB.OBJECTS := c11n.o c11n_io.o | 128 | libc11n.LIB.OBJECTS := c11n.o c11n_io.o | |
| 129 | libc11n.LIB.OBJECTS += c11n_io_handler_binarish.o | 129 | libc11n.LIB.OBJECTS += c11n_io_handler_binarish.o | |
| 130 | libc11n.LIB.OBJECTS += c11n_stream_FILE.o | 130 | libc11n.LIB.OBJECTS += c11n_stream_FILE.o | |
| 131 | libc11n.LIB.OBJECTS += c11n_stream_whclob.o | | | 131 | libc11n.LIB.OBJECTS += c11n_stream_memblob.o |
| 132 | libc11n.DLL.LDFLAGS += $(SQLITE3.LDFLAGS) $(EXPAT_LDFLAGS) | 132 | libc11n.DLL.LDFLAGS += $(SQLITE3.LDFLAGS) $(EXPAT_LDFLAGS) | |
| 133 | 133 | |||
| 134 | ifeq (1,$(USE_SQLITE3)) | 134 | ifeq (1,$(USE_SQLITE3)) | |
| 135 | libc11n.LIB.OBJECTS += c11n_io_handler_sql.o | 135 | libc11n.LIB.OBJECTS += c11n_io_handler_sql.o | |
| 136 | test.o c11n_io.o c11n_io_handler_sql.o: CPPFLAGS+=$(SQLITE3.CPPFLAGS) | 136 | test.o c11n_io.o c11n_io_handler_sql.o: CPPFLAGS+=$(SQLITE3.CPPFLAGS) | |
| 13 hidden lines | ||||
| 150 | libc11n.LIB.OBJECTS += $(libc11n.LIB.EXTRALIBS) | 150 | libc11n.LIB.OBJECTS += $(libc11n.LIB.EXTRALIBS) | |
| 151 | endif | 151 | endif | |
| 152 | libc11n.DLL.OBJECTS := $(libc11n.LIB.OBJECTS) | 152 | libc11n.DLL.OBJECTS := $(libc11n.LIB.OBJECTS) | |
| 153 | $(call ShakeNMake.CALL.RULES.LIBS,libc11n) | 153 | $(call ShakeNMake.CALL.RULES.LIBS,libc11n) | |
| 154 | $(call ShakeNMake.CALL.RULES.DLLS,libc11n) | 154 | $(call ShakeNMake.CALL.RULES.DLLS,libc11n) | |
| 155 | $(libc11n.LIB): $(libwhhash.LIB) $(libwhclob.LIB) | | | 155 | $(libc11n.LIB): $(libwhhash.LIB) $(libmemblob.LIB) |
| 156 | $(libc11n.DLL): $(libwhhash.LIB) $(libwhclob.LIB) | | | 156 | $(libc11n.DLL): $(libwhhash.LIB) $(libmemblob.LIB) |
| 157 | libs: $(libc11n.LIB) | 157 | libs: $(libc11n.LIB) | |
| 158 | ifneq (1,$(TCC)) | 158 | ifneq (1,$(TCC)) | |
| 159 | libs: $(libc11n.DLL) | 159 | libs: $(libc11n.DLL) | |
| 160 | endif | 160 | endif | |
| 161 | 161 | |||
| 9 hidden lines | ||||
| 171 | bins: $(test.BIN) | 171 | bins: $(test.BIN) | |
| 172 | bins: | 172 | bins: | |
| 173 | 173 | |||
| 174 | scratch.o: CFLAGS += -Wno-format | 174 | scratch.o: CFLAGS += -Wno-format | |
| 175 | scratch.BIN.LDFLAGS := $(libc11n.LIB) $(EXPAT_LDFLAGS) $(SQLITE3.LDFLAGS) | 175 | scratch.BIN.LDFLAGS := $(libc11n.LIB) $(EXPAT_LDFLAGS) $(SQLITE3.LDFLAGS) | |
| 176 | scratch.BIN.OBJECTS := scratch.o whclob.o | | | 176 | scratch.BIN.OBJECTS := scratch.o memblob.o |
| 177 | $(call ShakeNMake.CALL.RULES.BINS,scratch) | 177 | $(call ShakeNMake.CALL.RULES.BINS,scratch) | |
| 178 | $(scratch.BIN): $(libc11n.LIB) | 178 | $(scratch.BIN): $(libc11n.LIB) | |
| 179 | bins: $(scratch.BIN) | 179 | bins: $(scratch.BIN) | |
| 180 | 180 | |||
| 181 | 181 | |||
| 182 | clobtest.o: CFLAGS += -Wno-format | 182 | clobtest.o: CFLAGS += -Wno-format | |
| 183 | clobtest.BIN.LDFLAGS := $(libwhclob.LIB) | | | 183 | clobtest.BIN.LDFLAGS := $(libmemblob.LIB) |
| 184 | clobtest.BIN.OBJECTS := test-clob.o | 184 | clobtest.BIN.OBJECTS := test-clob.o | |
| 185 | $(call ShakeNMake.CALL.RULES.BINS,clobtest) | 185 | $(call ShakeNMake.CALL.RULES.BINS,clobtest) | |
| 186 | $(clobtest.BIN): $(libwhclob.LIB) | | | 186 | $(clobtest.BIN): $(libmemblob.LIB) |
| 187 | bins: $(clobtest.BIN) | 187 | bins: $(clobtest.BIN) | |
| 188 | 188 | |||
| 189 | 189 | |||
| 190 | c11nconvert.BIN.LDFLAGS := $(libc11n.LIB) $(libwhgc.LIB) $(SQLITE3.LDFLAGS) $(EXPAT_LDFLAGS) | 190 | c11nconvert.BIN.LDFLAGS := $(libc11n.LIB) $(libwhgc.LIB) $(SQLITE3.LDFLAGS) $(EXPAT_LDFLAGS) | |
| 191 | c11nconvert.BIN.OBJECTS := c11nconvert.o | 191 | c11nconvert.BIN.OBJECTS := c11nconvert.o | |
| 11 hidden lines | ||||
| 203 | #$(MEGA.BIN): $(libc11n.LIB) $(libwhgc.LIB) | 203 | #$(MEGA.BIN): $(libc11n.LIB) $(libwhgc.LIB) | |
| 204 | # tcc $(INCLUDES) -r -o $(MEGA.OBJ) $(wildcard c11n*.c wh*.c vappendf.c) | 204 | # tcc $(INCLUDES) -r -o $(MEGA.OBJ) $(wildcard c11n*.c wh*.c vappendf.c) | |
| 205 | # tcc -o $(MEGA.BIN) $(MEGA.OBJ) $(SQLITE3.LDFLAGS) | 205 | # tcc -o $(MEGA.BIN) $(MEGA.OBJ) $(SQLITE3.LDFLAGS) | |
| 206 | 206 | |||
| 207 | all: libs bins | 207 | all: libs bins | |
Changes to src/c11n.c
| Old (b5a36e9c9e733543) | New (086c5ad92b49d852) | |||
|---|---|---|---|---|
| 1 | /** | 1 | /** | |
| 2 | This the main implementation file for the c11n core library. Some | 2 | This the main implementation file for the c11n core library. Some | |
| 3 | maintenance notes: | 3 | maintenance notes: | |
| 4 | 4 | |||
| 5 | - NO dependency on any code from the c11n_io API is allowed. | 5 | - NO dependency on any code from the c11n_io API is allowed. | |
| 51 hidden lines | ||||
| 57 | 57 | |||
| 58 | See 'man feature_test_macros': | 58 | See 'man feature_test_macros': | |
| 59 | 59 | |||
| 60 | _FORTIFY_SOURCE | 60 | _FORTIFY_SOURCE | |
| 61 | 61 | |||
| 62 | we should add that to the whclob and whhash APIs. ??? | | | 62 | we should add that to the memblob and whhash APIs. ??? |
| 63 | 63 | |||
| 64 | */ | 64 | */ | |
| 65 | 65 | |||
| 66 | #include <stdlib.h> | 66 | #include <stdlib.h> | |
| 67 | #include <string.h> /* strcmp() */ | 67 | #include <string.h> /* strcmp() */ | |
| 68 | 68 | |||
| 69 | #include "s11n.net/c11n/c11n.h" | 69 | #include "s11n.net/c11n/c11n.h" | |
| 70 | //#include "whgc.h" | 70 | //#include "whgc.h" | |
| 71 | //#include "whhash.h" | 71 | //#include "whhash.h" | |
| 72 | #include "s11n.net/c11n/detail/whclob.h" | | | 72 | #include "s11n.net/c11n/detail/memblob.h" |
| 73 | #include "s11n.net/c11n/detail/vappendf.h" | 73 | #include "s11n.net/c11n/detail/vappendf.h" | |
| 74 | 74 | |||
| 75 | #ifdef __cplusplus | 75 | #ifdef __cplusplus | |
| 76 | #define ARG_UNUSED(X) | 76 | #define ARG_UNUSED(X) | |
| 77 | extern "C" { | 77 | extern "C" { | |
| 337 hidden lines | ||||
| 415 | Maybe todo: don't implement in terms of c11n_node_prop_give_kvp() because | 415 | Maybe todo: don't implement in terms of c11n_node_prop_give_kvp() because | |
| 416 | doing so costs us one extra copy of key when re-setting an existing | 416 | doing so costs us one extra copy of key when re-setting an existing | |
| 417 | property. | 417 | property. | |
| 418 | */ | 418 | */ | |
| 419 | return c11n_node_prop_give_kvp( n, c11n_copy_str(key), | 419 | return c11n_node_prop_give_kvp( n, c11n_copy_str(key), | |
| 420 | fmt ? whclob_vmprintf( fmt, vargs ) : 0 ); | | | 420 | fmt ? memblob_vmprintf( fmt, vargs ) : 0 ); |
| 421 | } | 421 | } | |
| 422 | 422 | |||
| 423 | bool c11n_node_prop_set_fe( c11n_node *n, c11n_key_type key, c11n_const_string_t fmt, ... ) | 423 | bool c11n_node_prop_set_fe( c11n_node *n, c11n_key_type key, c11n_const_string_t fmt, ... ) | |
| 424 | { | 424 | { | |
| 425 | va_list vargs; | 425 | va_list vargs; | |
| 639 hidden lines | ||||
| 1065 | } | 1065 | } | |
| 1066 | 1066 | |||
| 1067 | bool c11n_serialize_binary( c11n_node * dest, void const * src, size_t sizeOf ) | 1067 | bool c11n_serialize_binary( c11n_node * dest, void const * src, size_t sizeOf ) | |
| 1068 | { | 1068 | { | |
| 1069 | if( ! dest || !src || !sizeOf ) return false; | 1069 | if( ! dest || !src || !sizeOf ) return false; | |
| 1070 | whclob * buf = whclob_new_n( sizeOf ); | | | 1070 | memblob * buf = memblob_new_n( sizeOf ); |
| 1071 | if( ! buf ) return false; | 1071 | if( ! buf ) return false; | |
| 1072 | whclob_append( buf, src, sizeOf ); | | | 1072 | memblob_append( buf, src, sizeOf ); |
| 1073 | whclob_base64_enc( buf, buf ); | | | 1073 | memblob_base64_enc( buf, buf ); |
| 1074 | c11n_node_prop_set_fe( dest, "size", "%u", sizeOf ); | 1074 | c11n_node_prop_set_fe( dest, "size", "%u", sizeOf ); | |
| 1075 | c11n_string_t key = c11n_copy_str( "base64" ); | 1075 | c11n_string_t key = c11n_copy_str( "base64" ); | |
| 1076 | char * val = whclob_take_buffer( buf ); | | | 1076 | char * val = memblob_take_buffer( buf ); |
| 1077 | if( ! c11n_node_prop_give_kvp( dest, key, val ) ) | 1077 | if( ! c11n_node_prop_give_kvp( dest, key, val ) ) | |
| 1078 | { | 1078 | { | |
| 1079 | free(key); | 1079 | free(key); | |
| 1080 | free(val); | 1080 | free(val); | |
| 1081 | } | 1081 | } | |
| 1082 | whclob_finalize( buf ); | | | 1082 | memblob_finalize( buf ); |
| 1083 | return true; | 1083 | return true; | |
| 1084 | } | 1084 | } | |
| 1085 | 1085 | |||
| 1086 | bool c11n_deserialize_binary( c11n_node const * src, c11n_binary_data * dest ) | 1086 | bool c11n_deserialize_binary( c11n_node const * src, c11n_binary_data * dest ) | |
| 1087 | { | 1087 | { | |
| 6 hidden lines | ||||
| 1094 | c11n_const_string_t val = 0; | 1094 | c11n_const_string_t val = 0; | |
| 1095 | if( ! c11n_node_prop_get( src, "base64", &val ) || !val ) return false; | 1095 | if( ! c11n_node_prop_get( src, "base64", &val ) || !val ) return false; | |
| 1096 | dest->data = malloc(sz); | 1096 | dest->data = malloc(sz); | |
| 1097 | if( ! dest->data ) return false; | 1097 | if( ! dest->data ) return false; | |
| 1098 | memset( dest->data, 0, sz ); | 1098 | memset( dest->data, 0, sz ); | |
| 1099 | whclob * cb = whclob_new(); | | | 1099 | memblob * cb = memblob_new(); |
| 1100 | whclob_append( cb, val, -1 ); | | | 1100 | memblob_append( cb, val, -1 ); |
| 1101 | //MARKER("whclob_size(cb) ==%ld, strlen(val)=%d val=[%s]\n",whclob_size(cb),strlen(val),val); | | | 1101 | //MARKER("memblob_size(cb) ==%ld, strlen(val)=%d val=[%s]\n",memblob_size(cb),strlen(val),val); |
| 1102 | bool rc = true; | 1102 | bool rc = true; | |
| 1103 | if( ! cb ) | 1103 | if( ! cb ) | |
| 1104 | { | 1104 | { | |
| 1105 | rc = false; | 1105 | rc = false; | |
| 1106 | free( dest->data ); | 1106 | free( dest->data ); | |
| 1107 | dest->data = 0; | 1107 | dest->data = 0; | |
| 1108 | } | 1108 | } | |
| 1109 | else | 1109 | else | |
| 1110 | { | 1110 | { | |
| 1111 | whclob_base64_dec( cb, cb ); | | | 1111 | memblob_base64_dec( cb, cb ); |
| 1112 | if( (size_t)whclob_size(cb) != sz ) | | | 1112 | if( (size_t)memblob_size(cb) != sz ) |
| 1113 | { | 1113 | { | |
| 1114 | rc = false; | 1114 | rc = false; | |
| 1115 | C11N_LOG(C11N_LOG_ERROR)("Declared size of data (%u) is not the same as the decoded size (%ld)", | 1115 | C11N_LOG(C11N_LOG_ERROR)("Declared size of data (%u) is not the same as the decoded size (%ld)", | |
| 1116 | sz, whclob_size(cb)); | | | 1116 | sz, memblob_size(cb)); |
| 1117 | } | 1117 | } | |
| 1118 | else | 1118 | else | |
| 1119 | { | 1119 | { | |
| 1120 | memcpy( dest->data, whclob_bufferc(cb), sz ); | | | 1120 | memcpy( dest->data, memblob_bufferc(cb), sz ); |
| 1121 | } | 1121 | } | |
| 1122 | } | 1122 | } | |
| 1123 | whclob_finalize( cb ); | | | 1123 | memblob_finalize( cb ); |
| 1124 | return rc; | 1124 | return rc; | |
| 1125 | } | 1125 | } | |
| 1126 | 1126 | |||
| 1127 | 1127 | |||
| 1128 | 1128 | |||
| 373 hidden lines | ||||
| 1502 | #undef C11N_MARSHALLER_INIT | 1502 | #undef C11N_MARSHALLER_INIT | |
| 1503 | #undef C11N_MARSHALLER_API_DEFAULT | 1503 | #undef C11N_MARSHALLER_API_DEFAULT | |
| 1504 | #ifdef __cplusplus | 1504 | #ifdef __cplusplus | |
| 1505 | } /* extern "C" */ | 1505 | } /* extern "C" */ | |
| 1506 | #endif | 1506 | #endif | |
Changes to src/c11n_io.c
| Old (05c59b17a65104d1) | New (0ffdba378af16ac7) | |||
|---|---|---|---|---|
| 1 | #ifndef _FILE_OFFSET_BITS | 1 | #ifndef _FILE_OFFSET_BITS | |
| 2 | /** See 'man feature_test_macros' on a gcc system */ | 2 | /** See 'man feature_test_macros' on a gcc system */ | |
| 3 | # define _FILE_OFFSET_BITS 64 | 3 | # define _FILE_OFFSET_BITS 64 | |
| 4 | #endif | 4 | #endif | |
| 5 | #ifndef _ISOC99_SOURCE | 5 | #ifndef _ISOC99_SOURCE | |
| 12 hidden lines | ||||
| 18 | #include <string.h> /* strlen() */ | 18 | #include <string.h> /* strlen() */ | |
| 19 | #include <ctype.h> /* isspace() and friends. */ | 19 | #include <ctype.h> /* isspace() and friends. */ | |
| 20 | #include <stddef.h> /* size_t */ | 20 | #include <stddef.h> /* size_t */ | |
| 21 | 21 | |||
| 22 | #include "s11n.net/c11n/io/c11n_io.h" | 22 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 23 | #include "s11n.net/c11n/detail/whclob.h" | | | 23 | #include "s11n.net/c11n/detail/memblob.h" |
| 24 | #include "s11n.net/c11n/detail/vappendf.h" | 24 | #include "s11n.net/c11n/detail/vappendf.h" | |
| 25 | 25 | |||
| 26 | #ifdef __cplusplus | 26 | #ifdef __cplusplus | |
| 27 | #define ARG_UNUSED(X) | 27 | #define ARG_UNUSED(X) | |
| 28 | extern "C" { | 28 | extern "C" { | |
| 277 hidden lines | ||||
| 306 | 306 | |||
| 307 | 307 | |||
| 308 | c11n_node * c11n_load_node( c11n_stream * src ) | 308 | c11n_node * c11n_load_node( c11n_stream * src ) | |
| 309 | { | 309 | { | |
| 310 | if( ! src ) return 0; | 310 | if( ! src ) return 0; | |
| 311 | whclob * cb = 0; | | | 311 | memblob * cb = 0; |
| 312 | whclob_init( &cb, 0, 80 ); | | | 312 | memblob_init( &cb, 0, 80 ); |
| 313 | char ch; | 313 | char ch; | |
| 314 | while( c11n_stream_getchar( src, &ch ) ) | 314 | while( c11n_stream_getchar( src, &ch ) ) | |
| 315 | { | 315 | { | |
| 316 | if( (ch < 32) || (ch>=127) ) | 316 | if( (ch < 32) || (ch>=127) ) | |
| 317 | { | 317 | { | |
| 318 | break; | 318 | break; | |
| 319 | } | 319 | } | |
| 320 | whclob_append( cb, &ch, 1 ); | | | 320 | memblob_append( cb, &ch, 1 ); |
| 321 | } | 321 | } | |
| 322 | char const * cookie = whclob_bufferc(cb); | | | 322 | char const * cookie = memblob_bufferc(cb); |
| 323 | //MARKER("cookie=[%s]\n",cookie); | 323 | //MARKER("cookie=[%s]\n",cookie); | |
| 324 | if( ! cookie || (whclob_size(cb)<1) ) | | | 324 | if( ! cookie || (memblob_size(cb)<1) ) |
| 325 | { | 325 | { | |
| 326 | whclob_finalize(cb); | | | 326 | memblob_finalize(cb); |
| 327 | return 0; | 327 | return 0; | |
| 328 | } | 328 | } | |
| 329 | c11n_node * n = 0; | 329 | c11n_node * n = 0; | |
| 330 | c11n_io_handler * h = c11n_io_handler_by_name(cookie); | 330 | c11n_io_handler * h = c11n_io_handler_by_name(cookie); | |
| 331 | whclob_finalize(cb); | | | 331 | memblob_finalize(cb); |
| 332 | if( h ) | 332 | if( h ) | |
| 333 | { | 333 | { | |
| 334 | n = h->api->load_node( h, src ); | 334 | n = h->api->load_node( h, src ); | |
| 335 | //MARKER("h->load_node() == %p\n",n); | 335 | //MARKER("h->load_node() == %p\n",n); | |
| 336 | h->api->destroy(h); | 336 | h->api->destroy(h); | |
| 59 hidden lines | ||||
| 396 | 396 | |||
| 397 | 397 | |||
| 398 | size_t c11n_io_escape_string( c11n_const_string_t input, size_t inlen, | 398 | size_t c11n_io_escape_string( c11n_const_string_t input, size_t inlen, | |
| 399 | c11n_string_escape_info const * table, | 399 | c11n_string_escape_info const * table, | |
| 400 | bool doEscape, | 400 | bool doEscape, | |
| 401 | whclob * target ) | | | 401 | memblob * target ) |
| 402 | { | 402 | { | |
| 403 | c11n_const_string_t at = input; | 403 | c11n_const_string_t at = input; | |
| 404 | size_t count = 0; | 404 | size_t count = 0; | |
| 405 | if( ! input || !*input || !inlen || ! table || !target ) return 0; | 405 | if( ! input || !*input || !inlen || ! table || !target ) return 0; | |
| 406 | c11n_string_escape_info bogo; /* simplifies unescaping. */ | 406 | c11n_string_escape_info bogo; /* simplifies unescaping. */ | |
| 11 hidden lines | ||||
| 418 | bogo.esc = e->unesc; | 418 | bogo.esc = e->unesc; | |
| 419 | bogo.esc_len = e->unesc_len; | 419 | bogo.esc_len = e->unesc_len; | |
| 420 | } | 420 | } | |
| 421 | if( bogo.unesc_len && (0 == strncmp( at, bogo.unesc, bogo.unesc_len )) ) | 421 | if( bogo.unesc_len && (0 == strncmp( at, bogo.unesc, bogo.unesc_len )) ) | |
| 422 | { | 422 | { | |
| 423 | whclob_append( target, bogo.esc, (long) bogo.esc_len ); | | | 423 | memblob_append( target, bogo.esc, (long) bogo.esc_len ); |
| 424 | at += bogo.unesc_len; | 424 | at += bogo.unesc_len; | |
| 425 | ++count; | 425 | ++count; | |
| 426 | gotmatch = true; | 426 | gotmatch = true; | |
| 427 | break; | 427 | break; | |
| 428 | } | 428 | } | |
| 429 | } | 429 | } | |
| 430 | if( ! gotmatch ) | 430 | if( ! gotmatch ) | |
| 431 | { | 431 | { | |
| 432 | whclob_append( target, at++, 1 ); | | | 432 | memblob_append( target, at++, 1 ); |
| 433 | } | 433 | } | |
| 434 | } | 434 | } | |
| 435 | return count; | 435 | return count; | |
| 436 | } | 436 | } | |
| 437 | 437 | |||
| 438 | 438 | |||
| 439 | size_t c11n_stream_readln_membuf(c11n_stream * stream, whclob * dest ) | | | 439 | size_t c11n_stream_readln_membuf(c11n_stream * stream, memblob * dest ) |
| 440 | { | 440 | { | |
| 441 | if( !stream || !dest || !stream->api->isgood(stream)) return 0; | 441 | if( !stream || !dest || !stream->api->isgood(stream)) return 0; | |
| 442 | char ch = 0; | 442 | char ch = 0; | |
| 443 | size_t ret = 0; | 443 | size_t ret = 0; | |
| 444 | while( '\n' != ch ) | 444 | while( '\n' != ch ) | |
| 446 | if( ! c11n_stream_getchar( stream, &ch ) ) | 446 | if( ! c11n_stream_getchar( stream, &ch ) ) | |
| 447 | { | 447 | { | |
| 448 | return 0; | 448 | return 0; | |
| 449 | } | 449 | } | |
| 450 | ++ret; | 450 | ++ret; | |
| 451 | whclob_append( dest, &ch, 1 ); | | | 451 | memblob_append( dest, &ch, 1 ); |
| 452 | } | 452 | } | |
| 453 | return ret; | 453 | return ret; | |
| 454 | } | 454 | } | |
| 455 | 455 | |||
| 456 | char * c11n_stream_readln(c11n_stream * stream) | 456 | char * c11n_stream_readln(c11n_stream * stream) | |
| 457 | { | 457 | { | |
| 458 | if(0) c11n_stream_readln(0); /* kludge for "static defined but not used" warning. */ | 458 | if(0) c11n_stream_readln(0); /* kludge for "static defined but not used" warning. */ | |
| 459 | if( !stream || !stream->api->isgood(stream)) return 0; | 459 | if( !stream || !stream->api->isgood(stream)) return 0; | |
| 460 | whclob * cb = whclob_new(); | | | 460 | memblob * cb = memblob_new(); |
| 461 | c11n_stream_readln_membuf( stream, cb ); | 461 | c11n_stream_readln_membuf( stream, cb ); | |
| 462 | char * buf = whclob_take_buffer(cb); | | | 462 | char * buf = memblob_take_buffer(cb); |
| 463 | whclob_finalize(cb); | | | 463 | memblob_finalize(cb); |
| 464 | return buf; | 464 | return buf; | |
| 465 | } | 465 | } | |
| 466 | 466 | |||
| 467 | #ifdef __cplusplus | 467 | #ifdef __cplusplus | |
| 468 | } /* extern "C" */ | 468 | } /* extern "C" */ | |
| 469 | #endif | 469 | #endif | |
Changes to src/c11n_io_handler_binarish.c
| Old (253bb514b07d1350) | New (55e9331e47b86198) | |||
|---|---|---|---|---|
| 1 | #include "s11n.net/c11n/io/c11n_io.h" | 1 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 2 | #include "s11n.net/c11n/detail/whclob.h" | | | 2 | #include "s11n.net/c11n/detail/memblob.h" |
| 3 | 3 | |||
| 4 | #include <stdlib.h> | 4 | #include <stdlib.h> | |
| 5 | #include <ctype.h> /* isspace() and friends. */ | 5 | #include <ctype.h> /* isspace() and friends. */ | |
| 6 | #include <string.h> /* memset() */ | 6 | #include <string.h> /* memset() */ | |
| 7 | #include <assert.h> | 7 | #include <assert.h> | |
| 102 hidden lines | ||||
| 110 | c11n_stream * stream; | 110 | c11n_stream * stream; | |
| 111 | /** | 111 | /** | |
| 112 | Blob for accumulating read-in tokens. Owned by | 112 | Blob for accumulating read-in tokens. Owned by | |
| 113 | this object. | 113 | this object. | |
| 114 | */ | 114 | */ | |
| 115 | whclob * clob; | | | 115 | memblob * clob; |
| 116 | } c11n_io_binarish_data; | 116 | } c11n_io_binarish_data; | |
| 117 | 117 | |||
| 118 | static const c11n_io_binarish_data c11n_io_binarish_data_init = | 118 | static const c11n_io_binarish_data c11n_io_binarish_data_init = | |
| 119 | { | 119 | { | |
| 120 | C11N_IO_TREE_BUILDER_INIT, | 120 | C11N_IO_TREE_BUILDER_INIT, | |
| 129 hidden lines | ||||
| 250 | if(0) return binarish_save_root_node(self,src,dest);/* kludge to avoid "static func defined but not used" warning*/ | 250 | if(0) return binarish_save_root_node(self,src,dest);/* kludge to avoid "static func defined but not used" warning*/ | |
| 251 | impl->stream = dest; | 251 | impl->stream = dest; | |
| 252 | #define WF c11n_stream_writef | 252 | #define WF c11n_stream_writef | |
| 253 | #define LEN(S) c11n_strlen(S) | 253 | #define LEN(S) c11n_strlen(S) | |
| 254 | 254 | |||
| 255 | whclob_finalize( impl->clob ); | | | 255 | memblob_finalize( impl->clob ); |
| 256 | impl->clob = whclob_new(); | | | 256 | impl->clob = memblob_new(); |
| 257 | 257 | |||
| 258 | WF( dest, "%s\n", self->api->cookie_string ); | 258 | WF( dest, "%s\n", self->api->cookie_string ); | |
| 259 | 259 | |||
| 260 | bool ret = binarish_save_node( self, src ); | 260 | bool ret = binarish_save_node( self, src ); | |
| 261 | if( ret ) | 261 | if( ret ) | |
| 262 | { | 262 | { | |
| 263 | 263 | |||
| 264 | WF( dest, "%s\n", impl->cookie_close ); | 264 | WF( dest, "%s\n", impl->cookie_close ); | |
| 265 | } | 265 | } | |
| 266 | whclob_finalize( impl->clob ); | | | 266 | memblob_finalize( impl->clob ); |
| 267 | impl->clob = 0; | 267 | impl->clob = 0; | |
| 268 | impl->stream = 0; | 268 | impl->stream = 0; | |
| 269 | #undef LEN | 269 | #undef LEN | |
| 270 | #undef WF | 270 | #undef WF | |
| 271 | return ret; | 271 | return ret; | |
| 26 hidden lines | ||||
| 298 | { | 298 | { | |
| 299 | IMPLDECL(false); | 299 | IMPLDECL(false); | |
| 300 | if( !self || (0 == size) ) return false; | 300 | if( !self || (0 == size) ) return false; | |
| 301 | #if 1 | 301 | #if 1 | |
| 302 | /* | 302 | /* | |
| 303 | This requires much fewer allocs than whclob_reset(), though it | | | 303 | This requires much fewer allocs than memblob_reset(), though it |
| 304 | also means that impl->clob will stay the size of the largest | 304 | also means that impl->clob will stay the size of the largest | |
| 305 | token throughout the parse process. | 305 | token throughout the parse process. | |
| 306 | */ | 306 | */ | |
| 307 | whclob_reserve( impl->clob, size ? size : 1 ); | | | 307 | memblob_reserve( impl->clob, size ? size : 1 ); |
| 308 | whclob_truncate( impl->clob, 0, 0 ); | | | 308 | memblob_truncate( impl->clob, 0, 0 ); |
| 309 | #else | 309 | #else | |
| 310 | whclob_reset(impl->clob); | | | 310 | memblob_reset(impl->clob); |
| 311 | whclob_reserve( impl->clob, size ); | | | 311 | memblob_reserve( impl->clob, size ); |
| 312 | #endif | 312 | #endif | |
| 313 | char * buf = whclob_buffer(impl->clob); | | | 313 | char * buf = memblob_buffer(impl->clob); |
| 314 | if( skipWS ) | 314 | if( skipWS ) | |
| 315 | { | 315 | { | |
| 316 | char ch = binarish_read_skip_space( impl->stream ); | 316 | char ch = binarish_read_skip_space( impl->stream ); | |
| 317 | if( ! ch ) | 317 | if( ! ch ) | |
| 318 | { | 318 | { | |
| 319 | C11N_LOG(C11N_LOG_IO_ERR)("hit EOF while expecting a length-%u token",size); | 319 | C11N_LOG(C11N_LOG_IO_ERR)("hit EOF while expecting a length-%u token",size); | |
| 320 | return false; | 320 | return false; | |
| 321 | } | 321 | } | |
| 322 | whclob_append( impl->clob, &ch, 1 ); | | | 322 | memblob_append( impl->clob, &ch, 1 ); |
| 323 | if( 1 == size ) return true; | 323 | if( 1 == size ) return true; | |
| 324 | --size; | 324 | --size; | |
| 325 | buf += 1; | 325 | buf += 1; | |
| 326 | } | 326 | } | |
| 327 | if( size != impl->stream->api->read(impl->stream, buf, size ) ) | 327 | if( size != impl->stream->api->read(impl->stream, buf, size ) ) | |
| 8 hidden lines | ||||
| 336 | */ | 336 | */ | |
| 337 | static bool binarish_compare_token(c11n_io_handler * self, c11n_key_type key, bool skipWS ) | 337 | static bool binarish_compare_token(c11n_io_handler * self, c11n_key_type key, bool skipWS ) | |
| 338 | { | 338 | { | |
| 339 | IMPLDECL(false); | 339 | IMPLDECL(false); | |
| 340 | return binarish_read_token( self, c11n_strlen(key),skipWS ) | 340 | return binarish_read_token( self, c11n_strlen(key),skipWS ) | |
| 341 | ? c11n_compare_str( key, whclob_bufferc(impl->clob) ) | | | 341 | ? c11n_compare_str( key, memblob_bufferc(impl->clob) ) |
| 342 | : false; | 342 | : false; | |
| 343 | } | 343 | } | |
| 344 | 344 | |||
| 345 | static int binarish_read_size_token( c11n_io_handler * self, size_t sizeLen ) | 345 | static int binarish_read_size_token( c11n_io_handler * self, size_t sizeLen ) | |
| 346 | { | 346 | { | |
| 347 | IMPLDECL(-1); | 347 | IMPLDECL(-1); | |
| 348 | if( ! self || !sizeLen ) return false; | 348 | if( ! self || !sizeLen ) return false; | |
| 349 | if( ! binarish_read_token(self,sizeLen,false) ) return false; | 349 | if( ! binarish_read_token(self,sizeLen,false) ) return false; | |
| 350 | char const * digits = whclob_bufferc(impl->clob); | | | 350 | char const * digits = memblob_bufferc(impl->clob); |
| 351 | int num = -1; | 351 | int num = -1; | |
| 352 | char fmt[10]; memset(fmt,0,10); | 352 | char fmt[10]; memset(fmt,0,10); | |
| 353 | sprintf( fmt, "%%%ux", sizeLen ); | 353 | sprintf( fmt, "%%%ux", sizeLen ); | |
| 354 | if( 1 != sscanf( digits, fmt, &num) ) return -1; | 354 | if( 1 != sscanf( digits, fmt, &num) ) return -1; | |
| 355 | return num; | 355 | return num; | |
| 4 hidden lines | ||||
| 360 | if( -1 == rdlen ) return false; | 360 | if( -1 == rdlen ) return false; | |
| 361 | //MARKER("rdlen=%d/%x\n",rdlen,rdlen); | 361 | //MARKER("rdlen=%d/%x\n",rdlen,rdlen); | |
| 362 | return binarish_read_token( self, rdlen, false ); | 362 | return binarish_read_token( self, rdlen, false ); | |
| 363 | } | 363 | } | |
| 364 | 364 | |||
| 365 | #define TOKEN whclob_bufferc(impl->clob) | | | 365 | #define TOKEN memblob_bufferc(impl->clob) |
| 366 | #define SHOWTOKEN if(0){MARKER("token=[%s]\n",TOKEN);} | 366 | #define SHOWTOKEN if(0){MARKER("token=[%s]\n",TOKEN);} | |
| 367 | 367 | |||
| 368 | static bool binarish_read_prop( c11n_io_handler * self ) | 368 | static bool binarish_read_prop( c11n_io_handler * self ) | |
| 369 | { | 369 | { | |
| 370 | IMPLDECL(false); | 370 | IMPLDECL(false); | |
| 371 | if( ! binarish_read_sized_token( self, impl->keySizeLen ) ) return false; | 371 | if( ! binarish_read_sized_token( self, impl->keySizeLen ) ) return false; | |
| 372 | SHOWTOKEN; | 372 | SHOWTOKEN; | |
| 373 | /* | 373 | /* | |
| 374 | FIXME: add this whclob as a member of impl, to avoid having to | | | 374 | FIXME: add this memblob as a member of impl, to avoid having to |
| 375 | re-alloc it (and its internals) for every property. | 375 | re-alloc it (and its internals) for every property. | |
| 376 | */ | 376 | */ | |
| 377 | whclob * key = 0; | | | 377 | memblob * key = 0; |
| 378 | if( whclob_rc.OK != whclob_init(&key,TOKEN,-1) ) return false; | | | 378 | if( memblob_rc.OK != memblob_init(&key,TOKEN,-1) ) return false; |
| 379 | if( ! binarish_read_sized_token( self, impl->valSizeLen ) ) | 379 | if( ! binarish_read_sized_token( self, impl->valSizeLen ) ) | |
| 380 | { | 380 | { | |
| 381 | SHOWTOKEN; | 381 | SHOWTOKEN; | |
| 382 | whclob_finalize(key); | | | 382 | memblob_finalize(key); |
| 383 | return false; | 383 | return false; | |
| 384 | } | 384 | } | |
| 385 | impl->bld.set_prop( &impl->bld, whclob_bufferc(key), TOKEN ); | | | 385 | impl->bld.set_prop( &impl->bld, memblob_bufferc(key), TOKEN ); |
| 386 | SHOWTOKEN; | 386 | SHOWTOKEN; | |
| 387 | whclob_finalize(key); | | | 387 | memblob_finalize(key); |
| 388 | return true; | 388 | return true; | |
| 389 | 389 | |||
| 390 | } | 390 | } | |
| 391 | // bool binarish_read_kvp( c11n_io_handler *, | 391 | // bool binarish_read_kvp( c11n_io_handler *, | |
| 392 | static bool binarish_load_a_node( c11n_io_handler * self, bool requireOpener ) | 392 | static bool binarish_load_a_node( c11n_io_handler * self, bool requireOpener ) | |
| 66 hidden lines | ||||
| 459 | 459 | |||
| 460 | static c11n_node * binarish_load_root_node( c11n_io_handler * self, c11n_stream * src ) | 460 | static c11n_node * binarish_load_root_node( c11n_io_handler * self, c11n_stream * src ) | |
| 461 | { | 461 | { | |
| 462 | IMPLDECL(0); | 462 | IMPLDECL(0); | |
| 463 | impl->stream = src; | 463 | impl->stream = src; | |
| 464 | whclob_finalize( impl->clob ); | | | 464 | memblob_finalize( impl->clob ); |
| 465 | impl->clob = whclob_new(); | | | 465 | impl->clob = memblob_new(); |
| 466 | c11n_node * ret = 0; | 466 | c11n_node * ret = 0; | |
| 467 | if( binarish_load_start( self ) ) | 467 | if( binarish_load_start( self ) ) | |
| 468 | { | 468 | { | |
| 469 | ret = impl->bld.root_node; | 469 | ret = impl->bld.root_node; | |
| 470 | impl->bld.root_node = 0; | 470 | impl->bld.root_node = 0; | |
| 471 | } | 471 | } | |
| 472 | impl->bld.clear( &impl->bld ); | 472 | impl->bld.clear( &impl->bld ); | |
| 473 | whclob_finalize( impl->clob ); | | | 473 | memblob_finalize( impl->clob ); |
| 474 | impl->clob = 0; | 474 | impl->clob = 0; | |
| 475 | impl->stream = 0; | 475 | impl->stream = 0; | |
| 476 | return ret; | 476 | return ret; | |
| 477 | } | 477 | } | |
| 478 | static void binarish_clear( c11n_io_handler * self ) | 478 | static void binarish_clear( c11n_io_handler * self ) | |
| 480 | if( self ) | 480 | if( self ) | |
| 481 | { | 481 | { | |
| 482 | IMPLDECL(); | 482 | IMPLDECL(); | |
| 483 | if( impl->clob) | 483 | if( impl->clob) | |
| 484 | { | 484 | { | |
| 485 | whclob_finalize(impl->clob); | | | 485 | memblob_finalize(impl->clob); |
| 486 | impl->clob = 0; | 486 | impl->clob = 0; | |
| 487 | } | 487 | } | |
| 488 | impl->stream = 0; | 488 | impl->stream = 0; | |
| 489 | impl->bld.clear( &impl->bld ); | 489 | impl->bld.clear( &impl->bld ); | |
| 490 | } | 490 | } | |
| 41 hidden lines | ||||
| 532 | 532 | |||
| 533 | c11n_io_handler * c11n_io_handler_factory_binarish( c11n_const_string_t ignored ) | 533 | c11n_io_handler * c11n_io_handler_factory_binarish( c11n_const_string_t ignored ) | |
| 534 | { | 534 | { | |
| 535 | return c11n_io_handler_create_binarish(); | 535 | return c11n_io_handler_create_binarish(); | |
| 536 | } | 536 | } | |
Changes to src/c11n_io_handler_expat.c
| Old (735eeeee89d7518e) | New (8c2659da55349183) | |||
|---|---|---|---|---|
| 1 | #include "s11n.net/c11n/io/c11n_io.h" | 1 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 2 | #include "s11n.net/c11n/io/c11n_io_handler_expat.h" | 2 | #include "s11n.net/c11n/io/c11n_io_handler_expat.h" | |
| 3 | #include "s11n.net/c11n/detail/whclob.h" | | | 3 | #include "s11n.net/c11n/detail/memblob.h" |
| 4 | 4 | |||
| 5 | #include <stdlib.h> | 5 | #include <stdlib.h> | |
| 6 | #include <ctype.h> /* isspace() and friends. */ | 6 | #include <ctype.h> /* isspace() and friends. */ | |
| 7 | #include <string.h> /* memset() */ | 7 | #include <string.h> /* memset() */ | |
| 8 | #include <assert.h> | 8 | #include <assert.h> | |
| 20 hidden lines | ||||
| 29 | c11n_stream * stream; | 29 | c11n_stream * stream; | |
| 30 | /** | 30 | /** | |
| 31 | Blob for accumulating read-in tokens. Owned by | 31 | Blob for accumulating read-in tokens. Owned by | |
| 32 | this object. | 32 | this object. | |
| 33 | */ | 33 | */ | |
| 34 | whclob * clob; | | | 34 | memblob * clob; |
| 35 | whclob * tabs; | | | 35 | memblob * tabs; |
| 36 | whclob * xlate; | | | 36 | memblob * xlate; |
| 37 | XML_Parser expat; | 37 | XML_Parser expat; | |
| 38 | } c11n_io_expat_data; | 38 | } c11n_io_expat_data; | |
| 39 | 39 | |||
| 40 | static const c11n_io_expat_data c11n_io_expat_data_init = | 40 | static const c11n_io_expat_data c11n_io_expat_data_init = | |
| 41 | { | 41 | { | |
| 47 hidden lines | ||||
| 89 | #define WF c11n_stream_writef | 89 | #define WF c11n_stream_writef | |
| 90 | c11n_stream * dest = impl->stream; | 90 | c11n_stream * dest = impl->stream; | |
| 91 | 91 | |||
| 92 | if( impl->indentLevel++ != 0 ) | 92 | if( impl->indentLevel++ != 0 ) | |
| 93 | { | 93 | { | |
| 94 | whclob_append( impl->tabs, "\t", 1 ); | | | 94 | memblob_append( impl->tabs, "\t", 1 ); |
| 95 | //whclob_null_terminate( impl->tabs ); | | | 95 | //memblob_null_terminate( impl->tabs ); |
| 96 | } | 96 | } | |
| 97 | char const * tabs = whclob_bufferc( impl->tabs ); | | | 97 | char const * tabs = memblob_bufferc( impl->tabs ); |
| 98 | if( ! tabs || !*tabs ) tabs = ""; | 98 | if( ! tabs || !*tabs ) tabs = ""; | |
| 99 | 99 | |||
| 100 | WF( dest, "%s<%s class=\"%s\">\n", tabs, c11n_node_get_name( src ), c11n_node_get_class(src) ); | 100 | WF( dest, "%s<%s class=\"%s\">\n", tabs, c11n_node_get_name( src ), c11n_node_get_class(src) ); | |
| 101 | #if 1 | 101 | #if 1 | |
| 102 | c11n_prop_iter piter = c11n_node_prop_iter(src); | 102 | c11n_prop_iter piter = c11n_node_prop_iter(src); | |
| 103 | while( c11n_prop_iter_isvalid( &piter ) ) | 103 | while( c11n_prop_iter_isvalid( &piter ) ) | |
| 104 | { | 104 | { | |
| 105 | c11n_const_string_t key = c11n_prop_iter_key( &piter ); | 105 | c11n_const_string_t key = c11n_prop_iter_key( &piter ); | |
| 106 | c11n_const_string_t val = c11n_prop_iter_val( &piter ); | 106 | c11n_const_string_t val = c11n_prop_iter_val( &piter ); | |
| 107 | whclob_truncate( impl->xlate, 0, 0 ); | | | 107 | memblob_truncate( impl->xlate, 0, 0 ); |
| 108 | if( val ) | 108 | if( val ) | |
| 109 | { | 109 | { | |
| 110 | c11n_io_escape_string( val, c11n_strlen( val ), expat_val_escapes, true, impl->xlate ); | 110 | c11n_io_escape_string( val, c11n_strlen( val ), expat_val_escapes, true, impl->xlate ); | |
| 111 | } | 111 | } | |
| 112 | WF( dest, "\t%s<%s>%s</%s>\n", tabs, key, | 112 | WF( dest, "\t%s<%s>%s</%s>\n", tabs, key, | |
| 113 | whclob_size(impl->xlate) ? whclob_bufferc(impl->xlate) : "", | | | 113 | memblob_size(impl->xlate) ? memblob_bufferc(impl->xlate) : "", |
| 114 | key ); | 114 | key ); | |
| 115 | c11n_prop_iter_next(&piter); | 115 | c11n_prop_iter_next(&piter); | |
| 116 | } | 116 | } | |
| 117 | #endif | 117 | #endif | |
| 118 | #if 1 | 118 | #if 1 | |
| 3 hidden lines | ||||
| 122 | if( ! expat_save_node( self, chi.node ) ) return false; | 122 | if( ! expat_save_node( self, chi.node ) ) return false; | |
| 123 | c11n_node_iter_next_c(&chi); | 123 | c11n_node_iter_next_c(&chi); | |
| 124 | } | 124 | } | |
| 125 | #endif | 125 | #endif | |
| 126 | --impl->indentLevel; | 126 | --impl->indentLevel; | |
| 127 | whclob_truncate( impl->tabs, impl->indentLevel, 0 ); | | | 127 | memblob_truncate( impl->tabs, impl->indentLevel, 0 ); |
| 128 | WF( dest, "%s</%s>\n", tabs, c11n_node_get_name( src ) ); | 128 | WF( dest, "%s</%s>\n", tabs, c11n_node_get_name( src ) ); | |
| 129 | #undef WF | 129 | #undef WF | |
| 130 | #undef W | 130 | #undef W | |
| 131 | //whclob_null_terminate( impl->tabs ); | | | 131 | //memblob_null_terminate( impl->tabs ); |
| 132 | return true; | 132 | return true; | |
| 133 | } | 133 | } | |
| 134 | 134 | |||
| 135 | static bool expat_save_root_node( c11n_io_handler * self, | 135 | static bool expat_save_root_node( c11n_io_handler * self, | |
| 136 | c11n_node const * src, | 136 | c11n_node const * src, | |
| 2 hidden lines | ||||
| 139 | IMPLDECL(false); | 139 | IMPLDECL(false); | |
| 140 | if( !src || (!dest || !dest->api->isgood(dest)) ) return false; | 140 | if( !src || (!dest || !dest->api->isgood(dest)) ) return false; | |
| 141 | if(0) return expat_save_root_node(self,src,dest);/* kludge to avoid "static func defined but not used" warning*/ | 141 | if(0) return expat_save_root_node(self,src,dest);/* kludge to avoid "static func defined but not used" warning*/ | |
| 142 | self->api->clear(self); | 142 | self->api->clear(self); | |
| 143 | impl->stream = dest; | 143 | impl->stream = dest; | |
| 144 | impl->tabs = whclob_new(); | | | 144 | impl->tabs = memblob_new(); |
| 145 | impl->xlate = whclob_new(); | | | 145 | impl->xlate = memblob_new(); |
| 146 | c11n_stream_writef( dest, "%s\n", self->api->cookie_string ); | 146 | c11n_stream_writef( dest, "%s\n", self->api->cookie_string ); | |
| 147 | bool ret = expat_save_node( self, src ); | 147 | bool ret = expat_save_node( self, src ); | |
| 148 | self->api->clear(self); | 148 | self->api->clear(self); | |
| 149 | return ret; | 149 | return ret; | |
| 150 | } | 150 | } | |
| 2 hidden lines | ||||
| 153 | #define XSELFDECL c11n_io_expat_data * impl = (c11n_io_expat_data *)uArg; assert(impl && "impl failed!"); if(!impl) return | 153 | #define XSELFDECL c11n_io_expat_data * impl = (c11n_io_expat_data *)uArg; assert(impl && "impl failed!"); if(!impl) return | |
| 154 | 154 | |||
| 155 | static void XMLCALL expat_start_node( void * uArg, const char * name, const char ** attr ) | 155 | static void XMLCALL expat_start_node( void * uArg, const char * name, const char ** attr ) | |
| 156 | { | 156 | { | |
| 157 | XSELFDECL; | 157 | XSELFDECL; | |
| 158 | //whclob_truncate(impl->clob, 0, 0 ); | | | 158 | //memblob_truncate(impl->clob, 0, 0 ); |
| 159 | if( attr[0] ) | 159 | if( attr[0] ) | |
| 160 | { /* object node */ | 160 | { /* object node */ | |
| 161 | impl->propKey = 0; | 161 | impl->propKey = 0; | |
| 162 | c11n_const_string_t cln = 0; | 162 | c11n_const_string_t cln = 0; | |
| 163 | int i = 0; | 163 | int i = 0; | |
| 20 hidden lines | ||||
| 184 | { /* object node */ | 184 | { /* object node */ | |
| 185 | impl->bld.close_node( &impl->bld ); | 185 | impl->bld.close_node( &impl->bld ); | |
| 186 | } | 186 | } | |
| 187 | else | 187 | else | |
| 188 | { /* property node */ | 188 | { /* property node */ | |
| 189 | whclob_null_terminate( impl->clob ); | | | 189 | memblob_null_terminate( impl->clob ); |
| 190 | impl->bld.set_prop( &impl->bld, impl->propKey, whclob_bufferc(impl->clob) ); | | | 190 | impl->bld.set_prop( &impl->bld, impl->propKey, memblob_bufferc(impl->clob) ); |
| 191 | impl->propKey = 0; | 191 | impl->propKey = 0; | |
| 192 | whclob_truncate( impl->clob, 0, 0 ); | | | 192 | memblob_truncate( impl->clob, 0, 0 ); |
| 193 | } | 193 | } | |
| 194 | } | 194 | } | |
| 195 | 195 | |||
| 196 | static void XMLCALL expat_char_handler( void * uArg, const char * txt, int len ) | 196 | static void XMLCALL expat_char_handler( void * uArg, const char * txt, int len ) | |
| 197 | { | 197 | { | |
| 198 | XSELFDECL; | 198 | XSELFDECL; | |
| 199 | if( ! impl->propKey ) return; /* we're not in a property. */ | 199 | if( ! impl->propKey ) return; /* we're not in a property. */ | |
| 200 | whclob_append( impl->clob, txt, len ); | | | 200 | memblob_append( impl->clob, txt, len ); |
| 201 | } | 201 | } | |
| 202 | 202 | |||
| 203 | static bool expat_load_a_node( c11n_io_handler * self ) | 203 | static bool expat_load_a_node( c11n_io_handler * self ) | |
| 204 | { | 204 | { | |
| 205 | IMPLDECL(false); | 205 | IMPLDECL(false); | |
| 206 | 206 | |||
| 207 | char * line = 0; | 207 | char * line = 0; | |
| 208 | whclob * lineBuf = whclob_new(); | | | 208 | memblob * lineBuf = memblob_new(); |
| 209 | while( true ) | 209 | while( true ) | |
| 210 | { | 210 | { | |
| 211 | size_t len = c11n_stream_readln_membuf( impl->stream, lineBuf ); | 211 | size_t len = c11n_stream_readln_membuf( impl->stream, lineBuf ); | |
| 212 | if( XML_STATUS_ERROR == XML_Parse( impl->expat, whclob_bufferc(lineBuf), len, (len == 0) ) ) | | | 212 | if( XML_STATUS_ERROR == XML_Parse( impl->expat, memblob_bufferc(lineBuf), len, (len == 0) ) ) |
| 213 | { | 213 | { | |
| 214 | C11N_LOG(C11N_LOG_IO_ERR)("Parse error at line %d: %s: buffer=[%s]", | 214 | C11N_LOG(C11N_LOG_IO_ERR)("Parse error at line %d: %s: buffer=[%s]", | |
| 215 | XML_GetCurrentLineNumber(impl->expat), | 215 | XML_GetCurrentLineNumber(impl->expat), | |
| 216 | XML_ErrorString(XML_GetErrorCode(impl->expat)), | 216 | XML_ErrorString(XML_GetErrorCode(impl->expat)), | |
| 217 | line ); | 217 | line ); | |
| 218 | break; | 218 | break; | |
| 219 | } | 219 | } | |
| 220 | whclob_truncate( lineBuf, 0, 0 ); | | | 220 | memblob_truncate( lineBuf, 0, 0 ); |
| 221 | if( !len ) break; | 221 | if( !len ) break; | |
| 222 | } | 222 | } | |
| 223 | whclob_finalize( lineBuf ); | | | 223 | memblob_finalize( lineBuf ); |
| 224 | return impl->bld.root_node && !impl->bld.current_node; | 224 | return impl->bld.root_node && !impl->bld.current_node; | |
| 225 | } | 225 | } | |
| 226 | 226 | |||
| 227 | static c11n_node * expat_load_root_node( c11n_io_handler * self, c11n_stream * src ) | 227 | static c11n_node * expat_load_root_node( c11n_io_handler * self, c11n_stream * src ) | |
| 228 | { | 228 | { | |
| 229 | IMPLDECL(0); | 229 | IMPLDECL(0); | |
| 230 | c11n_node * ret = 0; | 230 | c11n_node * ret = 0; | |
| 231 | 231 | |||
| 232 | impl->expat = XML_ParserCreate(NULL); | 232 | impl->expat = XML_ParserCreate(NULL); | |
| 233 | if( ! impl->expat ) return 0; | 233 | if( ! impl->expat ) return 0; | |
| 234 | impl->clob = whclob_new(); | | | 234 | impl->clob = memblob_new(); |
| 235 | impl->xlate = whclob_new(); | | | 235 | impl->xlate = memblob_new(); |
| 236 | 236 | |||
| 237 | XML_SetUserData( impl->expat, impl ); | 237 | XML_SetUserData( impl->expat, impl ); | |
| 238 | XML_SetElementHandler( impl->expat, expat_start_node, expat_end_node); | 238 | XML_SetElementHandler( impl->expat, expat_start_node, expat_end_node); | |
| 239 | XML_SetCharacterDataHandler( impl->expat, expat_char_handler ); | 239 | XML_SetCharacterDataHandler( impl->expat, expat_char_handler ); | |
| 240 | 240 | |||
| 12 hidden lines | ||||
| 253 | { | 253 | { | |
| 254 | if( self ) | 254 | if( self ) | |
| 255 | { | 255 | { | |
| 256 | IMPLDECL(); | 256 | IMPLDECL(); | |
| 257 | if( impl->expat ) XML_ParserFree( impl->expat ); | 257 | if( impl->expat ) XML_ParserFree( impl->expat ); | |
| 258 | whclob_finalize(impl->clob); | | | 258 | memblob_finalize(impl->clob); |
| 259 | whclob_finalize(impl->tabs); | | | 259 | memblob_finalize(impl->tabs); |
| 260 | whclob_finalize(impl->xlate); | | | 260 | memblob_finalize(impl->xlate); |
| 261 | impl->bld.clear( &impl->bld ); | 261 | impl->bld.clear( &impl->bld ); | |
| 262 | *impl = c11n_io_expat_data_init; | 262 | *impl = c11n_io_expat_data_init; | |
| 263 | } | 263 | } | |
| 264 | } | 264 | } | |
| 265 | static void expat_dtor( c11n_io_handler * self ) | 265 | static void expat_dtor( c11n_io_handler * self ) | |
| 37 hidden lines | ||||
| 303 | 303 | |||
| 304 | c11n_io_handler * c11n_io_handler_factory_expat( c11n_const_string_t ignored ) | 304 | c11n_io_handler * c11n_io_handler_factory_expat( c11n_const_string_t ignored ) | |
| 305 | { | 305 | { | |
| 306 | return c11n_io_handler_create_expat(); | 306 | return c11n_io_handler_create_expat(); | |
| 307 | } | 307 | } | |
Changes to src/c11n_io_handler_sql.c
| Old (f6ec0e47e47cda19) | New (33a14a2c8b91e5ba) | |||
|---|---|---|---|---|
| 1 | #include <stdlib.h> /* malloc()/free() */ | 1 | #include <stdlib.h> /* malloc()/free() */ | |
| 2 | #include <sqlite3.h> | 2 | #include <sqlite3.h> | |
| 3 | #include <assert.h> | 3 | #include <assert.h> | |
| 4 | #include "s11n.net/c11n/io/c11n_io_handler_sql.h" | 4 | #include "s11n.net/c11n/io/c11n_io_handler_sql.h" | |
| 5 | #include "s11n.net/c11n/io/c11n_stream_whclob.h" | | | 5 | #include "s11n.net/c11n/io/c11n_stream_memblob.h" |
| 6 | #include "s11n.net/c11n/detail/whclob.h" | | | 6 | #include "s11n.net/c11n/detail/memblob.h" |
| 7 | #include "s11n.net/c11n/detail/whhash.h" | 7 | #include "s11n.net/c11n/detail/whhash.h" | |
| 8 | 8 | |||
| 9 | #if 1 | 9 | #if 1 | |
| 10 | #define MARKER if(1) printf("MARKER: %s:%d:%s(): ",__FILE__,__LINE__,__func__); if(1) printf | 10 | #define MARKER if(1) printf("MARKER: %s:%d:%s(): ",__FILE__,__LINE__,__func__); if(1) printf | |
| 11 | #else | 11 | #else | |
| 30 hidden lines | ||||
| 42 | 42 | |||
| 43 | static bool | 43 | static bool | |
| 44 | c11n_io_handler_sql_do_props( c11n_io_handler * self, c11n_node * tgt, size_t nid ) | 44 | c11n_io_handler_sql_do_props( c11n_io_handler * self, c11n_node * tgt, size_t nid ) | |
| 45 | { | 45 | { | |
| 46 | IMPLDECL(false); | 46 | IMPLDECL(false); | |
| 47 | whclob * sql = 0; | | | 47 | memblob * sql = 0; |
| 48 | whclob_init( &sql, 0, 128 ); | | | 48 | memblob_init( &sql, 0, 128 ); |
| 49 | sqlite3_stmt * stmt = 0; | 49 | sqlite3_stmt * stmt = 0; | |
| 50 | int rc = 0; | 50 | int rc = 0; | |
| 51 | whclob_appendf( sql, "SELECT k,v FROM p WHERE n=%u;",nid); | | | 51 | memblob_appendf( sql, "SELECT k,v FROM p WHERE n=%u;",nid); |
| 52 | rc = sqlite3_prepare_v2( impl->db, | 52 | rc = sqlite3_prepare_v2( impl->db, | |
| 53 | whclob_bufferc(sql), | | | 53 | memblob_bufferc(sql), |
| 54 | -1,&stmt,0 ); | 54 | -1,&stmt,0 ); | |
| 55 | whclob_finalize(sql); | | | 55 | memblob_finalize(sql); |
| 56 | if( SQLITE_OK == rc ) rc = sqlite3_step(stmt); | 56 | if( SQLITE_OK == rc ) rc = sqlite3_step(stmt); | |
| 57 | while( SQLITE_ROW == rc ) | 57 | while( SQLITE_ROW == rc ) | |
| 58 | { | 58 | { | |
| 59 | const char * k = (char const *)sqlite3_column_text(stmt,0); | 59 | const char * k = (char const *)sqlite3_column_text(stmt,0); | |
| 60 | const char * v = (char const *)sqlite3_column_text(stmt,1); | 60 | const char * v = (char const *)sqlite3_column_text(stmt,1); | |
| 8 hidden lines | ||||
| 69 | 69 | |||
| 70 | static bool | 70 | static bool | |
| 71 | c11n_io_handler_sql_desql( c11n_io_handler * self ) | 71 | c11n_io_handler_sql_desql( c11n_io_handler * self ) | |
| 72 | { | 72 | { | |
| 73 | IMPLDECL(false); | 73 | IMPLDECL(false); | |
| 74 | whclob * sql = 0; | | | 74 | memblob * sql = 0; |
| 75 | whclob_init( &sql, 0, 128 ); | | | 75 | memblob_init( &sql, 0, 128 ); |
| 76 | sqlite3_stmt * stmt = 0; | 76 | sqlite3_stmt * stmt = 0; | |
| 77 | int rc = 0; | 77 | int rc = 0; | |
| 78 | whclob_append( sql, "SELECT id,pid,name,class FROM n ORDER BY pid",-1); | | | 78 | memblob_append( sql, "SELECT id,pid,name,class FROM n ORDER BY pid",-1); |
| 79 | rc = sqlite3_prepare_v2( impl->db, | 79 | rc = sqlite3_prepare_v2( impl->db, | |
| 80 | whclob_bufferc(sql), | | | 80 | memblob_bufferc(sql), |
| 81 | -1,&stmt,0 ); | 81 | -1,&stmt,0 ); | |
| 82 | whclob_finalize(sql); | | | 82 | memblob_finalize(sql); |
| 83 | /** | 83 | /** | |
| 84 | We first read in all nodes and then iterate through them to get | 84 | We first read in all nodes and then iterate through them to get | |
| 85 | their properties. This avoids us having nested sqlite3_stmt | 85 | their properties. This avoids us having nested sqlite3_stmt | |
| 86 | activations (which i'm not sure sqlite3 allows?). To do this we | 86 | activations (which i'm not sure sqlite3 allows?). To do this we | |
| 87 | have to add a kludge: we temporarily add two bogus properties | 87 | have to add a kludge: we temporarily add two bogus properties | |
| 103 hidden lines | ||||
| 191 | sqlite3_close( impl->db ); | 191 | sqlite3_close( impl->db ); | |
| 192 | impl->db = 0; | 192 | impl->db = 0; | |
| 193 | return 0; | 193 | return 0; | |
| 194 | } | 194 | } | |
| 195 | 195 | |||
| 196 | whclob * sql = 0; | | | 196 | memblob * sql = 0; |
| 197 | if( whclob_rc.OK != whclob_init( &sql, 0, 1024 * 16 ) ) | | | 197 | if( memblob_rc.OK != memblob_init( &sql, 0, 1024 * 16 ) ) |
| 198 | { | 198 | { | |
| 199 | return false; | 199 | return false; | |
| 200 | } | 200 | } | |
| 201 | size_t rd = 0; | 201 | size_t rd = 0; | |
| 202 | bool isokay = true; | 202 | bool isokay = true; | |
| 203 | while( (rd = c11n_stream_buffer_read( src, sql, 1024 )) ) | 203 | while( (rd = c11n_stream_buffer_read( src, sql, 1024 )) ) | |
| 204 | { | 204 | { | |
| 205 | } | 205 | } | |
| 206 | if( ! whclob_size(sql) ) | | | 206 | if( ! memblob_size(sql) ) |
| 207 | { | 207 | { | |
| 208 | C11N_LOG(C11N_LOG_IO_ERR)("SQL input is empty!"); | 208 | C11N_LOG(C11N_LOG_IO_ERR)("SQL input is empty!"); | |
| 209 | isokay = false; | 209 | isokay = false; | |
| 210 | } | 210 | } | |
| 211 | 211 | |||
| 212 | if( isokay | 212 | if( isokay | |
| 213 | && (SQLITE_OK != | 213 | && (SQLITE_OK != | |
| 214 | sqlite3_exec( impl->db, whclob_bufferc( sql ), 0, 0, 0 )) | | | 214 | sqlite3_exec( impl->db, memblob_bufferc( sql ), 0, 0, 0 )) |
| 215 | ) | 215 | ) | |
| 216 | { | 216 | { | |
| 217 | C11N_LOG(C11N_LOG_IO_ERR)("SQL error: [%s]",sqlite3_errmsg(impl->db)); | 217 | C11N_LOG(C11N_LOG_IO_ERR)("SQL error: [%s]",sqlite3_errmsg(impl->db)); | |
| 218 | isokay = false; | 218 | isokay = false; | |
| 219 | } | 219 | } | |
| 220 | whclob_finalize( sql ); | | | 220 | memblob_finalize( sql ); |
| 221 | //C11N_LOG(C11N_LOG_FYI)("Loaded SQL data!"); | 221 | //C11N_LOG(C11N_LOG_FYI)("Loaded SQL data!"); | |
| 222 | if( isokay && ! c11n_io_handler_sql_desql( self ) ) | 222 | if( isokay && ! c11n_io_handler_sql_desql( self ) ) | |
| 223 | { | 223 | { | |
| 224 | isokay = false; | 224 | isokay = false; | |
| 225 | } | 225 | } | |
| 211 hidden lines | ||||
| 437 | 437 | |||
| 438 | c11n_io_handler * c11n_io_handler_factory_sql( c11n_const_string_t ignored ) | 438 | c11n_io_handler * c11n_io_handler_factory_sql( c11n_const_string_t ignored ) | |
| 439 | { | 439 | { | |
| 440 | return c11n_io_handler_sql_new(); | 440 | return c11n_io_handler_sql_new(); | |
| 441 | } | 441 | } | |
Added src/c11n_stream_memblob.c
| Old () | New (adaed3400e1112d8) | |||
|---|---|---|---|---|
| > | 1 | #include <stdlib.h> /* malloc()/free() */ | ||
| > | 2 | #include "s11n.net/c11n/io/c11n_stream_memblob.h" | ||
| > | 3 | #include "s11n.net/c11n/detail/memblob.h" | ||
| > | 4 | #include <assert.h> | ||
| > | 5 | |||
| > | 6 | #if 1 | ||
| > | 7 | #include <stdio.h> // only for debuggering | ||
| > | 8 | #define MARKER if(1) printf("MARKER: %s:%d:%s():\n",__FILE__,__LINE__,__func__); if(1) printf | ||
| > | 9 | #else | ||
| > | 10 | static void bogo_printf(char const * fmt, ...) {} | ||
| > | 11 | #define MARKER if(0) bogo_printf | ||
| > | 12 | #endif | ||
| > | 13 | |||
| > | 14 | |||
| > | 15 | static void c11n_stream_memblob_destroy( c11n_stream * self ); | ||
| > | 16 | static bool c11n_stream_memblob_write( c11n_stream * self, char const * src, size_t len ); | ||
| > | 17 | static size_t c11n_stream_memblob_read( c11n_stream * self, char * dest, size_t max ); | ||
| > | 18 | static bool c11n_stream_memblob_isgood( c11n_stream * self ); | ||
| > | 19 | |||
| > | 20 | static const c11n_stream_api c11n_stream_api_memblob = | ||
| > | 21 | C11N_STREAM_API_INIT(c11n_stream_memblob_isgood, | ||
| > | 22 | c11n_stream_memblob_read, | ||
| > | 23 | c11n_stream_memblob_write, | ||
| > | 24 | c11n_stream_memblob_destroy); | ||
| > | 25 | #define CLOBDECL(RV) memblob * clob = self ? ((memblob *)self->implData) : 0; assert(clob && "meta failed!"); if(!clob) return RV | ||
| > | 26 | /** | ||
| > | 27 | c11n_stream_api::isgood() implementation for c11n_stream_memblob. | ||
| > | 28 | */ | ||
| > | 29 | static bool c11n_stream_memblob_isgood( c11n_stream * self ) | ||
| > | 30 | { | ||
| > | 31 | CLOBDECL(false); | ||
| > | 32 | return clob != 0; | ||
| > | 33 | } | ||
| > | 34 | /** | ||
| > | 35 | c11n_stream_api::read() implementation for c11n_stream_memblob. | ||
| > | 36 | */ | ||
| > | 37 | static size_t c11n_stream_memblob_read( c11n_stream * self, char * dest, size_t max ) | ||
| > | 38 | { | ||
| > | 39 | if( ! self || !max || !dest ) return 0; | ||
| > | 40 | //MARKER("READ 1\n"); | ||
| > | 41 | CLOBDECL(0); | ||
| > | 42 | //MARKER("READ 2\n"); | ||
| > | 43 | const long pos = memblob_tell( clob ); | ||
| > | 44 | const long npos = memblob_seek( clob, (long)max, MEMBLOB_SEEK_CUR ); | ||
| > | 45 | const long count = npos - pos; | ||
| > | 46 | //MARKER("Reading %ld bytes from the clob (size=%ld).\n",count,memblob_size(clob)); | ||
| > | 47 | if( 0 >= count ) return 0; | ||
| > | 48 | char const * buf = memblob_bufferc( clob ) + pos; | ||
| > | 49 | long i = 0; | ||
| > | 50 | for( ; i < count; ++i ) | ||
| > | 51 | { | ||
| > | 52 | *(dest++) = *(buf++); | ||
| > | 53 | } | ||
| > | 54 | //MARKER("READ 3: %ld\n",count); | ||
| > | 55 | return (size_t)count; | ||
| > | 56 | } | ||
| > | 57 | |||
| > | 58 | /** | ||
| > | 59 | c11n_stream_api::write() implementation for c11n_stream_memblob. | ||
| > | 60 | */ | ||
| > | 61 | static bool c11n_stream_memblob_write( c11n_stream * self, char const * src, size_t len ) | ||
| > | 62 | { | ||
| > | 63 | if( !len | ||
| > | 64 | || !self | ||
| > | 65 | //|| (!self || !self->api->isgood( self )) | ||
| > | 66 | ) return false; | ||
| > | 67 | // || !SELF->writeMode | ||
| > | 68 | CLOBDECL(false); | ||
| > | 69 | //MARKER("Appending %u/%ld bytes to clob.",len,(long)len); | ||
| > | 70 | long x = memblob_append( clob, src, (long)len); | ||
| > | 71 | bool ret = ((long)len == x); | ||
| > | 72 | //MARKER("AppendED %ld of %u bytes to clob (size=%ld).",x,len,memblob_size(clob)); | ||
| > | 73 | return ret; | ||
| > | 74 | } | ||
| > | 75 | #undef CLOBDECL | ||
| > | 76 | |||
| > | 77 | /** | ||
| > | 78 | c11n_stream_api::destroy() implementation for c11n_stream_memblob. | ||
| > | 79 | */ | ||
| > | 80 | static void c11n_stream_memblob_destroy( c11n_stream * self ) | ||
| > | 81 | { | ||
| > | 82 | /* Reminder: we don't own self->implData */ | ||
| > | 83 | free(self); | ||
| > | 84 | } | ||
| > | 85 | |||
| > | 86 | c11n_stream * c11n_stream_for_memblob( memblob * clob ) | ||
| > | 87 | { | ||
| > | 88 | if( ! clob ) return 0; | ||
| > | 89 | c11n_stream * st = (c11n_stream*)malloc(sizeof(c11n_stream)); | ||
| > | 90 | if( st ) | ||
| > | 91 | { | ||
| > | 92 | st->implData = clob; | ||
| > | 93 | st->api = &c11n_stream_api_memblob; | ||
| > | 94 | } | ||
| > | 95 | return st; | ||
| > | 96 | } | ||
| > | 97 | |||
| > | 98 | size_t c11n_stream_buffer_read( c11n_stream * src, memblob * dest, const size_t max ) | ||
| > | 99 | { | ||
| > | 100 | if( ! src || !dest || !max ) return false; | ||
| > | 101 | long pos = memblob_tell(dest); | ||
| > | 102 | //MARKER("buffering read of %u bytes at pos %ld\n",max,pos); | ||
| > | 103 | if( memblob_rc.OK > memblob_reserve( dest, max + pos ) ) return false; | ||
| > | 104 | memblob_append_char_n( dest, 0, max ); // unfortunate, but necessary to get the clob cursor and our stuff to match | ||
| > | 105 | //MARKER("buffering read of %u bytes at pos %ld. clob size=%ld, capacity=%ld\n",max,pos,memblob_size(dest),memblob_capacity(dest)); | ||
| > | 106 | char * buf = memblob_buffer(dest) + pos; | ||
| > | 107 | size_t rd = src->api->read(src, buf, max ); | ||
| > | 108 | if( 0 != rd ) | ||
| > | 109 | { | ||
| > | 110 | long newpos = (long)(pos + rd); | ||
| > | 111 | //MARKER("seek()ing to pos %ld\n",newpos); | ||
| > | 112 | memblob_seek( dest, newpos, MEMBLOB_SEEK_SET ); | ||
| > | 113 | //MARKER("seek()ed to pos %ld\n",memblob_tell(dest)); | ||
| > | 114 | } | ||
| > | 115 | { | ||
| > | 116 | //MARKER("read() returned 0!\n"); | ||
| > | 117 | } | ||
| > | 118 | return (size_t)rd; | ||
| > | 119 | } | ||
Deleted src/c11n_stream_whclob.c
| Old (3009bc207d2f11f0) | New () | |||
|---|---|---|---|---|
| 1 | #include <stdlib.h> /* malloc()/free() */ | < | ||
| 2 | #include "s11n.net/c11n/io/c11n_stream_whclob.h" | < | ||
| 3 | #include "s11n.net/c11n/detail/whclob.h" | < | ||
| 4 | #include <assert.h> | < | ||
| 5 | < | |||
| 6 | #if 1 | < | ||
| 7 | #include <stdio.h> // only for debuggering | < | ||
| 8 | #define MARKER if(1) printf("MARKER: %s:%d:%s():\n",__FILE__,__LINE__,__func__); if(1) printf | < | ||
| 9 | #else | < | ||
| 10 | static void bogo_printf(char const * fmt, ...) {} | < | ||
| 11 | #define MARKER if(0) bogo_printf | < | ||
| 12 | #endif | < | ||
| 13 | < | |||
| 14 | < | |||
| 15 | static void c11n_stream_whclob_destroy( c11n_stream * self ); | < | ||
| 16 | static bool c11n_stream_whclob_write( c11n_stream * self, char const * src, size_t len ); | < | ||
| 17 | static size_t c11n_stream_whclob_read( c11n_stream * self, char * dest, size_t max ); | < | ||
| 18 | static bool c11n_stream_whclob_isgood( c11n_stream * self ); | < | ||
| 19 | < | |||
| 20 | static const c11n_stream_api c11n_stream_api_whclob = | < | ||
| 21 | C11N_STREAM_API_INIT(c11n_stream_whclob_isgood, | < | ||
| 22 | c11n_stream_whclob_read, | < | ||
| 23 | c11n_stream_whclob_write, | < | ||
| 24 | c11n_stream_whclob_destroy); | < | ||
| 25 | #define CLOBDECL(RV) whclob * clob = self ? ((whclob *)self->implData) : 0; assert(clob && "meta failed!"); if(!clob) return RV | < | ||
| 26 | /** | < | ||
| 27 | c11n_stream_api::isgood() implementation for c11n_stream_whclob. | < | ||
| 28 | */ | < | ||
| 29 | static bool c11n_stream_whclob_isgood( c11n_stream * self ) | < | ||
| 30 | { | < | ||
| 31 | CLOBDECL(false); | < | ||
| 32 | return clob != 0; | < | ||
| 33 | } | < | ||
| 34 | /** | < | ||
| 35 | c11n_stream_api::read() implementation for c11n_stream_whclob. | < | ||
| 36 | */ | < | ||
| 37 | static size_t c11n_stream_whclob_read( c11n_stream * self, char * dest, size_t max ) | < | ||
| 38 | { | < | ||
| 39 | if( ! self || !max || !dest ) return 0; | < | ||
| 40 | //MARKER("READ 1\n"); | < | ||
| 41 | CLOBDECL(0); | < | ||
| 42 | //MARKER("READ 2\n"); | < | ||
| 43 | const long pos = whclob_tell( clob ); | < | ||
| 44 | const long npos = whclob_seek( clob, (long)max, WHCLOB_SEEK_CUR ); | < | ||
| 45 | const long count = npos - pos; | < | ||
| 46 | //MARKER("Reading %ld bytes from the clob (size=%ld).\n",count,whclob_size(clob)); | < | ||
| 47 | if( 0 >= count ) return 0; | < | ||
| 48 | char const * buf = whclob_bufferc( clob ) + pos; | < | ||
| 49 | long i = 0; | < | ||
| 50 | for( ; i < count; ++i ) | < | ||
| 51 | { | < | ||
| 52 | *(dest++) = *(buf++); | < | ||
| 53 | } | < | ||
| 54 | //MARKER("READ 3: %ld\n",count); | < | ||
| 55 | return (size_t)count; | < | ||
| 56 | } | < | ||
| 57 | < | |||
| 58 | /** | < | ||
| 59 | c11n_stream_api::write() implementation for c11n_stream_whclob. | < | ||
| 60 | */ | < | ||
| 61 | static bool c11n_stream_whclob_write( c11n_stream * self, char const * src, size_t len ) | < | ||
| 62 | { | < | ||
| 63 | if( !len | < | ||
| 64 | || !self | < | ||
| 65 | //|| (!self || !self->api->isgood( self )) | < | ||
| 66 | ) return false; | < | ||
| 67 | // || !SELF->writeMode | < | ||
| 68 | CLOBDECL(false); | < | ||
| 69 | //MARKER("Appending %u/%ld bytes to clob.",len,(long)len); | < | ||
| 70 | long x = whclob_append( clob, src, (long)len); | < | ||
| 71 | bool ret = ((long)len == x); | < | ||
| 72 | //MARKER("AppendED %ld of %u bytes to clob (size=%ld).",x,len,whclob_size(clob)); | < | ||
| 73 | return ret; | < | ||
| 74 | } | < | ||
| 75 | #undef CLOBDECL | < | ||
| 76 | < | |||
| 77 | /** | < | ||
| 78 | c11n_stream_api::destroy() implementation for c11n_stream_whclob. | < | ||
| 79 | */ | < | ||
| 80 | static void c11n_stream_whclob_destroy( c11n_stream * self ) | < | ||
| 81 | { | < | ||
| 82 | /* Reminder: we don't own self->implData */ | < | ||
| 83 | free(self); | < | ||
| 84 | } | < | ||
| 85 | < | |||
| 86 | c11n_stream * c11n_stream_for_whclob( whclob * clob ) | < | ||
| 87 | { | < | ||
| 88 | if( ! clob ) return 0; | < | ||
| 89 | c11n_stream * st = (c11n_stream*)malloc(sizeof(c11n_stream)); | < | ||
| 90 | if( st ) | < | ||
| 91 | { | < | ||
| 92 | st->implData = clob; | < | ||
| 93 | st->api = &c11n_stream_api_whclob; | < | ||
| 94 | } | < | ||
| 95 | return st; | < | ||
| 96 | } | < | ||
| 97 | < | |||
| 98 | size_t c11n_stream_buffer_read( c11n_stream * src, whclob * dest, const size_t max ) | < | ||
| 99 | { | < | ||
| 100 | if( ! src || !dest || !max ) return false; | < | ||
| 101 | long pos = whclob_tell(dest); | < | ||
| 102 | //MARKER("buffering read of %u bytes at pos %ld\n",max,pos); | < | ||
| 103 | if( whclob_rc.OK > whclob_reserve( dest, max + pos ) ) return false; | < | ||
| 104 | whclob_append_char_n( dest, 0, max ); // unfortunate, but necessary to get the clob cursor and our stuff to match | < | ||
| 105 | //MARKER("buffering read of %u bytes at pos %ld. clob size=%ld, capacity=%ld\n",max,pos,whclob_size(dest),whclob_capacity(dest)); | < | ||
| 106 | char * buf = whclob_buffer(dest) + pos; | < | ||
| 107 | size_t rd = src->api->read(src, buf, max ); | < | ||
| 108 | if( 0 != rd ) | < | ||
| 109 | { | < | ||
| 110 | long newpos = (long)(pos + rd); | < | ||
| 111 | //MARKER("seek()ing to pos %ld\n",newpos); | < | ||
| 112 | whclob_seek( dest, newpos, WHCLOB_SEEK_SET ); | < | ||
| 113 | //MARKER("seek()ed to pos %ld\n",whclob_tell(dest)); | < | ||
| 114 | } | < | ||
| 115 | { | < | ||
| 116 | //MARKER("read() returned 0!\n"); | < | ||
| 117 | } | < | ||
| 118 | return (size_t)rd; | < | ||
| 119 | } | < | ||
Changes to src/c11nconvert.c
| Old (8470a76984a6c793) | New (6bc923952ec0057a) | |||
|---|---|---|---|---|
| 1 | #include "s11n.net/c11n/c11n.h" | 1 | #include "s11n.net/c11n/c11n.h" | |
| 2 | #include "s11n.net/c11n/io/c11n_io.h" | 2 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 3 | #include "s11n.net/c11n/io/c11n_stream_FILE.h" | 3 | #include "s11n.net/c11n/io/c11n_stream_FILE.h" | |
| 4 | 4 | |||
| 5 | #include <stdio.h> | 5 | #include <stdio.h> | |
| 7 | #include <string.h> | 7 | #include <string.h> | |
| 8 | #include <ctype.h> | 8 | #include <ctype.h> | |
| 9 | #include "s11n.net/c11n/c11n.h" | 9 | #include "s11n.net/c11n/c11n.h" | |
| 10 | #include "s11n.net/c11n/io/c11n_io.h" | 10 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 11 | #include "s11n.net/c11n/io/c11n_stream_FILE.h" | 11 | #include "s11n.net/c11n/io/c11n_stream_FILE.h" | |
| 12 | #include "s11n.net/c11n/io/c11n_stream_whclob.h" | | | 12 | #include "s11n.net/c11n/io/c11n_stream_memblob.h" |
| 13 | #include "s11n.net/c11n/detail/whclob.h" | | | 13 | #include "s11n.net/c11n/detail/memblob.h" |
| 14 | #include "s11n.net/c11n/detail/whgc.h" | 14 | #include "s11n.net/c11n/detail/whgc.h" | |
| 15 | 15 | |||
| 16 | /** | 16 | /** | |
| 17 | A test/demo app for libc11n. Note that we don't take too much care | 17 | A test/demo app for libc11n. Note that we don't take too much care | |
| 18 | to free up memory on an error, because we expect that the app will | 18 | to free up memory on an error, because we expect that the app will | |
| 162 hidden lines | ||||
| 181 | (0==rc) | 181 | (0==rc) | |
| 182 | ? "You win :)" | 182 | ? "You win :)" | |
| 183 | : "You lose :("); | 183 | : "You lose :("); | |
| 184 | return rc; | 184 | return rc; | |
| 185 | } | 185 | } | |
Changes to src/scratch.c
| Old (4b4b55ed6892218f) | New (7026ceb311271115) | |||
|---|---|---|---|---|
| 1 | #include <stdio.h> | 1 | #include <stdio.h> | |
| 2 | #include <stdlib.h> | 2 | #include <stdlib.h> | |
| 3 | #include <string.h> | 3 | #include <string.h> | |
| 4 | #include <ctype.h> | 4 | #include <ctype.h> | |
| 5 | #include <assert.h> | 5 | #include <assert.h> | |
| 6 | 6 | |||
| 7 | #include "s11n.net/c11n/c11n.h" | 7 | #include "s11n.net/c11n/c11n.h" | |
| 8 | #include "s11n.net/c11n/io/c11n_io.h" | 8 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 9 | #include "s11n.net/c11n/detail/whclob.h" | | | 9 | #include "s11n.net/c11n/detail/memblob.h" |
| 10 | 10 | |||
| 11 | #if 1 | 11 | #if 1 | |
| 12 | #define MARKER if(1) printf("MARKER: %s:%d:%s(): ",__FILE__,__LINE__,__func__); if(1) printf | 12 | #define MARKER if(1) printf("MARKER: %s:%d:%s(): ",__FILE__,__LINE__,__func__); if(1) printf | |
| 13 | #else | 13 | #else | |
| 14 | #define MARKER if(0) printf | 14 | #define MARKER if(0) printf | |
| 19 hidden lines | ||||
| 34 | {">",1,">",4}, | 34 | {">",1,">",4}, | |
| 35 | {0,0,0,0} | 35 | {0,0,0,0} | |
| 36 | }; | 36 | }; | |
| 37 | MARKER("Input = [%s]\n",input); | 37 | MARKER("Input = [%s]\n",input); | |
| 38 | 38 | |||
| 39 | whclob * cdec = whclob_new(); | | | 39 | memblob * cdec = memblob_new(); |
| 40 | size_t rc = c11n_io_escape_string( input, inlen, escapes, true, cdec ); | 40 | size_t rc = c11n_io_escape_string( input, inlen, escapes, true, cdec ); | |
| 41 | MARKER("Escaped: [%s]\n", whclob_bufferc(cdec) ); | | | 41 | MARKER("Escaped: [%s]\n", memblob_bufferc(cdec) ); |
| 42 | whclob * cb = whclob_new(); | | | 42 | memblob * cb = memblob_new(); |
| 43 | rc = c11n_io_escape_string( whclob_bufferc(cdec), whclob_size(cdec), escapes, false, cb ); | | | 43 | rc = c11n_io_escape_string( memblob_bufferc(cdec), memblob_size(cdec), escapes, false, cb ); |
| 44 | MARKER( "Unescaped: [%s]\n", whclob_bufferc(cb) ); | | | 44 | MARKER( "Unescaped: [%s]\n", memblob_bufferc(cb) ); |
| 45 | whclob_finalize(cb); | | | 45 | memblob_finalize(cb); |
| 46 | whclob_finalize(cdec); | | | 46 | memblob_finalize(cdec); |
| 47 | 47 | |||
| 48 | return 0; | 48 | return 0; | |
| 49 | } | 49 | } | |
Changes to src/test-clob.c
| Old (05fbebc50bbe33f8) | New (ce88e7ed005276b6) | |||
|---|---|---|---|---|
| 1 | #include <stdio.h> | 1 | #include <stdio.h> | |
| 2 | #include <stdlib.h> | 2 | #include <stdlib.h> | |
| 3 | #include <string.h> | 3 | #include <string.h> | |
| 4 | #include <ctype.h> | 4 | #include <ctype.h> | |
| 5 | #include <assert.h> | 5 | #include <assert.h> | |
| 6 | 6 | |||
| 7 | #include "s11n.net/c11n/detail/whclob.h" | | | 7 | #include "s11n.net/c11n/detail/memblob.h" |
| 8 | 8 | |||
| 9 | #if 1 | 9 | #if 1 | |
| 10 | #define MARKER if(1) printf("MARKER: %s:%d:%s(): ",__FILE__,__LINE__,__func__); if(1) printf | 10 | #define MARKER if(1) printf("MARKER: %s:%d:%s(): ",__FILE__,__LINE__,__func__); if(1) printf | |
| 11 | #else | 11 | #else | |
| 12 | #define MARKER if(0) printf | 12 | #define MARKER if(0) printf | |
| 13 | #endif | 13 | #endif | |
| 14 | 14 | |||
| 15 | #define DUMP(CL) MARKER("clob@%p size=%ld capacity=%ld data=[%s]\n",(void const *)CL,whclob_size(CL),whclob_capacity(CL),whclob_bufferc(CL)) | | | 15 | #define DUMP(CL) MARKER("clob@%p size=%ld capacity=%ld data=[%s]\n",(void const *)CL,memblob_size(CL),memblob_capacity(CL),memblob_bufferc(CL)) |
| 16 | 16 | |||
| 17 | typedef struct MyStruct | 17 | typedef struct MyStruct | |
| 18 | { | 18 | { | |
| 19 | int x; | 19 | int x; | |
| 20 | int y; | 20 | int y; | |
| 3 hidden lines | ||||
| 24 | { | 24 | { | |
| 25 | char const * input = | 25 | char const * input = | |
| 26 | //"a b c" | 26 | //"a b c" | |
| 27 | "A <B> C*D \"inner string\"" | 27 | "A <B> C*D \"inner string\"" | |
| 28 | ; | 28 | ; | |
| 29 | whclob * cb = whclob_new_n(40); | | | 29 | memblob * cb = memblob_new_n(40); |
| | | 30 | DUMP(cb); | ||
| | | 31 | memblob_appendf( cb, "%s", input ); | ||
| | | 32 | DUMP(cb); | ||
| | | 33 | memblob_truncate(cb,3,1); | ||
| 30 | DUMP(cb); | 34 | DUMP(cb); | |
| 31 | whclob_appendf( cb, "%s", input ); | | | 35 | memblob_append( cb, "HIHI", 4 ); |
| 32 | DUMP(cb); | 36 | DUMP(cb); | |
| 33 | whclob_truncate(cb,3,1); | | | 37 | memblob_truncate(cb,5,0); |
| 34 | DUMP(cb); | 38 | DUMP(cb); | |
| 35 | whclob_append( cb, "HIHI", 4 ); | | | 39 | memblob_truncate(cb,8,-1); |
| 36 | DUMP(cb); | | | ||
| 37 | whclob_truncate(cb,5,0); | | | ||
| 38 | DUMP(cb); | | | ||
| 39 | whclob_truncate(cb,8,-1); | | | ||
| 40 | DUMP(cb); | 40 | DUMP(cb); | |
| 41 | whclob_reset(cb); | | | 41 | memblob_reset(cb); |
| 42 | 42 | |||
| 43 | long rc = whclob_import_filename( cb, __FILE__ ); | | | 43 | long rc = memblob_import_filename( cb, __FILE__ ); |
| 44 | MARKER("Import [%s] rc = %ld\n",__FILE__, rc); | 44 | MARKER("Import [%s] rc = %ld\n",__FILE__, rc); | |
| 45 | whclob_base64_enc( cb, cb ); | | | 45 | memblob_base64_enc( cb, cb ); |
| 46 | 46 | |||
| 47 | MARKER("base64-encoded (size=%ld):\n",whclob_size(cb)); | | | 47 | MARKER("base64-encoded (size=%ld):\n",memblob_size(cb)); |
| 48 | //whclob_export_FILE( cb, stdout ); | | | 48 | //memblob_export_FILE( cb, stdout ); |
| 49 | //fputc( '\n', stdout ); | 49 | //fputc( '\n', stdout ); | |
| 50 | MARKER("End encoded data.\n"); | 50 | MARKER("End encoded data.\n"); | |
| 51 | whclob_base64_dec( cb, cb ); | | | 51 | memblob_base64_dec( cb, cb ); |
| 52 | MARKER("base64-decoded size=%ld\n",whclob_size(cb)); | | | 52 | MARKER("base64-decoded size=%ld\n",memblob_size(cb)); |
| 53 | //MARKER("base64-decoded:\n"); | 53 | //MARKER("base64-decoded:\n"); | |
| 54 | //whclob_export_FILE( cb, stdout ); | | | 54 | //memblob_export_FILE( cb, stdout ); |
| 55 | 55 | |||
| 56 | whclob_reset(cb); | | | 56 | memblob_reset(cb); |
| 57 | MyStruct my; | 57 | MyStruct my; | |
| 58 | my.x = 42; | 58 | my.x = 42; | |
| 59 | my.y = -42; | 59 | my.y = -42; | |
| 60 | whclob_append( cb, (char const *)&my, sizeof(MyStruct)); | | | 60 | memblob_append( cb, (char const *)&my, sizeof(MyStruct)); |
| 61 | MARKER("MyStruct clob size: %ld\n", whclob_size(cb) ); | | | 61 | MARKER("MyStruct clob size: %ld\n", memblob_size(cb) ); |
| 62 | whclob_base64_enc( cb, cb ); | | | 62 | memblob_base64_enc( cb, cb ); |
| 63 | MARKER("MyStruct clob encoded size: %ld\n", whclob_size(cb) ); | | | 63 | MARKER("MyStruct clob encoded size: %ld\n", memblob_size(cb) ); |
| 64 | whclob_export_FILE( cb, stdout ); | | | 64 | memblob_export_FILE( cb, stdout ); |
| 65 | 65 | |||
| 66 | MyStruct my2; | 66 | MyStruct my2; | |
| 67 | whclob_base64_dec( cb, cb ); | | | 67 | memblob_base64_dec( cb, cb ); |
| 68 | memcpy( &my2, whclob_bufferc(cb), (size_t) whclob_size(cb) ); | | | 68 | memcpy( &my2, memblob_bufferc(cb), (size_t) memblob_size(cb) ); |
| 69 | MARKER("my2: x=%d y=%d\n", my2.x, my2.y ); | 69 | MARKER("my2: x=%d y=%d\n", my2.x, my2.y ); | |
| 70 | whclob_reset(cb); | | | 70 | memblob_reset(cb); |
| 71 | 71 | |||
| 72 | whclob_finalize(cb); | | | 72 | memblob_finalize(cb); |
| 73 | return 0; | 73 | return 0; | |
| 74 | } | 74 | } | |
Changes to src/test.c
| Old (5a68ab0207bd4620) | New (caa3355a092dd802) | |||
|---|---|---|---|---|
| 1 | #include <stdio.h> | 1 | #include <stdio.h> | |
| 2 | #include <stdlib.h> | 2 | #include <stdlib.h> | |
| 3 | #include <string.h> | 3 | #include <string.h> | |
| 4 | #include <ctype.h> | 4 | #include <ctype.h> | |
| 5 | #include <assert.h> | 5 | #include <assert.h> | |
| 6 | 6 | |||
| 7 | #include "s11n.net/c11n/c11n.h" | 7 | #include "s11n.net/c11n/c11n.h" | |
| 8 | #include "s11n.net/c11n/io/c11n_io.h" | 8 | #include "s11n.net/c11n/io/c11n_io.h" | |
| 9 | #include "s11n.net/c11n/io/c11n_stream_FILE.h" | 9 | #include "s11n.net/c11n/io/c11n_stream_FILE.h" | |
| 10 | #include "s11n.net/c11n/io/c11n_stream_whclob.h" | | | 10 | #include "s11n.net/c11n/io/c11n_stream_memblob.h" |
| 11 | #include "s11n.net/c11n/detail/whclob.h" | | | 11 | #include "s11n.net/c11n/detail/memblob.h" |
| 12 | #include "s11n.net/c11n/io/c11n_io_handler_binarish.h" | 12 | #include "s11n.net/c11n/io/c11n_io_handler_binarish.h" | |
| 13 | #include "MyType.h" /* example class */ | 13 | #include "MyType.h" /* example class */ | |
| 14 | 14 | |||
| 15 | /** | 15 | /** | |
| 16 | A test/demo app for libc11n. Note that we don't take too much care | 16 | A test/demo app for libc11n. Note that we don't take too much care | |
| 13 hidden lines | ||||
| 30 | whgc_context * gc; | 30 | whgc_context * gc; | |
| 31 | c11n_stream * cout; | 31 | c11n_stream * cout; | |
| 32 | } ThisApp; | 32 | } ThisApp; | |
| 33 | 33 | |||
| 34 | /** | 34 | /** | |
| 35 | Increasing the whclob alloc policy to around 1.5x actually lowers | | | 35 | Increasing the memblob alloc policy to around 1.5x actually lowers |
| 36 | the peak max aggregate memory allocated (per valgrind data). | 36 | the peak max aggregate memory allocated (per valgrind data). | |
| 37 | */ | 37 | */ | |
| 38 | long my_whclob_alloc_policy( long n ) | | | 38 | long my_memblob_alloc_policy( long n ) |
| 39 | { | 39 | { | |
| 40 | long ret = n; | 40 | long ret = n; | |
| 41 | #if 0 | 41 | #if 0 | |
| 42 | ret = (long) (n * 1.5); | 42 | ret = (long) (n * 1.5); | |
| 43 | #else | 43 | #else | |
| 55 hidden lines | ||||
| 99 | GET(N,"pX"); | 99 | GET(N,"pX"); | |
| 100 | 100 | |||
| 101 | c11n_node * CH = c11n_node_create_child( N, "aChild" ); | 101 | c11n_node * CH = c11n_node_create_child( N, "aChild" ); | |
| 102 | SET(CH, "anglebone", "hi, world" ); | 102 | SET(CH, "anglebone", "hi, world" ); | |
| 103 | int i = 0; | 103 | int i = 0; | |
| 104 | whclob * clob = whclob_new(); | | | 104 | memblob * clob = memblob_new(); |
| 105 | for( ; i < 3; ++i ) | 105 | for( ; i < 3; ++i ) | |
| 106 | { | 106 | { | |
| 107 | whclob_appendf( clob, "key%d",i); | | | 107 | memblob_appendf( clob, "key%d",i); |
| 108 | c11n_node_prop_set_fe( CH, whclob_bufferc(clob), "value #%d",i ); | | | 108 | c11n_node_prop_set_fe( CH, memblob_bufferc(clob), "value #%d",i ); |
| 109 | whclob_reset(clob); | | | 109 | memblob_reset(clob); |
| 110 | } | 110 | } | |
| 111 | //whclob_finalize(clob); | | | 111 | //memblob_finalize(clob); |
| 112 | GET(CH,"key2"); | 112 | GET(CH,"key2"); | |
| 113 | #undef SET | 113 | #undef SET | |
| 114 | #undef GET | 114 | #undef GET | |
| 115 | 115 | |||
| 116 | typedef double CType; | 116 | typedef double CType; | |
| 120 hidden lines | ||||
| 237 | return 22; | 237 | return 22; | |
| 238 | } | 238 | } | |
| 239 | o1t->api->destroy(o1t); | 239 | o1t->api->destroy(o1t); | |
| 240 | 240 | |||
| 241 | c11n_node_destroy( N ); | 241 | c11n_node_destroy( N ); | |
| 242 | whclob_finalize(clob); | | | 242 | memblob_finalize(clob); |
| 243 | return rc; | 243 | return rc; | |
| 244 | } | 244 | } | |
| 245 | 245 | |||
| 246 | static void gc_c11n_stream( void * v ) | 246 | static void gc_c11n_stream( void * v ) | |
| 247 | { | 247 | { | |
| 2 hidden lines | ||||
| 250 | { | 250 | { | |
| 251 | MARKER("GC'ing c11n_stream @%p\n",v); | 251 | MARKER("GC'ing c11n_stream @%p\n",v); | |
| 252 | s->api->destroy(s); | 252 | s->api->destroy(s); | |
| 253 | } | 253 | } | |
| 254 | } | 254 | } | |
| 255 | static void gc_whclob( void * v) | | | 255 | static void gc_memblob( void * v) |
| 256 | { | 256 | { | |
| 257 | whclob * s = v ? (whclob *)v : 0; | | | 257 | memblob * s = v ? (memblob *)v : 0; |
| 258 | if( s ) | 258 | if( s ) | |
| 259 | { | 259 | { | |
| 260 | MARKER("GC'ing whclob @%p\n",v); | | | 260 | MARKER("GC'ing memblob @%p\n",v); |
| 261 | whclob_finalize(s); | | | 261 | memblob_finalize(s); |
| 262 | } | 262 | } | |
| 263 | } | 263 | } | |
| 264 | int test_streams() | 264 | int test_streams() | |
| 265 | { | 265 | { | |
| 266 | c11n_stream * is = 0; | 266 | c11n_stream * is = 0; | |
| 267 | const size_t blockSize = 1024; | 267 | const size_t blockSize = 1024; | |
| 268 | char const * ofile = "ostr.out"; | 268 | char const * ofile = "ostr.out"; | |
| 269 | char const * infile = __FILE__; | 269 | char const * infile = __FILE__; | |
| 270 | 270 | |||
| 271 | whclob * cb = 0; | | | 271 | memblob * cb = 0; |
| 272 | whclob_init( &cb, 0, blockSize ); | | | 272 | memblob_init( &cb, 0, blockSize ); |
| 273 | whgc_add( ThisApp.gc, cb, gc_whclob ); | | | 273 | whgc_add( ThisApp.gc, cb, gc_memblob ); |
| 274 | 274 | |||
| 275 | 275 | |||
| 276 | char * buf = whclob_buffer(cb); | | | 276 | char * buf = memblob_buffer(cb); |
| 277 | 277 | |||
| 278 | size_t count = 0; | 278 | size_t count = 0; | |
| 279 | 279 | |||
| 280 | whclob * membuf = whclob_new(); | | | 280 | memblob * membuf = memblob_new(); |
| 281 | whclob_reserve( membuf, blockSize * 10 ); | | | 281 | memblob_reserve( membuf, blockSize * 10 ); |
| 282 | whclob_set_alloc_policy( membuf, my_whclob_alloc_policy ); | | | 282 | memblob_set_alloc_policy( membuf, my_memblob_alloc_policy ); |
| 283 | whgc_add( ThisApp.gc, membuf, gc_whclob ); | | | 283 | whgc_add( ThisApp.gc, membuf, gc_memblob ); |
| 284 | c11n_stream * mems = c11n_stream_for_whclob( membuf ); | | | 284 | c11n_stream * mems = c11n_stream_for_memblob( membuf ); |
| 285 | assert(mems && "Got memory stream"); | 285 | assert(mems && "Got memory stream"); | |
| 286 | whgc_add( ThisApp.gc, mems, gc_c11n_stream ); | 286 | whgc_add( ThisApp.gc, mems, gc_c11n_stream ); | |
| 287 | MARKER("***** START OF FILE %s\n",infile); | 287 | MARKER("***** START OF FILE %s\n",infile); | |
| 288 | is = c11n_stream_for_filename( infile, false ); | 288 | is = c11n_stream_for_filename( infile, false ); | |
| 289 | if( ! is ) { return 1; } | 289 | if( ! is ) { return 1; } | |
| 7 hidden lines | ||||
| 297 | if( ! mems->api->write( mems, buf, count ) ) | 297 | if( ! mems->api->write( mems, buf, count ) ) | |
| 298 | { | 298 | { | |
| 299 | MARKER("Write of %u bytes to memory buffer failed!\n",count ); | 299 | MARKER("Write of %u bytes to memory buffer failed!\n",count ); | |
| 300 | return 3; | 300 | return 3; | |
| 301 | } | 301 | } | |
| 302 | MARKER("buf=%p, membuf size=%ld capacity=%ld\n",buf,whclob_size(membuf),whclob_capacity(membuf)); | | | 302 | MARKER("buf=%p, membuf size=%ld capacity=%ld\n",buf,memblob_size(membuf),memblob_capacity(membuf)); |
| 303 | //whclob_append( cb, "\0", 1 );//same thing: buf[count] = 0; | | | 303 | //memblob_append( cb, "\0", 1 );//same thing: buf[count] = 0; |
| 304 | //MARKER("Read %u of %u byte(s).\n",count,blockSize); | 304 | //MARKER("Read %u of %u byte(s).\n",count,blockSize); | |
| 305 | //printf("[[%s]]",buf); | 305 | //printf("[[%s]]",buf); | |
| 306 | } | 306 | } | |
| 307 | whgc_unregister( ThisApp.gc, is ); | 307 | whgc_unregister( ThisApp.gc, is ); | |
| 308 | is->api->destroy(is); | 308 | is->api->destroy(is); | |
| 309 | MARKER("***** END OF FILE %s\n",infile); | 309 | MARKER("***** END OF FILE %s\n",infile); | |
| 310 | //MARKER("membuf size=%ld capacity=%ld\n",whclob_size(membuf),whclob_capacity(membuf)); | | | 310 | //MARKER("membuf size=%ld capacity=%ld\n",memblob_size(membuf),memblob_capacity(membuf)); |
| 311 | //whclob_truncate( membuf, whclob_size( membuf ), -1 ); | | | 311 | //memblob_truncate( membuf, memblob_size( membuf ), -1 ); |
| 312 | MARKER("membuf size=%ld capacity=%ld\n",whclob_size(membuf),whclob_capacity(membuf)); | | | 312 | MARKER("membuf size=%ld capacity=%ld\n",memblob_size(membuf),memblob_capacity(membuf)); |
| 313 | whclob_export_filename( membuf, "membuf.out" ); | | | 313 | memblob_export_filename( membuf, "membuf.out" ); |
| 314 | 314 | |||
| 315 | c11n_stream * ostr = c11n_stream_for_filename( ofile, true ); | 315 | c11n_stream * ostr = c11n_stream_for_filename( ofile, true ); | |
| 316 | if( ! ostr ) return 4; | 316 | if( ! ostr ) return 4; | |
| 317 | whgc_add( ThisApp.gc, ostr, gc_c11n_stream ); | 317 | whgc_add( ThisApp.gc, ostr, gc_c11n_stream ); | |
| 318 | if( ! ostr->api->isgood(ostr) ) { ostr->api->destroy(ostr); return 5; } | 318 | if( ! ostr->api->isgood(ostr) ) { ostr->api->destroy(ostr); return 5; } | |
| 319 | //whclob_rewind(membuf); | | | 319 | //memblob_rewind(membuf); |
| 320 | size_t total = 0; | 320 | size_t total = 0; | |
| 321 | whclob * checker = whclob_new(); | | | 321 | memblob * checker = memblob_new(); |
| 322 | whgc_add( ThisApp.gc, checker, gc_whclob ); | | | 322 | whgc_add( ThisApp.gc, checker, gc_memblob ); |
| 323 | while( (count = mems->api->read( mems, buf, blockSize ) ) ) | 323 | while( (count = mems->api->read( mems, buf, blockSize ) ) ) | |
| 324 | { | 324 | { | |
| 325 | total += count; | 325 | total += count; | |
| 326 | whclob_append( checker, buf, count ); | | | 326 | memblob_append( checker, buf, count ); |
| 327 | if( ! ostr->api->write( ostr, buf, count ) ) | 327 | if( ! ostr->api->write( ostr, buf, count ) ) | |
| 328 | { | 328 | { | |
| 329 | MARKER("Write of %u bytes to file %s failed!\n",count, ofile); | 329 | MARKER("Write of %u bytes to file %s failed!\n",count, ofile); | |
| 330 | return 6; | 330 | return 6; | |
| 331 | } | 331 | } | |
| 332 | //MARKER("buf=%p Wrote %u of %u byte-block. Total=%u.\n",buf,count,blockSize,total); | 332 | //MARKER("buf=%p Wrote %u of %u byte-block. Total=%u.\n",buf,count,blockSize,total); | |
| 333 | } | 333 | } | |
| 334 | whclob_export_filename( checker, "checker.out" ); | | | 334 | memblob_export_filename( checker, "checker.out" ); |
| 335 | whgc_unregister( ThisApp.gc, ostr ); | 335 | whgc_unregister( ThisApp.gc, ostr ); | |
| 336 | ostr->api->destroy(ostr); | 336 | ostr->api->destroy(ostr); | |
| 337 | 337 | |||
| 338 | MARKER("Wrote %ld bytes to file %s.\n",whclob_size(membuf),ofile); | | | 338 | MARKER("Wrote %ld bytes to file %s.\n",memblob_size(membuf),ofile); |
| 339 | 339 | |||
| 340 | whclob_rewind(membuf); | | | 340 | memblob_rewind(membuf); |
| 341 | ostr = c11n_stream_for_filename( "FILE.out", true ); | 341 | ostr = c11n_stream_for_filename( "FILE.out", true ); | |
| 342 | bool worked = ostr->api->write( ostr, whclob_bufferc(membuf), whclob_size(membuf) ); | | | 342 | bool worked = ostr->api->write( ostr, memblob_bufferc(membuf), memblob_size(membuf) ); |
| 343 | MARKER("ostr->api->write worked? == %d\n",worked); | 343 | MARKER("ostr->api->write worked? == %d\n",worked); | |
| 344 | ostr->api->destroy(ostr); | 344 | ostr->api->destroy(ostr); | |
| 345 | //mems->api->destroy(mems); | 345 | //mems->api->destroy(mems); | |
| 346 | whclob_export_filename( membuf, "membuf2.out" ); | | | 346 | memblob_export_filename( membuf, "membuf2.out" ); |
| 347 | whgc_clear_context( ThisApp.gc ); | 347 | whgc_clear_context( ThisApp.gc ); | |
| 348 | #endif | 348 | #endif | |
| 349 | return 0; | 349 | return 0; | |
| 350 | } | 350 | } | |
| 351 | 351 | |||
| 55 hidden lines | ||||
| 407 | return 0; | 407 | return 0; | |
| 408 | } | 408 | } | |
| 409 | 409 | |||
| 410 | int test_otherstuff() | 410 | int test_otherstuff() | |
| 411 | { | 411 | { | |
| 412 | whclob * cb = whclob_new(); | | | 412 | memblob * cb = memblob_new(); |
| 413 | whgc_add( ThisApp.gc, cb, gc_whclob ); | | | 413 | whgc_add( ThisApp.gc, cb, gc_memblob ); |
| 414 | whclob_import_filename(cb,__FILE__); | | | 414 | memblob_import_filename(cb,__FILE__); |
| 415 | c11n_stream * is = c11n_stream_for_whclob( cb ); | | | 415 | c11n_stream * is = c11n_stream_for_memblob( cb ); |
| 416 | whgc_add( ThisApp.gc, is, gc_c11n_stream ); | 416 | whgc_add( ThisApp.gc, is, gc_c11n_stream ); | |
| 417 | whclob * check = 0; | | | 417 | memblob * check = 0; |
| 418 | whclob_init( &check, 0, 1024 ); | | | 418 | memblob_init( &check, 0, 1024 ); |
| 419 | whgc_add( ThisApp.gc, check, gc_whclob ); | | | 419 | whgc_add( ThisApp.gc, check, gc_memblob ); |
| 420 | size_t at = 1; | 420 | size_t at = 1; | |
| 421 | bool rc = true; | 421 | bool rc = true; | |
| 422 | for( ; at < 31; at += at ) | 422 | for( ; at < 31; at += at ) | |
| 423 | { | 423 | { | |
| 424 | rc = c11n_stream_buffer_read( is, check, at ); | 424 | rc = c11n_stream_buffer_read( is, check, at ); | |
| 425 | if( ! rc ) break; | 425 | if( ! rc ) break; | |
| 426 | MARKER("buffered read. clob size=%ld, capacity=%ld\n",whclob_size(check),whclob_capacity(check)); | | | 426 | MARKER("buffered read. clob size=%ld, capacity=%ld\n",memblob_size(check),memblob_capacity(check)); |
| 427 | } | 427 | } | |
| 428 | if( ! rc ) | 428 | if( ! rc ) | |
| 429 | { | 429 | { | |
| 430 | MARKER("c11n_stream_buffer_read() failed.\n"); | 430 | MARKER("c11n_stream_buffer_read() failed.\n"); | |
| 431 | return -1; | 431 | return -1; | |
| 432 | } | 432 | } | |
| 433 | else | 433 | else | |
| 434 | { | 434 | { | |
| 435 | MARKER("Read in %ld bytes: [%s]\n",whclob_size(check),whclob_bufferc(check)); | | | 435 | MARKER("Read in %ld bytes: [%s]\n",memblob_size(check),memblob_bufferc(check)); |
| 436 | } | 436 | } | |
| 437 | if( ! c11n_io_handler_register( "bin", c11n_io_handler_factory_binarish ) ) | 437 | if( ! c11n_io_handler_register( "bin", c11n_io_handler_factory_binarish ) ) | |
| 438 | { | 438 | { | |
| 439 | MARKER("Factory registration failed!\n"); | 439 | MARKER("Factory registration failed!\n"); | |
| 440 | return -2; | 440 | return -2; | |
| 8 hidden lines | ||||
| 449 | { | 449 | { | |
| 450 | MARKER("Loaded file handler for cookie.\n"); | 450 | MARKER("Loaded file handler for cookie.\n"); | |
| 451 | } | 451 | } | |
| 452 | h->api->destroy(h); | 452 | h->api->destroy(h); | |
| 453 | 453 | |||
| 454 | //whclob_finalize(check); | | | 454 | //memblob_finalize(check); |
| 455 | //whclob_finalize(cb); | | | 455 | //memblob_finalize(cb); |
| 456 | return 0; | 456 | return 0; | |
| 457 | } | 457 | } | |
| 458 | 458 | |||
| 459 | int test_binary() | 459 | int test_binary() | |
| 460 | { | 460 | { | |
| 87 hidden lines | ||||
| 548 | #endif // C11N_IO_USE_SQL | 548 | #endif // C11N_IO_USE_SQL | |
| 549 | 549 | |||
| 550 | 550 | |||
| 551 | int main( int argc, char ** argv ) | 551 | int main( int argc, char ** argv ) | |
| 552 | { | 552 | { | |
| 553 | //whclob_set_default_alloc_policy( my_whclob_alloc_policy ); | | | 553 | //memblob_set_default_alloc_policy( my_memblob_alloc_policy ); |
| 554 | ThisApp.gc = whgc_create_context(&ThisApp); | 554 | ThisApp.gc = whgc_create_context(&ThisApp); | |
| 555 | ThisApp.cout = c11n_stream_for_FILE( stdout ); | 555 | ThisApp.cout = c11n_stream_for_FILE( stdout ); | |
| 556 | 556 | |||
| 557 | c11n_log_set_stream( stderr ); | 557 | c11n_log_set_stream( stderr ); | |
| 558 | //c11n_log_set_flags( c11n_log_get_flags() | C11N_LOG_DEALLOC ); | 558 | //c11n_log_set_flags( c11n_log_get_flags() | C11N_LOG_DEALLOC ); | |
| 17 hidden lines | ||||
| 576 | : "You lose :("); | 576 | : "You lose :("); | |
| 577 | ThisApp.cout->api->destroy(ThisApp.cout); | 577 | ThisApp.cout->api->destroy(ThisApp.cout); | |
| 578 | whgc_destroy_context(ThisApp.gc); | 578 | whgc_destroy_context(ThisApp.gc); | |
| 579 | return rc; | 579 | return rc; | |
| 580 | } | 580 | } | |
Deleted src/whclob.c
| Old (11d6042d3c580e26) | New () | |||
|---|---|---|---|---|
| 1 | #include <string.h> | < | ||
| 2 | #include <stdlib.h> | < | ||
| 3 | #include <stdio.h> | < | ||
| 4 | #include <stdarg.h> | < | ||
| 5 | < | |||
| 6 | #include "s11n.net/c11n/detail/whclob.h" | < | ||
| 7 | #include "s11n.net/c11n/detail/vappendf.h" | < | ||
| 8 | < | |||
| 9 | #if WHCLOB_USE_ZLIB | < | ||
| 10 | # include <zlib.h> | < | ||
| 11 | #endif | < | ||
| 12 | < | |||
| 13 | #define MARKER if(1) printf("MARKER: %s:%d:%s() ",__FILE__,__LINE__,__func__);if(1)printf | < | ||
| 14 | < | |||
| 15 | #define WHCLOB_DEBUG 0 | < | ||
| 16 | < | |||
| 17 | < | |||
| 18 | const whclob_rc_t whclob_rc = {0, /* OK */ | < | ||
| 19 | -1, /* Err */ | < | ||
| 20 | -2, /* AllocError */ | < | ||
| 21 | -3, /* UnexpectedNull */ | < | ||
| 22 | -4, /* RangeError */ | < | ||
| 23 | -5, /* IOError */ | < | ||
| 24 | -6 /* ArgError */ | < | ||
| 25 | }; | < | ||
| 26 | < | |||
| 27 | < | |||
| 28 | struct whclob | < | ||
| 29 | { | < | ||
| 30 | /* | < | ||
| 31 | The address of the memory this blob refers to. See below | < | ||
| 32 | for more info. | < | ||
| 33 | < | |||
| 34 | If aData is pointed to a const string or a string owned by | < | ||
| 35 | another entity, then nAlloc must be set to 0. This indicates | < | ||
| 36 | to the framework that aData is not to be deleted when the | < | ||
| 37 | blob is freed. In this case, nUsed must be set to the full | < | ||
| 38 | length of the pointed-to data object. When shallow copies | < | ||
| 39 | like this exist, any change made to pointed-to copies will | < | ||
| 40 | invalidate the state of the doing-the-pointing whclob object. | < | ||
| 41 | < | |||
| 42 | The framework tries to ensure that aData[nUsed] is always | < | ||
| 43 | set to 0 (assuming that aData is not manipulated outside of | < | ||
| 44 | the clob API). Note that since aData may contain binary data | < | ||
| 45 | (and embedded nulls), such a trailing null cannot be used | < | ||
| 46 | for length determination purposes. | < | ||
| 47 | */ | < | ||
| 48 | char * aData; | < | ||
| 49 | /** | < | ||
| 50 | long nAlloc = the number of contiguous bytes allocated to | < | ||
| 51 | aData. See below for more info. | < | ||
| 52 | */ | < | ||
| 53 | long nAlloc; | < | ||
| 54 | /* | < | ||
| 55 | long nUsed = the number of contiguous bytes "used" in the | < | ||
| 56 | aData array. | < | ||
| 57 | */ | < | ||
| 58 | long nUsed; | < | ||
| 59 | /* | < | ||
| 60 | The current position marker for some read operations. | < | ||
| 61 | */ | < | ||
| 62 | long nCursor; | < | ||
| 63 | whclob_alloc_policy_t allocPolicy; | < | ||
| 64 | }; | < | ||
| 65 | < | |||
| 66 | < | |||
| 67 | /** | < | ||
| 68 | Default alloc size policy, simply returns n. | < | ||
| 69 | */ | < | ||
| 70 | static long whclob_default_alloc_policy( long n ) | < | ||
| 71 | { | < | ||
| 72 | return n; | < | ||
| 73 | } | < | ||
| 74 | < | |||
| 75 | /* | < | ||
| 76 | Clob_empty is an empty whclob used for init purposes. | < | ||
| 77 | */ | < | ||
| 78 | static const whclob Clob_empty = {0, /* aData */ | < | ||
| 79 | 0, /* nAlloc */ | < | ||
| 80 | 0, /* nUsed */ | < | ||
| 81 | 0, /* nCursor */ | < | ||
| 82 | whclob_default_alloc_policy | < | ||
| 83 | }; | < | ||
| 84 | < | |||
| 85 | /** | < | ||
| 86 | A debugging-only function. Do not use it in client code. | < | ||
| 87 | */ | < | ||
| 88 | void whclob_dump( whclob * cb, int doString ); | < | ||
| 89 | < | |||
| 90 | typedef whclob_alloc_policy_t RePol; | < | ||
| 91 | static RePol whclob_current_alloc_policy = whclob_default_alloc_policy; | < | ||
| 92 | RePol whclob_set_default_alloc_policy( RePol f ) | < | ||
| 93 | { | < | ||
| 94 | RePol old = whclob_current_alloc_policy; | < | ||
| 95 | whclob_current_alloc_policy = f ? f : whclob_default_alloc_policy; | < | ||
| 96 | return old; | < | ||
| 97 | } | < | ||
| 98 | whclob_alloc_policy_t whclob_set_alloc_policy( whclob * cb, whclob_alloc_policy_t f ) | < | ||
| 99 | { | < | ||
| 100 | RePol old = cb ? cb->allocPolicy : 0; | < | ||
| 101 | if( cb ) cb->allocPolicy = f; | < | ||
| 102 | return old; | < | ||
| 103 | } | < | ||
| 104 | < | |||
| 105 | < | |||
| 106 | #define WHCLOB_DUMP(X,B) if(WHCLOB_DEBUG) { printf(X ": blob [%s]: ", # B ); whclob_dump(B,1); } | < | ||
| 107 | void whclob_dump( whclob * cb, int doString ) | < | ||
| 108 | { | < | ||
| 109 | whclob * dest = whclob_new(); | < | ||
| 110 | if( ! dest ) return; | < | ||
| 111 | whclob_appendf( dest, | < | ||
| 112 | "whclob@%p[nUsed=%d, nAlloc=%d, nCursor=%d][data@%p]", | < | ||
| 113 | cb, cb->nUsed, cb->nAlloc, cb->nCursor, cb->aData | < | ||
| 114 | ); | < | ||
| 115 | if( doString ) | < | ||
| 116 | { | < | ||
| 117 | if( cb->nAlloc && cb->aData[0] ) | < | ||
| 118 | { | < | ||
| 119 | whclob_appendf( dest, "=[%s]", whclob_buffer(cb) ); | < | ||
| 120 | } | < | ||
| 121 | else | < | ||
| 122 | { | < | ||
| 123 | whclob_appendf( dest, "=[NULL]", cb ); | < | ||
| 124 | } | < | ||
| 125 | } | < | ||
| 126 | fappendf( stderr, "%s\n", whclob_buffer( dest ) ); | < | ||
| 127 | whclob_finalize( dest ); | < | ||
| 128 | } | < | ||
| 129 | < | |||
| 130 | < | |||
| 131 | long whclob_reset( whclob * cb ) | < | ||
| 132 | { | < | ||
| 133 | if( cb ) | < | ||
| 134 | { | < | ||
| 135 | #if WHCLOB_DEBUG | < | ||
| 136 | printf( "Freeing clob @ [%p], bytes=%ld\n", cb, cb->nAlloc ); | < | ||
| 137 | /* endless loop: whclob_dump(cb,1); */ | < | ||
| 138 | #endif | < | ||
| 139 | if( cb->nAlloc ) | < | ||
| 140 | { | < | ||
| 141 | /* crash? memset( cb->aData, 0, cb->nAlloc ); */ | < | ||
| 142 | free( cb->aData ); | < | ||
| 143 | cb->aData = 0; | < | ||
| 144 | } | < | ||
| 145 | *cb = Clob_empty; | < | ||
| 146 | return whclob_rc.OK; | < | ||
| 147 | } | < | ||
| 148 | return whclob_rc.UnexpectedNull; | < | ||
| 149 | } | < | ||
| 150 | < | |||
| 151 | long whclob_finalize( whclob * cb ) | < | ||
| 152 | { | < | ||
| 153 | if( ! cb ) return whclob_rc.UnexpectedNull; | < | ||
| 154 | whclob_reset(cb); | < | ||
| 155 | free( cb ); | < | ||
| 156 | return whclob_rc.OK; | < | ||
| 157 | } | < | ||
| 158 | < | |||
| 159 | void whclob_force_in_bounds( whclob * cb ) | < | ||
| 160 | { | < | ||
| 161 | if( cb->nUsed > cb->nAlloc ) cb->nUsed = (cb->nAlloc ? (cb->nAlloc - 1) : 0); | < | ||
| 162 | if( cb->nCursor > cb->nUsed ) cb->nCursor = cb->nUsed; | < | ||
| 163 | } | < | ||
| 164 | < | |||
| 165 | static long whclob_do_resize( whclob * cb, | < | ||
| 166 | unsigned int sz, | < | ||
| 167 | short usePolicyHint) | < | ||
| 168 | { | < | ||
| 169 | static const int fudge = 2; | < | ||
| 170 | char const * zOld = 0; | < | ||
| 171 | long oldUsed = 0; | < | ||
| 172 | long oldAlloc = 0; | < | ||
| 173 | long allocsize = 0; | < | ||
| 174 | char * pNew = 0; | < | ||
| 175 | if( !cb ) return whclob_rc.UnexpectedNull; | < | ||
| 176 | if( cb->nAlloc == (long)sz ) return cb->nAlloc; | < | ||
| 177 | /* ^^^ over-allocate by 1 to ensure we have space for | < | ||
| 178 | a trailing 0. */ | < | ||
| 179 | /* const int shrinkage = 16; */ | < | ||
| 180 | /* if we can save more than this much, then try to do so. */ | < | ||
| 181 | if( 0 == sz ) | < | ||
| 182 | { | < | ||
| 183 | whclob_reset( cb ); | < | ||
| 184 | return 0; | < | ||
| 185 | } | < | ||
| 186 | zOld = cb->aData; | < | ||
| 187 | oldUsed = cb->nUsed; | < | ||
| 188 | oldAlloc = cb->nAlloc; | < | ||
| 189 | allocsize = 0; | < | ||
| 190 | if( (usePolicyHint && (0 != cb->allocPolicy)) ) | < | ||
| 191 | { | < | ||
| 192 | allocsize = cb->allocPolicy(sz); | < | ||
| 193 | } | < | ||
| 194 | else if( (usePolicyHint && (0 != whclob_current_alloc_policy)) ) | < | ||
| 195 | { | < | ||
| 196 | allocsize = (*whclob_current_alloc_policy)(sz); | < | ||
| 197 | } | < | ||
| 198 | else | < | ||
| 199 | { | < | ||
| 200 | allocsize = (long)sz; | < | ||
| 201 | } | < | ||
| 202 | allocsize += fudge; | < | ||
| 203 | if( allocsize < (fudge + (long)sz) ) allocsize = fudge + sz; | < | ||
| 204 | #if 0 | < | ||
| 205 | pNew = cb->aData /* oldAlloc */ | < | ||
| 206 | ? realloc( cb->aData, allocsize ) | < | ||
| 207 | : malloc( fudge + allocsize ); | < | ||
| 208 | #else | < | ||
| 209 | pNew = realloc( cb->aData, allocsize ); | < | ||
| 210 | #endif | < | ||
| 211 | if( ! pNew ) return whclob_rc.AllocError; | < | ||
| 212 | /* if( !oldAlloc ) */ | < | ||
| 213 | if( ! cb->aData ) | < | ||
| 214 | { /** cb has/had no data */ | < | ||
| 215 | if( zOld ) | < | ||
| 216 | { /* cb was pointing to shared data. Copy it. */ | < | ||
| 217 | memcpy( pNew, zOld, (oldUsed > allocsize) ? allocsize : oldUsed ); | < | ||
| 218 | } | < | ||
| 219 | else | < | ||
| 220 | { /* cb had no buffer - create one. */ | < | ||
| 221 | memset( pNew, 0, allocsize ); | < | ||
| 222 | cb->nUsed = cb->nCursor = 0; | < | ||
| 223 | } | < | ||
| 224 | } | < | ||
| 225 | else | < | ||
| 226 | { /** cb had data and we realloced. Zero out any new | < | ||
| 227 | memory. */ | < | ||
| 228 | if( oldAlloc && (oldAlloc < allocsize) ) | < | ||
| 229 | { | < | ||
| 230 | memset( pNew + oldAlloc, 0, allocsize - oldAlloc); | < | ||
| 231 | } | < | ||
| 232 | } | < | ||
| 233 | pNew[allocsize-fudge] = 0; | < | ||
| 234 | cb->aData = pNew; | < | ||
| 235 | cb->nAlloc = allocsize; | < | ||
| 236 | whclob_force_in_bounds( cb ); | < | ||
| 237 | return cb->nAlloc; | < | ||
| 238 | } | < | ||
| 239 | < | |||
| 240 | long whclob_reserve( whclob * cb, unsigned int sz ) | < | ||
| 241 | { | < | ||
| 242 | long rc = cb->nAlloc; | < | ||
| 243 | if( ((long)sz > cb->nAlloc) || (sz==0) ) | < | ||
| 244 | { | < | ||
| 245 | rc = whclob_do_resize( cb, sz, 1 ); | < | ||
| 246 | } | < | ||
| 247 | return rc; | < | ||
| 248 | } | < | ||
| 249 | < | |||
| 250 | long whclob_size( whclob const * cb ) { return cb ? cb->nUsed : whclob_rc.UnexpectedNull; } | < | ||
| 251 | long whclob_capacity( whclob const * cb ) { return cb ? cb->nAlloc : whclob_rc.UnexpectedNull; } | < | ||
| 252 | char * whclob_buffer( whclob * cb ) { return cb ? cb->aData : 0; } | < | ||
| 253 | char const * whclob_bufferc( whclob const * cb ) { return cb ? cb->aData : 0; } | < | ||
| 254 | < | |||
| 255 | long whclob_resize( whclob * cb, unsigned int sz ) | < | ||
| 256 | { | < | ||
| 257 | unsigned long ret = whclob_do_resize( cb, sz, 1 ); | < | ||
| 258 | if( sz && (ret >= sz) ) | < | ||
| 259 | { | < | ||
| 260 | cb->nUsed = sz; | < | ||
| 261 | cb->aData[sz] = 0; | < | ||
| 262 | } | < | ||
| 263 | return ret; | < | ||
| 264 | } | < | ||
| 265 | < | |||
| 266 | #if 0 | < | ||
| 267 | /* | < | ||
| 268 | NOT part of the public API! | < | ||
| 269 | < | |||
| 270 | sz is forced into bounds (>=0 and <=cb->nAlloc) then cb->nUsed is | < | ||
| 271 | set to sz. cb->aData[sz] is set to 0 to enforce the null-termination | < | ||
| 272 | policy. | < | ||
| 273 | */ | < | ||
| 274 | static long whclob_set_used_size( whclob * cb, long sz ) | < | ||
| 275 | { | < | ||
| 276 | if( sz < 0 ) sz = 0; | < | ||
| 277 | else if( sz > cb->nAlloc ) sz = cb->nAlloc-1; | < | ||
| 278 | cb->nUsed = sz; | < | ||
| 279 | cb->aData[sz] = 0; | < | ||
| 280 | return sz; | < | ||
| 281 | } | < | ||
| 282 | #endif /* 0|1 */ | < | ||
| 283 | < | |||
| 284 | whclob * whclob_new_n( size_t reserved ) | < | ||
| 285 | { | < | ||
| 286 | whclob * c = 0; | < | ||
| 287 | whclob_init( &c, 0, (long)reserved ); | < | ||
| 288 | return c; | < | ||
| 289 | } | < | ||
| 290 | whclob * whclob_new() | < | ||
| 291 | { | < | ||
| 292 | return whclob_new_n(0); | < | ||
| 293 | } | < | ||
| 294 | < | |||
| 295 | < | |||
| 296 | long whclob_init( whclob ** cb, char const * data, long n ) | < | ||
| 297 | { | < | ||
| 298 | long rc = 0; | < | ||
| 299 | if( ! cb ) | < | ||
| 300 | { | < | ||
| 301 | return whclob_rc.UnexpectedNull; | < | ||
| 302 | } | < | ||
| 303 | *cb = (whclob *) malloc( sizeof(whclob) ); | < | ||
| 304 | if( ! *cb ) | < | ||
| 305 | { | < | ||
| 306 | return whclob_rc.AllocError; | < | ||
| 307 | } | < | ||
| 308 | *(*cb) = Clob_empty; | < | ||
| 309 | if( !data ) | < | ||
| 310 | { | < | ||
| 311 | if( n < 1 ) return whclob_rc.OK; | < | ||
| 312 | } | < | ||
| 313 | else | < | ||
| 314 | { | < | ||
| 315 | if( !n ) return whclob_rc.OK; | < | ||
| 316 | } | < | ||
| 317 | if( data && (n < 0) ) n = strlen( data ); | < | ||
| 318 | #if 1 | < | ||
| 319 | rc = whclob_reserve( *cb, n ); | < | ||
| 320 | //rc = whclob_resize( *cb, n ); | < | ||
| 321 | if( rc < whclob_rc.OK ) | < | ||
| 322 | { | < | ||
| 323 | free( *cb ); | < | ||
| 324 | *cb = 0; | < | ||
| 325 | return rc; | < | ||
| 326 | } | < | ||
| 327 | if( data ) | < | ||
| 328 | { | < | ||
| 329 | memcpy( (*cb)->aData, data, n ); | < | ||
| 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 | < | ||
| 340 | return whclob_rc.OK; | < | ||
| 341 | } | < | ||
| 342 | < | |||
| 343 | < | |||
| 344 | long whclob_seek( whclob * cb, long offset, int whence ) | < | ||
| 345 | { | < | ||
| 346 | long pos = cb->nCursor; | < | ||
| 347 | switch( whence ) | < | ||
| 348 | { | < | ||
| 349 | case WHCLOB_SEEK_SET: | < | ||
| 350 | pos = offset; | < | ||
| 351 | break; | < | ||
| 352 | case WHCLOB_SEEK_CUR: | < | ||
| 353 | pos += offset; | < | ||
| 354 | break; | < | ||
| 355 | case WHCLOB_SEEK_END: | < | ||
| 356 | pos = cb->nUsed + offset; | < | ||
| 357 | break; | < | ||
| 358 | default: | < | ||
| 359 | return whclob_rc.RangeError; | < | ||
| 360 | }; | < | ||
| 361 | if( pos < 0 ) pos = 0; | < | ||
| 362 | else if( pos > cb->nUsed ) pos = cb->nUsed; | < | ||
| 363 | return (cb->nCursor = pos); | < | ||
| 364 | } | < | ||
| 365 | < | |||
| 366 | void whclob_rewind( whclob * cb ) | < | ||
| 367 | { | < | ||
| 368 | cb->nCursor = 0; | < | ||
| 369 | } | < | ||
| 370 | < | |||
| 371 | long whclob_tell( whclob const * cb ) | < | ||
| 372 | { | < | ||
| 373 | return cb->nCursor; | < | ||
| 374 | } | < | ||
| 375 | < | |||
| 376 | long whclob_pos_in_bounds( whclob * cb, long pos ) | < | ||
| 377 | { | < | ||
| 378 | return (cb && (pos >= 0) && (pos < cb->nUsed)) | < | ||
| 379 | ? whclob_rc.OK | < | ||
| 380 | : whclob_rc.RangeError; | < | ||
| 381 | } | < | ||
| 382 | < | |||
| 383 | long whclob_char_filln( whclob * cb, char ch, long startPos, long n ) | < | ||
| 384 | { | < | ||
| 385 | long rc = 0; | < | ||
| 386 | if( ! cb->nAlloc ) return whclob_rc.Err; | < | ||
| 387 | if( n <= 0 ) return whclob_rc.RangeError; | < | ||
| 388 | rc = whclob_pos_in_bounds(cb,startPos); | < | ||
| 389 | if( whclob_rc.OK != rc ) return rc; | < | ||
| 390 | /* if( whclob_rc.OK == rc ) rc = whclob_is_in_bounds(cb,startPos + n); */ | < | ||
| 391 | if( (startPos + n) > cb->nAlloc ) n = cb->nAlloc - startPos; | < | ||
| 392 | memset( cb->aData + startPos, ch, n ); | < | ||
| 393 | return n; | < | ||
| 394 | } | < | ||
| 395 | < | |||
| 396 | long whclob_zero_fill( whclob * cb ) | < | ||
| 397 | { | < | ||
| 398 | return whclob_char_filln( cb, '\0', 0, cb->nAlloc ); | < | ||
| 399 | } | < | ||
| 400 | < | |||
| 401 | /** | < | ||
| 402 | This function ensures that the one-past-the-last item in the blob | < | ||
| 403 | to 0. The "used" size of cb does not change. | < | ||
| 404 | < | |||
| 405 | Returns one of the values defined in whclob_rc: | < | ||
| 406 | < | |||
| 407 | - whclob_rc.AllocError if a memory (re)allocation fails. | < | ||
| 408 | < | |||
| 409 | - whclob_rc.OK on success. | < | ||
| 410 | */ | < | ||
| 411 | long whclob_null_terminate( whclob * cb ) | < | ||
| 412 | { | < | ||
| 413 | if( ! cb->nAlloc ) return whclob_rc.Err; /* do not modify a data obj we don't own. */ | < | ||
| 414 | if( (cb->nUsed + 1) >= cb->nAlloc ) | < | ||
| 415 | { | < | ||
| 416 | long rc = whclob_reserve( cb, cb->nUsed + 1 ); | < | ||
| 417 | if( rc < whclob_rc.OK ) return rc; | < | ||
| 418 | } | < | ||
| 419 | cb->aData[cb->nUsed] = 0; | < | ||
| 420 | return whclob_rc.OK; | < | ||
| 421 | } | < | ||
| 422 | < | |||
| 423 | /** | < | ||
| 424 | Writes n bytes of data from cb, starting at startPos. It expands cb | < | ||
| 425 | if needed. It does NOT move the cursor. | < | ||
| 426 | < | |||
| 427 | If n is -1 then strlen(data) is used for n. | < | ||
| 428 | < | |||
| 429 | On success returns the number of bytes added. On failure it returns | < | ||
| 430 | a negative integer error code defined in whclob_rc. If either data or | < | ||
| 431 | dsize are 0 then 0 is returned. If cb is null then | < | ||
| 432 | whclob_rc.UnexpectedNull is returned. | < | ||
| 433 | */ | < | ||
| 434 | static long whclob_writeat( whclob * cb, long startPos, char const * data, long dsize ) | < | ||
| 435 | { | < | ||
| 436 | if( ! cb ) return whclob_rc.UnexpectedNull; | < | ||
| 437 | if( ! data || !dsize ) return 0; | < | ||
| 438 | if( dsize < 0 ) dsize = strlen(data); | < | ||
| 439 | if( (startPos + dsize) >= cb->nAlloc ) | < | ||
| 440 | { | < | ||
| 441 | long allocsz = startPos + dsize; /* + (cb->nAlloc * 11 / 20); */ | < | ||
| 442 | long rc = whclob_reserve( cb, allocsz ); | < | ||
| 443 | if( rc < whclob_rc.OK ) return rc; | < | ||
| 444 | } | < | ||
| 445 | memcpy( cb->aData + startPos, data, dsize ); | < | ||
| 446 | return dsize; | < | ||
| 447 | } | < | ||
| 448 | < | |||
| 449 | < | |||
| 450 | long whclob_write( whclob * cb, char const * data, long dsize ) | < | ||
| 451 | { | < | ||
| 452 | long old = cb->nCursor; | < | ||
| 453 | WHCLOB_DUMP("whclob_write()", cb ); | < | ||
| 454 | cb->nCursor += whclob_writeat( cb, cb->nCursor, data, dsize ); | < | ||
| 455 | if( cb->nUsed < cb->nCursor ) | < | ||
| 456 | { | < | ||
| 457 | cb->nUsed = cb->nCursor; | < | ||
| 458 | } | < | ||
| 459 | WHCLOB_DUMP("whclob_write()", cb ); | < | ||
| 460 | return cb->nCursor - old; | < | ||
| 461 | } | < | ||
| 462 | < | |||
| 463 | < | |||
| 464 | long whclob_append( whclob * cb, char const * data, long dsize ) | < | ||
| 465 | { | < | ||
| 466 | long old = cb->nUsed; | < | ||
| 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); | < | ||
| 472 | return cb->nUsed - old; | < | ||
| 473 | } | < | ||
| 474 | < | |||
| 475 | long whclob_append_char_n( whclob * cb, char c, long n ) | < | ||
| 476 | { | < | ||
| 477 | long rc = 0; | < | ||
| 478 | if( !cb || (n <= 0) ) return whclob_rc.RangeError; | < | ||
| 479 | rc = whclob_reserve( cb, cb->nUsed + n ); | < | ||
| 480 | if( rc < 0 ) return rc; | < | ||
| 481 | memset( cb->aData + cb->nUsed, c, n ); | < | ||
| 482 | cb->nUsed += n; | < | ||
| 483 | /* do we want to do a whclob_null_terminate() here? */ | < | ||
| 484 | /* whclob_null_terminate(cb); */ | < | ||
| 485 | return n; | < | ||
| 486 | } | < | ||
| 487 | < | |||
| 488 | < | |||
| 489 | long whclob_copy( whclob * src, whclob * dest ) | < | ||
| 490 | { | < | ||
| 491 | long allocsz = 0; | < | ||
| 492 | long rc = 0; | < | ||
| 493 | if( src == dest ) return whclob_rc.RangeError; | < | ||
| 494 | if( src->aData == dest->aData ) return whclob_rc.RangeError; | < | ||
| 495 | allocsz = src->nAlloc; | < | ||
| 496 | WHCLOB_DUMP( "copy src before",src ); | < | ||
| 497 | WHCLOB_DUMP( "copy dest before",dest ); | < | ||
| 498 | whclob_reset( dest ); | < | ||
| 499 | rc = whclob_reserve( dest, allocsz ); | < | ||
| 500 | if( rc < whclob_rc.OK ) return rc; | < | ||
| 501 | dest->nUsed = src->nUsed; | < | ||
| 502 | dest->nAlloc = allocsz; | < | ||
| 503 | dest->nCursor = src->nCursor; | < | ||
| 504 | memcpy( dest->aData, src->aData, allocsz ); | < | ||
| 505 | WHCLOB_DUMP( "copy src after",src ); | < | ||
| 506 | WHCLOB_DUMP( "copy dest after",dest ); | < | ||
| 507 | return whclob_rc.OK; | < | ||
| 508 | } | < | ||
| 509 | < | |||
| 510 | long whclob_copy_slice( whclob * src, whclob * dest, long startPos, long n ) | < | ||
| 511 | { | < | ||
| 512 | long bpos = 0; | < | ||
| 513 | long epos = 0; | < | ||
| 514 | long ret = 0; | < | ||
| 515 | if( ! src || !dest ) return whclob_rc.UnexpectedNull; | < | ||
| 516 | if( n<1 ) return whclob_rc.RangeError; | < | ||
| 517 | if( whclob_rc.OK != whclob_pos_in_bounds( src, startPos ) ) return whclob_rc.RangeError; | < | ||
| 518 | bpos = startPos; | < | ||
| 519 | if( bpos >= src->nUsed ) return 0; | < | ||
| 520 | epos = bpos + n; /* 1-past-end marker */ | < | ||
| 521 | if( epos > src->nUsed ) epos = src->nUsed; | < | ||
| 522 | ret = whclob_append( dest, src->aData + bpos, epos - bpos ); | < | ||
| 523 | return ret; | < | ||
| 524 | } | < | ||
| 525 | < | |||
| 526 | long whclob_read( whclob * src, whclob * dest, long n ) | < | ||
| 527 | { | < | ||
| 528 | long bpos = 0; | < | ||
| 529 | long epos = 0; | < | ||
| 530 | long ret = 0; | < | ||
| 531 | if( ! src || !dest || n<1 ) return 0; | < | ||
| 532 | bpos = src->nCursor; | < | ||
| 533 | if( bpos == src->nUsed ) return 0; | < | ||
| 534 | epos = bpos + n; /* 1-past-end marker */ | < | ||
| 535 | if( epos > src->nUsed ) epos = src->nUsed; | < | ||
| 536 | ret = whclob_append( dest, src->aData + bpos, epos - bpos ); | < | ||
| 537 | src->nCursor += ret; | < | ||
| 538 | return ret; | < | ||
| 539 | } | < | ||
| 540 | < | |||
| 541 | long whclob_truncate( whclob * cb, long pos, int memPolicy ) | < | ||
| 542 | { | < | ||
| 543 | long rc = 0; | < | ||
| 544 | if( ! cb ) return whclob_rc.UnexpectedNull; | < | ||
| 545 | /* if( cb->nUsed <= pos ) return whclob_rc.OK; */ | < | ||
| 546 | < | |||
| 547 | if( pos < cb->nAlloc ) | < | ||
| 548 | { /* adding a single \0 to the data isn't sufficient here. */ | < | ||
| 549 | memset( cb->aData + pos, 0, (cb->nAlloc-pos)); | < | ||
| 550 | } | < | ||
| 551 | < | |||
| 552 | if( cb->nAlloc <= pos ) | < | ||
| 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 | ) | < | ||
| 575 | { | < | ||
| 576 | /* rc = whclob_resize( cb, cb->nUsed ); */ | < | ||
| 577 | rc = whclob_do_resize( cb, pos, 0 ); | < | ||
| 578 | } | < | ||
| 579 | #else | < | ||
| 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; | < | ||
| 589 | } | < | ||
| 590 | < | |||
| 591 | < | |||
| 592 | long whclob_memmove( whclob * cb, int start1, int n, int start2 ) | < | ||
| 593 | { | < | ||
| 594 | return whclob_memmove_fill( cb, 0, start1, n, start2 ); | < | ||
| 595 | } | < | ||
| 596 | long whclob_memmove_fill( whclob * cb, char const filler, int start1, int n, int start2 ) | < | ||
| 597 | { | < | ||
| 598 | char * src = 0; | < | ||
| 599 | char * dest = 0; | < | ||
| 600 | long pos = 0; /* here we'll take a long "pos" ... */ | < | ||
| 601 | if( ! cb ) return whclob_rc.UnexpectedNull; | < | ||
| 602 | if( | < | ||
| 603 | ( (n<1) || (start2 == start1) ) | < | ||
| 604 | || | < | ||
| 605 | (whclob_rc.OK != whclob_pos_in_bounds(cb,start1)) | < | ||
| 606 | || | < | ||
| 607 | (whclob_rc.OK != whclob_pos_in_bounds(cb,start1+n)) | < | ||
| 608 | || | < | ||
| 609 | (whclob_rc.OK != whclob_pos_in_bounds(cb,start2)) | < | ||
| 610 | || | < | ||
| 611 | (whclob_rc.OK != whclob_pos_in_bounds(cb,start2+n)) | < | ||
| 612 | ) | < | ||
| 613 | { | < | ||
| 614 | return whclob_rc.RangeError; | < | ||
| 615 | } | < | ||
| 616 | src = cb->aData + start1; | < | ||
| 617 | dest = cb->aData + start2; | < | ||
| 618 | pos = 0; | < | ||
| 619 | while( pos < n ) | < | ||
| 620 | { | < | ||
| 621 | dest[start2++] = src[pos]; | < | ||
| 622 | src[pos++] = filler; | < | ||
| 623 | } | < | ||
| 624 | return n; | < | ||
| 625 | } | < | ||
| 626 | < | |||
| 627 | /** | < | ||
| 628 | Swaps n bytes of memory contents between m1 and m2. No bounds | < | ||
| 629 | checking is (or can be) done here, so m1 and m2 must both be large | < | ||
| 630 | enough for the given start1, start2, and n parameters. | < | ||
| 631 | */ | < | ||
| 632 | static long memswap( char * m1, | < | ||
| 633 | long n, | < | ||
| 634 | char * m2 ) | < | ||
| 635 | { | < | ||
| 636 | char buf; | < | ||
| 637 | long pos = 0; | < | ||
| 638 | for( ; pos < n; ++pos ) | < | ||
| 639 | { | < | ||
| 640 | buf = m2[pos]; | < | ||
| 641 | m2[pos] = m1[pos]; | < | ||
| 642 | m1[pos] = buf; | < | ||
| 643 | } | < | ||
| 644 | return pos; | < | ||
| 645 | } | < | ||
| 646 | < | |||
| 647 | long whclob_memswap( whclob * c1, int start1, int n, whclob * c2, int start2 ) | < | ||
| 648 | { | < | ||
| 649 | if( ! c1 || ! c2 ) return whclob_rc.UnexpectedNull; | < | ||
| 650 | if( | < | ||
| 651 | ( (n<1) ) | < | ||
| 652 | || | < | ||
| 653 | (whclob_rc.OK != whclob_pos_in_bounds(c1,start1)) | < | ||
| 654 | || | < | ||
| 655 | (whclob_rc.OK != whclob_pos_in_bounds(c1,start1+n)) | < | ||
| 656 | || | < | ||
| 657 | (whclob_rc.OK != whclob_pos_in_bounds(c2,start2)) | < | ||
| 658 | || | < | ||
| 659 | (whclob_rc.OK != whclob_pos_in_bounds(c2,start2+n)) | < | ||
| 660 | ) | < | ||
| 661 | { | < | ||
| 662 | return whclob_rc.RangeError; | < | ||
| 663 | } | < | ||
| 664 | return memswap( c1->aData + start1, n, c2->aData + start2 ); | < | ||
| 665 | } | < | ||
| 666 | < | |||
| 667 | < | |||
| 668 | long whclob_swap( whclob * c1, whclob * c2 ) | < | ||
| 669 | { | < | ||
| 670 | whclob x; | < | ||
| 671 | if( ! c1 || ! c2 ) return whclob_rc.UnexpectedNull; | < | ||
| 672 | x = *c1; | < | ||
| 673 | *c1 = *c2; | < | ||
| 674 | *c2 = x; | < | ||
| 675 | return whclob_rc.OK; | < | ||
| 676 | } | < | ||
| 677 | < | |||
| 678 | long whclob_clone( whclob * src, whclob ** dest ) | < | ||
| 679 | { | < | ||
| 680 | long rc = 0; | < | ||
| 681 | if( ! src ) return whclob_rc.UnexpectedNull; | < | ||
| 682 | rc = whclob_init( dest, src->aData, src->nUsed ); | < | ||
| 683 | if( whclob_rc.OK != rc ) return rc; | < | ||
| 684 | memcpy( (*dest)->aData, src->aData, src->nUsed ); | < | ||
| 685 | (*dest)->nUsed = src->nUsed; | < | ||
| 686 | (*dest)->nCursor = src->nCursor; | < | ||
| 687 | return whclob_rc.OK; | < | ||
| 688 | } | < | ||
| 689 | < | |||
| 690 | /** | < | ||
| 691 | A whclob vappendf_appender implementation. It assumes that | < | ||
| 692 | arg is a (whclob *) and uses whclob_append() to push | < | ||
| 693 | all data to that clob. | < | ||
| 694 | < | |||
| 695 | If s is null then 0 is returned. | < | ||
| 696 | < | |||
| 697 | Returns the number of bytes appended. | < | ||
| 698 | */ | < | ||
| 699 | static long whclob_vappendf_appender( void * arg, char const * s, long n ) | < | ||
| 700 | { | < | ||
| 701 | whclob * c = (whclob *)arg; | < | ||
| 702 | if( ! c ) return 0; | < | ||
| 703 | return whclob_append( c, s, n ); | < | ||
| 704 | } | < | ||
| 705 | < | |||
| 706 | long whclob_vappendf( whclob * cb, char const * fmt, va_list vargs ) | < | ||
| 707 | { | < | ||
| 708 | return vappendf( whclob_vappendf_appender, cb, fmt, vargs ); | < | ||
| 709 | } | < | ||
| 710 | < | |||
| 711 | long whclob_appendf( whclob * cb, const char * fmt, ... ) | < | ||
| 712 | { | < | ||
| 713 | va_list vargs; | < | ||
| 714 | long ret = 0; | < | ||
| 715 | va_start( vargs, fmt ); | < | ||
| 716 | ret = whclob_vappendf( cb, fmt, vargs ); | < | ||
| 717 | va_end(vargs); | < | ||
| 718 | return ret; | < | ||
| 719 | } | < | ||
| 720 | < | |||
| 721 | < | |||
| 722 | < | |||
| 723 | long whclob_export( whclob const * cb, void * varg, whclob_exporter pf ) | < | ||
| 724 | { | < | ||
| 725 | if( ! cb->nAlloc ) return whclob_rc.UnexpectedNull; | < | ||
| 726 | return pf( varg, cb->aData, cb->nUsed ); | < | ||
| 727 | } | < | ||
| 728 | < | |||
| 729 | < | |||
| 730 | long whclob_import( whclob * dest, void * arg, whclob_importer pf ) | < | ||
| 731 | { | < | ||
| 732 | return pf( dest, arg ); | < | ||
| 733 | } | < | ||
| 734 | < | |||
| 735 | < | |||
| 736 | char * whclob_vmprintf( char const * fmt, va_list vargs ) | < | ||
| 737 | { | < | ||
| 738 | whclob * buf = 0; | < | ||
| 739 | char * ret = 0; | < | ||
| 740 | if( whclob_rc.OK != whclob_init(&buf,0,0) ) return 0; | < | ||
| 741 | whclob_vappendf( buf, fmt, vargs ); | < | ||
| 742 | ret = buf->aData; | < | ||
| 743 | *buf = Clob_empty; | < | ||
| 744 | whclob_finalize( buf ); | < | ||
| 745 | return ret; | < | ||
| 746 | } | < | ||
| 747 | char * whclob_mprintf( char const * fmt, ... ) | < | ||
| 748 | { | < | ||
| 749 | va_list vargs; | < | ||
| 750 | char * ret = 0; | < | ||
| 751 | va_start( vargs, fmt ); | < | ||
| 752 | ret = whclob_vmprintf( fmt, vargs ); | < | ||
| 753 | va_end(vargs); | < | ||
| 754 | return ret; | < | ||
| 755 | } | < | ||
| 756 | < | |||
| 757 | char * whclob_take_buffer( whclob * cb ) | < | ||
| 758 | { | < | ||
| 759 | char * c = cb->aData; | < | ||
| 760 | *cb = Clob_empty; | < | ||
| 761 | return c; | < | ||
| 762 | } | < | ||
| 763 | < | |||
| 764 | < | |||
| 765 | < | |||
| 766 | #if WHCLOB_USE_ZLIB | < | ||
| 767 | /* ! whclob_zheader_prefix == magic cookie for our compressed whclob.header */ | < | ||
| 768 | static char const whclob_zheader_version = '1'; | < | ||
| 769 | static char const * whclob_zheader_prefix = "clob32"; | < | ||
| 770 | static int const whclob_zheader_prefix_len = 7; /* ^^^^ must be 1 + strlen(whclob_zheader_prefix)! */ | < | ||
| 771 | /* ! whclob_zheader_lensize == number of bytes used to store size in compressed data */ | < | ||
| 772 | static short const whclob_zheader_lensize = 4; | < | ||
| 773 | /* ! whclob_zheader_crcsize == number of bytes used to store size in compressed data */ | < | ||
| 774 | static short const whclob_zheader_crcsize = 4; | < | ||
| 775 | static int const whclob_zheader_size = 15; /* 1 + prefix_len + lensize + whclob_zheader_crcsize */ | < | ||
| 776 | < | |||
| 777 | /** | < | ||
| 778 | Stamps the initial header in cIn, which must be an initialized clob | < | ||
| 779 | with at least whclob_zheader_size bytes allocated. srcSize must be | < | ||
| 780 | the decompressed size of data which will presumably be compressed | < | ||
| 781 | into the cIn clob at some point and crc must be the adler32 | < | ||
| 782 | checksum of the uncompressed data. Returns whclob_zheader_size on | < | ||
| 783 | success, or a negative number on error. | < | ||
| 784 | */ | < | ||
| 785 | static int whclob_write_zheader( whclob * cIn, unsigned int srcSize, unsigned long crc ) | < | ||
| 786 | { | < | ||
| 787 | if( whclob_size(cIn) < whclob_zheader_size ) | < | ||
| 788 | { | < | ||
| 789 | return whclob_rc.RangeError; | < | ||
| 790 | } | < | ||
| 791 | whclob_writeat( cIn, 0, whclob_zheader_prefix, whclob_zheader_prefix_len ); | < | ||
| 792 | { | < | ||
| 793 | int i = whclob_zheader_prefix_len - 1; | < | ||
| 794 | unsigned char * oBuf = (unsigned char *)whclob_buffer(cIn); | < | ||
| 795 | oBuf[i++] = whclob_zheader_version; | < | ||
| 796 | oBuf[i++] = srcSize>>24 & 0xff; | < | ||
| 797 | oBuf[i++] = srcSize>>16 & 0xff; | < | ||
| 798 | oBuf[i++] = srcSize>>8 & 0xff; | < | ||
| 799 | oBuf[i++] = srcSize & 0xff; | < | ||
| 800 | < | |||
| 801 | oBuf[i++] = crc>>24 & 0xff; | < | ||
| 802 | oBuf[i++] = crc>>16 & 0xff; | < | ||
| 803 | oBuf[i++] = crc>>8 & 0xff; | < | ||
| 804 | oBuf[i++] = crc & 0xff; | < | ||
| 805 | /* MARKER; printf( "Writing zsize header at pos %d-%d: %u\n", whclob_zheader_prefix_len, i, srcSize ); */ | < | ||
| 806 | MARKER( "Writing zsize header: version=%c uSize=%u adler32=%lx\n", whclob_zheader_version, srcSize, crc ); | < | ||
| 807 | } | < | ||
| 808 | return whclob_zheader_size; | < | ||
| 809 | } | < | ||
| 810 | < | |||
| 811 | /** | < | ||
| 812 | Checks first bytes of cIn to see if this is data compressed | < | ||
| 813 | by this API. If it is, the decompressed size of the compressed | < | ||
| 814 | data is set in sz and the adler32 checksum of the uncompressed | < | ||
| 815 | data is written to crc. On success 0 or greater is returned, else | < | ||
| 816 | a negative value from whclob_rc is returned: | < | ||
| 817 | < | |||
| 818 | - whclob_rc.RangeError: cIn is too small to contain the header or | < | ||
| 819 | the header was written by a different API version. | < | ||
| 820 | < | |||
| 821 | - whclob_rc.ArgError: header seems to be invalid, or maybe not | < | ||
| 822 | produced by the same version of this API. | < | ||
| 823 | < | |||
| 824 | */ | < | ||
| 825 | static int whclob_confirm_zheader( whclob const * cIn, unsigned int * sz, unsigned long * crc ) | < | ||
| 826 | { | < | ||
| 827 | int i; | < | ||
| 828 | char ver; | < | ||
| 829 | if( whclob_size(cIn) < whclob_zheader_size ) | < | ||
| 830 | { | < | ||
| 831 | return whclob_rc.RangeError; | < | ||
| 832 | } | < | ||
| 833 | unsigned char const * inBuf = (unsigned char *) whclob_bufferc(cIn); | < | ||
| 834 | for( i = 0; i < (whclob_zheader_prefix_len-1); ++i, ++inBuf ) | < | ||
| 835 | { | < | ||
| 836 | if( *inBuf != whclob_zheader_prefix[i] ) | < | ||
| 837 | { | < | ||
| 838 | return whclob_rc.ArgError; | < | ||
| 839 | } | < | ||
| 840 | /* MARKER( "confirm header: %c\n", *inBuf ); */ | < | ||
| 841 | } | < | ||
| 842 | /* MARKER( "confirm header: %d\n", *inBuf ); */ | < | ||
| 843 | inBuf = (unsigned const char *) whclob_bufferc(cIn) + (whclob_zheader_prefix_len - 1); | < | ||
| 844 | ver = *inBuf; | < | ||
| 845 | if( ver != whclob_zheader_version ) | < | ||
| 846 | { | < | ||
| 847 | return whclob_rc.RangeError; | < | ||
| 848 | } | < | ||
| 849 | ++inBuf; | < | ||
| 850 | /* MARKER( "confirm header: %d\n", *inBuf ); */ | < | ||
| 851 | *sz = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3]; | < | ||
| 852 | *crc = (inBuf[4]<<24) + (inBuf[5]<<16) + (inBuf[6]<<8) + inBuf[7]; | < | ||
| 853 | /* MARKER( "header says zsize == %u\n", *sz ); */ | < | ||
| 854 | /* MARKER( "header says adler32 == %lx\n", *crc ); */ | < | ||
| 855 | return whclob_rc.OK; | < | ||
| 856 | } | < | ||
| 857 | < | |||
| 858 | < | |||
| 859 | int whclob_compress( whclob * cIn, whclob * cOut ) | < | ||
| 860 | { | < | ||
| 861 | const unsigned int szIn = whclob_size(cIn); | < | ||
| 862 | const unsigned int szOut = 13 + szIn + (szIn+999)/1000; | < | ||
| 863 | unsigned long nOut; | < | ||
| 864 | int rc; | < | ||
| 865 | whclob * tmp; | < | ||
| 866 | unsigned long adler; | < | ||
| 867 | tmp = 0; | < | ||
| 868 | if( cOut != cIn ) whclob_reset(cOut); | < | ||
| 869 | nOut = (long int) szOut; | < | ||
| 870 | rc = whclob_init( &tmp, 0, nOut+whclob_zheader_size ); | < | ||
| 871 | if( 0 != rc ) return rc; | < | ||
| 872 | < | |||
| 873 | adler = adler32(0L, Z_NULL, 0); | < | ||
| 874 | adler = adler32( adler, (const Byte *) whclob_bufferc(cIn), szIn ); | < | ||
| 875 | /* MARKER( "adler=%lx\n", adler ); */ | < | ||
| 876 | whclob_write_zheader( tmp, szIn, adler ); | < | ||
| 877 | rc = compress( (unsigned char *)(whclob_buffer(tmp) + whclob_zheader_size), | < | ||
| 878 | &nOut, | < | ||
| 879 | (unsigned char *)whclob_buffer(cIn), | < | ||
| 880 | szIn ); | < | ||
| 881 | if( Z_OK != rc ) | < | ||
| 882 | { | < | ||
| 883 | whclob_finalize(tmp); | < | ||
| 884 | return whclob_rc.IOError; | < | ||
| 885 | } | < | ||
| 886 | if( cOut == cIn ) | < | ||
| 887 | { | < | ||
| 888 | whclob_reset(cOut); | < | ||
| 889 | } | < | ||
| 890 | < | |||
| 891 | rc = whclob_resize( tmp, nOut+whclob_zheader_size ); | < | ||
| 892 | if( rc < (nOut+whclob_zheader_size) ) | < | ||
| 893 | { | < | ||
| 894 | whclob_finalize( tmp ); | < | ||
| 895 | return rc; | < | ||
| 896 | } | < | ||
| 897 | whclob_swap( cOut, tmp ); | < | ||
| 898 | whclob_finalize( tmp ); | < | ||
| 899 | return whclob_rc.OK; | < | ||
| 900 | } | < | ||
| 901 | < | |||
| 902 | < | |||
| 903 | < | |||
| 904 | int whclob_uncompress(whclob *pIn, whclob *pOut) | < | ||
| 905 | { | < | ||
| 906 | unsigned int unzSize; | < | ||
| 907 | unsigned int nIn = whclob_size(pIn); | < | ||
| 908 | whclob * temp; | < | ||
| 909 | int rc; | < | ||
| 910 | unsigned long int nOut2; | < | ||
| 911 | unsigned long adlerExp; | < | ||
| 912 | unsigned long adlerGot; | < | ||
| 913 | if( nIn<=4 ) | < | ||
| 914 | { | < | ||
| 915 | /* MARKER; */ | < | ||
| 916 | return whclob_rc.Err; | < | ||
| 917 | } | < | ||
| 918 | if( pOut != pIn ) whclob_reset(pOut); | < | ||
| 919 | < | |||
| 920 | rc = whclob_confirm_zheader( pIn, &unzSize, &adlerExp ); | < | ||
| 921 | /* MARKER( "zsize = %u\n", unzSize ); */ | < | ||
| 922 | /* MARKER( "zsize = %u, adlerExp=%lx\n", unzSize, adlerExp ); */ | < | ||
| 923 | if( whclob_rc.OK > rc) | < | ||
| 924 | { | < | ||
| 925 | /* MARKER; */ | < | ||
| 926 | return rc; | < | ||
| 927 | } | < | ||
| 928 | rc = whclob_init(&temp,0,unzSize+1); | < | ||
| 929 | if( whclob_rc.OK != rc ) | < | ||
| 930 | { | < | ||
| 931 | /* MARKER; */ | < | ||
| 932 | return rc; | < | ||
| 933 | } | < | ||
| 934 | < | |||
| 935 | { | < | ||
| 936 | unsigned char *inBuf; | < | ||
| 937 | inBuf = (unsigned char*) (whclob_buffer(pIn) + whclob_zheader_size); | < | ||
| 938 | nOut2 = whclob_size( temp ); | < | ||
| 939 | /* MARKER( "nOut2 = %ld\n", nOut2 ); */ | < | ||
| 940 | /* MARKER( "input length = %u\n", nIn - whclob_zheader_size ); */ | < | ||
| 941 | /* MARKER( "zsize = %u\n", unzSize ); */ | < | ||
| 942 | /* MARKER( "zblob size = %u\n",nIn ); */ | < | ||
| 943 | rc = uncompress((unsigned char*)whclob_buffer(temp), &nOut2, | < | ||
| 944 | inBuf, nIn - whclob_zheader_size); | < | ||
| 945 | } | < | ||
| 946 | if( rc!=Z_OK ) | < | ||
| 947 | { | < | ||
| 948 | /* MARKER; */ | < | ||
| 949 | whclob_finalize(temp); | < | ||
| 950 | return whclob_rc.IOError; | < | ||
| 951 | } | < | ||
| 952 | adlerGot = adler32(0L,Z_NULL,0); | < | ||
| 953 | adlerGot = adler32( adlerGot, (Bytef const *) whclob_bufferc(temp), nOut2 ); | < | ||
| 954 | if( adlerGot != adlerExp ) | < | ||
| 955 | { | < | ||
| 956 | /* MARKER( "adler32 mismatch: %lx != %lx\n", adlerExp, adlerGot ); */ | < | ||
| 957 | return whclob_rc.RangeError; | < | ||
| 958 | } | < | ||
| 959 | < | |||
| 960 | rc = whclob_resize(temp, nOut2); | < | ||
| 961 | if( rc < nOut2 ) | < | ||
| 962 | { | < | ||
| 963 | /* MARKER; */ | < | ||
| 964 | whclob_finalize(temp); | < | ||
| 965 | return rc; | < | ||
| 966 | } | < | ||
| 967 | whclob_swap( temp, pOut ); | < | ||
| 968 | whclob_finalize(temp); | < | ||
| 969 | return whclob_rc.OK; | < | ||
| 970 | } | < | ||
| 971 | < | |||
| 972 | int whclob_deflate( whclob *cIn, whclob *cOut ) | < | ||
| 973 | { | < | ||
| 974 | const int kludge = 4; | < | ||
| 975 | z_stream zS; | < | ||
| 976 | unsigned int szIn = whclob_size(cIn); | < | ||
| 977 | unsigned int szOut = kludge + 13 + szIn + (szIn+999)/1000; | < | ||
| 978 | int rc; | < | ||
| 979 | whclob * tmp; | < | ||
| 980 | tmp = 0; | < | ||
| 981 | zS.zalloc = Z_NULL; | < | ||
| 982 | zS.zfree = Z_NULL; | < | ||
| 983 | zS.opaque = Z_NULL; | < | ||
| 984 | < | |||
| 985 | if( cOut != cIn ) whclob_reset(cOut); | < | ||
| 986 | rc = whclob_init( &tmp, 0, szOut ); | < | ||
| 987 | if( 0 != rc ) | < | ||
| 988 | { | < | ||
| 989 | return rc; | < | ||
| 990 | } | < | ||
| 991 | < | |||
| 992 | { | < | ||
| 993 | unsigned char * cBuf; | < | ||
| 994 | cBuf = (unsigned char *) whclob_buffer(tmp); | < | ||
| 995 | cBuf[0] = szIn>>24 & 0xff; | < | ||
| 996 | cBuf[1] = szIn>>16 & 0xff; | < | ||
| 997 | cBuf[2] = szIn>>8 & 0xff; | < | ||
| 998 | cBuf[3] = szIn & 0xff; | < | ||
| 999 | < | |||
| 1000 | zS.next_in = (Bytef*) whclob_buffer(cIn); | < | ||
| 1001 | zS.avail_in = whclob_size(cIn); | < | ||
| 1002 | zS.next_out = (Bytef*) (cBuf + kludge); | < | ||
| 1003 | zS.avail_out = szOut; | < | ||
| 1004 | } | < | ||
| 1005 | < | |||
| 1006 | if( Z_OK != deflateInit( &zS, Z_DEFAULT_COMPRESSION ) ) | < | ||
| 1007 | { | < | ||
| 1008 | whclob_finalize(tmp); | < | ||
| 1009 | return whclob_rc.IOError; | < | ||
| 1010 | } | < | ||
| 1011 | < | |||
| 1012 | /* printf("sizes: in=%d out=%d\n", zS.avail_in, zS.avail_out ); */ | < | ||
| 1013 | < | |||
| 1014 | rc = deflate( &zS, Z_FINISH ); | < | ||
| 1015 | szOut = szOut - zS.avail_out; | < | ||
| 1016 | deflateEnd( &zS ); | < | ||
| 1017 | /* printf("deflate() rc == %d\n", rc ); */ | < | ||
| 1018 | /* printf("sizes: in=%d out=%d\n", zS.avail_in, zS.avail_out ); */ | < | ||
| 1019 | if( Z_STREAM_END != rc ) | < | ||
| 1020 | { | < | ||
| 1021 | /* printf("deflate() rc == %d\n", rc ); */ | < | ||
| 1022 | whclob_finalize(tmp); | < | ||
| 1023 | return whclob_rc.IOError; | < | ||
| 1024 | } | < | ||
| 1025 | if( cOut == cIn ) | < | ||
| 1026 | { | < | ||
| 1027 | whclob_reset(cOut); | < | ||
| 1028 | } | < | ||
| 1029 | rc = whclob_resize( tmp, szOut ); | < | ||
| 1030 | if( rc < (szOut) ) | < | ||
| 1031 | { | < | ||
| 1032 | whclob_finalize( tmp ); | < | ||
| 1033 | return rc; | < | ||
| 1034 | } | < | ||
| 1035 | whclob_swap( cOut, tmp ); | < | ||
| 1036 | whclob_finalize( tmp ); | < | ||
| 1037 | return whclob_rc.OK; | < | ||
| 1038 | } | < | ||
| 1039 | < | |||
| 1040 | < | |||
| 1041 | int whclob_inflate(whclob *cIn, whclob *cOut) | < | ||
| 1042 | { | < | ||
| 1043 | unsigned int uSize; | < | ||
| 1044 | unsigned int nIn = whclob_size(cIn); | < | ||
| 1045 | whclob * temp; | < | ||
| 1046 | int rc; | < | ||
| 1047 | z_stream zS; | < | ||
| 1048 | const int kludge = 4; | < | ||
| 1049 | unsigned int infSize; | < | ||
| 1050 | zS.zalloc = Z_NULL; | < | ||
| 1051 | zS.zfree = Z_NULL; | < | ||
| 1052 | zS.opaque = Z_NULL; | < | ||
| 1053 | < | |||
| 1054 | if( cOut != cIn ) whclob_reset(cOut); | < | ||
| 1055 | if( nIn<=kludge ) | < | ||
| 1056 | { | < | ||
| 1057 | return whclob_rc.Err; | < | ||
| 1058 | } | < | ||
| 1059 | < | |||
| 1060 | < | |||
| 1061 | { | < | ||
| 1062 | unsigned char * cBuf = (unsigned char *) whclob_buffer(cIn); | < | ||
| 1063 | uSize = (cBuf[0]<<24) + (cBuf[1]<<16) + (cBuf[2]<<8) + cBuf[3]; | < | ||
| 1064 | } | < | ||
| 1065 | rc = whclob_init( &temp, 0, uSize + (uSize * 10 / 100)); | < | ||
| 1066 | if( whclob_rc.OK != rc ) | < | ||
| 1067 | { | < | ||
| 1068 | return rc; | < | ||
| 1069 | } | < | ||
| 1070 | /* fprintf(stderr,"uSize = %u, whclob_capacity(temp) = %ld\n", uSize, whclob_capacity(temp) ); */ | < | ||
| 1071 | zS.avail_out = whclob_capacity(temp); | < | ||
| 1072 | zS.next_out = (Bytef*) whclob_buffer(temp); | < | ||
| 1073 | zS.next_in = (Bytef*) (whclob_buffer(cIn) + kludge); | < | ||
| 1074 | zS.avail_in = whclob_size(cIn) - kludge; | < | ||
| 1075 | < | |||
| 1076 | /* fprintf(stderr,"avail_in == %d avail_out == %d\n", zS.avail_in, zS.avail_out ); */ | < | ||
| 1077 | < | |||
| 1078 | rc = inflateInit( &zS ); | < | ||
| 1079 | if( Z_OK != rc ) | < | ||
| 1080 | { | < | ||
| 1081 | /* fprintf(stderr,"inflateInit() failed. rc == %d\n", rc ); */ | < | ||
| 1082 | whclob_finalize(temp); | < | ||
| 1083 | return whclob_rc.IOError; | < | ||
| 1084 | } | < | ||
| 1085 | /** weird: the return from inflate() is always an error (normally | < | ||
| 1086 | Z_DATA_ERR) for me, but inflateEnd() succeeds and the data is | < | ||
| 1087 | correct. | < | ||
| 1088 | */ | < | ||
| 1089 | rc = inflate( &zS, Z_FINISH ); | < | ||
| 1090 | /* fprintf(stderr,"inflate() rc == %d\n", rc ); */ | < | ||
| 1091 | infSize = whclob_capacity(temp) - zS.avail_out; | < | ||
| 1092 | /* fprintf(stderr,"post: infSize == %d uSize == %d\n", infSize, uSize ); */ | < | ||
| 1093 | /* fprintf(stderr,"post: avail_in == %d avail_out == %d\n", zS.avail_in, zS.avail_out ); */ | < | ||
| 1094 | rc = inflateEnd( &zS ); | < | ||
| 1095 | if( rc != Z_OK ) /* STREAM_END ) */ | < | ||
| 1096 | { | < | ||
| 1097 | /* fprintf(stderr, "inflate() rc == %d\n",rc); */ | < | ||
| 1098 | whclob_finalize(temp); | < | ||
| 1099 | return whclob_rc.IOError; | < | ||
| 1100 | } | < | ||
| 1101 | rc = whclob_resize(temp, infSize); | < | ||
| 1102 | if( rc < infSize ) | < | ||
| 1103 | { | < | ||
| 1104 | whclob_finalize(temp); | < | ||
| 1105 | return rc; | < | ||
| 1106 | } | < | ||
| 1107 | if( cOut == cIn ) whclob_reset(cOut); | < | ||
| 1108 | whclob_swap( temp, cOut ); | < | ||
| 1109 | whclob_finalize(temp); | < | ||
| 1110 | return whclob_rc.OK; | < | ||
| 1111 | } | < | ||
| 1112 | #endif /* WHCLOB_USE_ZLIB */ | < | ||
| 1113 | < | |||
| 1114 | #if WHCLOB_USE_FILE | < | ||
| 1115 | long whclob_exporter_FILE( void * arg, char const * data, long n ) | < | ||
| 1116 | { | < | ||
| 1117 | FILE * fp = (FILE *) arg; | < | ||
| 1118 | if( ! fp ) return whclob_rc.UnexpectedNull; | < | ||
| 1119 | return (n == (long)fwrite( data, 1, n, fp )) | < | ||
| 1120 | ? n | < | ||
| 1121 | : whclob_rc.IOError; | < | ||
| 1122 | } | < | ||
| 1123 | < | |||
| 1124 | long whclob_export_FILE( whclob const * cb, FILE * dest ) | < | ||
| 1125 | { | < | ||
| 1126 | return whclob_export( cb, dest, whclob_exporter_FILE ); | < | ||
| 1127 | } | < | ||
| 1128 | < | |||
| 1129 | long whclob_exporter_filename( void * arg, char const * data, long n ) | < | ||
| 1130 | { | < | ||
| 1131 | char const * fname = (char const *)arg; | < | ||
| 1132 | FILE * fp = 0; | < | ||
| 1133 | long ret = 0; | < | ||
| 1134 | if( ! fname ) return whclob_rc.UnexpectedNull; | < | ||
| 1135 | fp = fopen( fname, "wb" ); | < | ||
| 1136 | if( ! fp ) return whclob_rc.IOError; | < | ||
| 1137 | ret = whclob_exporter_FILE( fp, data, n ); | < | ||
| 1138 | fclose( fp ); | < | ||
| 1139 | return ret; | < | ||
| 1140 | } | < | ||
| 1141 | < | |||
| 1142 | long whclob_export_filename( whclob const * cb, char const * dest ) | < | ||
| 1143 | { | < | ||
| 1144 | return whclob_export( cb, (char *)dest, whclob_exporter_filename ); | < | ||
| 1145 | /* ^^ i hate that cast, but it's the least evil option here. */ | < | ||
| 1146 | } | < | ||
| 1147 | long whclob_importer_FILE( whclob * dest, void * arg ) | < | ||
| 1148 | { | < | ||
| 1149 | FILE * fp = (FILE *) arg; | < | ||
| 1150 | long oldUsed = whclob_size(dest); | < | ||
| 1151 | /*const long blocksize = 4096;*/ | < | ||
| 1152 | #define blocksize 4096 | < | ||
| 1153 | long rdsz = 0; | < | ||
| 1154 | char * bcbuf[blocksize]; | < | ||
| 1155 | int rc; | < | ||
| 1156 | if( ! fp ) return whclob_rc.ArgError; | < | ||
| 1157 | while( ! feof(fp) ) | < | ||
| 1158 | { | < | ||
| 1159 | rdsz = fread( bcbuf, sizeof(char), blocksize, fp ); | < | ||
| 1160 | if( rdsz == 0 ) break; | < | ||
| 1161 | rc = whclob_append( dest, (char const *)bcbuf, rdsz ); | < | ||
| 1162 | if( rc < 0 ) | < | ||
| 1163 | { | < | ||
| 1164 | return rc; | < | ||
| 1165 | } | < | ||
| 1166 | } | < | ||
| 1167 | #undef blocksize | < | ||
| 1168 | return whclob_size(dest) - oldUsed; | < | ||
| 1169 | } | < | ||
| 1170 | < | |||
| 1171 | long whclob_importer_filename( whclob * dest, void * arg ) | < | ||
| 1172 | { | < | ||
| 1173 | char const * fname = (char const *)arg; | < | ||
| 1174 | FILE * fh = 0; | < | ||
| 1175 | long ret = 0; | < | ||
| 1176 | if( ! fname ) return whclob_rc.ArgError; | < | ||
| 1177 | fh = fopen( fname, "rb" ); | < | ||
| 1178 | if( !fh ) | < | ||
| 1179 | { | < | ||
| 1180 | ret = whclob_rc.IOError; | < | ||
| 1181 | } | < | ||
| 1182 | else | < | ||
| 1183 | { | < | ||
| 1184 | ret = whclob_import( dest, fh, whclob_importer_FILE ); | < | ||
| 1185 | fclose( fh ); | < | ||
| 1186 | } | < | ||
| 1187 | return ret; | < | ||
| 1188 | } | < | ||
| 1189 | < | |||
| 1190 | long whclob_import_FILE( whclob * dest, FILE * fp ) | < | ||
| 1191 | { | < | ||
| 1192 | return whclob_import( dest, fp, whclob_importer_FILE ); | < | ||
| 1193 | } | < | ||
| 1194 | < | |||
| 1195 | long whclob_import_filename( whclob * dest, char const * fn ) | < | ||
| 1196 | { | < | ||
| 1197 | return whclob_import( dest, (void*)fn, whclob_importer_filename ); | < | ||
| 1198 | /* i HATE that cast, but we know the importer won't change fn. */ | < | ||
| 1199 | } | < | ||
| 1200 | #endif /* WHCLOB_USE_FILE */ | < | ||
| 1201 | < | |||
| 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 | < | |||
| 1256 | #undef WHCLOB_DEBUG | < | ||