forked from ElementsProject/libwally-core
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathwordlist.c
105 lines (94 loc) · 2.66 KB
/
wordlist.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "internal.h"
#include "wordlist.h"
static int bstrcmp(const void *l, const void *r)
{
return strcmp(l, (*(const char **)r));
}
/* https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious */
static size_t get_bits(size_t n)
{
size_t bits = 0;
while (n >>= 1)
++bits;
return bits;
}
/* Allocate a new words structure */
static struct words *wordlist_alloc(const char *words, size_t len)
{
struct words *w = wally_malloc(sizeof(struct words));
if (w) {
wally_clear(w, sizeof(*w));
w->str = wally_strdup(words);
if (w->str) {
w->str_len = strlen(w->str);
w->len = len;
w->bits = get_bits(len);
w->indices = wally_malloc(len * sizeof(const char *));
if (w->indices)
return w;
}
wordlist_free(w);
}
return NULL;
}
static size_t wordlist_count(const char *words)
{
size_t len = 1u; /* Always 1 less separator than words, so start from 1 */
while (*words)
len += *words++ == ' '; /* FIXME: utf-8 sep */
return len;
}
struct words *wordlist_init(const char *words)
{
size_t i, len = wordlist_count(words);
struct words *w = wordlist_alloc(words, len);
if (w) {
/* Tokenise the strings into w->indices */
const char *p = w->str;
for (len = 0; len < w->len; ++len) {
w->indices[len] = p;
while (*p && *p != ' ') /* FIXME: utf-8 sep */
++p;
*((char *)p) = '\0';
++p;
}
w->sorted = true;
for (i = 1; i < len && w->sorted; ++i)
if (strcmp(w->indices[i - 1], w->indices[i]) > 0)
w->sorted = false;
}
return w;
}
size_t wordlist_lookup_word(const struct words *w, const char *word)
{
const size_t size = sizeof(const char *);
const char **found = NULL;
if (w->sorted)
found = (const char **)bsearch(word, w->indices, w->len, size, bstrcmp);
else {
size_t i;
for (i = 0; i < w->len && !found; ++i)
if (!strcmp(word, w->indices[i]))
found = w->indices + i;
}
return found ? found - w->indices + 1u : 0u;
}
const char *wordlist_lookup_index(const struct words *w, size_t idx)
{
if (idx >= w->len)
return NULL;
return w->indices[idx];
}
void wordlist_free(struct words *w)
{
if (w) {
if (w->str) {
if (w->str_len)
wally_clear((void *)w->str, w->str_len);
wally_free((void *)w->str);
}
if (w->indices)
wally_free((void *)w->indices); /* No need to clear */
clear_and_free(w, sizeof(*w));
}
}