Juha Hyttinen | ff8dccd | 2019-12-10 14:34:07 +0200 | [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 | va_end(args); |
| 21 | return -1; |
| 22 | } |
| 23 | break; |
| 24 | } |
| 25 | |
| 26 | buf_size <<= 1; |
| 27 | if(buf == scratch) { |
| 28 | buf = MALLOC(buf_size); |
| 29 | if(!buf) return -1; |
| 30 | } else { |
| 31 | void *p = REALLOC(buf, buf_size); |
| 32 | if(!p) { |
| 33 | FREEMEM(buf); |
| 34 | return -1; |
| 35 | } |
| 36 | buf = p; |
| 37 | } |
| 38 | } while(1); |
| 39 | |
| 40 | cb_ret = cb(buf, wrote, key); |
| 41 | if(buf != scratch) FREEMEM(buf); |
| 42 | if(cb_ret < 0) { |
| 43 | return -1; |
| 44 | } |
| 45 | |
| 46 | return wrote; |
| 47 | } |
| 48 | |