29 #include "cx/printf.h" |
29 #include "cx/printf.h" |
30 |
30 |
31 #include <stdio.h> |
31 #include <stdio.h> |
32 #include <string.h> |
32 #include <string.h> |
33 |
33 |
34 #define UCX_PRINTF_BUFSIZE 256 |
34 #ifndef CX_PRINTF_SBO_SIZE |
|
35 #define CX_PRINTF_SBO_SIZE 512 |
|
36 #endif |
35 |
37 |
36 int cx_fprintf(void *stream, cx_write_func wfc, char const *fmt, ...) { |
38 int cx_fprintf( |
|
39 void *stream, |
|
40 cx_write_func wfc, |
|
41 char const *fmt, |
|
42 ... |
|
43 ) { |
37 int ret; |
44 int ret; |
38 va_list ap; |
45 va_list ap; |
39 va_start(ap, fmt); |
46 va_start(ap, fmt); |
40 ret = cx_vfprintf(stream, wfc, fmt, ap); |
47 ret = cx_vfprintf(stream, wfc, fmt, ap); |
41 va_end(ap); |
48 va_end(ap); |
42 return ret; |
49 return ret; |
43 } |
50 } |
44 |
51 |
45 int cx_vfprintf(void *stream, cx_write_func wfc, char const *fmt, va_list ap) { |
52 int cx_vfprintf( |
46 char buf[UCX_PRINTF_BUFSIZE]; |
53 void *stream, |
|
54 cx_write_func wfc, |
|
55 char const *fmt, |
|
56 va_list ap |
|
57 ) { |
|
58 char buf[CX_PRINTF_SBO_SIZE]; |
47 va_list ap2; |
59 va_list ap2; |
48 va_copy(ap2, ap); |
60 va_copy(ap2, ap); |
49 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); |
61 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); |
50 if (ret < 0) { |
62 if (ret < 0) { |
51 return ret; |
63 return ret; |
52 } else if (ret < UCX_PRINTF_BUFSIZE) { |
64 } else if (ret < CX_PRINTF_SBO_SIZE) { |
53 return (int) wfc(buf, 1, ret, stream); |
65 return (int) wfc(buf, 1, ret, stream); |
54 } else { |
66 } else { |
55 int len = ret + 1; |
67 int len = ret + 1; |
56 char *newbuf = malloc(len); |
68 char *newbuf = malloc(len); |
57 if (!newbuf) { |
69 if (!newbuf) { |
65 free(newbuf); |
77 free(newbuf); |
66 } |
78 } |
67 return ret; |
79 return ret; |
68 } |
80 } |
69 |
81 |
70 cxmutstr cx_asprintf_a(CxAllocator *allocator, char const *fmt, ...) { |
82 cxmutstr cx_asprintf_a( |
|
83 CxAllocator const *allocator, |
|
84 char const *fmt, |
|
85 ... |
|
86 ) { |
71 va_list ap; |
87 va_list ap; |
72 cxmutstr ret; |
88 cxmutstr ret; |
73 va_start(ap, fmt); |
89 va_start(ap, fmt); |
74 ret = cx_vasprintf_a(allocator, fmt, ap); |
90 ret = cx_vasprintf_a(allocator, fmt, ap); |
75 va_end(ap); |
91 va_end(ap); |
76 return ret; |
92 return ret; |
77 } |
93 } |
78 |
94 |
79 cxmutstr cx_vasprintf_a(CxAllocator *a, char const *fmt, va_list ap) { |
95 cxmutstr cx_vasprintf_a( |
|
96 CxAllocator const *a, |
|
97 char const *fmt, |
|
98 va_list ap |
|
99 ) { |
80 cxmutstr s; |
100 cxmutstr s; |
81 s.ptr = NULL; |
101 s.ptr = NULL; |
82 s.length = 0; |
102 s.length = 0; |
83 char buf[UCX_PRINTF_BUFSIZE]; |
103 char buf[CX_PRINTF_SBO_SIZE]; |
84 va_list ap2; |
104 va_list ap2; |
85 va_copy(ap2, ap); |
105 va_copy(ap2, ap); |
86 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); |
106 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); |
87 if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { |
107 if (ret > 0 && ret < CX_PRINTF_SBO_SIZE) { |
88 s.ptr = cxMalloc(a, ret + 1); |
108 s.ptr = cxMalloc(a, ret + 1); |
89 if (s.ptr) { |
109 if (s.ptr) { |
90 s.length = (size_t) ret; |
110 s.length = (size_t) ret; |
91 memcpy(s.ptr, buf, ret); |
111 memcpy(s.ptr, buf, ret); |
92 s.ptr[s.length] = '\0'; |
112 s.ptr[s.length] = '\0'; |