UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "cx/printf.h" 30 31 #include <stdio.h> 32 #include <string.h> 33 34 #ifndef CX_PRINTF_SBO_SIZE 35 #define CX_PRINTF_SBO_SIZE 512 36 #endif 37 38 int cx_fprintf( 39 void *stream, 40 cx_write_func wfc, 41 char const *fmt, 42 ... 43 ) { 44 int ret; 45 va_list ap; 46 va_start(ap, fmt); 47 ret = cx_vfprintf(stream, wfc, fmt, ap); 48 va_end(ap); 49 return ret; 50 } 51 52 int cx_vfprintf( 53 void *stream, 54 cx_write_func wfc, 55 char const *fmt, 56 va_list ap 57 ) { 58 char buf[CX_PRINTF_SBO_SIZE]; 59 va_list ap2; 60 va_copy(ap2, ap); 61 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); 62 if (ret < 0) { 63 return ret; 64 } else if (ret < CX_PRINTF_SBO_SIZE) { 65 return (int) wfc(buf, 1, ret, stream); 66 } else { 67 int len = ret + 1; 68 char *newbuf = malloc(len); 69 if (!newbuf) { 70 return -1; 71 } 72 73 ret = vsnprintf(newbuf, len, fmt, ap2); 74 if (ret > 0) { 75 ret = (int) wfc(newbuf, 1, ret, stream); 76 } 77 free(newbuf); 78 } 79 return ret; 80 } 81 82 cxmutstr cx_asprintf_a( 83 CxAllocator const *allocator, 84 char const *fmt, 85 ... 86 ) { 87 va_list ap; 88 cxmutstr ret; 89 va_start(ap, fmt); 90 ret = cx_vasprintf_a(allocator, fmt, ap); 91 va_end(ap); 92 return ret; 93 } 94 95 cxmutstr cx_vasprintf_a( 96 CxAllocator const *a, 97 char const *fmt, 98 va_list ap 99 ) { 100 cxmutstr s; 101 s.ptr = NULL; 102 s.length = 0; 103 char buf[CX_PRINTF_SBO_SIZE]; 104 va_list ap2; 105 va_copy(ap2, ap); 106 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); 107 if (ret > 0 && ret < CX_PRINTF_SBO_SIZE) { 108 s.ptr = cxMalloc(a, ret + 1); 109 if (s.ptr) { 110 s.length = (size_t) ret; 111 memcpy(s.ptr, buf, ret); 112 s.ptr[s.length] = '\0'; 113 } 114 } else { 115 int len = ret + 1; 116 s.ptr = cxMalloc(a, len); 117 if (s.ptr) { 118 ret = vsnprintf(s.ptr, len, fmt, ap2); 119 if (ret < 0) { 120 free(s.ptr); 121 s.ptr = NULL; 122 } else { 123 s.length = (size_t) ret; 124 } 125 } 126 } 127 return s; 128 } 129 130