Lumiera  0.pre.03
»edit your freedom«
tmpbuf.c
Go to the documentation of this file.
1 /*
2  Tmpbuf - Round Robin Temporary buffers
3 
4  Copyright (C)
5  2008, 2010 Christian Thaeter <ct@pipapo.org>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
23 #include "lib/safeclib.h"
24 #include "lib/tmpbuf.h"
25 
26 
27 #include <string.h>
28 #include <pthread.h>
29 #include <stdint.h>
30 #include <stdarg.h>
31 #include <nobug.h>
32 
33 
34 
36 {
37  void* buffers[64];
38  size_t sizes[64];
39  unsigned idx;
40 };
41 
42 static pthread_once_t lumiera_tmpbuf_tls_once = PTHREAD_ONCE_INIT;
43 static pthread_key_t lumiera_tmpbuf_tls_key;
44 
45 void
47 
48 static void
49 lumiera_tmpbuf_destroy (void* buf)
50 {
51  (void) buf;
53 }
54 
55 static void
56 lumiera_tmpbuf_init (void)
57 {
58  pthread_key_create (&lumiera_tmpbuf_tls_key, lumiera_tmpbuf_destroy);
59  atexit (lumiera_tmpbuf_freeall);
60 }
61 
62 
63 void
65 {
66  pthread_once (&lumiera_tmpbuf_tls_once, lumiera_tmpbuf_init);
67 
68  struct lumiera_tmpbuf_struct* buf = pthread_getspecific (lumiera_tmpbuf_tls_key);
69  if (buf)
70  {
71  pthread_setspecific (lumiera_tmpbuf_tls_key, NULL);
72  for (int idx = 0; idx < LUMIERA_TMPBUF_NUM; ++idx)
73  lumiera_free (buf->buffers[idx]);
74  lumiera_free (buf);
75  }
76 }
77 
78 
79 void*
81 {
82  pthread_once (&lumiera_tmpbuf_tls_once, lumiera_tmpbuf_init);
83 
84  struct lumiera_tmpbuf_struct* buf = pthread_getspecific (lumiera_tmpbuf_tls_key);
85  if (!buf)
86  pthread_setspecific (lumiera_tmpbuf_tls_key,
87  buf = lumiera_calloc (1, sizeof (struct lumiera_tmpbuf_struct)));
88 
89  buf->idx = (buf->idx + 1) & 0x3f;
90 
91  if (buf->sizes[buf->idx] < size || buf->sizes[buf->idx] > 8*size)
92  {
93  lumiera_free (buf->buffers[buf->idx]);
94  buf->sizes[buf->idx] = (size+4*sizeof(long)) & ~(4*sizeof(long)-1);
95  buf->buffers[buf->idx] = lumiera_malloc (buf->sizes[buf->idx]);
96  }
97  return buf->buffers[buf->idx];
98 }
99 
100 
101 char*
102 lumiera_tmpbuf_strndup (const char* src, size_t size)
103 {
104  size_t len = strlen (src);
105  len = len > size ? size : len;
106 
107  char* buf = lumiera_tmpbuf_provide (len + 1);
108  strncpy (buf, src, len);
109  buf[len] = '\0';
110 
111  return buf;
112 }
113 
114 
115 char*
116 lumiera_tmpbuf_snprintf (size_t size, const char* fmt, ...)
117 {
118  va_list args;
119 
120  va_start (args, fmt);
121  size_t len = vsnprintf (NULL, 0, fmt, args);
122  va_end (args);
123 
124  len = len > size ? size : len;
125  char* buf = lumiera_tmpbuf_provide (len+1);
126  va_start (args, fmt);
127  vsnprintf (buf, len+1, fmt, args);
128  va_end (args);
129 
130  return buf;
131 }
132 
133 
134 char*
135 lumiera_tmpbuf_strcat3 (const char* str1, size_t str1_len,
136  const char* str2, size_t str2_len,
137  const char* str3, size_t str3_len)
138 {
139  return lumiera_tmpbuf_snprintf (SIZE_MAX, "%.*s%s%.*s%s%.*s",
140  str1?str1_len:0, str1?str1:"", str1?".":"",
141  str2?str2_len:0, str2?str2:"",
142  str3?".":"", str3?str3_len:0, str3?str3:"");
143 }
144 
145 
146 char*
147 lumiera_tmpbuf_tr (const char* in, const char* from, const char* to, const char* def)
148 {
149  REQUIRE (strlen (from) == strlen (to), "from and to character set must have equal length");
150 
151  char* ret = lumiera_tmpbuf_strndup (in, SIZE_MAX);
152 
153  char* wpos;
154  char* rpos;
155  for (wpos = rpos = ret; *rpos; ++rpos, ++wpos)
156  {
157  char* found = strchr (from, *rpos);
158  if (found)
159  *wpos = to[found-from];
160  else if (def)
161  {
162  if (*def)
163  *wpos = *def;
164  else
165  {
166  ++rpos;
167  if (!*rpos)
168  break;
169  }
170  }
171  else
172  return NULL;
173  }
174  *wpos = '\0';
175 
176  return ret;
177 }
178 
179 
180 /*
181 // Local Variables:
182 // mode: C
183 // c-file-style: "gnu"
184 // indent-tabs-mode: nil
185 // End:
186 */
Portable and safe wrappers around some C-Lib functions.
void * lumiera_calloc(size_t n, size_t size)
Allocate cleared memory for an array.
Definition: safeclib.c:130
void * lumiera_tmpbuf_provide(size_t size)
Query a thread local tmpbuf.
Definition: tmpbuf.c:80
char * lumiera_tmpbuf_strndup(const char *src, size_t size)
Duplicate string to a tmpbuf.
Definition: tmpbuf.c:102
Round robin temporary buffers.
static void lumiera_free(void *mem)
Free previously allocated memory.
Definition: safeclib.h:73
void lumiera_tmpbuf_freeall(void)
free all buffers associated with this thread.
Definition: tmpbuf.c:64
void * lumiera_malloc(size_t size)
Allocate memory.
Definition: safeclib.c:113
char * lumiera_tmpbuf_tr(const char *in, const char *from, const char *to, const char *def)
Translates characters in a string, similar to the shell &#39;tr&#39; utility.
Definition: tmpbuf.c:147
char * lumiera_tmpbuf_strcat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
Concat up to 3 strings in a tmpbuf.
Definition: tmpbuf.c:135
#define LUMIERA_TMPBUF_NUM
Number of buffers in the ring This also defines how many concurent buffers can be in use in one threa...
Definition: tmpbuf.h:43
char * lumiera_tmpbuf_snprintf(size_t size, const char *fmt,...)
Construct a string in a tmpbuf.
Definition: tmpbuf.c:116