Add missing calls to refcount_init()
[helenos.git] / uspace / lib / drv / generic / logbuf.c
bloba37313e6117e7782e82eaf0f8e1d9ec1510e0a40
1 /*
2 * Copyright (c) 2011 Vojtech Horky
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
29 /** @addtogroup libdrv
30 * @{
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <ddf/log.h>
36 #include <assert.h>
37 #include <str.h>
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).
44 #define REMAINDER_STR_LEN (5 + 1 + 10)
46 /** Groups size. */
47 #define BUFFER_DUMP_GROUP_SIZE 4
49 /** Space between two items. */
50 #define SPACE_NORMAL " "
51 /** Space between two groups. */
52 #define SPACE_GROUP " "
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]);
59 /** Dump one item into given buffer.
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).
68 static int dump_one_item(const void *buffer, size_t item_size, size_t index,
69 char *dump, size_t dump_size)
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;
81 /* Let buf point to the item to be printed. */
82 const uint8_t *buf = (const uint8_t *) buffer;
83 buf += index * item_size;
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);
95 /** Count number of characters needed for dumping buffer of given size.
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.
101 static size_t count_dump_length(size_t item_size, size_t items)
103 size_t group_space_count = items / BUFFER_DUMP_GROUP_SIZE - 1;
104 size_t normal_space_count = items - 1 - group_space_count;
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;
110 return dump_itself + group_spaces + normal_spaces;
113 /** Dumps data buffer to a string in hexadecimal format.
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.
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.
126 void 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)
129 if ((dump_size == 0) || (dump == NULL)) {
130 return;
132 /* We need space for one byte at least. */
133 if (dump_size < 3) {
134 str_cpy(dump, dump_size, "...");
135 return;
138 /* Special cases first. */
139 if (buffer == NULL) {
140 str_cpy(dump, dump_size, "(null)");
141 return;
143 if (items == 0) {
144 str_cpy(dump, dump_size, "(empty)");
147 if (items_to_print > items) {
148 items_to_print = items;
151 bool print_remainder = items_to_print == 0;
153 /* How many available bytes we do have. */
154 size_t dump_size_remaining = dump_size - 1;
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;
168 items_to_print = items;
171 str_cpy(dump, dump_size, "");
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);
180 if ((size_t) printed > dump_size_remaining) {
181 break;
184 str_append(dump, dump_size, current_item);
186 dump_size_remaining -= printed;
187 index++;
189 if (index >= items_to_print) {
190 break;
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);
201 /** @}