LCOV - code coverage report
Current view: top level - lib - simap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 87 91 95.6 %
Date: 2016-09-14 01:02:56 Functions: 19 20 95.0 %
Branches: 26 34 76.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include "simap.h"
      19                 :            : #include "hash.h"
      20                 :            : 
      21                 :            : static size_t hash_name(const char *, size_t length);
      22                 :            : static struct simap_node *simap_find__(const struct simap *,
      23                 :            :                                        const char *name, size_t name_len,
      24                 :            :                                        size_t hash);
      25                 :            : static struct simap_node *simap_add_nocopy__(struct simap *,
      26                 :            :                                              char *name, unsigned int data,
      27                 :            :                                              size_t hash);
      28                 :            : static int compare_nodes_by_name(const void *a_, const void *b_);
      29                 :            : 
      30                 :            : /* Initializes 'simap' as an empty string-to-integer map. */
      31                 :            : void
      32                 :      19993 : simap_init(struct simap *simap)
      33                 :            : {
      34                 :      19993 :     hmap_init(&simap->map);
      35                 :      19993 : }
      36                 :            : 
      37                 :            : /* Frees all the data that 'simap' contains. */
      38                 :            : void
      39                 :      29821 : simap_destroy(struct simap *simap)
      40                 :            : {
      41         [ +  - ]:      29821 :     if (simap) {
      42                 :      29821 :         simap_clear(simap);
      43                 :      29821 :         hmap_destroy(&simap->map);
      44                 :            :     }
      45                 :      29821 : }
      46                 :            : 
      47                 :            : /* Exchanges the contents of 'a' and 'b'. */
      48                 :            : void
      49                 :      18244 : simap_swap(struct simap *a, struct simap *b)
      50                 :            : {
      51                 :      18244 :     hmap_swap(&a->map, &b->map);
      52                 :      18244 : }
      53                 :            : 
      54                 :            : /* Adjusts 'simap' so that it is still valid after it has been moved around in
      55                 :            :  * memory (e.g. due to realloc()). */
      56                 :            : void
      57                 :          0 : simap_moved(struct simap *simap)
      58                 :            : {
      59                 :          0 :     hmap_moved(&simap->map);
      60                 :          0 : }
      61                 :            : 
      62                 :            : /* Removes all of the mappings from 'simap' and frees them. */
      63                 :            : void
      64                 :      29821 : simap_clear(struct simap *simap)
      65                 :            : {
      66                 :            :     struct simap_node *node, *next;
      67                 :            : 
      68 [ +  + ][ -  + ]:      73783 :     SIMAP_FOR_EACH_SAFE (node, next, simap) {
                 [ +  + ]
      69                 :      43962 :         hmap_remove(&simap->map, &node->node);
      70                 :      43962 :         free(node->name);
      71                 :      43962 :         free(node);
      72                 :            :     }
      73                 :      29821 : }
      74                 :            : 
      75                 :            : /* Returns true if 'simap' contains no mappings, false if it contains at least
      76                 :            :  * one. */
      77                 :            : bool
      78                 :        145 : simap_is_empty(const struct simap *simap)
      79                 :            : {
      80                 :        145 :     return hmap_is_empty(&simap->map);
      81                 :            : }
      82                 :            : 
      83                 :            : /* Returns the number of mappings in 'simap'. */
      84                 :            : size_t
      85                 :        289 : simap_count(const struct simap *simap)
      86                 :            : {
      87                 :        289 :     return hmap_count(&simap->map);
      88                 :            : }
      89                 :            : 
      90                 :            : /* Inserts a mapping from 'name' to 'data' into 'simap', replacing any
      91                 :            :  * existing mapping for 'name'.  Returns true if a new mapping was added,
      92                 :            :  * false if an existing mapping's value was replaced.
      93                 :            :  *
      94                 :            :  * The caller retains ownership of 'name'. */
      95                 :            : bool
      96                 :      49237 : simap_put(struct simap *simap, const char *name, unsigned int data)
      97                 :            : {
      98                 :      49237 :     size_t length = strlen(name);
      99                 :      49237 :     size_t hash = hash_name(name, length);
     100                 :            :     struct simap_node *node;
     101                 :            : 
     102                 :      49237 :     node = simap_find__(simap, name, length, hash);
     103         [ +  + ]:      49237 :     if (node) {
     104                 :        266 :         node->data = data;
     105                 :        266 :         return false;
     106                 :            :     } else {
     107                 :      48971 :         simap_add_nocopy__(simap, xmemdup0(name, length), data, hash);
     108                 :      48971 :         return true;
     109                 :            :     }
     110                 :            : }
     111                 :            : 
     112                 :            : /* Increases the data value in the mapping for 'name' by 'amt', or inserts a
     113                 :            :  * mapping from 'name' to 'amt' if no such mapping exists.  Returns the
     114                 :            :  * new total data value for the mapping.
     115                 :            :  *
     116                 :            :  * If 'amt' is zero, this function does nothing and returns 0.  That is, this
     117                 :            :  * function won't create a mapping with a initial value of 0.
     118                 :            :  *
     119                 :            :  * The caller retains ownership of 'name'. */
     120                 :            : unsigned int
     121                 :      37888 : simap_increase(struct simap *simap, const char *name, unsigned int amt)
     122                 :            : {
     123         [ +  + ]:      37888 :     if (amt) {
     124                 :        819 :         size_t length = strlen(name);
     125                 :        819 :         size_t hash = hash_name(name, length);
     126                 :            :         struct simap_node *node;
     127                 :            : 
     128                 :        819 :         node = simap_find__(simap, name, length, hash);
     129         [ +  + ]:        819 :         if (node) {
     130                 :        281 :             node->data += amt;
     131                 :            :         } else {
     132                 :        538 :             node = simap_add_nocopy__(simap, xmemdup0(name, length),
     133                 :            :                                       amt, hash);
     134                 :            :         }
     135                 :        819 :         return node->data;
     136                 :            :     } else {
     137                 :      37069 :         return 0;
     138                 :            :     }
     139                 :            : }
     140                 :            : 
     141                 :            : /* Deletes 'node' from 'simap' and frees its associated memory. */
     142                 :            : void
     143                 :       3181 : simap_delete(struct simap *simap, struct simap_node *node)
     144                 :            : {
     145                 :       3181 :     hmap_remove(&simap->map, &node->node);
     146                 :       3181 :     free(node->name);
     147                 :       3181 :     free(node);
     148                 :       3181 : }
     149                 :            : 
     150                 :            : /* Searches for 'name' in 'simap'.  If found, deletes it and returns true.  If
     151                 :            :  * not found, returns false without modifying 'simap'. */
     152                 :            : bool
     153                 :         35 : simap_find_and_delete(struct simap *simap, const char *name)
     154                 :            : {
     155                 :         35 :     struct simap_node *node = simap_find(simap, name);
     156         [ +  - ]:         35 :     if (node) {
     157                 :         35 :         simap_delete(simap, node);
     158                 :         35 :         return true;
     159                 :            :     }
     160                 :          0 :     return false;
     161                 :            : }
     162                 :            : 
     163                 :            : /* Searches 'simap' for a mapping with the given 'name'.  Returns it, if found,
     164                 :            :  * or a null pointer if not. */
     165                 :            : struct simap_node *
     166                 :     456107 : simap_find(const struct simap *simap, const char *name)
     167                 :            : {
     168                 :     456107 :     return simap_find_len(simap, name, strlen(name));
     169                 :            : }
     170                 :            : 
     171                 :            : /* Searches 'simap' for a mapping whose name is the first 'name_len' bytes
     172                 :            :  * starting at 'name'.  Returns it, if found, or a null pointer if not. */
     173                 :            : struct simap_node *
     174                 :     456378 : simap_find_len(const struct simap *simap, const char *name, size_t len)
     175                 :            : {
     176                 :     456378 :     return simap_find__(simap, name, len, hash_name(name, len));
     177                 :            : }
     178                 :            : 
     179                 :            : /* Searches 'simap' for a mapping with the given 'name'.  Returns the
     180                 :            :  * associated data value, if found, otherwise zero. */
     181                 :            : unsigned int
     182                 :     337739 : simap_get(const struct simap *simap, const char *name)
     183                 :            : {
     184                 :     337739 :     struct simap_node *node = simap_find(simap, name);
     185         [ +  + ]:     337739 :     return node ? node->data : 0;
     186                 :            : }
     187                 :            : 
     188                 :            : /* Returns true if 'simap' contains a copy of 'name', false otherwise. */
     189                 :            : bool
     190                 :      66376 : simap_contains(const struct simap *simap, const char *name)
     191                 :            : {
     192                 :      66376 :     return simap_find(simap, name) != NULL;
     193                 :            : }
     194                 :            : 
     195                 :            : /* Returns an array that contains a pointer to each mapping in 'simap',
     196                 :            :  * ordered alphabetically by name.  The returned array has simap_count(simap)
     197                 :            :  * elements.
     198                 :            :  *
     199                 :            :  * The caller is responsible for freeing the returned array (with free()).  It
     200                 :            :  * should not free the individual "simap_node"s in the array, because they are
     201                 :            :  * still part of 'simap'. */
     202                 :            : const struct simap_node **
     203                 :        145 : simap_sort(const struct simap *simap)
     204                 :            : {
     205         [ +  + ]:        145 :     if (simap_is_empty(simap)) {
     206                 :          1 :         return NULL;
     207                 :            :     } else {
     208                 :            :         const struct simap_node **nodes;
     209                 :            :         struct simap_node *node;
     210                 :            :         size_t i, n;
     211                 :            : 
     212                 :        144 :         n = simap_count(simap);
     213                 :        144 :         nodes = xmalloc(n * sizeof *nodes);
     214                 :        144 :         i = 0;
     215 [ +  + ][ -  + ]:        754 :         SIMAP_FOR_EACH (node, simap) {
     216                 :        610 :             nodes[i++] = node;
     217                 :            :         }
     218         [ -  + ]:        144 :         ovs_assert(i == n);
     219                 :            : 
     220                 :        144 :         qsort(nodes, n, sizeof *nodes, compare_nodes_by_name);
     221                 :            : 
     222                 :        144 :         return nodes;
     223                 :            :     }
     224                 :            : }
     225                 :            : 
     226                 :            : static size_t
     227                 :     506434 : hash_name(const char *name, size_t length)
     228                 :            : {
     229                 :     506434 :     return hash_bytes(name, length, 0);
     230                 :            : }
     231                 :            : 
     232                 :            : static struct simap_node *
     233                 :     506434 : simap_find__(const struct simap *simap, const char *name, size_t name_len,
     234                 :            :              size_t hash)
     235                 :            : {
     236                 :            :     struct simap_node *node;
     237                 :            : 
     238 [ +  + ][ -  + ]:     506434 :     HMAP_FOR_EACH_WITH_HASH (node, node, hash, &simap->map) {
     239 [ +  - ][ +  - ]:     238066 :         if (!strncmp(node->name, name, name_len) && !node->name[name_len]) {
     240                 :     238066 :             return node;
     241                 :            :         }
     242                 :            :     }
     243                 :     268368 :     return NULL;
     244                 :            : }
     245                 :            : 
     246                 :            : static struct simap_node *
     247                 :      49509 : simap_add_nocopy__(struct simap *simap, char *name, unsigned int data,
     248                 :            :                    size_t hash)
     249                 :            : {
     250                 :      49509 :     struct simap_node *node = xmalloc(sizeof *node);
     251                 :      49509 :     node->name = name;
     252                 :      49509 :     node->data = data;
     253                 :      49509 :     hmap_insert(&simap->map, &node->node, hash);
     254                 :      49509 :     return node;
     255                 :            : }
     256                 :            : 
     257                 :            : static int
     258                 :        739 : compare_nodes_by_name(const void *a_, const void *b_)
     259                 :            : {
     260                 :        739 :     const struct simap_node *const *a = a_;
     261                 :        739 :     const struct simap_node *const *b = b_;
     262                 :        739 :     return strcmp((*a)->name, (*b)->name);
     263                 :            : }

Generated by: LCOV version 1.12