Fix crash when opening empty dataset
[pspp-builds.git] / src / libpspp / hmapx.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2008 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include <libpspp/hmapx.h>
22 #include <stdlib.h>
23 #include "xalloc.h"
24
25 /* Frees the memory, if any, allocated by hash map MAP, including
26    all hmapx_nodes that it contains.  The user-defined data items
27    that the hmapx_nodes point to are not affected.  If those
28    items should be freed, then it should be done by iterating
29    through MAP's contents before destroying MAP. */
30 void
31 hmapx_destroy (struct hmapx *map) 
32 {
33   if (map != NULL) 
34     {
35       if (hmapx_count (map) > 0) 
36         {
37           struct hmapx_node *node, *next;
38           for (node = hmapx_first (map); node != NULL; node = next)
39             {
40               next = hmapx_next (map, node);
41               free (node); 
42             }
43         }
44       hmap_destroy (&map->hmap);
45     }
46 }
47
48 /* Allocates and returns a new hmapx_node with DATA as its data
49    item. */
50 static struct hmapx_node *
51 make_hmapx_node (void *data) 
52 {
53   struct hmapx_node *node = xmalloc (sizeof *node);
54   node->data = data;
55   return node;
56 }
57
58 /* Inserts DATA into MAP with hash value HASH and returns the new
59    hmapx_node created to contain DATA.  If the insertion causes
60    MAP's current capacity, as reported by hmapx_capacity(), to be
61    exceeded, rehashes MAP with an increased number of hash
62    buckets.
63
64    This function runs in constant time amortized over all the
65    insertions into MAP.
66
67    This function does not verify that MAP does not already
68    contain a data item with the same value as DATA.  If
69    duplicates should be disallowed (which is the usual case),
70    then the client must check for duplicates itself before
71    inserting the new item. */
72 struct hmapx_node *
73 hmapx_insert (struct hmapx *map, void *data, size_t hash) 
74 {
75   struct hmapx_node *node = make_hmapx_node (data);
76   hmap_insert (&map->hmap, &node->hmap_node, hash);
77   return node;
78 }
79
80 /* Inserts DATA into MAP with hash value HASH and returns the new
81    hmapx_node created to contain DATA.  Does not check whether
82    this causes MAP's current capacity to be exceeded.  The caller
83    must take responsibility for that (or use hmapx_insert()
84    instead).
85
86    This function runs in constant time.
87
88    This function does not verify that MAP does not already
89    contain a data item with the same value as DATA.  If
90    duplicates should be disallowed (which is the usual case),
91    then the client must check for duplicates itself before
92    inserting the new node. */
93 struct hmapx_node *
94 hmapx_insert_fast (struct hmapx *map, void *data, size_t hash) 
95 {
96   struct hmapx_node *node = make_hmapx_node (data);
97   hmap_insert_fast (&map->hmap, &node->hmap_node, hash);
98   return node;
99 }