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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a46e56b was 1d6dd2a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Remove unnecessary includes from <stdio.h>.

  • 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#include <str.h>
38
39/** Formatting string for printing number of not-printed items. */
40#define REMAINDER_STR_FMT " (%zu)..."
41/** Expected max size of the remainder string.
42 * String + terminator + number width (enough for 4GB).*/
43#define REMAINDER_STR_LEN (5 + 1 + 10)
44
45/** Groups size. */
46#define BUFFER_DUMP_GROUP_SIZE 4
47
48/** Space between two items. */
49#define SPACE_NORMAL " "
50/** Space between two groups. */
51#define SPACE_GROUP " "
52
53/** Dump one item into given buffer.
54 *
55 * @param buffer Data buffer.
56 * @param item_size Size of the item (1, 2, 4).
57 * @param index Index into the @p buffer (respecting @p item_size).
58 * @param dump Where to store the dump.
59 * @param dump_size Size of @p dump size.
60 * @return Number of characters printed (see snprintf).
61 */
62static int dump_one_item(const void *buffer, size_t item_size, size_t index,
63 char *dump, size_t dump_size)
64{
65 /* Determine space before the number. */
66 const char *space_before;
67 if (index == 0) {
68 space_before = "";
69 } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
70 space_before = SPACE_GROUP;
71 } else {
72 space_before = SPACE_NORMAL;
73 }
74
75 /* Let buf point to the item to be printed. */
76 const uint8_t *buf = (const uint8_t *) buffer;
77 buf += index * item_size;
78
79/* Formats the dump with space before, takes care of type casting (ugly). */
80#define _FORMAT(digits, bits) \
81 snprintf(dump, dump_size, "%s%0" #digits PRIx##bits, \
82 space_before, ((uint##bits##_t *)buf)[0]);
83
84 switch (item_size) {
85 case 4:
86 return _FORMAT(8, 32);
87 case 2:
88 return _FORMAT(4, 16);
89 default:
90 return _FORMAT(2, 8);
91 }
92#undef _FORMAT
93}
94
95/** Count number of characters needed for dumping buffer of given size.
96 *
97 * @param item_size Item size in bytes.
98 * @param items Number of items to print.
99 * @return Number of characters the full dump would occupy.
100 */
101static size_t count_dump_length(size_t item_size, size_t items)
102{
103 size_t group_space_count = items / BUFFER_DUMP_GROUP_SIZE - 1;
104 size_t normal_space_count = items - 1 - group_space_count;
105
106 size_t dump_itself = item_size * 2 * items;
107 size_t group_spaces = str_size(SPACE_GROUP) * group_space_count;
108 size_t normal_spaces = str_size(SPACE_NORMAL) * normal_space_count;
109
110 return dump_itself + group_spaces + normal_spaces;
111}
112
113
114/** Dumps data buffer to a string in hexadecimal format.
115 *
116 * Setting @p items_to_print to zero would dump the whole buffer together
117 * with information how many items were omitted. Otherwise, no information
118 * about omitted items is printed.
119 *
120 * @param dump Where to store the dumped buffer.
121 * @param dump_size Size of @p dump in bytes.
122 * @param buffer Data buffer to be dumped.
123 * @param item_size Size of items in the @p buffer in bytes (1,2,4 allowed).
124 * @param items Number of items in the @p buffer.
125 * @param items_to_print How many items to actually print.
126 */
127void ddf_dump_buffer(char *dump, size_t dump_size,
128 const void *buffer, size_t item_size, size_t items, size_t items_to_print)
129{
130 if ((dump_size == 0) || (dump == NULL)) {
131 return;
132 }
133 /* We need space for one byte at least. */
134 if (dump_size < 3) {
135 str_cpy(dump, dump_size, "...");
136 return;
137 }
138
139 /* Special cases first. */
140 if (buffer == NULL) {
141 str_cpy(dump, dump_size, "(null)");
142 return;
143 }
144 if (items == 0) {
145 str_cpy(dump, dump_size, "(empty)");
146 }
147
148 if (items_to_print > items) {
149 items_to_print = items;
150 }
151
152 bool print_remainder = items_to_print == 0;
153
154 /* How many available bytes we do have. */
155 size_t dump_size_remaining = dump_size - 1;
156
157 if (print_remainder) {
158 /* Can't do much when user supplied small buffer. */
159 if (dump_size_remaining < REMAINDER_STR_LEN) {
160 print_remainder = false;
161 } else {
162 size_t needed_size = count_dump_length(item_size, items);
163 if (needed_size > dump_size_remaining) {
164 dump_size_remaining -= REMAINDER_STR_LEN;
165 } else {
166 print_remainder = false;
167 }
168 }
169 items_to_print = items;
170 }
171
172 str_cpy(dump, dump_size, "");
173
174 size_t index = 0;
175 while (index < items) {
176 char current_item[32];
177 int printed = dump_one_item(buffer, item_size, index,
178 current_item, 32);
179 assert(printed >= 0);
180
181 if ((size_t) printed > dump_size_remaining) {
182 break;
183 }
184
185 str_append(dump, dump_size, current_item);
186
187 dump_size_remaining -= printed;
188 index++;
189
190 if (index >= items_to_print) {
191 break;
192 }
193 }
194
195 if (print_remainder && (index < items)) {
196 size_t s = str_size(dump);
197 snprintf(dump + s, dump_size - s ,REMAINDER_STR_FMT,
198 items - index);
199 }
200}
201
202/** @}
203 */
Note: See TracBrowser for help on using the repository browser.