LCOV - code coverage report
Current view: top level - lib - smap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 111 139 79.9 %
Date: 2016-09-14 01:02:56 Functions: 24 29 82.8 %
Branches: 37 64 57.8 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2012, 2014, 2015, 2016 Nicira, Inc.
       2                 :            :  *
       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                 :            : #include <config.h>
      16                 :            : #include "smap.h"
      17                 :            : 
      18                 :            : #include <strings.h>
      19                 :            : 
      20                 :            : #include "hash.h"
      21                 :            : #include "openvswitch/json.h"
      22                 :            : #include "packets.h"
      23                 :            : #include "uuid.h"
      24                 :            : 
      25                 :            : static struct smap_node *smap_add__(struct smap *, char *, void *,
      26                 :            :                                     size_t hash);
      27                 :            : static struct smap_node *smap_find__(const struct smap *, const char *key,
      28                 :            :                                      size_t key_len, size_t hash);
      29                 :            : static int compare_nodes_by_key(const void *, const void *);
      30                 :            : 
      31                 :            : /* Public Functions. */
      32                 :            : 
      33                 :            : void
      34                 :    1735860 : smap_init(struct smap *smap)
      35                 :            : {
      36                 :    1735860 :     hmap_init(&smap->map);
      37                 :    1735860 : }
      38                 :            : 
      39                 :            : void
      40                 :     953382 : smap_destroy(struct smap *smap)
      41                 :            : {
      42         [ +  - ]:     953382 :     if (smap) {
      43                 :     953382 :         smap_clear(smap);
      44                 :     953382 :         hmap_destroy(&smap->map);
      45                 :            :     }
      46                 :     953382 : }
      47                 :            : 
      48                 :            : /* Adds 'key' paired with 'value' to 'smap'.  It is the caller's responsibility
      49                 :            :  * to avoid duplicate keys if desirable. */
      50                 :            : struct smap_node *
      51                 :     364495 : smap_add(struct smap *smap, const char *key, const char *value)
      52                 :            : {
      53                 :     364495 :     size_t key_len = strlen(key);
      54                 :     364495 :     return smap_add__(smap, xmemdup0(key, key_len), xstrdup(value),
      55                 :     364495 :                       hash_bytes(key, key_len, 0));
      56                 :            : }
      57                 :            : 
      58                 :            : /* Adds 'key' paired with 'value' to 'smap'.  Takes ownership of 'key' and
      59                 :            :  * 'value' (which will eventually be freed with free()).  It is the caller's
      60                 :            :  * responsibility to avoid duplicate keys if desirable. */
      61                 :            : struct smap_node *
      62                 :          0 : smap_add_nocopy(struct smap *smap, char *key, char *value)
      63                 :            : {
      64                 :          0 :     return smap_add__(smap, key, value, hash_bytes(key, strlen(key), 0));
      65                 :            : }
      66                 :            : 
      67                 :            : /* Attempts to add 'key' to 'smap' associated with 'value'.  If 'key' already
      68                 :            :  * exists in 'smap', does nothing and returns false.  Otherwise, performs the
      69                 :            :  * addition and returns true. */
      70                 :            : bool
      71                 :          0 : smap_add_once(struct smap *smap, const char *key, const char *value)
      72                 :            : {
      73         [ #  # ]:          0 :     if (!smap_get(smap, key)) {
      74                 :          0 :         smap_add(smap, key, value);
      75                 :          0 :         return true;
      76                 :            :     } else {
      77                 :          0 :         return false;
      78                 :            :     }
      79                 :            : }
      80                 :            : 
      81                 :            : /* Adds 'key' paired with a value derived from 'format' (similar to printf).
      82                 :            :  * It is the caller's responsibility to avoid duplicate keys if desirable. */
      83                 :            : void
      84                 :      20631 : smap_add_format(struct smap *smap, const char *key, const char *format, ...)
      85                 :            : {
      86                 :            :     size_t key_len;
      87                 :            :     va_list args;
      88                 :            :     char *value;
      89                 :            : 
      90                 :      20631 :     va_start(args, format);
      91                 :      20631 :     value = xvasprintf(format, args);
      92                 :      20631 :     va_end(args);
      93                 :            : 
      94                 :      20631 :     key_len = strlen(key);
      95                 :      20631 :     smap_add__(smap, xmemdup0(key, key_len), value,
      96                 :      20631 :                hash_bytes(key, key_len, 0));
      97                 :      20631 : }
      98                 :            : 
      99                 :            : /* Adds 'key' paired with a string representation of 'addr'. It is the
     100                 :            :  * caller's responsibility to avoid duplicate keys if desirable. */
     101                 :            : void
     102                 :         41 : smap_add_ipv6(struct smap *smap, const char *key, struct in6_addr *addr)
     103                 :            : {
     104                 :            :     char buf[INET6_ADDRSTRLEN];
     105                 :         41 :     ipv6_string_mapped(buf, addr);
     106                 :         41 :     smap_add(smap, key, buf);
     107                 :         41 : }
     108                 :            : 
     109                 :            : /* Searches for 'key' in 'smap'.  If it does not already exists, adds it.
     110                 :            :  * Otherwise, changes its value to 'value'. */
     111                 :            : void
     112                 :         53 : smap_replace(struct smap *smap, const char *key, const char *value)
     113                 :            : {
     114                 :         53 :     size_t  key_len = strlen(key);
     115                 :         53 :     size_t hash = hash_bytes(key, key_len, 0);
     116                 :            : 
     117                 :            :     struct smap_node *node;
     118                 :            : 
     119                 :         53 :     node = smap_find__(smap, key, key_len, hash);
     120         [ +  + ]:         53 :     if (node) {
     121                 :         28 :         free(node->value);
     122                 :         28 :         node->value = xstrdup(value);
     123                 :            :     } else {
     124                 :         25 :         smap_add__(smap, xmemdup0(key, key_len), xstrdup(value), hash);
     125                 :            :     }
     126                 :         53 : }
     127                 :            : 
     128                 :            : /* If 'key' is in 'smap', removes it.  Otherwise does nothing. */
     129                 :            : void
     130                 :         49 : smap_remove(struct smap *smap, const char *key)
     131                 :            : {
     132                 :         49 :     struct smap_node *node = smap_get_node(smap, key);
     133                 :            : 
     134         [ +  - ]:         49 :     if (node) {
     135                 :         49 :         smap_remove_node(smap, node);
     136                 :            :     }
     137                 :         49 : }
     138                 :            : 
     139                 :            : /* Removes 'node' from 'smap'. */
     140                 :            : void
     141                 :     385380 : smap_remove_node(struct smap *smap, struct smap_node *node)
     142                 :            : {
     143                 :     385380 :     hmap_remove(&smap->map, &node->node);
     144                 :     385380 :     free(node->key);
     145                 :     385380 :     free(node->value);
     146                 :     385380 :     free(node);
     147                 :     385380 : }
     148                 :            : 
     149                 :            : /* Deletes 'node' from 'smap'.
     150                 :            :  *
     151                 :            :  * If 'keyp' is nonnull, stores the node's key in '*keyp' and transfers
     152                 :            :  * ownership to the caller.  Otherwise, frees the node's key.  Similarly for
     153                 :            :  * 'valuep' and the node's value. */
     154                 :            : void
     155                 :          0 : smap_steal(struct smap *smap, struct smap_node *node,
     156                 :            :            char **keyp, char **valuep)
     157                 :            : {
     158         [ #  # ]:          0 :     if (keyp) {
     159                 :          0 :         *keyp = node->key;
     160                 :            :     } else {
     161                 :          0 :         free(node->key);
     162                 :            :     }
     163                 :            : 
     164         [ #  # ]:          0 :     if (valuep) {
     165                 :          0 :         *valuep = node->value;
     166                 :            :     } else {
     167                 :          0 :         free(node->value);
     168                 :            :     }
     169                 :            : 
     170                 :          0 :     hmap_remove(&smap->map, &node->node);
     171                 :          0 :     free(node);
     172                 :          0 : }
     173                 :            : 
     174                 :            : /* Removes all key-value pairs from 'smap'. */
     175                 :            : void
     176                 :     953535 : smap_clear(struct smap *smap)
     177                 :            : {
     178                 :            :     struct smap_node *node, *next;
     179                 :            : 
     180 [ +  + ][ -  + ]:    1338866 :     SMAP_FOR_EACH_SAFE (node, next, smap) {
                 [ +  + ]
     181                 :     385331 :         smap_remove_node(smap, node);
     182                 :            :     }
     183                 :     953535 : }
     184                 :            : 
     185                 :            : /* Returns the value associated with 'key' in 'smap'.
     186                 :            :  * If 'smap' does not contain 'key', returns NULL. */
     187                 :            : const char *
     188                 :    2672544 : smap_get(const struct smap *smap, const char *key)
     189                 :            : {
     190                 :    2672544 :     return smap_get_def(smap, key, NULL);
     191                 :            : }
     192                 :            : 
     193                 :            : /* Returns the value associated with 'key' in 'smap'.
     194                 :            :  * If 'smap' does not contain 'key', returns 'def'. */
     195                 :            : const char *
     196                 :    3442331 : smap_get_def(const struct smap *smap, const char *key, const char *def)
     197                 :            : {
     198                 :    3442331 :     struct smap_node *node = smap_get_node(smap, key);
     199         [ +  + ]:    3442331 :     return node ? node->value : def;
     200                 :            : }
     201                 :            : 
     202                 :            : /* Returns the node associated with 'key' in 'smap', or NULL. */
     203                 :            : struct smap_node *
     204                 :    3442380 : smap_get_node(const struct smap *smap, const char *key)
     205                 :            : {
     206                 :    3442380 :     size_t key_len = strlen(key);
     207                 :    3442380 :     return smap_find__(smap, key, key_len, hash_bytes(key, key_len, 0));
     208                 :            : }
     209                 :            : 
     210                 :            : /* Gets the value associated with 'key' in 'smap' and converts it to a boolean.
     211                 :            :  * If 'key' is not in 'smap', or its value is neither "true" nor "false",
     212                 :            :  * returns 'def'. */
     213                 :            : bool
     214                 :     195753 : smap_get_bool(const struct smap *smap, const char *key, bool def)
     215                 :            : {
     216                 :     195753 :     const char *value = smap_get_def(smap, key, "");
     217         [ +  + ]:     195753 :     if (def) {
     218                 :        301 :         return strcasecmp("false", value) != 0;
     219                 :            :     } else {
     220                 :     195452 :         return !strcasecmp("true", value);
     221                 :            :     }
     222                 :            : }
     223                 :            : 
     224                 :            : /* Gets the value associated with 'key' in 'smap' and converts it to an int
     225                 :            :  * using atoi().  If 'key' is not in 'smap', returns 'def'. */
     226                 :            : int
     227                 :     229819 : smap_get_int(const struct smap *smap, const char *key, int def)
     228                 :            : {
     229                 :     229819 :     const char *value = smap_get(smap, key);
     230                 :            : 
     231         [ +  + ]:     229819 :     return value ? atoi(value) : def;
     232                 :            : }
     233                 :            : 
     234                 :            : /* Gets the value associated with 'key' in 'smap' and converts it to an int
     235                 :            :  * using strtoull().  If 'key' is not in 'smap', returns 'def'. */
     236                 :            : unsigned long long int
     237                 :        121 : smap_get_ullong(const struct smap *smap, const char *key,
     238                 :            :                 unsigned long long def)
     239                 :            : {
     240                 :        121 :     const char *value = smap_get(smap, key);
     241                 :            : 
     242         [ -  + ]:        121 :     return value ? strtoull(value, NULL, 10) : def;
     243                 :            : }
     244                 :            : 
     245                 :            : /* Gets the value associated with 'key' in 'smap' and converts it to a UUID
     246                 :            :  * using uuid_from_string().  Returns true if successful, false if 'key' is not
     247                 :            :  * in 'smap' or if 'key' does not have the correct syntax for a UUID. */
     248                 :            : bool
     249                 :     441859 : smap_get_uuid(const struct smap *smap, const char *key, struct uuid *uuid)
     250                 :            : {
     251                 :     441859 :     return uuid_from_string(uuid, smap_get_def(smap, key, ""));
     252                 :            : }
     253                 :            : 
     254                 :            : /* Returns true of there are no elements in 'smap'. */
     255                 :            : bool
     256                 :       4317 : smap_is_empty(const struct smap *smap)
     257                 :            : {
     258                 :       4317 :     return hmap_is_empty(&smap->map);
     259                 :            : }
     260                 :            : 
     261                 :            : /* Returns the number of elements in 'smap'. */
     262                 :            : size_t
     263                 :     101619 : smap_count(const struct smap *smap)
     264                 :            : {
     265                 :     101619 :     return hmap_count(&smap->map);
     266                 :            : }
     267                 :            : 
     268                 :            : /* Initializes 'dst' as a clone of 'src. */
     269                 :            : void
     270                 :         84 : smap_clone(struct smap *dst, const struct smap *src)
     271                 :            : {
     272                 :            :     const struct smap_node *node;
     273                 :            : 
     274                 :         84 :     smap_init(dst);
     275 [ +  + ][ -  + ]:        314 :     SMAP_FOR_EACH (node, src) {
     276                 :        230 :         smap_add__(dst, xstrdup(node->key), xstrdup(node->value),
     277                 :            :                    node->node.hash);
     278                 :            :     }
     279                 :         84 : }
     280                 :            : 
     281                 :            : /* Returns an array of nodes sorted on key or NULL if 'smap' is empty.  The
     282                 :            :  * caller is responsible for freeing this array. */
     283                 :            : const struct smap_node **
     284                 :        142 : smap_sort(const struct smap *smap)
     285                 :            : {
     286         [ +  + ]:        142 :     if (smap_is_empty(smap)) {
     287                 :         72 :         return NULL;
     288                 :            :     } else {
     289                 :            :         const struct smap_node **nodes;
     290                 :            :         struct smap_node *node;
     291                 :            :         size_t i, n;
     292                 :            : 
     293                 :         70 :         n = smap_count(smap);
     294                 :         70 :         nodes = xmalloc(n * sizeof *nodes);
     295                 :         70 :         i = 0;
     296 [ +  + ][ -  + ]:        197 :         SMAP_FOR_EACH (node, smap) {
     297                 :        127 :             nodes[i++] = node;
     298                 :            :         }
     299         [ -  + ]:         70 :         ovs_assert(i == n);
     300                 :            : 
     301                 :         70 :         qsort(nodes, n, sizeof *nodes, compare_nodes_by_key);
     302                 :            : 
     303                 :         70 :         return nodes;
     304                 :            :     }
     305                 :            : }
     306                 :            : 
     307                 :            : /* Adds each of the key-value pairs from 'json' (which must be a JSON object
     308                 :            :  * whose values are strings) to 'smap'.
     309                 :            :  *
     310                 :            :  * The caller must have initialized 'smap'.
     311                 :            :  *
     312                 :            :  * The caller retains ownership of 'json' and everything in it. */
     313                 :            : void
     314                 :          0 : smap_from_json(struct smap *smap, const struct json *json)
     315                 :            : {
     316                 :            :     const struct shash_node *node;
     317                 :            : 
     318 [ #  # ][ #  # ]:          0 :     SHASH_FOR_EACH (node, json_object(json)) {
     319                 :          0 :         const struct json *value = node->data;
     320                 :          0 :         smap_add(smap, node->name, json_string(value));
     321                 :            :     }
     322                 :          0 : }
     323                 :            : 
     324                 :            : /* Returns a JSON object that maps from the keys in 'smap' to their values.
     325                 :            :  *
     326                 :            :  * The caller owns the returned value and must eventually json_destroy() it.
     327                 :            :  *
     328                 :            :  * The caller retains ownership of 'smap' and everything in it. */
     329                 :            : struct json *
     330                 :          0 : smap_to_json(const struct smap *smap)
     331                 :            : {
     332                 :            :     const struct smap_node *node;
     333                 :            :     struct json *json;
     334                 :            : 
     335                 :          0 :     json = json_object_create();
     336 [ #  # ][ #  # ]:          0 :     SMAP_FOR_EACH (node, smap) {
     337                 :          0 :         json_object_put_string(json, node->key, node->value);
     338                 :            :     }
     339                 :          0 :     return json;
     340                 :            : }
     341                 :            : 
     342                 :            : /* Returns true if the two maps are equal, meaning that they have the same set
     343                 :            :  * of key-value pairs.
     344                 :            :  */
     345                 :            : bool
     346                 :       3294 : smap_equal(const struct smap *smap1, const struct smap *smap2)
     347                 :            : {
     348         [ -  + ]:       3294 :     if (smap_count(smap1) != smap_count(smap2)) {
     349                 :          0 :         return false;
     350                 :            :     }
     351                 :            : 
     352                 :            :     const struct smap_node *node;
     353 [ +  + ][ -  + ]:      13152 :     SMAP_FOR_EACH (node, smap1) {
     354                 :       9859 :         const char *value2 = smap_get(smap2, node->key);
     355 [ +  - ][ +  + ]:       9859 :         if (!value2 || strcmp(node->value, value2)) {
     356                 :          1 :             return false;
     357                 :            :         }
     358                 :            :     }
     359                 :       3293 :     return true;
     360                 :            : }
     361                 :            : 
     362                 :            : /* Private Helpers. */
     363                 :            : 
     364                 :            : static struct smap_node *
     365                 :     385381 : smap_add__(struct smap *smap, char *key, void *value, size_t hash)
     366                 :            : {
     367                 :     385381 :     struct smap_node *node = xmalloc(sizeof *node);
     368                 :     385381 :     node->key = key;
     369                 :     385381 :     node->value = value;
     370                 :     385381 :     hmap_insert(&smap->map, &node->node, hash);
     371                 :     385381 :     return node;
     372                 :            : }
     373                 :            : 
     374                 :            : static struct smap_node *
     375                 :    3442433 : smap_find__(const struct smap *smap, const char *key, size_t key_len,
     376                 :            :             size_t hash)
     377                 :            : {
     378                 :            :     struct smap_node *node;
     379                 :            : 
     380 [ +  + ][ -  + ]:    3442433 :     HMAP_FOR_EACH_WITH_HASH (node, node, hash, &smap->map) {
     381 [ +  - ][ +  - ]:    1593062 :         if (!strncmp(node->key, key, key_len) && !node->key[key_len]) {
     382                 :    1593062 :             return node;
     383                 :            :         }
     384                 :            :     }
     385                 :            : 
     386                 :    1849371 :     return NULL;
     387                 :            : }
     388                 :            : 
     389                 :            : static int
     390                 :         75 : compare_nodes_by_key(const void *a_, const void *b_)
     391                 :            : {
     392                 :         75 :     const struct smap_node *const *a = a_;
     393                 :         75 :     const struct smap_node *const *b = b_;
     394                 :         75 :     return strcmp((*a)->key, (*b)->key);
     395                 :            : }

Generated by: LCOV version 1.12