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

Last change on this file was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • 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 */
44#define REMAINDER_STR_LEN (5 + 1 + 10)
45
46/** Groups size. */
47#define BUFFER_DUMP_GROUP_SIZE 4
48
49/** Space between two items. */
50#define SPACE_NORMAL " "
51/** Space between two groups. */
52#define SPACE_GROUP " "
53
54/** Formats the dump with space before, takes care of type casting (ugly). */
55#define _FORMAT(digits, bits) \
56 snprintf(dump, dump_size, "%s%0" #digits PRIx##bits, \
57 space_before, ((uint##bits##_t *)buf)[0]);
58
59/** Dump one item into given buffer.
60 *
61 * @param buffer Data buffer.
62 * @param item_size Size of the item (1, 2, 4).
63 * @param index Index into the @p buffer (respecting @p item_size).
64 * @param dump Where to store the dump.
65 * @param dump_size Size of @p dump size.
66 * @return Number of characters printed (see snprintf).
67 */
68static int dump_one_item(const void *buffer, size_t item_size, size_t index,
69 char *dump, size_t dump_size)
70{
71 /* Determine space before the number. */
72 const char *space_before;
73 if (index == 0) {
74 space_before = "";
75 } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
76 space_before = SPACE_GROUP;
77 } else {
78 space_before = SPACE_NORMAL;
79 }
80
81 /* Let buf point to the item to be printed. */
82 const uint8_t *buf = (const uint8_t *) buffer;
83 buf += index * item_size;
84
85 switch (item_size) {
86 case 4:
87 return _FORMAT(8, 32);
88 case 2:
89 return _FORMAT(4, 16);
90 default:
91 return _FORMAT(2, 8);
92 }
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/** 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.