24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
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 |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 #include "ucx/utils.h" |
29 #include "cx/utils.h" |
30 |
30 |
31 #include <math.h> |
31 #define CX_STREAM_BCOPY_BUF_SIZE 8192 |
32 #include <stdio.h> |
32 #define CX_STREAM_COPY_BUF_SIZE 1024 |
33 #include <limits.h> |
|
34 #include <errno.h> |
|
35 |
33 |
36 /* COPY FUCNTIONS */ |
34 size_t cx_stream_bncopy( |
37 void* ucx_strcpy(const void* s, void* data) { |
35 void *src, |
38 const char *str = (const char*) s; |
36 void *dest, |
39 size_t n = 1+strlen(str); |
37 cx_read_func rfnc, |
40 char *cpy = (char*) malloc(n); |
38 cx_write_func wfnc, |
41 memcpy(cpy, str, n); |
39 char *buf, |
42 return cpy; |
40 size_t bufsize, |
43 } |
41 size_t n |
44 |
42 ) { |
45 void* ucx_memcpy(const void* m, void* n) { |
43 if (n == 0) { |
46 size_t k = *((size_t*)n); |
|
47 void *cpy = malloc(k); |
|
48 memcpy(cpy, m, k); |
|
49 return cpy; |
|
50 } |
|
51 |
|
52 size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc, |
|
53 write_func writefnc, char* buf, size_t bufsize, size_t n) { |
|
54 if(n == 0 || bufsize == 0) { |
|
55 return 0; |
44 return 0; |
56 } |
45 } |
57 |
46 |
58 char *lbuf; |
47 char *lbuf; |
59 size_t ncp = 0; |
48 size_t ncp = 0; |
60 |
49 |
61 if(buf) { |
50 if (buf) { |
|
51 if (bufsize == 0) return 0; |
62 lbuf = buf; |
52 lbuf = buf; |
63 } else { |
53 } else { |
64 lbuf = (char*)malloc(bufsize); |
54 if (bufsize == 0) bufsize = CX_STREAM_BCOPY_BUF_SIZE; |
65 if(lbuf == NULL) { |
55 lbuf = malloc(bufsize); |
|
56 if (lbuf == NULL) { |
66 return 0; |
57 return 0; |
67 } |
58 } |
68 } |
59 } |
69 |
60 |
70 size_t r; |
61 size_t r; |
71 size_t rn = bufsize > n ? n : bufsize; |
62 size_t rn = bufsize > n ? n : bufsize; |
72 while((r = readfnc(lbuf, 1, rn, src)) != 0) { |
63 while ((r = rfnc(lbuf, 1, rn, src)) != 0) { |
73 r = writefnc(lbuf, 1, r, dest); |
64 r = wfnc(lbuf, 1, r, dest); |
74 ncp += r; |
65 ncp += r; |
75 n -= r; |
66 n -= r; |
76 rn = bufsize > n ? n : bufsize; |
67 rn = bufsize > n ? n : bufsize; |
77 if(r == 0 || n == 0) { |
68 if (r == 0 || n == 0) { |
78 break; |
69 break; |
79 } |
70 } |
80 } |
71 } |
81 |
72 |
82 if (lbuf != buf) { |
73 if (lbuf != buf) { |
83 free(lbuf); |
74 free(lbuf); |
84 } |
75 } |
85 |
76 |
86 return ncp; |
77 return ncp; |
87 } |
78 } |
88 |
79 |
89 /* COMPARE FUNCTIONS */ |
80 size_t cx_stream_ncopy( |
90 |
81 void *src, |
91 int ucx_cmp_str(const void *s1, const void *s2, void *data) { |
82 void *dest, |
92 return strcmp((const char*)s1, (const char*)s2); |
83 cx_read_func rfnc, |
|
84 cx_write_func wfnc, |
|
85 size_t n |
|
86 ) { |
|
87 char buf[CX_STREAM_COPY_BUF_SIZE]; |
|
88 return cx_stream_bncopy(src, dest, rfnc, wfnc, |
|
89 buf, CX_STREAM_COPY_BUF_SIZE, n); |
93 } |
90 } |
94 |
91 |
95 int ucx_cmp_strn(const void *s1, const void *s2, void *n) { |
92 #ifndef CX_SZMUL_BUILTIN |
96 return strncmp((const char*)s1, (const char*)s2, *((size_t*) n)); |
93 #include "szmul.c" |
97 } |
|
98 |
|
99 int ucx_cmp_sstr(const void *s1, const void *s2, void *data) { |
|
100 sstr_t a = *(const sstr_t*) s1; |
|
101 sstr_t b = *(const sstr_t*) s2; |
|
102 return sstrcmp(a, b); |
|
103 } |
|
104 |
|
105 int ucx_cmp_int(const void *i1, const void *i2, void *data) { |
|
106 int a = *((const int*) i1); |
|
107 int b = *((const int*) i2); |
|
108 if (a == b) { |
|
109 return 0; |
|
110 } else { |
|
111 return a < b ? -1 : 1; |
|
112 } |
|
113 } |
|
114 |
|
115 int ucx_cmp_longint(const void *i1, const void *i2, void *data) { |
|
116 int a = *((const long int*) i1); |
|
117 int b = *((const long int*) i2); |
|
118 if (a == b) { |
|
119 return 0; |
|
120 } else { |
|
121 return a < b ? -1 : 1; |
|
122 } |
|
123 } |
|
124 |
|
125 intmax_t ucx_dist_int(const void *i1, const void *i2, void *data) { |
|
126 intmax_t a = *((const int*) i1); |
|
127 intmax_t b = *((const int*) i2); |
|
128 return a - b; |
|
129 } |
|
130 |
|
131 intmax_t ucx_dist_longint(const void *i1, const void *i2, void *data) { |
|
132 intmax_t a = *((const long int*) i1); |
|
133 intmax_t b = *((const long int*) i2); |
|
134 return a - b; |
|
135 } |
|
136 |
|
137 int ucx_cmp_float(const void *f1, const void *f2, void *epsilon) { |
|
138 float a = *((const float*) f1); |
|
139 float b = *((const float*) f2); |
|
140 float e = !epsilon ? 1e-6f : *((float*)epsilon); |
|
141 if (fabsf(a - b) < e) { |
|
142 return 0; |
|
143 } else { |
|
144 return a < b ? -1 : 1; |
|
145 } |
|
146 } |
|
147 |
|
148 int ucx_cmp_double(const void *d1, const void *d2, void *epsilon) { |
|
149 double a = *((const double*) d1); |
|
150 double b = *((const double*) d2); |
|
151 double e = !epsilon ? 1e-14 : *((double*)epsilon); |
|
152 if (fabs(a - b) < e) { |
|
153 return 0; |
|
154 } else { |
|
155 return a < b ? -1 : 1; |
|
156 } |
|
157 } |
|
158 |
|
159 int ucx_cmp_ptr(const void *ptr1, const void *ptr2, void *data) { |
|
160 const intptr_t p1 = (const intptr_t) ptr1; |
|
161 const intptr_t p2 = (const intptr_t) ptr2; |
|
162 if (p1 == p2) { |
|
163 return 0; |
|
164 } else { |
|
165 return p1 < p2 ? -1 : 1; |
|
166 } |
|
167 } |
|
168 |
|
169 int ucx_cmp_mem(const void *ptr1, const void *ptr2, void *n) { |
|
170 return memcmp(ptr1, ptr2, *((size_t*)n)); |
|
171 } |
|
172 |
|
173 /* PRINTF FUNCTIONS */ |
|
174 |
|
175 #ifdef va_copy |
|
176 #define UCX_PRINTF_BUFSIZE 256 |
|
177 #else |
|
178 #pragma message("WARNING: C99 va_copy macro not supported by this platform" \ |
|
179 " - limiting ucx_*printf to 2 KiB") |
|
180 #define UCX_PRINTF_BUFSIZE 0x800 |
|
181 #endif |
94 #endif |
182 |
|
183 int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) { |
|
184 int ret; |
|
185 va_list ap; |
|
186 va_start(ap, fmt); |
|
187 ret = ucx_vfprintf(stream, wfc, fmt, ap); |
|
188 va_end(ap); |
|
189 return ret; |
|
190 } |
|
191 |
|
192 int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) { |
|
193 char buf[UCX_PRINTF_BUFSIZE]; |
|
194 #ifdef va_copy |
|
195 va_list ap2; |
|
196 va_copy(ap2, ap); |
|
197 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); |
|
198 if (ret < 0) { |
|
199 return ret; |
|
200 } else if (ret < UCX_PRINTF_BUFSIZE) { |
|
201 return (int)wfc(buf, 1, ret, stream); |
|
202 } else { |
|
203 if (ret == INT_MAX) { |
|
204 errno = ENOMEM; |
|
205 return -1; |
|
206 } |
|
207 |
|
208 int len = ret + 1; |
|
209 char *newbuf = (char*)malloc(len); |
|
210 if (!newbuf) { |
|
211 return -1; |
|
212 } |
|
213 |
|
214 ret = vsnprintf(newbuf, len, fmt, ap2); |
|
215 if (ret > 0) { |
|
216 ret = (int)wfc(newbuf, 1, ret, stream); |
|
217 } |
|
218 free(newbuf); |
|
219 } |
|
220 return ret; |
|
221 #else |
|
222 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); |
|
223 if (ret < 0) { |
|
224 return ret; |
|
225 } else if (ret < UCX_PRINTF_BUFSIZE) { |
|
226 return (int)wfc(buf, 1, ret, stream); |
|
227 } else { |
|
228 errno = ENOMEM; |
|
229 return -1; |
|
230 } |
|
231 #endif |
|
232 } |
|
233 |
|
234 sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) { |
|
235 va_list ap; |
|
236 sstr_t ret; |
|
237 va_start(ap, fmt); |
|
238 ret = ucx_vasprintf(allocator, fmt, ap); |
|
239 va_end(ap); |
|
240 return ret; |
|
241 } |
|
242 |
|
243 sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) { |
|
244 sstr_t s; |
|
245 s.ptr = NULL; |
|
246 s.length = 0; |
|
247 char buf[UCX_PRINTF_BUFSIZE]; |
|
248 #ifdef va_copy |
|
249 va_list ap2; |
|
250 va_copy(ap2, ap); |
|
251 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); |
|
252 if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { |
|
253 s.ptr = (char*)almalloc(a, ret + 1); |
|
254 if (s.ptr) { |
|
255 s.length = (size_t)ret; |
|
256 memcpy(s.ptr, buf, ret); |
|
257 s.ptr[s.length] = '\0'; |
|
258 } |
|
259 } else if (ret == INT_MAX) { |
|
260 errno = ENOMEM; |
|
261 } else { |
|
262 int len = ret + 1; |
|
263 s.ptr = (char*)almalloc(a, len); |
|
264 if (s.ptr) { |
|
265 ret = vsnprintf(s.ptr, len, fmt, ap2); |
|
266 if (ret < 0) { |
|
267 free(s.ptr); |
|
268 s.ptr = NULL; |
|
269 } else { |
|
270 s.length = (size_t)ret; |
|
271 } |
|
272 } |
|
273 } |
|
274 #else |
|
275 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); |
|
276 if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { |
|
277 s.ptr = (char*)almalloc(a, ret + 1); |
|
278 if (s.ptr) { |
|
279 s.length = (size_t)ret; |
|
280 memcpy(s.ptr, buf, ret); |
|
281 s.ptr[s.length] = '\0'; |
|
282 } |
|
283 } else { |
|
284 errno = ENOMEM; |
|
285 } |
|
286 #endif |
|
287 return s; |
|
288 } |
|