4 * @brief Generic types.
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33 ENUM(status_names
, SUCCESS
, DESTROY_ME
,
51 chunk_t CHUNK_INITIALIZER
= { NULL
, 0 };
54 * Described in header.
56 chunk_t
chunk_clone(chunk_t chunk
)
58 chunk_t clone
= CHUNK_INITIALIZER
;
60 if (chunk
.ptr
&& chunk
.len
> 0)
62 clone
.ptr
= malloc(chunk
.len
);
63 clone
.len
= chunk
.len
;
64 memcpy(clone
.ptr
, chunk
.ptr
, chunk
.len
);
73 chunk_t
chunk_cat(const char* mode
, ...)
79 int count
= strlen(mode
);
81 /* sum up lengths of individual chunks */
82 va_start(chunks
, mode
);
84 for (i
= 0; i
< count
; i
++)
86 chunk_t ch
= va_arg(chunks
, chunk_t
);
87 construct
.len
+= ch
.len
;
91 /* allocate needed memory for construct */
92 construct
.ptr
= malloc(construct
.len
);
95 /* copy or move the chunks */
96 va_start(chunks
, mode
);
97 for (i
= 0; i
< count
; i
++)
99 chunk_t ch
= va_arg(chunks
, chunk_t
);
103 memcpy(pos
, ch
.ptr
, ch
.len
);
109 memcpy(pos
, ch
.ptr
, ch
.len
);
119 * Described in header.
121 void chunk_free(chunk_t
*chunk
)
129 * Described in header.
131 chunk_t
chunk_alloc(size_t bytes
)
134 new_chunk
.ptr
= malloc(bytes
);
135 new_chunk
.len
= bytes
;
140 * Described in header.
142 bool chunk_equals(chunk_t a
, chunk_t b
)
144 return a
.ptr
!= NULL
&& b
.ptr
!= NULL
&&
145 a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
149 * Described in header.
151 bool chunk_equals_or_null(chunk_t a
, chunk_t b
)
153 if (a
.ptr
== NULL
|| b
.ptr
== NULL
)
155 return a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
159 * Described in header.
161 void *clalloc(void * pointer
, size_t size
)
166 memcpy(data
, pointer
,size
);
172 * We use a single mutex for all refcount variables. This
173 * is not optimal for performance, but the critical section
174 * is not that long...
175 * TODO: Consider to include a mutex in each refcount_t variable.
177 static pthread_mutex_t ref_mutex
= PTHREAD_MUTEX_INITIALIZER
;
180 * Described in header.
182 * TODO: May be implemented with atomic CPU instructions
183 * instead of a mutex.
185 void ref_get(refcount_t
*ref
)
187 pthread_mutex_lock(&ref_mutex
);
189 pthread_mutex_unlock(&ref_mutex
);
193 * Described in header.
195 * TODO: May be implemented with atomic CPU instructions
196 * instead of a mutex.
198 bool ref_put(refcount_t
*ref
)
202 pthread_mutex_lock(&ref_mutex
);
203 more_refs
= --(*ref
);
204 pthread_mutex_unlock(&ref_mutex
);
209 * Number of bytes per line to dump raw data
211 #define BYTES_PER_LINE 16
214 * output handler in printf() for byte ranges
216 static int print_bytes(FILE *stream
, const struct printf_info
*info
,
217 const void *const *args
)
219 char *bytes
= *((void**)(args
[0]));
220 int len
= *((size_t*)(args
[1]));
222 char buffer
[BYTES_PER_LINE
* 3];
223 char ascii_buffer
[BYTES_PER_LINE
+ 1];
224 char *buffer_pos
= buffer
;
225 char *bytes_pos
= bytes
;
226 char *bytes_roof
= bytes
+ len
;
231 written
+= fprintf(stream
, "=> %d bytes @ %p", len
, bytes
);
233 while (bytes_pos
< bytes_roof
)
235 static char hexdig
[] = "0123456789ABCDEF";
237 *buffer_pos
++ = hexdig
[(*bytes_pos
>> 4) & 0xF];
238 *buffer_pos
++ = hexdig
[ *bytes_pos
& 0xF];
241 (*bytes_pos
> 31 && *bytes_pos
< 127) ?
*bytes_pos
: '.';
243 if (++bytes_pos
== bytes_roof
|| i
== BYTES_PER_LINE
)
245 int padding
= 3 * (BYTES_PER_LINE
- i
);
252 *buffer_pos
++ = '\0';
253 ascii_buffer
[i
] = '\0';
255 written
+= fprintf(stream
, "\n%4d: %s %s",
256 line_start
, buffer
, ascii_buffer
);
260 line_start
+= BYTES_PER_LINE
;
272 * output handler in printf() for chunks
274 static int print_chunk(FILE *stream
, const struct printf_info
*info
,
275 const void *const *args
)
277 chunk_t
*chunk
= *((chunk_t
**)(args
[0]));
279 chunk_t copy
= *chunk
;
284 const void *new_args
[] = {&chunk
->ptr
, &chunk
->len
};
285 return print_bytes(stream
, info
, new_args
);
290 static char hexdig
[] = "0123456789abcdef";
297 written
+= fprintf(stream
, ":");
299 written
+= fprintf(stream
, "%c%c",
300 hexdig
[(*copy
.ptr
>> 4) & 0x0f],
301 hexdig
[ *copy
.ptr
++ & 0x0f]);
308 * output handler in printf() for time_t
310 static int print_time(FILE *stream
, const struct printf_info
*info
,
311 const void *const *args
)
313 static const char* months
[] = {
314 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
315 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
317 time_t time
= *((time_t*)(args
[0]));
323 utc
= *((bool*)(args
[1]));
325 if (time
== UNDEFINED_TIME
)
327 return fprintf(stream
, "--- -- --:--:--%s----",
328 info
->alt ?
" UTC " : " ");
336 localtime_r(&time
, &t
);
338 return fprintf(stream
, "%s %02d %02d:%02d:%02d%s%04d",
339 months
[t
.tm_mon
], t
.tm_mday
, t
.tm_hour
, t
.tm_min
,
340 t
.tm_sec
, info
->alt ?
" UTC " : " ", t
.tm_year
+ 1900);
344 * output handler in printf() for time deltas
346 static int print_time_delta(FILE *stream
, const struct printf_info
*info
,
347 const void *const *args
)
349 time_t start
= *((time_t*)(args
[0]));
350 time_t end
= *((time_t*)(args
[1]));
351 u_int delta
= abs(end
- start
);
352 char* unit
= "second";
354 if (delta
> 2 * 60 * 60 * 24)
356 delta
/= 60 * 60 * 24;
359 else if (delta
> 2 * 60 * 60)
364 else if (delta
> 2 * 60)
369 return fprintf(stream
, "%d %s", delta
, unit
);
373 * arginfo handler in printf() for byte ranges
375 static int print_bytes_arginfo(const struct printf_info
*info
, size_t n
, int *argtypes
)
379 argtypes
[0] = PA_POINTER
;
380 argtypes
[1] = PA_INT
;
386 * arginfo handler in printf() for time deltas
388 static int print_time_delta_arginfo(const struct printf_info
*info
, size_t n
, int *argtypes
)
392 argtypes
[0] = PA_INT
;
393 argtypes
[1] = PA_INT
;
399 * arginfo handler in printf() for time_t
401 static int print_time_arginfo(const struct printf_info
*info
, size_t n
, int *argtypes
)
407 argtypes
[0] = PA_INT
;
408 argtypes
[1] = PA_INT
;
415 argtypes
[0] = PA_INT
;
421 * arginfo handler in printf() for chunks
423 static int print_chunk_arginfo(const struct printf_info
*info
, size_t n
, int *argtypes
)
427 argtypes
[0] = PA_POINTER
;
433 * register printf() handlers for time_t
435 static void __attribute__ ((constructor
))print_register()
437 register_printf_function(CHUNK_PRINTF_SPEC
, print_chunk
, print_chunk_arginfo
);
438 register_printf_function(BYTES_PRINTF_SPEC
, print_bytes
, print_bytes_arginfo
);
439 register_printf_function(TIME_PRINTF_SPEC
, print_time
, print_time_arginfo
);
440 register_printf_function(TIME_DELTA_PRINTF_SPEC
, print_time_delta
, print_time_delta_arginfo
);