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

Generated by: LCOV version 1.14