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 | |
| 111 | /* Add variable number of spaces. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 112 | u8 * |
| 113 | format_white_space (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 114 | { |
Gabriel Ganne | e3ea797 | 2017-10-12 10:53:31 +0200 | [diff] [blame] | 115 | u32 n = va_arg (*va, u32); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 116 | while (n-- > 0) |
| 117 | vec_add1 (s, ' '); |
| 118 | return s; |
| 119 | } |
| 120 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 121 | u8 * |
| 122 | format_time_interval (u8 * s, va_list * args) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 123 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 124 | u8 *fmt = va_arg (*args, u8 *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 125 | f64 t = va_arg (*args, f64); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 126 | u8 *f; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 127 | |
| 128 | const f64 seconds_per_minute = 60; |
| 129 | const f64 seconds_per_hour = 60 * seconds_per_minute; |
| 130 | const f64 seconds_per_day = 24 * seconds_per_hour; |
| 131 | uword days, hours, minutes, secs, msecs, usecs; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 132 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 133 | days = t / seconds_per_day; |
| 134 | t -= days * seconds_per_day; |
| 135 | |
| 136 | hours = t / seconds_per_hour; |
| 137 | t -= hours * seconds_per_hour; |
| 138 | |
| 139 | minutes = t / seconds_per_minute; |
| 140 | t -= minutes * seconds_per_minute; |
| 141 | |
| 142 | secs = t; |
| 143 | t -= secs; |
| 144 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 145 | msecs = 1e3 * t; |
| 146 | usecs = 1e6 * t; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 147 | |
| 148 | for (f = fmt; *f; f++) |
| 149 | { |
| 150 | uword what, c; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 151 | char *what_fmt = "%d"; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 152 | |
| 153 | switch (c = *f) |
| 154 | { |
| 155 | default: |
| 156 | vec_add1 (s, c); |
| 157 | continue; |
| 158 | |
| 159 | case 'd': |
| 160 | what = days; |
| 161 | what_fmt = "%d"; |
| 162 | break; |
| 163 | case 'h': |
| 164 | what = hours; |
| 165 | what_fmt = "%02d"; |
| 166 | break; |
| 167 | case 'm': |
| 168 | what = minutes; |
| 169 | what_fmt = "%02d"; |
| 170 | break; |
| 171 | case 's': |
| 172 | what = secs; |
| 173 | what_fmt = "%02d"; |
| 174 | break; |
| 175 | case 'f': |
| 176 | what = msecs; |
| 177 | what_fmt = "%03d"; |
| 178 | break; |
| 179 | case 'u': |
| 180 | what = usecs; |
| 181 | what_fmt = "%06d"; |
| 182 | break; |
| 183 | } |
| 184 | |
| 185 | s = format (s, what_fmt, what); |
| 186 | } |
| 187 | |
| 188 | return s; |
| 189 | } |
| 190 | |
| 191 | /* Unparse memory size e.g. 100, 100k, 100m, 100g. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 192 | u8 * |
| 193 | format_memory_size (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 194 | { |
| 195 | uword size = va_arg (*va, uword); |
| 196 | uword l, u, log_u; |
| 197 | |
| 198 | l = size > 0 ? min_log2 (size) : 0; |
| 199 | if (l < 10) |
| 200 | log_u = 0; |
| 201 | else if (l < 20) |
| 202 | log_u = 10; |
| 203 | else if (l < 30) |
| 204 | log_u = 20; |
| 205 | else |
| 206 | log_u = 30; |
| 207 | |
| 208 | u = (uword) 1 << log_u; |
| 209 | if (size & (u - 1)) |
| 210 | s = format (s, "%.2f", (f64) size / (f64) u); |
| 211 | else |
| 212 | s = format (s, "%d", size >> log_u); |
| 213 | |
| 214 | if (log_u != 0) |
| 215 | s = format (s, "%c", " kmg"[log_u / 10]); |
| 216 | |
| 217 | return s; |
| 218 | } |
| 219 | |
| 220 | /* Parse memory size e.g. 100, 100k, 100m, 100g. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 221 | uword |
| 222 | unformat_memory_size (unformat_input_t * input, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 223 | { |
| 224 | uword amount, shift, c; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 225 | uword *result = va_arg (*va, uword *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 226 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 227 | if (!unformat (input, "%wd%_", &amount)) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 228 | return 0; |
| 229 | |
| 230 | c = unformat_get_input (input); |
| 231 | switch (c) |
| 232 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 233 | case 'k': |
| 234 | case 'K': |
| 235 | shift = 10; |
| 236 | break; |
| 237 | case 'm': |
| 238 | case 'M': |
| 239 | shift = 20; |
| 240 | break; |
| 241 | case 'g': |
| 242 | case 'G': |
| 243 | shift = 30; |
| 244 | break; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 245 | default: |
| 246 | shift = 0; |
| 247 | unformat_put_input (input); |
| 248 | break; |
| 249 | } |
| 250 | |
| 251 | *result = amount << shift; |
| 252 | return 1; |
| 253 | } |
| 254 | |
| 255 | /* Format c identifier: e.g. a_name -> "a name". |
| 256 | Words for both vector names and null terminated c strings. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 257 | u8 * |
| 258 | format_c_identifier (u8 * s, va_list * va) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 259 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 260 | u8 *id = va_arg (*va, u8 *); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 261 | uword i, l; |
| 262 | |
| 263 | l = ~0; |
| 264 | if (clib_mem_is_vec (id)) |
| 265 | l = vec_len (id); |
| 266 | |
| 267 | if (id) |
| 268 | for (i = 0; id[i] != 0 && i < l; i++) |
| 269 | { |
| 270 | u8 c = id[i]; |
| 271 | |
| 272 | if (c == '_') |
| 273 | c = ' '; |
| 274 | vec_add1 (s, c); |
| 275 | } |
| 276 | |
| 277 | return s; |
| 278 | } |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 279 | |
| 280 | u8 * |
| 281 | format_hexdump (u8 * s, va_list * args) |
| 282 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 283 | u8 *data = va_arg (*args, u8 *); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 284 | uword len = va_arg (*args, uword); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 285 | int i, index = 0; |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 286 | const int line_len = 16; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 287 | u8 *line_hex = 0; |
| 288 | u8 *line_str = 0; |
Christophe Fontaine | d3c008d | 2017-10-02 18:10:54 +0200 | [diff] [blame] | 289 | u32 indent = format_get_indent (s); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 290 | |
| 291 | if (!len) |
| 292 | return s; |
| 293 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 294 | for (i = 0; i < len; i++) |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 295 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 296 | line_hex = format (line_hex, "%02x ", data[i]); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 297 | line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.'); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 298 | if (!((i + 1) % line_len)) |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 299 | { |
| 300 | s = format (s, "%U%05x: %v[%v]", |
| 301 | format_white_space, index ? indent : 0, |
| 302 | index, line_hex, line_str); |
| 303 | if (i < len - 1) |
| 304 | s = format (s, "\n"); |
| 305 | index = i + 1; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 306 | vec_reset_length (line_hex); |
| 307 | vec_reset_length (line_str); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 308 | } |
| 309 | } |
| 310 | |
| 311 | while (i++ % line_len) |
| 312 | line_hex = format (line_hex, " "); |
| 313 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 314 | if (vec_len (line_hex)) |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 315 | s = format (s, "%U%05x: %v[%v]", |
Damjan Marion | 1e33663 | 2018-02-17 14:05:08 +0100 | [diff] [blame] | 316 | format_white_space, index ? indent : 0, |
| 317 | index, line_hex, line_str); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 318 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 319 | vec_free (line_hex); |
| 320 | vec_free (line_str); |
Damjan Marion | a7e83ce | 2016-06-09 12:38:22 +0200 | [diff] [blame] | 321 | |
| 322 | return s; |
| 323 | } |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 324 | |
| 325 | /* |
| 326 | * fd.io coding-style-patch-verification: ON |
| 327 | * |
| 328 | * Local Variables: |
| 329 | * eval: (c-set-style "gnu") |
| 330 | * End: |
| 331 | */ |