00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "lib/error.h"
00022 #include "lib/safeclib.h"
00023
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include <pthread.h>
00027 #include <stdint.h>
00028 #include <stdarg.h>
00029 #include <nobug.h>
00030
00031
00032 LUMIERA_ERROR_DEFINE (NO_MEMORY, "Out of Memory!");
00033
00034 void*
00035 lumiera_malloc (size_t size)
00036 {
00037 void* o = size ? malloc (size) : NULL;
00038 if (!o)
00039 LUMIERA_DIE (NO_MEMORY);
00040 return o;
00041 }
00042
00043
00044 void*
00045 lumiera_calloc (size_t n, size_t size)
00046 {
00047 void* o = (n&&size)? calloc (n, size) : NULL;
00048 if (!o)
00049 LUMIERA_DIE (NO_MEMORY);
00050 return o;
00051 }
00052
00053
00054 void*
00055 lumiera_realloc (void* ptr, size_t size)
00056 {
00057 void* o = size ? realloc (ptr, size) : NULL;
00058 if (!o)
00059 LUMIERA_DIE (NO_MEMORY);
00060
00061 return o;
00062 }
00063
00064
00065 char*
00066 lumiera_strndup (const char* str, size_t len)
00067 {
00068 char* o;
00069 if (str)
00070 o = strndup (str, len);
00071 else
00072 o = strdup ("");
00073
00074 if (!o)
00075 LUMIERA_DIE (NO_MEMORY);
00076 return o;
00077 }
00078
00079
00080 int
00081 lumiera_strncmp (const char* a, const char* b, size_t len)
00082 {
00083 return a == b ? 0 : strncmp (a?a:"", b?b:"", len);
00084 }
00085
00086
00087 int
00088 lumiera_streq (const char* a, const char* b)
00089 {
00090 return !lumiera_strncmp (a, b, SIZE_MAX);
00091 }
00092
00093
00094 struct lumiera_tmpbuf_struct
00095 {
00096 void* buffers[64];
00097 size_t sizes[64];
00098 unsigned idx;
00099 };
00100
00101 static pthread_once_t lumiera_tmpbuf_tls_once = PTHREAD_ONCE_INIT;
00102 static pthread_key_t lumiera_tmpbuf_tls_key;
00103
00104 void
00105 lumiera_tmpbuf_freeall (void);
00106
00107 static void
00108 lumiera_tmpbuf_destroy (void* buf)
00109 {
00110 lumiera_tmpbuf_freeall ();
00111 }
00112
00113 static void
00114 lumiera_tmpbuf_init (void)
00115 {
00116 pthread_key_create (&lumiera_tmpbuf_tls_key, lumiera_tmpbuf_destroy);
00117 TODO ("register an atexit() handler to free tmpbufs");
00118 }
00119
00120
00121 void
00122 lumiera_tmpbuf_freeall (void)
00123 {
00124 pthread_once (&lumiera_tmpbuf_tls_once, lumiera_tmpbuf_init);
00125 struct lumiera_tmpbuf_struct* buf = pthread_getspecific (lumiera_tmpbuf_tls_key);
00126 if (buf)
00127 {
00128 pthread_setspecific (lumiera_tmpbuf_tls_key, NULL);
00129 for (int idx = 0; idx < 64; ++idx)
00130 lumiera_free (buf->buffers[idx]);
00131 lumiera_free (buf);
00132 }
00133 }
00134
00135
00136 void*
00137 lumiera_tmpbuf_provide (size_t size)
00138 {
00139 pthread_once (&lumiera_tmpbuf_tls_once, lumiera_tmpbuf_init);
00140 struct lumiera_tmpbuf_struct* buf = pthread_getspecific (lumiera_tmpbuf_tls_key);
00141 if (!buf)
00142 pthread_setspecific (lumiera_tmpbuf_tls_key,
00143 buf = lumiera_calloc (1, sizeof (struct lumiera_tmpbuf_struct)));
00144
00145 buf->idx = (buf->idx + 1) & 0x3f;
00146
00147 if (buf->sizes[buf->idx] < size || buf->sizes[buf->idx] > 8*size)
00148 {
00149 lumiera_free (buf->buffers[buf->idx]);
00150 buf->sizes[buf->idx] = (size+4*sizeof(long)) & ~(4*sizeof(long)-1);
00151 buf->buffers[buf->idx] = lumiera_malloc (buf->sizes[buf->idx]);
00152 }
00153 return buf->buffers[buf->idx];
00154 }
00155
00156
00157 char*
00158 lumiera_tmpbuf_strndup (const char* src, size_t size)
00159 {
00160 size_t len = strlen (src);
00161 len = len > size ? size : len;
00162
00163 char* buf = lumiera_tmpbuf_provide (len + 1);
00164 strncpy (buf, src, len);
00165 buf[len] = '\0';
00166
00167 return buf;
00168 }
00169
00170
00171 char*
00172 lumiera_tmpbuf_snprintf (size_t size, const char* fmt, ...)
00173 {
00174 va_list args;
00175
00176 va_start (args, fmt);
00177 size_t len = vsnprintf (NULL, 0, fmt, args);
00178 va_end (args);
00179
00180 len = len > size ? size : len;
00181 char* buf = lumiera_tmpbuf_provide (len+1);
00182 va_start (args, fmt);
00183 vsnprintf (buf, len+1, fmt, args);
00184 va_end (args);
00185
00186 return buf;
00187 }
00188
00189
00190 char*
00191 lumiera_tmpbuf_strcat3 (const char* str1, size_t str1_len,
00192 const char* str2, size_t str2_len,
00193 const char* str3, size_t str3_len)
00194 {
00195 return lumiera_tmpbuf_snprintf (SIZE_MAX, "%.*s%s%.*s%s%.*s",
00196 str1?str1_len:0, str1?str1:"", str1?".":"",
00197 str2?str2_len:0, str2?str2:"",
00198 str3?".":"", str3?str3_len:0, str3?str3:"");
00199 }
00200
00201
00202 char*
00203 lumiera_tmpbuf_tr (const char* in, const char* from, const char* to, const char* def)
00204 {
00205 REQUIRE (strlen (from) == strlen (to), "from and to character set must have equal length");
00206
00207 char* ret = lumiera_tmpbuf_strndup (in, SIZE_MAX);
00208
00209 char* wpos;
00210 char* rpos;
00211 for (wpos = rpos = ret; *rpos; ++rpos, ++wpos)
00212 {
00213 char* found = strchr (from, *rpos);
00214 if (found)
00215 *wpos = to[found-from];
00216 else if (def)
00217 {
00218 if (*def)
00219 *wpos = *def;
00220 else
00221 {
00222 ++rpos;
00223 if (!*rpos)
00224 break;
00225 }
00226 }
00227 else
00228 return NULL;
00229 }
00230 *wpos = '\0';
00231
00232 return ret;
00233 }