free bugs [fixed]
[coupserv.git] / table.c
blobf23471736c86c5427f888d0fff922600511cb349
1 // My table library thing
2 //
3 // Written by: Test_User <hax@andrewyu.org>
4 //
5 // This is free and unencumbered software released into the public
6 // domain.
7 //
8 // Anyone is free to copy, modify, publish, use, compile, sell, or
9 // distribute this software, either in source code form or as a compiled
10 // binary, for any purpose, commercial or non-commercial, and by any
11 // means.
13 // In jurisdictions that recognize copyright laws, the author or authors
14 // of this software dedicate any and all copyright interest in the
15 // software to the public domain. We make this dedication for the benefit
16 // of the public at large and to the detriment of our heirs and
17 // successors. We intend this dedication to be an overt act of
18 // relinquishment in perpetuity of all present and future rights to this
19 // software under copyright law.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 // OTHER DEALINGS IN THE SOFTWARE.
29 #include <string.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <stdint.h>
35 #include "types.h"
36 #include "table.h"
38 // currently going with a binary lookup...
40 static inline int compare(struct string a, struct string b) {
41 size_t len;
42 if (a.len > b.len)
43 len = b.len;
44 else
45 len = a.len;
47 int val = memcmp(a.data, b.data, len);
49 if (val == 0) {
50 if (a.len < b.len)
51 return 1;
52 else if (a.len > b.len)
53 return -1;
56 return val;
59 static inline uint64_t search(struct table tbl, struct string name, uint8_t *exists) {
60 if (tbl.len == 0) {
61 *exists = 0;
62 return 0;
65 size_t low = 0, high = tbl.len - 1;
67 size_t mid = high/2;
69 while (low != high) {
70 int val = compare(tbl.array[mid].name, name);
72 if (val == 0) {
73 *exists = 1;
74 return mid;
75 } else if (val > 0) {
76 low = mid + 1;
77 if (mid > low)
78 break;
79 if (low > high)
80 low = high;
81 } else {
82 high = mid - 1;
83 if (mid < high)
84 break;
85 if (high < low)
86 high = low;
89 mid = low + ((high-low)/2);
92 int val = compare(tbl.array[mid].name, name);
93 if (val > 0) {
94 *exists = 0;
95 return mid+1;
96 } else if (val == 0) {
97 *exists = 1;
98 return mid;
99 } else {
100 *exists = 0;
101 return mid;
105 int set_table_index(struct table *tbl, struct string name, void *ptr) {
106 uint8_t exists;
107 uint64_t index = search(*tbl, name, &exists);
109 if (index == tbl->len) {
110 void *tmp = realloc(tbl->array, sizeof(*(tbl->array)) * (tbl->len+1));
111 if (tmp == 0)
112 return 1;
114 tbl->array = tmp;
116 tbl->len++;
117 } else if (!exists) {
118 void *tmp = realloc(tbl->array, sizeof(*(tbl->array)) * (tbl->len+1));
119 if (tmp == 0)
120 return 1;
122 tbl->array = tmp;
124 memmove(&(tbl->array[index+1]), &(tbl->array[index]), (tbl->len - index) * sizeof(*(tbl->array)));
125 tbl->len++;
126 } else {
127 tbl->array[index].ptr = ptr;
129 return 0; // don't overwrite old allocated name
132 char *data = malloc(name.len);
133 if (data == 0)
134 return 1;
136 memcpy(data, name.data, name.len);
138 tbl->array[index] = (struct table_index){{data, name.len}, ptr};
140 return 0;
143 void * get_table_index(struct table tbl, struct string name) {
144 uint8_t exists;
145 uint64_t index = search(tbl, name, &exists);
146 if (!exists)
147 return 0;
149 return tbl.array[index].ptr;
152 uint8_t has_table_index(struct table tbl, struct string name) {
153 uint8_t exists;
154 search(tbl, name, &exists);
155 return exists;
158 void * remove_table_index(struct table *tbl, struct string name) {
159 uint8_t exists;
160 uint64_t index = search(*tbl, name, &exists);
162 if (!exists)
163 return 0;
165 void *ptr = tbl->array[index].ptr;
166 free(tbl->array[index].name.data);
168 memmove(&(tbl->array[index]), &(tbl->array[index+1]), (tbl->len - index - 1) * sizeof(*(tbl->array)));
169 tbl->len--;
171 void *tmp = realloc(tbl->array, sizeof(*(tbl->array)) * tbl->len);
172 if (tmp || (tbl->len == 0))
173 tbl->array = tmp;
174 // else: realloc failed on shrinking... so now we have a table that's allocated a bit too big, not much of an issue
176 return ptr;
179 void clear_table(struct table *tbl) {
180 for (uint64_t i = 0; i < tbl->len; i++)
181 free(tbl->array[i].name.data);
183 tbl->array = realloc(tbl->array, 0);
184 tbl->len = 0;