source: mainline/uspace/lib/drv/generic/logbuf.c@ cde999a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cde999a was 002fd5f, checked in by jzr <zarevucky.jiri@…>, 8 years ago

Replace parts of system headers with <_bits/…>.

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libdrv
30 * @{
31 */
32
33#include <stdio.h>
34#include <stddef.h>
35#include <ddf/log.h>
36#include <assert.h>
37
38/** Formatting string for printing number of not-printed items. */
39#define REMAINDER_STR_FMT " (%zu)..."
40/** Expected max size of the remainder string.
41 * String + terminator + number width (enough for 4GB).*/
42#define REMAINDER_STR_LEN (5 + 1 + 10)
43
44/** Groups size. */
45#define BUFFER_DUMP_GROUP_SIZE 4
46
47/** Space between two items. */
48#define SPACE_NORMAL " "
49/** Space between two groups. */
50#define SPACE_GROUP " "
51
52/** Dump one item into given buffer.
53 *
54 * @param buffer Data buffer.
55 * @param item_size Size of the item (1, 2, 4).
56 * @param index Index into the @p buffer (respecting @p item_size).
57 * @param dump Where to store the dump.
58 * @param dump_size Size of @p dump size.
59 * @return Number of characters printed (see snprintf).
60 */
61static int dump_one_item(const void *buffer, size_t item_size, size_t index,
62 char *dump, size_t dump_size)
63{
64 /* Determine space before the number. */
65 const char *space_before;
66 if (index == 0) {
67 space_before = "";
68 } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
69 space_before = SPACE_GROUP;
70 } else {
71 space_before = SPACE_NORMAL;
72 }
73
74 /* Let buf point to the item to be printed. */
75 const uint8_t *buf = (const uint8_t *) buffer;
76 buf += index * item_size;
77
78/* Formats the dump with space before, takes care of type casting (ugly). */
79#define _FORMAT(digits, bits) \
80 snprintf(dump, dump_size, "%s%0" #digits PRIx##bits, \
81 space_before, ((uint##bits##_t *)buf)[0]);
82
83 switch (item_size) {
84 case 4:
85 return _FORMAT(8, 32);
86 case 2:
87 return _FORMAT(4, 16);
88 default:
89 return _FORMAT(2, 8);
90 }
91#undef _FORMAT
92}
93
94/** Count number of characters needed for dumping buffer of given size.
95 *
96 * @param item_size Item size in bytes.
97 * @param items Number of items to print.
98 * @return Number of characters the full dump would occupy.
99 */
100static size_t count_dump_length(size_t item_size, size_t items)
101{
102 size_t group_space_count = items / BUFFER_DUMP_GROUP_SIZE - 1;
103 size_t normal_space_count = items - 1 - group_space_count;
104
105 size_t dump_itself = item_size * 2 * items;
106 size_t group_spaces = str_size(SPACE_GROUP) * group_space_count;
107 size_t normal_spaces = str_size(SPACE_NORMAL) * normal_space_count;
108
109 return dump_itself + group_spaces + normal_spaces;
110}
111
112
113/** Dumps data buffer to a string in hexadecimal format.
114 *
115 * Setting @p items_to_print to zero would dump the whole buffer together
116 * with information how many items were omitted. Otherwise, no information
117 * about omitted items is printed.
118 *
119 * @param dump Where to store the dumped buffer.
120 * @param dump_size Size of @p dump in bytes.
121 * @param buffer Data buffer to be dumped.
122 * @param item_size Size of items in the @p buffer in bytes (1,2,4 allowed).
123 * @param items Number of items in the @p buffer.
124 * @param items_to_print How many items to actually print.
125 */
126void ddf_dump_buffer(char *dump, size_t dump_size,
127 const void *buffer, size_t item_size, size_t items, size_t items_to_print)
128{
129 if ((dump_size == 0) || (dump == NULL)) {
130 return;
131 }
132 /* We need space for one byte at least. */
133 if (dump_size < 3) {
134 str_cpy(dump, dump_size, "...");
135 return;
136 }
137
138 /* Special cases first. */
139 if (buffer == NULL) {
140 str_cpy(dump, dump_size, "(null)");
141 return;
142 }
143 if (items == 0) {
144 str_cpy(dump, dump_size, "(empty)");
145 }
146
147 if (items_to_print > items) {
148 items_to_print = items;
149 }
150
151 bool print_remainder = items_to_print == 0;
152
153 /* How many available bytes we do have. */
154 size_t dump_size_remaining = dump_size - 1;
155
156 if (print_remainder) {
157 /* Can't do much when user supplied small buffer. */
158 if (dump_size_remaining < REMAINDER_STR_LEN) {
159 print_remainder = false;
160 } else {
161 size_t needed_size = count_dump_length(item_size, items);
162 if (needed_size > dump_size_remaining) {
163 dump_size_remaining -= REMAINDER_STR_LEN;
164 } else {
165 print_remainder = false;
166 }
167 }
168 items_to_print = items;
169 }
170
171 str_cpy(dump, dump_size, "");
172
173 size_t index = 0;
174 while (index < items) {
175 char current_item[32];
176 int printed = dump_one_item(buffer, item_size, index,
177 current_item, 32);
178 assert(printed >= 0);
179
180 if ((size_t) printed > dump_size_remaining) {
181 break;
182 }
183
184 str_append(dump, dump_size, current_item);
185
186 dump_size_remaining -= printed;
187 index++;
188
189 if (index >= items_to_print) {
190 break;
191 }
192 }
193
194 if (print_remainder && (index < items)) {
195 size_t s = str_size(dump);
196 snprintf(dump + s, dump_size - s ,REMAINDER_STR_FMT,
197 items - index);
198 }
199}
200
201/** @}
202 */
Note: See TracBrowser for help on using the repository browser.