1 /*
2  * libusual - Utility library for C
3  *
4  * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <usual/cxalloc.h>
20 #include <usual/statlist.h>
21 
22 #include <string.h>
23 
24 /*
25  * Utility routines for cx_* API.
26  */
27 
cx_alloc(CxMem * cx,size_t len)28 void *cx_alloc(CxMem *cx, size_t len)
29 {
30 	if (!len)
31 		return NULL;
32 	if (!cx)
33 		cx = USUAL_ALLOC;
34 	return cx->ops->c_alloc(cx->ctx, len);
35 }
36 
cx_realloc(CxMem * cx,void * ptr,size_t len)37 void *cx_realloc(CxMem *cx, void *ptr, size_t len)
38 {
39 	if (!cx)
40 		cx = USUAL_ALLOC;
41 	if (!ptr)
42 		return cx_alloc(cx, len);
43 	if (!len) {
44 		cx_free(cx, ptr);
45 		return NULL;
46 	}
47 	return cx->ops->c_realloc(cx->ctx, ptr, len);
48 }
49 
cx_free(CxMem * cx,void * ptr)50 void cx_free(CxMem *cx, void *ptr)
51 {
52 	if (!cx)
53 		cx = USUAL_ALLOC;
54 	if (ptr)
55 		cx->ops->c_free(cx->ctx, ptr);
56 }
57 
cx_destroy(CxMem * cx)58 void cx_destroy(CxMem *cx)
59 {
60 	if (!cx)
61 		return;
62 	if (!cx->ops->c_destroy)
63 		abort();
64 	cx->ops->c_destroy(cx->ctx);
65 }
66 
cx_alloc0(CxMem * cx,size_t len)67 void *cx_alloc0(CxMem *cx, size_t len)
68 {
69 	void *p = cx_alloc(cx, len);
70 	if (p)
71 		memset(p, 0, len);
72 	return p;
73 }
74 
cx_memdup(CxMem * cx,const void * src,size_t len)75 void *cx_memdup(CxMem *cx, const void *src, size_t len)
76 {
77 	void *p = cx_alloc(cx, len);
78 	if (p)
79 		memcpy(p, src, len);
80 	return p;
81 }
82 
cx_strdup(CxMem * cx,const char * s)83 void *cx_strdup(CxMem *cx, const char *s)
84 {
85 	return cx_memdup(cx, s, strlen(s) + 1);
86 }
87 
cx_sprintf(CxMem * cx,const char * fmt,...)88 char *cx_sprintf(CxMem *cx, const char *fmt, ...)
89 {
90 	char *res;
91 	va_list ap;
92 	va_start(ap, fmt);
93 	res = cx_vsprintf(cx, fmt, ap);
94 	va_end(ap);
95 	return res;
96 }
97 
cx_vsprintf(CxMem * cx,const char * fmt,va_list ap)98 char *cx_vsprintf(CxMem *cx, const char *fmt, va_list ap)
99 {
100 	char *res;
101 	cx_vasprintf(cx, &res, fmt, ap);
102 	return res;
103 }
104 
cx_asprintf(CxMem * cx,char ** dst_p,const char * fmt,...)105 int cx_asprintf(CxMem *cx, char **dst_p, const char *fmt, ...)
106 {
107 	int res;
108 	va_list ap;
109 	va_start(ap, fmt);
110 	res = cx_vasprintf(cx, dst_p, fmt, ap);
111 	va_end(ap);
112 	return res;
113 }
114 
cx_vasprintf(CxMem * cx,char ** dst_p,const char * fmt,va_list ap)115 int cx_vasprintf(CxMem *cx, char **dst_p, const char *fmt, va_list ap)
116 {
117 	char buf[128], *dst;
118 	int res, res2;
119 
120 	*dst_p = NULL;
121 
122 	res = vsnprintf(buf, sizeof buf, fmt, ap);
123 	if (res < 0)
124 		return -1;
125 	dst = cx_alloc(cx, res + 1);
126 	if (!dst)
127 		return -1;
128 
129 	if ((size_t)res < sizeof buf) {
130 		memcpy(dst, buf, res+1);
131 	} else {
132 		res2 = vsnprintf(dst, res+1, fmt, ap);
133 		if (res2 != res) {
134 			cx_free(cx, dst);
135 			return -1;
136 		}
137 	}
138 	*dst_p = dst;
139 	return res;
140 }
141 
142 /*
143  * Base allocator that uses libc routines.
144  */
145 
libc_alloc(void * ctx,size_t len)146 static void *libc_alloc(void *ctx, size_t len)
147 {
148 	return malloc(len);
149 }
150 
libc_realloc(void * ctx,void * ptr,size_t len)151 static void *libc_realloc(void *ctx, void *ptr, size_t len)
152 {
153 	return realloc(ptr, len);
154 }
155 
libc_free(void * ctx,void * ptr)156 static void libc_free(void *ctx, void *ptr)
157 {
158 	free(ptr);
159 }
160 
161 static const struct CxOps libc_alloc_ops = {
162 	libc_alloc,
163 	libc_realloc,
164 	libc_free,
165 };
166 
167 const struct CxMem cx_libc_allocator = {
168 	&libc_alloc_ops,
169 	NULL,
170 };
171