LCOV - code coverage report
Current view: top level - vppinfra - std-formats.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 88 299 29.4 %
Date: 2023-07-05 22:20:52 Functions: 6 19 31.6 %

          Line data    Source code
       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>
      39             : #include <ctype.h>
      40             : 
      41             : /* Format vectors. */
      42             : u8 *
      43        1518 : format_vec32 (u8 * s, va_list * va)
      44             : {
      45        1518 :   u32 *v = va_arg (*va, u32 *);
      46        1518 :   char *fmt = va_arg (*va, char *);
      47             :   uword i;
      48        2868 :   for (i = 0; i < vec_len (v); i++)
      49             :     {
      50        1350 :       if (i > 0)
      51         293 :         s = format (s, ", ");
      52        1350 :       s = format (s, fmt, v[i]);
      53             :     }
      54        1518 :   return s;
      55             : }
      56             : 
      57             : u8 *
      58           0 : format_vec_uword (u8 * s, va_list * va)
      59             : {
      60           0 :   uword *v = va_arg (*va, uword *);
      61           0 :   char *fmt = va_arg (*va, char *);
      62             :   uword i;
      63           0 :   for (i = 0; i < vec_len (v); i++)
      64             :     {
      65           0 :       if (i > 0)
      66           0 :         s = format (s, ", ");
      67           0 :       s = format (s, fmt, v[i]);
      68             :     }
      69           0 :   return s;
      70             : }
      71             : 
      72             : /* Ascii buffer and length. */
      73             : u8 *
      74           0 : format_ascii_bytes (u8 * s, va_list * va)
      75             : {
      76           0 :   u8 *v = va_arg (*va, u8 *);
      77           0 :   uword n_bytes = va_arg (*va, uword);
      78           0 :   vec_add (s, v, n_bytes);
      79           0 :   return s;
      80             : }
      81             : 
      82             : /* Format hex dump. */
      83             : u8 *
      84           0 : format_hex_bytes (u8 * s, va_list * va)
      85             : {
      86           0 :   u8 *bytes = va_arg (*va, u8 *);
      87           0 :   int n_bytes = va_arg (*va, int);
      88             :   uword i;
      89             : 
      90             :   /* Print short or long form depending on byte count. */
      91           0 :   uword short_form = n_bytes <= 32;
      92           0 :   u32 indent = format_get_indent (s);
      93             : 
      94           0 :   if (n_bytes == 0)
      95           0 :     return s;
      96             : 
      97           0 :   for (i = 0; i < n_bytes; i++)
      98             :     {
      99           0 :       if (!short_form && (i % 32) == 0)
     100           0 :         s = format (s, "%08x: ", i);
     101             : 
     102           0 :       s = format (s, "%02x", bytes[i]);
     103             : 
     104           0 :       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
     105           0 :         s = format (s, "\n%U", format_white_space, indent);
     106             :     }
     107             : 
     108           0 :   return s;
     109             : }
     110             : 
     111             : u8 *
     112           0 : format_hex_bytes_no_wrap (u8 * s, va_list * va)
     113             : {
     114           0 :   u8 *bytes = va_arg (*va, u8 *);
     115           0 :   int n_bytes = va_arg (*va, int);
     116             :   uword i;
     117             : 
     118           0 :   if (n_bytes == 0)
     119           0 :     return s;
     120             : 
     121           0 :   for (i = 0; i < n_bytes; i++)
     122           0 :     s = format (s, "%02x", bytes[i]);
     123             : 
     124           0 :   return s;
     125             : }
     126             : 
     127             : /* Add variable number of spaces. */
     128             : u8 *
     129    10007600 : format_white_space (u8 * s, va_list * va)
     130             : {
     131    10007600 :   u32 n = va_arg (*va, u32);
     132    47643700 :   while (n-- > 0)
     133    37636000 :     vec_add1 (s, ' ');
     134    10007600 :   return s;
     135             : }
     136             : 
     137             : u8 *
     138           0 : format_duration (u8 *s, va_list *args)
     139             : {
     140           0 :   f64 t = va_arg (*args, f64);
     141           0 :   s = format (s, "");
     142             : 
     143           0 :   const f64 seconds_per_minute = 60;
     144           0 :   const f64 seconds_per_hour = 60 * seconds_per_minute;
     145           0 :   const f64 seconds_per_day = 24 * seconds_per_hour;
     146             :   uword days, hours, minutes, secs, msecs, usecs;
     147             : 
     148           0 :   days = t / seconds_per_day;
     149           0 :   t -= days * seconds_per_day;
     150             : 
     151           0 :   hours = t / seconds_per_hour;
     152           0 :   t -= hours * seconds_per_hour;
     153             : 
     154           0 :   minutes = t / seconds_per_minute;
     155           0 :   t -= minutes * seconds_per_minute;
     156             : 
     157           0 :   secs = t;
     158           0 :   t -= secs;
     159             : 
     160           0 :   msecs = 1e3 * t;
     161             : 
     162           0 :   usecs = 1e6 * t;
     163           0 :   usecs = usecs % 1000;
     164             : 
     165           0 :   if (t == 0.)
     166           0 :     s = format (s, "0");
     167           0 :   if (days)
     168           0 :     s = format (s, "%ddays ", days);
     169           0 :   if (hours)
     170           0 :     s = format (s, "%dh ", hours);
     171           0 :   if (minutes)
     172           0 :     s = format (s, "%dmin ", minutes);
     173           0 :   if (secs)
     174           0 :     s = format (s, "%ds ", secs);
     175           0 :   if (msecs)
     176           0 :     s = format (s, "%dms ", msecs);
     177           0 :   if (usecs)
     178           0 :     s = format (s, "%dus", usecs);
     179             : 
     180           0 :   return (s);
     181             : }
     182             : 
     183             : u8 *
     184     3836920 : format_time_interval (u8 * s, va_list * args)
     185             : {
     186     3836920 :   u8 *fmt = va_arg (*args, u8 *);
     187     3836920 :   f64 t = va_arg (*args, f64);
     188             :   u8 *f;
     189             : 
     190     3836920 :   const f64 seconds_per_minute = 60;
     191     3836920 :   const f64 seconds_per_hour = 60 * seconds_per_minute;
     192     3836920 :   const f64 seconds_per_day = 24 * seconds_per_hour;
     193             :   uword days, hours, minutes, secs, msecs, usecs;
     194             : 
     195     3836920 :   days = t / seconds_per_day;
     196     3836920 :   t -= days * seconds_per_day;
     197             : 
     198     3836920 :   hours = t / seconds_per_hour;
     199     3836920 :   t -= hours * seconds_per_hour;
     200             : 
     201     3836920 :   minutes = t / seconds_per_minute;
     202     3836920 :   t -= minutes * seconds_per_minute;
     203             : 
     204     3836920 :   secs = t;
     205     3836920 :   t -= secs;
     206             : 
     207     3836920 :   msecs = 1e3 * t;
     208     3836920 :   usecs = 1e6 * t;
     209             : 
     210    30695400 :   for (f = fmt; *f; f++)
     211             :     {
     212             :       uword what, c;
     213    26858500 :       char *what_fmt = "%d";
     214             : 
     215    26858500 :       switch (c = *f)
     216             :         {
     217    11510800 :         default:
     218    11510800 :           vec_add1 (s, c);
     219    11510800 :           continue;
     220             : 
     221           0 :         case 'd':
     222           0 :           what = days;
     223           0 :           what_fmt = "%d";
     224           0 :           break;
     225     3836920 :         case 'h':
     226     3836920 :           what = hours;
     227     3836920 :           what_fmt = "%02d";
     228     3836920 :           break;
     229     3836920 :         case 'm':
     230     3836920 :           what = minutes;
     231     3836920 :           what_fmt = "%02d";
     232     3836920 :           break;
     233     3836920 :         case 's':
     234     3836920 :           what = secs;
     235     3836920 :           what_fmt = "%02d";
     236     3836920 :           break;
     237           0 :         case 'f':
     238           0 :           what = msecs;
     239           0 :           what_fmt = "%03d";
     240           0 :           break;
     241     3836920 :         case 'u':
     242     3836920 :           what = usecs;
     243     3836920 :           what_fmt = "%06d";
     244     3836920 :           break;
     245             :         }
     246             : 
     247    15347700 :       s = format (s, what_fmt, what);
     248             :     }
     249             : 
     250     3836920 :   return s;
     251             : }
     252             : 
     253             : /* Format base 10 e.g. 100, 100K, 100M, 100G */
     254             : __clib_export u8 *
     255           0 : format_base10 (u8 *s, va_list *va)
     256             : {
     257           0 :   u64 size = va_arg (*va, u64);
     258             : 
     259           0 :   if (size < 1000)
     260           0 :     s = format (s, "%d", size);
     261           0 :   else if (size < 1000000)
     262           0 :     s = format (s, "%.2fK", (f64) size / 1000.);
     263           0 :   else if (size < 1000000000)
     264           0 :     s = format (s, "%.2fM", (f64) size / 1000000.);
     265             :   else
     266           0 :     s = format (s, "%.2fG", (f64) size / 1000000000.);
     267             : 
     268           0 :   return s;
     269             : }
     270             : 
     271             : /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
     272             : __clib_export u8 *
     273       46467 : format_memory_size (u8 * s, va_list * va)
     274             : {
     275       46467 :   uword size = va_arg (*va, uword);
     276             :   uword l, u, log_u;
     277             : 
     278       46467 :   l = size > 0 ? min_log2 (size) : 0;
     279       46467 :   if (l < 10)
     280       17045 :     log_u = 0;
     281       29422 :   else if (l < 20)
     282       23118 :     log_u = 10;
     283        6304 :   else if (l < 30)
     284        6304 :     log_u = 20;
     285             :   else
     286           0 :     log_u = 30;
     287             : 
     288       46467 :   u = (uword) 1 << log_u;
     289       46467 :   if (size & (u - 1))
     290        8593 :     s = format (s, "%.2f", (f64) size / (f64) u);
     291             :   else
     292       37874 :     s = format (s, "%d", size >> log_u);
     293             : 
     294       46467 :   if (log_u != 0)
     295       29422 :     s = format (s, "%c", " kmg"[log_u / 10]);
     296             : 
     297       46467 :   return s;
     298             : }
     299             : 
     300             : /* Parse memory size e.g. 100, 100k, 100m, 100g. */
     301             : __clib_export uword
     302         651 : unformat_memory_size (unformat_input_t * input, va_list * va)
     303             : {
     304             :   uword amount, shift, c;
     305         651 :   uword *result = va_arg (*va, uword *);
     306             : 
     307         651 :   if (!unformat (input, "%wd%_", &amount))
     308           0 :     return 0;
     309             : 
     310         651 :   c = unformat_get_input (input);
     311         651 :   switch (c)
     312             :     {
     313           0 :     case 'k':
     314             :     case 'K':
     315           0 :       shift = 10;
     316           0 :       break;
     317         651 :     case 'm':
     318             :     case 'M':
     319         651 :       shift = 20;
     320         651 :       break;
     321           0 :     case 'g':
     322             :     case 'G':
     323           0 :       shift = 30;
     324           0 :       break;
     325           0 :     default:
     326           0 :       shift = 0;
     327           0 :       unformat_put_input (input);
     328           0 :       break;
     329             :     }
     330             : 
     331         651 :   *result = amount << shift;
     332         651 :   return 1;
     333             : }
     334             : 
     335             : /* Unparse memory page size e.g. 4K, 2M */
     336             : __clib_export u8 *
     337         841 : format_log2_page_size (u8 * s, va_list * va)
     338             : {
     339         841 :   clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
     340             : 
     341         841 :   if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
     342           0 :     return format (s, "unknown");
     343             : 
     344         841 :   if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
     345           0 :     return format (s, "default");
     346             : 
     347         841 :   if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
     348           0 :     return format (s, "default-hugepage");
     349             : 
     350         841 :   if (log2_page_sz >= 30)
     351           0 :     return format (s, "%uG", 1 << (log2_page_sz - 30));
     352             : 
     353         841 :   if (log2_page_sz >= 20)
     354           0 :     return format (s, "%uM", 1 << (log2_page_sz - 20));
     355             : 
     356         841 :   if (log2_page_sz >= 10)
     357         841 :     return format (s, "%uK", 1 << (log2_page_sz - 10));
     358             : 
     359           0 :   return format (s, "%u", 1 << log2_page_sz);
     360             : }
     361             : 
     362             : /* Parse memory page size e.g. 4K, 2M */
     363             : __clib_export uword
     364           0 : unformat_log2_page_size (unformat_input_t * input, va_list * va)
     365             : {
     366             :   uword amount;
     367           0 :   clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
     368             : 
     369           0 :   if (unformat (input, "default-hugepage"))
     370           0 :     *result = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
     371           0 :   else if (unformat (input, "default"))
     372           0 :     *result = CLIB_MEM_PAGE_SZ_DEFAULT;
     373           0 :   else if (unformat (input, "%wdk", &amount))
     374           0 :     *result = min_log2 (amount) + 10;
     375           0 :   else if (unformat (input, "%wdK", &amount))
     376           0 :     *result = min_log2 (amount) + 10;
     377           0 :   else if (unformat (input, "%wdm", &amount))
     378           0 :     *result = min_log2 (amount) + 20;
     379           0 :   else if (unformat (input, "%wdM", &amount))
     380           0 :     *result = min_log2 (amount) + 20;
     381           0 :   else if (unformat (input, "%wdg", &amount))
     382           0 :     *result = min_log2 (amount) + 30;
     383           0 :   else if (unformat (input, "%wdG", &amount))
     384           0 :     *result = min_log2 (amount) + 30;
     385             :   else
     386           0 :     return 0;
     387           0 :   return 1;
     388             : }
     389             : 
     390             : /* Format c identifier: e.g. a_name -> "a name".
     391             :    Works for both vector names and null terminated c strings. */
     392             : __clib_export u8 *
     393           0 : format_c_identifier (u8 * s, va_list * va)
     394             : {
     395           0 :   u8 *id = va_arg (*va, u8 *);
     396             :   uword i, l;
     397             : 
     398           0 :   l = ~0;
     399             : 
     400           0 :   if (id)
     401           0 :     for (i = 0; i < l && id[i] != 0; i++)
     402             :       {
     403           0 :         u8 c = id[i];
     404             : 
     405           0 :         if (c == '_')
     406           0 :           c = ' ';
     407           0 :         vec_add1 (s, c);
     408             :       }
     409             : 
     410           0 :   return s;
     411             : }
     412             : 
     413             : __clib_export u8 *
     414           0 : format_hexdump (u8 * s, va_list * args)
     415             : {
     416           0 :   u8 *data = va_arg (*args, u8 *);
     417           0 :   u32 len = va_arg (*args, u32);
     418           0 :   int i, index = 0;
     419           0 :   const int line_len = 16;
     420           0 :   u8 *line_hex = 0;
     421           0 :   u8 *line_str = 0;
     422           0 :   u32 indent = format_get_indent (s);
     423             : 
     424           0 :   if (!len)
     425           0 :     return s;
     426             : 
     427           0 :   for (i = 0; i < len; i++)
     428             :     {
     429           0 :       line_hex = format (line_hex, "%02x ", data[i]);
     430           0 :       line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
     431           0 :       if (!((i + 1) % line_len))
     432             :         {
     433           0 :           s = format (s, "%U%05x: %v[%v]",
     434             :                       format_white_space, index ? indent : 0,
     435             :                       index, line_hex, line_str);
     436           0 :           if (i < len - 1)
     437           0 :             s = format (s, "\n");
     438           0 :           index = i + 1;
     439           0 :           vec_reset_length (line_hex);
     440           0 :           vec_reset_length (line_str);
     441             :         }
     442             :     }
     443             : 
     444           0 :   while (i++ % line_len)
     445           0 :     line_hex = format (line_hex, "   ");
     446             : 
     447           0 :   if (vec_len (line_hex))
     448           0 :     s = format (s, "%U%05x: %v[%v]",
     449             :                 format_white_space, index ? indent : 0,
     450             :                 index, line_hex, line_str);
     451             : 
     452           0 :   vec_free (line_hex);
     453           0 :   vec_free (line_str);
     454             : 
     455           0 :   return s;
     456             : }
     457             : 
     458             : __clib_export u8 *
     459           0 : format_hexdump_u16 (u8 *s, va_list *args)
     460             : {
     461           0 :   u16 *data = va_arg (*args, u16 *);
     462           0 :   u32 len = va_arg (*args, u32);
     463           0 :   u32 indent = format_get_indent (s);
     464             : 
     465           0 :   if (!len)
     466           0 :     return s;
     467             : 
     468           0 :   for (int i = 0; i < len; i++)
     469             :     {
     470           0 :       if (i % 8 == 0)
     471             :         {
     472           0 :           s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
     473             :                       i ? indent : 0, i * 2);
     474             :         }
     475           0 :       s = format (s, " %04lx", data[i]);
     476             :     }
     477           0 :   return s;
     478             : }
     479             : 
     480             : __clib_export u8 *
     481           0 : format_hexdump_u32 (u8 *s, va_list *args)
     482             : {
     483           0 :   u32 *data = va_arg (*args, u32 *);
     484           0 :   u32 len = va_arg (*args, u32);
     485           0 :   u32 indent = format_get_indent (s);
     486             : 
     487           0 :   if (!len)
     488           0 :     return s;
     489             : 
     490           0 :   for (int i = 0; i < len; i++)
     491             :     {
     492           0 :       if (i % 4 == 0)
     493             :         {
     494           0 :           s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
     495             :                       i ? indent : 0, i * 4);
     496             :         }
     497           0 :       s = format (s, " %08lx", data[i]);
     498             :     }
     499           0 :   return s;
     500             : }
     501             : 
     502             : __clib_export u8 *
     503           0 : format_hexdump_u64 (u8 *s, va_list *args)
     504             : {
     505           0 :   u64 *data = va_arg (*args, u64 *);
     506           0 :   u32 len = va_arg (*args, u32);
     507           0 :   u32 indent = format_get_indent (s);
     508             : 
     509           0 :   if (!len)
     510           0 :     return s;
     511             : 
     512           0 :   for (int i = 0; i < len; i++)
     513             :     {
     514           0 :       if (i % 2 == 0)
     515             :         {
     516           0 :           s = format (s, "%s%U%05x: ", i ? "\n" : "", format_white_space,
     517             :                       i ? indent : 0, i * 8);
     518             :         }
     519           0 :       s = format (s, " %016lx", data[i]);
     520             :     }
     521           0 :   return s;
     522             : }
     523             : 
     524             : __clib_export u8 *
     525           0 : format_uword_bitmap (u8 *s, va_list *args)
     526             : {
     527           0 :   uword *bitmap = va_arg (*args, uword *);
     528           0 :   int n_uword = va_arg (*args, int);
     529           0 :   uword indent = format_get_indent (s);
     530             : 
     531           0 :   s = format (s, "%6s", "");
     532             : 
     533           0 :   for (int i = uword_bits - 4; i >= 0; i -= 4)
     534           0 :     s = format (s, "%5d", i);
     535             : 
     536           0 :   vec_add1 (s, '\n');
     537             : 
     538           0 :   for (int j = n_uword - 1; j >= 0; j--)
     539             :     {
     540           0 :       s = format (s, "%U0x%04x ", format_white_space, indent,
     541             :                   j * uword_bits / 8);
     542           0 :       for (int i = uword_bits - 1; i >= 0; i--)
     543             :         {
     544           0 :           vec_add1 (s, (1ULL << i) & bitmap[j] ? '1' : '.');
     545           0 :           if (i % 4 == 0)
     546           0 :             vec_add1 (s, ' ');
     547             :         }
     548           0 :       s = format (s, uword_bits == 64 ? "0x%016lx" : "0x%08lx", bitmap[j]);
     549           0 :       if (j)
     550           0 :         vec_add1 (s, '\n');
     551             :     }
     552             : 
     553           0 :   return s;
     554             : }
     555             : 
     556             : /*
     557             :  * fd.io coding-style-patch-verification: ON
     558             :  *
     559             :  * Local Variables:
     560             :  * eval: (c-set-style "gnu")
     561             :  * End:
     562             :  */

Generated by: LCOV version 1.14