| 164 | } |
| 165 | |
| 166 | char *strset_del(struct strset *set, const char *member) |
| 167 | { |
| 168 | size_t len = strlen(member); |
| 169 | const u8 *bytes = (const u8 *)member; |
| 170 | struct strset *parent = NULL, *n; |
| 171 | const char *ret = NULL; |
| 172 | u8 direction = 0; /* prevent bogus gcc warning. */ |
| 173 | |
| 174 | /* Empty set? */ |
| 175 | if (!set->u.n) { |
| 176 | errno = ENOENT; |
| 177 | return NULL; |
| 178 | } |
| 179 | |
| 180 | /* Find closest, but keep track of parent. */ |
| 181 | n = set; |
| 182 | /* Anything with first byte 0 is a node. */ |
| 183 | while (!n->u.s[0]) { |
| 184 | u8 c = 0; |
| 185 | |
| 186 | /* Special node which represents the empty string. */ |
| 187 | if (unlikely(n->u.n->byte_num == (size_t)-1)) { |
| 188 | const char *empty_str = n->u.n->child[0].u.s; |
| 189 | |
| 190 | if (member[0]) { |
| 191 | errno = ENOENT; |
| 192 | return NULL; |
| 193 | } |
| 194 | |
| 195 | /* Sew empty string back so remaining logic works */ |
| 196 | free(n->u.n); |
| 197 | n->u.s = empty_str; |
| 198 | break; |
| 199 | } |
| 200 | |
| 201 | parent = n; |
| 202 | if (n->u.n->byte_num < len) { |
| 203 | c = bytes[n->u.n->byte_num]; |
| 204 | direction = (c >> n->u.n->bit_num) & 1; |
| 205 | } else |
| 206 | direction = 0; |
| 207 | n = &n->u.n->child[direction]; |
| 208 | } |
| 209 | |
| 210 | /* Did we find it? */ |
| 211 | if (!streq(member, n->u.s)) { |
| 212 | errno = ENOENT; |
| 213 | return NULL; |
| 214 | } |
| 215 | |
| 216 | ret = n->u.s; |
| 217 | |
| 218 | if (!parent) { |
| 219 | /* We deleted last node. */ |
| 220 | set->u.n = NULL; |
| 221 | } else { |
| 222 | struct node *old = parent->u.n; |
| 223 | /* Raise other node to parent. */ |