LCOV - code coverage report
Current view: top level - lib/kvargs - rte_kvargs.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 70 83 84.3 %
Date: 2025-05-01 17:49:45 Functions: 10 11 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 67 84 79.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2013 Intel Corporation.
       3                 :            :  * Copyright(c) 2014 6WIND S.A.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <string.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <stdbool.h>
       9                 :            : 
      10                 :            : #include <eal_export.h>
      11                 :            : #include <rte_os_shim.h>
      12                 :            : 
      13                 :            : #include "rte_kvargs.h"
      14                 :            : 
      15                 :            : /*
      16                 :            :  * Receive a string with a list of arguments following the pattern
      17                 :            :  * key=value,key=value,... and insert them into the list.
      18                 :            :  * Params string will be copied to be modified.
      19                 :            :  * list "[]" and list element splitter ",", "-" is treated as value.
      20                 :            :  * Supported examples:
      21                 :            :  *   k1=v1,k2=v2
      22                 :            :  *   k1
      23                 :            :  *   k1=x[0-1]y[1,3-5,9]z
      24                 :            :  */
      25                 :            : static int
      26                 :        111 : rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params)
      27                 :            : {
      28                 :            :         char *str, *start;
      29                 :            :         bool in_list = false, end_key = false, end_value = false;
      30                 :            :         bool save = false, end_pair = false;
      31                 :            : 
      32                 :            :         /* Copy the const char *params to a modifiable string
      33                 :            :          * to pass to rte_strsplit
      34                 :            :          */
      35                 :        111 :         kvlist->str = strdup(params);
      36         [ +  - ]:        111 :         if (kvlist->str == NULL)
      37                 :            :                 return -1;
      38                 :            : 
      39                 :            :         /* browse each key/value pair and add it in kvlist */
      40                 :            :         str = kvlist->str;
      41                 :            :         start = str; /* start of current key or value */
      42                 :            :         while (1) {
      43   [ +  +  +  +  :       1679 :                 switch (*str) {
                   +  + ]
      44                 :        102 :                 case '=': /* End of key. */
      45                 :            :                         end_key = true;
      46                 :            :                         save = true;
      47                 :        102 :                         break;
      48                 :         53 :                 case ',':
      49                 :            :                         /* End of value, skip comma in middle of range */
      50         [ +  + ]:         53 :                         if (!in_list) {
      51         [ +  + ]:         51 :                                 if (end_key)
      52                 :            :                                         end_value = true;
      53                 :            :                                 else
      54                 :            :                                         end_key = true;
      55                 :            :                                 save = true;
      56                 :            :                                 end_pair = true;
      57                 :            :                         }
      58                 :            :                         break;
      59                 :          3 :                 case '[': /* Start of list. */
      60                 :            :                         in_list = true;
      61                 :          3 :                         break;
      62                 :          1 :                 case ']': /* End of list.  */
      63                 :            :                         if (in_list)
      64                 :            :                                 in_list = false;
      65                 :            :                         break;
      66                 :        111 :                 case '\0': /* End of string */
      67         [ +  + ]:        111 :                         if (end_key)
      68                 :            :                                 end_value = true;
      69                 :            :                         else
      70                 :            :                                 end_key = true;
      71                 :            :                         save = true;
      72                 :            :                         end_pair = true;
      73                 :            :                         break;
      74                 :            :                 default:
      75                 :            :                         break;
      76                 :            :                 }
      77                 :            : 
      78         [ +  + ]:       1679 :                 if (!save) {
      79                 :            :                         /* Continue if not end of key or value. */
      80                 :       1415 :                         str++;
      81                 :       1415 :                         continue;
      82                 :            :                 }
      83                 :            : 
      84         [ +  - ]:        264 :                 if (kvlist->count >= RTE_KVARGS_MAX)
      85                 :            :                         return -1;
      86                 :            : 
      87         [ +  + ]:        264 :                 if (end_value)
      88                 :            :                         /* Value parsed */
      89                 :        102 :                         kvlist->pairs[kvlist->count].value = start;
      90         [ +  - ]:        162 :                 else if (end_key)
      91                 :            :                         /* Key parsed. */
      92                 :        162 :                         kvlist->pairs[kvlist->count].key = start;
      93                 :            : 
      94         [ +  + ]:        264 :                 if (end_pair) {
      95         [ +  + ]:        162 :                         if (end_value || str != start)
      96                 :            :                                 /* Ignore empty pair. */
      97                 :        141 :                                 kvlist->count++;
      98                 :            :                         end_key = false;
      99                 :            :                         end_value = false;
     100                 :            :                         end_pair = false;
     101                 :            :                 }
     102                 :            : 
     103         [ +  + ]:        264 :                 if (*str == '\0') /* End of string. */
     104                 :            :                         break;
     105                 :        153 :                 *str = '\0';
     106                 :        153 :                 str++;
     107                 :            :                 start = str;
     108                 :            :                 save = false;
     109                 :            :         }
     110                 :            : 
     111                 :            :         return 0;
     112                 :            : }
     113                 :            : 
     114                 :            : /*
     115                 :            :  * Determine whether a key is valid or not by looking
     116                 :            :  * into a list of valid keys.
     117                 :            :  */
     118                 :            : static int
     119                 :            : is_valid_key(const char * const valid[], const char *key_match)
     120                 :            : {
     121                 :            :         const char * const *valid_ptr;
     122                 :            : 
     123         [ +  + ]:         47 :         for (valid_ptr = valid; *valid_ptr != NULL; valid_ptr++) {
     124         [ +  + ]:         45 :                 if (strcmp(key_match, *valid_ptr) == 0)
     125                 :            :                         return 1;
     126                 :            :         }
     127                 :            :         return 0;
     128                 :            : }
     129                 :            : 
     130                 :            : /*
     131                 :            :  * Determine whether all keys are valid or not by looking
     132                 :            :  * into a list of valid keys.
     133                 :            :  */
     134                 :            : static int
     135                 :         32 : check_for_valid_keys(struct rte_kvargs *kvlist,
     136                 :            :                 const char * const valid[])
     137                 :            : {
     138                 :            :         unsigned i, ret;
     139                 :            :         struct rte_kvargs_pair *pair;
     140                 :            : 
     141         [ +  + ]:         56 :         for (i = 0; i < kvlist->count; i++) {
     142                 :            :                 pair = &kvlist->pairs[i];
     143                 :         26 :                 ret = is_valid_key(valid, pair->key);
     144         [ +  + ]:         26 :                 if (!ret)
     145                 :            :                         return -1;
     146                 :            :         }
     147                 :            :         return 0;
     148                 :            : }
     149                 :            : 
     150                 :            : /*
     151                 :            :  * Return the number of times a given arg_name exists in the key/value list.
     152                 :            :  * E.g. given a list = { rx = 0, rx = 1, tx = 2 } the number of args for
     153                 :            :  * arg "rx" will be 2.
     154                 :            :  */
     155                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_count)
     156                 :            : unsigned
     157                 :         31 : rte_kvargs_count(const struct rte_kvargs *kvlist, const char *key_match)
     158                 :            : {
     159                 :            :         const struct rte_kvargs_pair *pair;
     160                 :            :         unsigned i, ret;
     161                 :            : 
     162                 :            :         ret = 0;
     163         [ +  + ]:         86 :         for (i = 0; i < kvlist->count; i++) {
     164                 :            :                 pair = &kvlist->pairs[i];
     165   [ +  +  +  + ]:         55 :                 if (key_match == NULL || strcmp(pair->key, key_match) == 0)
     166                 :         40 :                         ret++;
     167                 :            :         }
     168                 :            : 
     169                 :         31 :         return ret;
     170                 :            : }
     171                 :            : 
     172                 :            : static int
     173                 :         46 : kvargs_process_common(const struct rte_kvargs *kvlist, const char *key_match,
     174                 :            :                       arg_handler_t handler, void *opaque_arg, bool support_only_key)
     175                 :            : {
     176                 :            :         const struct rte_kvargs_pair *pair;
     177                 :            :         unsigned i;
     178                 :            : 
     179         [ +  - ]:         46 :         if (kvlist == NULL)
     180                 :            :                 return -1;
     181                 :            : 
     182         [ +  + ]:         78 :         for (i = 0; i < kvlist->count; i++) {
     183                 :            :                 pair = &kvlist->pairs[i];
     184   [ +  -  +  + ]:         35 :                 if (key_match == NULL || strcmp(pair->key, key_match) == 0) {
     185   [ +  +  +  + ]:         23 :                         if (!support_only_key && pair->value == NULL)
     186                 :            :                                 return -1;
     187         [ +  + ]:         22 :                         if ((*handler)(pair->key, pair->value, opaque_arg) < 0)
     188                 :            :                                 return -1;
     189                 :            :                 }
     190                 :            :         }
     191                 :            : 
     192                 :            :         return 0;
     193                 :            : }
     194                 :            : 
     195                 :            : /*
     196                 :            :  * For each matching key in key=value, call the given handler function.
     197                 :            :  */
     198                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_process)
     199                 :            : int
     200                 :         42 : rte_kvargs_process(const struct rte_kvargs *kvlist, const char *key_match, arg_handler_t handler,
     201                 :            :                    void *opaque_arg)
     202                 :            : {
     203                 :         42 :         return kvargs_process_common(kvlist, key_match, handler, opaque_arg, false);
     204                 :            : }
     205                 :            : 
     206                 :            : /*
     207                 :            :  * For each matching key in key=value or only-key, call the given handler function.
     208                 :            :  */
     209                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_process_opt)
     210                 :            : int
     211                 :          4 : rte_kvargs_process_opt(const struct rte_kvargs *kvlist, const char *key_match,
     212                 :            :                        arg_handler_t handler, void *opaque_arg)
     213                 :            : {
     214                 :          4 :         return kvargs_process_common(kvlist, key_match, handler, opaque_arg, true);
     215                 :            : }
     216                 :            : 
     217                 :            : /* free the rte_kvargs structure */
     218                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_free)
     219                 :            : void
     220                 :        381 : rte_kvargs_free(struct rte_kvargs *kvlist)
     221                 :            : {
     222         [ +  + ]:        381 :         if (!kvlist)
     223                 :            :                 return;
     224                 :            : 
     225                 :        111 :         free(kvlist->str);
     226                 :        111 :         free(kvlist);
     227                 :            : }
     228                 :            : 
     229                 :            : /* Lookup a value in an rte_kvargs list by its key and value. */
     230                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_get_with_value)
     231                 :            : const char *
     232                 :         14 : rte_kvargs_get_with_value(const struct rte_kvargs *kvlist, const char *key,
     233                 :            :                           const char *value)
     234                 :            : {
     235                 :            :         unsigned int i;
     236                 :            : 
     237         [ +  - ]:         14 :         if (kvlist == NULL)
     238                 :            :                 return NULL;
     239         [ +  + ]:         20 :         for (i = 0; i < kvlist->count; ++i) {
     240   [ +  -  +  + ]:         15 :                 if (key != NULL && strcmp(kvlist->pairs[i].key, key) != 0)
     241                 :          6 :                         continue;
     242   [ -  +  -  - ]:          9 :                 if (value != NULL && strcmp(kvlist->pairs[i].value, value) != 0)
     243                 :          0 :                         continue;
     244                 :          9 :                 return kvlist->pairs[i].value;
     245                 :            :         }
     246                 :            :         return NULL;
     247                 :            : }
     248                 :            : 
     249                 :            : /* Lookup a value in an rte_kvargs list by its key. */
     250                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_get)
     251                 :            : const char *
     252                 :         14 : rte_kvargs_get(const struct rte_kvargs *kvlist, const char *key)
     253                 :            : {
     254         [ +  - ]:         14 :         if (kvlist == NULL || key == NULL)
     255                 :            :                 return NULL;
     256                 :         14 :         return rte_kvargs_get_with_value(kvlist, key, NULL);
     257                 :            : }
     258                 :            : 
     259                 :            : /*
     260                 :            :  * Parse the arguments "key=value,key=value,..." string and return
     261                 :            :  * an allocated structure that contains a key/value list. Also
     262                 :            :  * check if only valid keys were used.
     263                 :            :  */
     264                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_parse)
     265                 :            : struct rte_kvargs *
     266                 :        111 : rte_kvargs_parse(const char *args, const char * const valid_keys[])
     267                 :            : {
     268                 :            :         struct rte_kvargs *kvlist;
     269                 :            : 
     270                 :        111 :         kvlist = malloc(sizeof(*kvlist));
     271         [ +  - ]:        111 :         if (kvlist == NULL)
     272                 :            :                 return NULL;
     273                 :            :         memset(kvlist, 0, sizeof(*kvlist));
     274                 :            : 
     275         [ -  + ]:        111 :         if (rte_kvargs_tokenize(kvlist, args) < 0) {
     276                 :          0 :                 rte_kvargs_free(kvlist);
     277                 :          0 :                 return NULL;
     278                 :            :         }
     279                 :            : 
     280   [ +  +  +  + ]:        111 :         if (valid_keys != NULL && check_for_valid_keys(kvlist, valid_keys) < 0) {
     281                 :          2 :                 rte_kvargs_free(kvlist);
     282                 :          2 :                 return NULL;
     283                 :            :         }
     284                 :            : 
     285                 :            :         return kvlist;
     286                 :            : }
     287                 :            : 
     288                 :            : RTE_EXPORT_SYMBOL(rte_kvargs_parse_delim)
     289                 :            : struct rte_kvargs *
     290                 :          0 : rte_kvargs_parse_delim(const char *args, const char * const valid_keys[],
     291                 :            :                        const char *valid_ends)
     292                 :            : {
     293                 :            :         struct rte_kvargs *kvlist = NULL;
     294                 :            :         char *copy;
     295                 :            :         size_t len;
     296                 :            : 
     297         [ #  # ]:          0 :         if (valid_ends == NULL)
     298                 :          0 :                 return rte_kvargs_parse(args, valid_keys);
     299                 :            : 
     300                 :          0 :         copy = strdup(args);
     301         [ #  # ]:          0 :         if (copy == NULL)
     302                 :            :                 return NULL;
     303                 :            : 
     304                 :          0 :         len = strcspn(copy, valid_ends);
     305                 :          0 :         copy[len] = '\0';
     306                 :            : 
     307                 :          0 :         kvlist = rte_kvargs_parse(copy, valid_keys);
     308                 :            : 
     309                 :          0 :         free(copy);
     310                 :          0 :         return kvlist;
     311                 :            : }

Generated by: LCOV version 1.14