Lev Walkin | ed93977 | 2017-10-08 23:04:04 -0700 | [diff] [blame] | 1 | #include <asn_internal.h> |
| 2 | |
| 3 | ssize_t |
| 4 | asn__format_to_callback(int (*cb)(const void *, size_t, void *key), void *key, |
| 5 | const char *fmt, ...) { |
| 6 | char scratch[64]; |
| 7 | char *buf = scratch; |
| 8 | size_t buf_size = sizeof(scratch); |
| 9 | int wrote; |
| 10 | int cb_ret; |
| 11 | |
| 12 | do { |
| 13 | va_list args; |
| 14 | va_start(args, fmt); |
| 15 | |
| 16 | wrote = vsnprintf(buf, buf_size, fmt, args); |
| 17 | if(wrote < (ssize_t)buf_size) { |
| 18 | if(wrote < 0) { |
| 19 | if(buf != scratch) FREEMEM(buf); |
| 20 | return -1; |
| 21 | } |
| 22 | break; |
| 23 | } |
| 24 | |
| 25 | buf_size <<= 1; |
| 26 | if(buf == scratch) { |
| 27 | buf = MALLOC(buf_size); |
| 28 | if(!buf) return -1; |
| 29 | } else { |
| 30 | void *p = REALLOC(buf, buf_size); |
| 31 | if(!p) { |
| 32 | FREEMEM(buf); |
| 33 | return -1; |
| 34 | } |
| 35 | buf = p; |
| 36 | } |
| 37 | } while(1); |
| 38 | |
| 39 | cb_ret = cb(buf, wrote, key); |
| 40 | if(buf != scratch) FREEMEM(buf); |
| 41 | if(cb_ret < 0) { |
| 42 | return -1; |
| 43 | } |
| 44 | |
| 45 | return wrote; |
| 46 | } |
| 47 | |