Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 Cisco and/or its affiliates. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | /* |
| 16 | Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus |
| 17 | |
| 18 | Permission is hereby granted, free of charge, to any person obtaining |
| 19 | a copy of this software and associated documentation files (the |
| 20 | "Software"), to deal in the Software without restriction, including |
| 21 | without limitation the rights to use, copy, modify, merge, publish, |
| 22 | distribute, sublicense, and/or sell copies of the Software, and to |
| 23 | permit persons to whom the Software is furnished to do so, subject to |
| 24 | the following conditions: |
| 25 | |
| 26 | The above copyright notice and this permission notice shall be |
| 27 | included in all copies or substantial portions of the Software. |
| 28 | |
| 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 33 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 34 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 36 | */ |
| 37 | |
| 38 | #include <vppinfra/format.h> |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 39 | #include <ctype.h> |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 40 | |
| 41 | /* Format vectors. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 42 | u8 * |
| 43 | format_vec32 (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 44 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 45 | u32 *v = va_arg (*va, u32 *); |
| 46 | char *fmt = va_arg (*va, char *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 47 | uword i; |
| 48 | for (i = 0; i < vec_len (v); i++) |
| 49 | { |
| 50 | if (i > 0) |
| 51 | s = format (s, ", "); |
| 52 | s = format (s, fmt, v[i]); |
| 53 | } |
| 54 | return s; |
| 55 | } |
| 56 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 57 | u8 * |
| 58 | format_vec_uword (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 59 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 60 | uword *v = va_arg (*va, uword *); |
| 61 | char *fmt = va_arg (*va, char *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 62 | uword i; |
| 63 | for (i = 0; i < vec_len (v); i++) |
| 64 | { |
| 65 | if (i > 0) |
| 66 | s = format (s, ", "); |
| 67 | s = format (s, fmt, v[i]); |
| 68 | } |
| 69 | return s; |
| 70 | } |
| 71 | |
| 72 | /* Ascii buffer and length. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 73 | u8 * |
| 74 | format_ascii_bytes (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 75 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 76 | u8 *v = va_arg (*va, u8 *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 77 | uword n_bytes = va_arg (*va, uword); |
| 78 | vec_add (s, v, n_bytes); |
| 79 | return s; |
| 80 | } |
| 81 | |
| 82 | /* Format hex dump. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 83 | u8 * |
| 84 | format_hex_bytes (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 85 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 86 | u8 *bytes = va_arg (*va, u8 *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 87 | int n_bytes = va_arg (*va, int); |
| 88 | uword i; |
| 89 | |
| 90 | /* Print short or long form depending on byte count. */ |
| 91 | uword short_form = n_bytes <= 32; |
Christophe Fontaine | d3c008d | 2017-10-02 18:10:54 +0200 | [diff] [blame] | 92 | u32 indent = format_get_indent (s); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 93 | |
| 94 | if (n_bytes == 0) |
| 95 | return s; |
| 96 | |
| 97 | for (i = 0; i < n_bytes; i++) |
| 98 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 99 | if (!short_form && (i % 32) == 0) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 100 | s = format (s, "%08x: ", i); |
| 101 | |
| 102 | s = format (s, "%02x", bytes[i]); |
| 103 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 104 | if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 105 | s = format (s, "\n%U", format_white_space, indent); |
| 106 | } |
| 107 | |
| 108 | return s; |
| 109 | } |
| 110 | |
Damjan Marion | 3860a77 | 2019-06-17 23:20:27 +0200 | [diff] [blame] | 111 | u8 * |
| 112 | format_hex_bytes_no_wrap (u8 * s, va_list * va) |
| 113 | { |
| 114 | u8 *bytes = va_arg (*va, u8 *); |
| 115 | int n_bytes = va_arg (*va, int); |
| 116 | uword i; |
| 117 | |
| 118 | if (n_bytes == 0) |
| 119 | return s; |
| 120 | |
| 121 | for (i = 0; i < n_bytes; i++) |
| 122 | s = format (s, "%02x", bytes[i]); |
| 123 | |
| 124 | return s; |
| 125 | } |
| 126 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 127 | /* Add variable number of spaces. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 128 | u8 * |
| 129 | format_white_space (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 130 | { |
Gabriel Ganne | e3ea797 | 2017-10-12 10:53:31 +0200 | [diff] [blame] | 131 | u32 n = va_arg (*va, u32); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 132 | while (n-- > 0) |
| 133 | vec_add1 (s, ' '); |
| 134 | return s; |
| 135 | } |
| 136 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 137 | u8 * |
| 138 | format_time_interval (u8 * s, va_list * args) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 139 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 140 | u8 *fmt = va_arg (*args, u8 *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 141 | f64 t = va_arg (*args, f64); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 142 | u8 *f; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 143 | |
| 144 | const f64 seconds_per_minute = 60; |
| 145 | const f64 seconds_per_hour = 60 * seconds_per_minute; |
| 146 | const f64 seconds_per_day = 24 * seconds_per_hour; |
| 147 | uword days, hours, minutes, secs, msecs, usecs; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 148 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 149 | days = t / seconds_per_day; |
| 150 | t -= days * seconds_per_day; |
| 151 | |
| 152 | hours = t / seconds_per_hour; |
| 153 | t -= hours * seconds_per_hour; |
| 154 | |
| 155 | minutes = t / seconds_per_minute; |
| 156 | t -= minutes * seconds_per_minute; |
| 157 | |
| 158 | secs = t; |
| 159 | t -= secs; |
| 160 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 161 | msecs = 1e3 * t; |
| 162 | usecs = 1e6 * t; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 163 | |
| 164 | for (f = fmt; *f; f++) |
| 165 | { |
| 166 | uword what, c; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 167 | char *what_fmt = "%d"; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 168 | |
| 169 | switch (c = *f) |
| 170 | { |
| 171 | default: |
| 172 | vec_add1 (s, c); |
| 173 | continue; |
| 174 | |
| 175 | case 'd': |
| 176 | what = days; |
| 177 | what_fmt = "%d"; |
| 178 | break; |
| 179 | case 'h': |
| 180 | what = hours; |
| 181 | what_fmt = "%02d"; |
| 182 | break; |
| 183 | case 'm': |
| 184 | what = minutes; |
| 185 | what_fmt = "%02d"; |
| 186 | break; |
| 187 | case 's': |
| 188 | what = secs; |
| 189 | what_fmt = "%02d"; |
| 190 | break; |
| 191 | case 'f': |
| 192 | what = msecs; |
| 193 | what_fmt = "%03d"; |
| 194 | break; |
| 195 | case 'u': |
| 196 | what = usecs; |
| 197 | what_fmt = "%06d"; |
| 198 | break; |
| 199 | } |
| 200 | |
| 201 | s = format (s, what_fmt, what); |
| 202 | } |
| 203 | |
| 204 | return s; |
| 205 | } |
| 206 | |
| 207 | /* Unparse memory size e.g. 100, 100k, 100m, 100g. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 208 | u8 * |
| 209 | format_memory_size (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 210 | { |
| 211 | uword size = va_arg (*va, uword); |
| 212 | uword l, u, log_u; |
| 213 | |
| 214 | l = size > 0 ? min_log2 (size) : 0; |
| 215 | if (l < 10) |
| 216 | log_u = 0; |
| 217 | else if (l < 20) |
| 218 | log_u = 10; |
| 219 | else if (l < 30) |
| 220 | log_u = 20; |
| 221 | else |
| 222 | log_u = 30; |
| 223 | |
| 224 | u = (uword) 1 << log_u; |
| 225 | if (size & (u - 1)) |
| 226 | s = format (s, "%.2f", (f64) size / (f64) u); |
| 227 | else |
| 228 | s = format (s, "%d", size >> log_u); |
| 229 | |
| 230 | if (log_u != 0) |
| 231 | s = format (s, "%c", " kmg"[log_u / 10]); |
| 232 | |
| 233 | return s; |
| 234 | } |
| 235 | |
| 236 | /* Parse memory size e.g. 100, 100k, 100m, 100g. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 237 | uword |
| 238 | unformat_memory_size (unformat_input_t * input, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 239 | { |
| 240 | uword amount, shift, c; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 241 | uword *result = va_arg (*va, uword *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 242 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 243 | if (!unformat (input, "%wd%_", &amount)) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 244 | return 0; |
| 245 | |
| 246 | c = unformat_get_input (input); |
| 247 | switch (c) |
| 248 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 249 | case 'k': |
| 250 | case 'K': |
| 251 | shift = 10; |
| 252 | break; |
| 253 | case 'm': |
| 254 | case 'M': |
| 255 | shift = 20; |
| 256 | break; |
| 257 | case 'g': |
| 258 | case 'G': |
| 259 | shift = 30; |
| 260 | break; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 261 | default: |
| 262 | shift = 0; |
| 263 | unformat_put_input (input); |
| 264 | break; |
| 265 | } |
| 266 | |
| 267 | *result = amount << shift; |
| 268 | return 1; |
| 269 | } |
| 270 | |
| 271 | /* Format c identifier: e.g. a_name -> "a name". |
Klement Sekera | ea84130 | 2018-05-11 12:59:05 +0200 | [diff] [blame] | 272 | Works for both vector names and null terminated c strings. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 273 | u8 * |
| 274 | format_c_identifier (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 275 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 276 | u8 *id = va_arg (*va, u8 *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 277 | uword i, l; |
| 278 | |
| 279 | l = ~0; |
| 280 | if (clib_mem_is_vec (id)) |
| 281 | l = vec_len (id); |
| 282 | |
| 283 | if (id) |
BenoƮt Ganne | 1bd6f61 | 2020-07-16 12:03:35 +0200 | [diff] [blame^] | 284 | for (i = 0; i < l && id[i] != 0; i++) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 285 | { |
| 286 | u8 c = id[i]; |
| 287 | |
| 288 | if (c == '_') |
| 289 | c = ' '; |
| 290 | vec_add1 (s, c); |
| 291 | } |
| 292 | |
| 293 | return s; |
| 294 | } |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 295 | |
| 296 | u8 * |
| 297 | format_hexdump (u8 * s, va_list * args) |
| 298 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 299 | u8 *data = va_arg (*args, u8 *); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 300 | uword len = va_arg (*args, uword); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 301 | int i, index = 0; |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 302 | const int line_len = 16; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 303 | u8 *line_hex = 0; |
| 304 | u8 *line_str = 0; |
Christophe Fontaine | d3c008d | 2017-10-02 18:10:54 +0200 | [diff] [blame] | 305 | u32 indent = format_get_indent (s); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 306 | |
| 307 | if (!len) |
| 308 | return s; |
| 309 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 310 | for (i = 0; i < len; i++) |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 311 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 312 | line_hex = format (line_hex, "%02x ", data[i]); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 313 | line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.'); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 314 | if (!((i + 1) % line_len)) |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 315 | { |
| 316 | s = format (s, "%U%05x: %v[%v]", |
| 317 | format_white_space, index ? indent : 0, |
| 318 | index, line_hex, line_str); |
| 319 | if (i < len - 1) |
| 320 | s = format (s, "\n"); |
| 321 | index = i + 1; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 322 | vec_reset_length (line_hex); |
| 323 | vec_reset_length (line_str); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 324 | } |
| 325 | } |
| 326 | |
| 327 | while (i++ % line_len) |
| 328 | line_hex = format (line_hex, " "); |
| 329 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 330 | if (vec_len (line_hex)) |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 331 | s = format (s, "%U%05x: %v[%v]", |
Damjan Marion | 1e33663 | 2018-02-17 14:05:08 +0100 | [diff] [blame] | 332 | format_white_space, index ? indent : 0, |
| 333 | index, line_hex, line_str); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 334 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 335 | vec_free (line_hex); |
| 336 | vec_free (line_str); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 337 | |
| 338 | return s; |
| 339 | } |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 340 | |
| 341 | /* |
| 342 | * fd.io coding-style-patch-verification: ON |
| 343 | * |
| 344 | * Local Variables: |
| 345 | * eval: (c-set-style "gnu") |
| 346 | * End: |
| 347 | */ |