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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#include "jdtalk.h"
struct Dictionary *dictionary_new() {
struct Dictionary *dict;
dict = malloc(1 * sizeof(*dict));
dict->words = malloc(DICT_INITIAL_SIZE * sizeof(**dict->words));
dict->nelem_alloc = DICT_INITIAL_SIZE;
dict->nelem_inuse = 0;
return dict;
}
void dictionary_append(struct Dictionary **dict, char *s, unsigned type) {
if ((*dict)->nelem_inuse + 1 > (*dict)->nelem_alloc) {
struct Word **tmp;
(*dict)->nelem_alloc += DICT_INITIAL_SIZE;
tmp = realloc((*dict)->words, (*dict)->nelem_alloc * sizeof((*dict)->words));
if (!tmp) {
perror("Unable to extend word list");
exit(1);
}
(*dict)->words = tmp;
}
(*dict)->words[(*dict)->nelem_inuse] = malloc(1 * sizeof(**(*dict)->words));
(*dict)->words[(*dict)->nelem_inuse]->word = strdup(s);
(*dict)->words[(*dict)->nelem_inuse]->nchar = strlen(s) - 1;
*((*dict)->words[(*dict)->nelem_inuse]->word + ((*dict)->words[(*dict)->nelem_inuse]->nchar)) = '\0';
(*dict)->words[(*dict)->nelem_inuse]->type = type;
(*dict)->nelem_inuse++;
}
int dictionary_read(FILE *fp, struct Dictionary **dict, unsigned type) {
char *buf;
buf = malloc(DICT_WORD_SIZE_MAX * sizeof(char));
while ((fgets(buf, DICT_WORD_SIZE_MAX - 1, fp) != NULL)) {
if (errno) {
return errno;
}
if (*buf == '\0' || *buf == '\n')
continue;
dictionary_append(&(*dict), buf, type);
}
free(buf);
return 0;
}
struct Dictionary *dictionary_populate() {
FILE *fp;
struct Dictionary *dict;
const char *files[] = {
"nouns.txt",
"adjectives.txt",
"adverbs.txt",
"verbs.txt",
NULL,
};
const unsigned files_type[] = {
WT_NOUN,
WT_ADJECTIVE,
WT_ADVERB,
WT_VERB,
};
dict = dictionary_new();
for (size_t i = 0; files[i] != NULL; i++) {
char *datadir;
char filename[PATH_MAX];
filename[0] = '\0';
datadir = getenv("JDTALK_DATA");
if (!datadir) {
fprintf(stderr, "JDTALK_DATA environment variable is not set\n");
exit(1);
}
sprintf(filename, "%s/%s", datadir, files[i]);
fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "Unable to open dictionary: %s", filename);
exit(1);
}
dictionary_read(fp, &dict, files_type[i]);
fclose(fp);
}
return dict;
}
int dictionary_contains(struct Dictionary *dict, const char *s, unsigned type) {
int result;
unsigned icase;
icase = type & WT_ICASE;
type &= 0x7f;
result = 0;
for (size_t i = 0; i < dict->nelem_inuse; i++) {
if (*s != *dict->words[i]->word) {
// Didn't start with first character in s
continue;
}
if (type != WT_ANY && dict->words[i]->type != type) {
// Incorrect type of word
continue;
}
if (icase) {
result = strcasecmp(dict->words[i]->word, s) == 0;
} else {
result = strcmp(dict->words[i]->word, s) == 0;
}
if (result) {
break;
}
}
return result;
}
char *dictionary_word(struct Dictionary *dict, unsigned type) {
struct Word *word;
while (1) {
size_t index = random() % dict->nelem_inuse;
word = dict->words[index];
if (word->type == type || type == WT_ANY) {
return word->word;
}
}
}
void dictionary_free(struct Dictionary *dict) {
for (size_t i = 0; i < dict->nelem_inuse; i++) {
free(dict->words[i]->word);
free(dict->words[i]);
}
free(dict->words);
free(dict);
}
|