4 * @brief Pointer/lenght abstraction and its functions.
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
28 #include <printf_hook.h>
33 chunk_t chunk_empty
= { NULL
, 0 };
36 * Described in header.
38 chunk_t
chunk_clone(chunk_t chunk
)
40 chunk_t clone
= chunk_empty
;
42 if (chunk
.ptr
&& chunk
.len
> 0)
44 clone
.ptr
= malloc(chunk
.len
);
45 clone
.len
= chunk
.len
;
46 memcpy(clone
.ptr
, chunk
.ptr
, chunk
.len
);
55 chunk_t
chunk_cat(const char* mode
, ...)
61 int count
= strlen(mode
);
63 /* sum up lengths of individual chunks */
64 va_start(chunks
, mode
);
66 for (i
= 0; i
< count
; i
++)
68 chunk_t ch
= va_arg(chunks
, chunk_t
);
69 construct
.len
+= ch
.len
;
73 /* allocate needed memory for construct */
74 construct
.ptr
= malloc(construct
.len
);
77 /* copy or move the chunks */
78 va_start(chunks
, mode
);
79 for (i
= 0; i
< count
; i
++)
81 chunk_t ch
= va_arg(chunks
, chunk_t
);
85 memcpy(pos
, ch
.ptr
, ch
.len
);
91 memcpy(pos
, ch
.ptr
, ch
.len
);
101 * Described in header.
103 void chunk_free(chunk_t
*chunk
)
111 * Described in header.
113 chunk_t
chunk_alloc(size_t bytes
)
116 new_chunk
.ptr
= malloc(bytes
);
117 new_chunk
.len
= bytes
;
122 * Described in header.
124 bool chunk_equals(chunk_t a
, chunk_t b
)
126 return a
.ptr
!= NULL
&& b
.ptr
!= NULL
&&
127 a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
131 * Described in header.
133 bool chunk_equals_or_null(chunk_t a
, chunk_t b
)
135 if (a
.ptr
== NULL
|| b
.ptr
== NULL
)
137 return a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
141 * Number of bytes per line to dump raw data
143 #define BYTES_PER_LINE 16
146 * output handler in printf() for byte ranges
148 static int print_bytes(FILE *stream
, const struct printf_info
*info
,
149 const void *const *args
)
151 char *bytes
= *((void**)(args
[0]));
152 int len
= *((size_t*)(args
[1]));
154 char buffer
[BYTES_PER_LINE
* 3];
155 char ascii_buffer
[BYTES_PER_LINE
+ 1];
156 char *buffer_pos
= buffer
;
157 char *bytes_pos
= bytes
;
158 char *bytes_roof
= bytes
+ len
;
163 written
+= fprintf(stream
, "=> %d bytes @ %p", len
, bytes
);
165 while (bytes_pos
< bytes_roof
)
167 static char hexdig
[] = "0123456789ABCDEF";
169 *buffer_pos
++ = hexdig
[(*bytes_pos
>> 4) & 0xF];
170 *buffer_pos
++ = hexdig
[ *bytes_pos
& 0xF];
173 (*bytes_pos
> 31 && *bytes_pos
< 127) ?
*bytes_pos
: '.';
175 if (++bytes_pos
== bytes_roof
|| i
== BYTES_PER_LINE
)
177 int padding
= 3 * (BYTES_PER_LINE
- i
);
184 *buffer_pos
++ = '\0';
185 ascii_buffer
[i
] = '\0';
187 written
+= fprintf(stream
, "\n%4d: %s %s",
188 line_start
, buffer
, ascii_buffer
);
192 line_start
+= BYTES_PER_LINE
;
204 * output handler in printf() for chunks
206 static int print_chunk(FILE *stream
, const struct printf_info
*info
,
207 const void *const *args
)
209 chunk_t
*chunk
= *((chunk_t
**)(args
[0]));
211 chunk_t copy
= *chunk
;
216 const void *new_args
[] = {&chunk
->ptr
, &chunk
->len
};
217 return print_bytes(stream
, info
, new_args
);
228 written
+= fprintf(stream
, ":");
230 written
+= fprintf(stream
, "%02x", *copy
.ptr
++);
237 * register printf() handlers
239 static void __attribute__ ((constructor
))print_register()
241 register_printf_function(PRINTF_CHUNK
, print_chunk
, arginfo_ptr
);
242 register_printf_function(PRINTF_BYTES
, print_bytes
, arginfo_ptr_int
);