chinwag 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +35 -0
- data/ext/chinwag/chinwag.c +246 -0
- data/ext/chinwag/chinwag.h +71 -0
- data/ext/chinwag/config.c +28 -0
- data/ext/chinwag/config.h +42 -0
- data/ext/chinwag/dict.c +670 -0
- data/ext/chinwag/dict.h +50 -0
- data/ext/chinwag/extconf.rb +11 -0
- data/ext/chinwag/generator.c +541 -0
- data/ext/chinwag/generator.h +25 -0
- data/ext/chinwag/ingredient.h +69 -0
- data/ext/chinwag/latin.c +4 -0
- data/ext/chinwag/latin.h +9 -0
- data/ext/chinwag/rb_chinwag_ext.c +792 -0
- data/ext/chinwag/rb_chinwag_ext.h +23 -0
- data/ext/chinwag/seuss.c +4 -0
- data/ext/chinwag/seuss.h +9 -0
- data/ext/chinwag/tokenize.c +53 -0
- data/ext/chinwag/tokenize.h +9 -0
- data/ext/chinwag/utility.c +143 -0
- data/ext/chinwag/utility.h +20 -0
- data/lib/chinwag.rb +5 -0
- metadata +70 -0
data/ext/chinwag/dict.c
ADDED
@@ -0,0 +1,670 @@
|
|
1
|
+
#include "dict.h"
|
2
|
+
|
3
|
+
drow_t open_drow()
|
4
|
+
{
|
5
|
+
drow_t d;
|
6
|
+
|
7
|
+
// set default values
|
8
|
+
d.sorted = false;
|
9
|
+
d.count = 0;
|
10
|
+
d.largest = 0;
|
11
|
+
d.largest_pos = 0;
|
12
|
+
d.words = NULL;
|
13
|
+
|
14
|
+
return d;
|
15
|
+
}
|
16
|
+
|
17
|
+
drow_t add_word_to_drow(drow_t drow, const char* word)
|
18
|
+
{
|
19
|
+
// cache strlen of word
|
20
|
+
U32 len = strlen(word);
|
21
|
+
|
22
|
+
if(len > 0)
|
23
|
+
{
|
24
|
+
// increment word count
|
25
|
+
++drow.count;
|
26
|
+
|
27
|
+
// increase dictionary size
|
28
|
+
drow.words = (char**)realloc(drow.words, sizeof(char*) * drow.count);
|
29
|
+
|
30
|
+
// add space for new word at added location; copy word
|
31
|
+
drow.words[drow.count - 1] = (char*)malloc(len + 1);
|
32
|
+
strcpy(drow.words[drow.count - 1], word);
|
33
|
+
drow.words[drow.count - 1][len] = '\0';
|
34
|
+
|
35
|
+
// set new largest (if applicable)
|
36
|
+
if(drow.largest < len)
|
37
|
+
{
|
38
|
+
drow.largest = len;
|
39
|
+
drow.largest_pos = drow.count - 1;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
return drow;
|
44
|
+
}
|
45
|
+
|
46
|
+
drow_t add_word_to_drow_limit(drow_t drow, const char* word, U32 size)
|
47
|
+
{
|
48
|
+
if(strlen(word) == size) drow = add_word_to_drow(drow, word);
|
49
|
+
return drow;
|
50
|
+
}
|
51
|
+
|
52
|
+
drow_t bubble_drow(drow_t drow)
|
53
|
+
{
|
54
|
+
for(U32 i = 0; i != drow.count - 1; ++i)
|
55
|
+
{
|
56
|
+
if(drow_word_blank(drow, i) && drow_word_present(drow, i + 1))
|
57
|
+
{
|
58
|
+
// bubble next one into current one
|
59
|
+
U32 len = strlen(drow.words[i + 1]);
|
60
|
+
|
61
|
+
// fprintf(stdout, "drow.words[i] : %s\n", drow.words[i]);
|
62
|
+
if(drow.words[i] != NULL) free(drow.words[i]);
|
63
|
+
drow.words[i] = (char*)malloc(len + 1);
|
64
|
+
strcpy(drow.words[i], drow.words[i + 1]);
|
65
|
+
drow.words[i][len] = '\0';
|
66
|
+
|
67
|
+
// clear next one that we just copied
|
68
|
+
free(drow.words[i + 1]);
|
69
|
+
drow.words[i + 1] = NULL;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
drow.sorted = true;
|
74
|
+
|
75
|
+
return drow;
|
76
|
+
}
|
77
|
+
|
78
|
+
bool drow_word_blank(drow_t drow, U32 i)
|
79
|
+
{
|
80
|
+
if(drow.words[i] == NULL || strlen(drow.words[i]) < 1)
|
81
|
+
{
|
82
|
+
return true;
|
83
|
+
}
|
84
|
+
|
85
|
+
return false;
|
86
|
+
}
|
87
|
+
|
88
|
+
bool drow_word_present(drow_t drow, U32 i)
|
89
|
+
{
|
90
|
+
if(drow.words[i] != NULL && strlen(drow.words[i]) > 0)
|
91
|
+
{
|
92
|
+
return true;
|
93
|
+
}
|
94
|
+
|
95
|
+
return false;
|
96
|
+
}
|
97
|
+
|
98
|
+
bool drow_exclude(drow_t drow, char const* str)
|
99
|
+
{
|
100
|
+
for(U32 i = 0; i != drow.count; ++i)
|
101
|
+
{
|
102
|
+
if(strcmp(drow.words[i], str) == 0) return false;
|
103
|
+
}
|
104
|
+
|
105
|
+
return true;
|
106
|
+
}
|
107
|
+
|
108
|
+
bool drow_include(drow_t drow, char const* str)
|
109
|
+
{
|
110
|
+
for(U32 i = 0; i != drow.count; ++i)
|
111
|
+
{
|
112
|
+
if(strcmp(drow.words[i], str) == 0) return true;
|
113
|
+
}
|
114
|
+
|
115
|
+
return false;
|
116
|
+
}
|
117
|
+
|
118
|
+
char* sample_drow(drow_t drow)
|
119
|
+
{
|
120
|
+
// immediately fail if empty
|
121
|
+
if(drow.count == 0) return NULL;
|
122
|
+
|
123
|
+
U32 max = (drow.count == 1 ? 0 : drow.count - 1);
|
124
|
+
U32 internal = (max == 0 ? 0 : motherr(0, max));
|
125
|
+
|
126
|
+
return drow.words[internal];
|
127
|
+
}
|
128
|
+
|
129
|
+
void puts_drow(drow_t drow)
|
130
|
+
{
|
131
|
+
#ifdef DEBUG
|
132
|
+
fprintf(stdout, "(%d)", drow.count);
|
133
|
+
#endif
|
134
|
+
|
135
|
+
fprintf(stdout, "[");
|
136
|
+
|
137
|
+
for(U32 i = 0; i != drow.count; ++i)
|
138
|
+
{
|
139
|
+
fprintf(stdout, "\"%s\"", drow.words[i]);
|
140
|
+
if(i < drow.count - 1) fprintf(stdout, ",");
|
141
|
+
}
|
142
|
+
|
143
|
+
fprintf(stdout, "]");
|
144
|
+
}
|
145
|
+
|
146
|
+
void close_drow(drow_t drow)
|
147
|
+
{
|
148
|
+
for(U32 i = 0; i != drow.count; ++i)
|
149
|
+
{
|
150
|
+
if(drow.words[i]) free(drow.words[i]);
|
151
|
+
}
|
152
|
+
|
153
|
+
if(drow.words) free(drow.words);
|
154
|
+
}
|
155
|
+
|
156
|
+
dict_t open_dict()
|
157
|
+
{
|
158
|
+
dict_t d;
|
159
|
+
|
160
|
+
// set default values
|
161
|
+
d.sorted = false;
|
162
|
+
d.count = 0;
|
163
|
+
d.drows = NULL;
|
164
|
+
d.name = NULL;
|
165
|
+
|
166
|
+
return d;
|
167
|
+
}
|
168
|
+
|
169
|
+
dict_t open_dict_with_name(const char* name)
|
170
|
+
{
|
171
|
+
dict_t d;
|
172
|
+
|
173
|
+
// set default values
|
174
|
+
d.sorted = false;
|
175
|
+
d.count = 0;
|
176
|
+
d.drows = NULL;
|
177
|
+
d.name = NULL;
|
178
|
+
|
179
|
+
d.name = (char*)malloc((strlen(name) + 1) * sizeof(char));
|
180
|
+
strcpy(d.name, name);
|
181
|
+
|
182
|
+
return d;
|
183
|
+
}
|
184
|
+
|
185
|
+
dict_t open_dict_with_tokens(const char* const buffer, const char* delimiters)
|
186
|
+
{
|
187
|
+
dict_t d = tokenize(buffer, delimiters);
|
188
|
+
d.name = NULL;
|
189
|
+
|
190
|
+
return d;
|
191
|
+
}
|
192
|
+
|
193
|
+
dict_t open_dict_with_name_and_tokens(const char* name, const char* const buffer, const char* delimiters)
|
194
|
+
{
|
195
|
+
dict_t d = tokenize(buffer, delimiters);
|
196
|
+
d.name = NULL;
|
197
|
+
|
198
|
+
d.name = (char*)malloc((strlen(name) + 1) * sizeof(char));
|
199
|
+
strcpy(d.name, name);
|
200
|
+
|
201
|
+
return d;
|
202
|
+
}
|
203
|
+
|
204
|
+
dict_t add_drow_to_dict(dict_t dict, drow_t drow)
|
205
|
+
{
|
206
|
+
++dict.count;
|
207
|
+
|
208
|
+
dict.drows = (drow_t*)realloc(dict.drows, sizeof(drow_t) * dict.count);
|
209
|
+
dict.drows[dict.count - 1] = drow;
|
210
|
+
|
211
|
+
return dict;
|
212
|
+
}
|
213
|
+
|
214
|
+
dict_t add_drow_to_dict_strict(dict_t dict, drow_t drow, U32 size)
|
215
|
+
{
|
216
|
+
if(drow.count >= size) dict = add_drow_to_dict(dict, drow);
|
217
|
+
return dict;
|
218
|
+
}
|
219
|
+
|
220
|
+
|
221
|
+
dict_t place_word_in_dict(dict_t dict, const char* word)
|
222
|
+
{
|
223
|
+
drow_t drow = open_drow();
|
224
|
+
|
225
|
+
drow = add_word_to_drow(drow, word);
|
226
|
+
dict = add_drow_to_dict(dict, drow);
|
227
|
+
|
228
|
+
return dict;
|
229
|
+
}
|
230
|
+
|
231
|
+
dict_t place_words_in_dict(dict_t dict, const char* const* words, U32 s)
|
232
|
+
{
|
233
|
+
for(U32 i = 0; i != s; ++i)
|
234
|
+
{
|
235
|
+
dict = place_word_in_dict(dict, words[i]);
|
236
|
+
}
|
237
|
+
|
238
|
+
return dict;
|
239
|
+
}
|
240
|
+
|
241
|
+
dict_t place_word_in_dict_strict(dict_t dict, const char* word)
|
242
|
+
{
|
243
|
+
bool inserted = false;
|
244
|
+
U32 len = strlen(word);
|
245
|
+
|
246
|
+
for(U32 i = 0; i != dict.count; ++i)
|
247
|
+
{
|
248
|
+
if(dict.drows[i].largest == len)
|
249
|
+
{
|
250
|
+
dict.drows[i] = add_word_to_drow(dict.drows[i], word);
|
251
|
+
inserted = true;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
if(inserted == false) dict = place_word_in_dict(dict, word);
|
256
|
+
|
257
|
+
return dict;
|
258
|
+
}
|
259
|
+
|
260
|
+
dict_t place_words_in_dict_strict(dict_t dict, const char* const* words,
|
261
|
+
U32 s)
|
262
|
+
{
|
263
|
+
for(U32 i = 0; i != s; ++i)
|
264
|
+
{
|
265
|
+
dict = place_word_in_dict_strict(dict, words[i]);
|
266
|
+
}
|
267
|
+
|
268
|
+
return dict;
|
269
|
+
}
|
270
|
+
|
271
|
+
dict_t bubble_dict(dict_t dict)
|
272
|
+
{
|
273
|
+
drow_t temp;
|
274
|
+
|
275
|
+
// sort individual drows' contents
|
276
|
+
for(U32 i = 0; i != dict.count; ++i)
|
277
|
+
{
|
278
|
+
dict.drows[i] = bubble_drow(dict.drows[i]);
|
279
|
+
}
|
280
|
+
|
281
|
+
// sort individual drows within dict
|
282
|
+
for(U32 i = 0; i != dict.count - 1; ++i)
|
283
|
+
{
|
284
|
+
for(U32 j = 0; j != dict.count - 1; ++j)
|
285
|
+
{
|
286
|
+
if(dict.drows[j].largest > dict.drows[j + 1].largest)
|
287
|
+
{
|
288
|
+
temp = dict.drows[j];
|
289
|
+
dict.drows[j] = dict.drows[j + 1];
|
290
|
+
dict.drows[j + 1] = temp;
|
291
|
+
}
|
292
|
+
}
|
293
|
+
}
|
294
|
+
|
295
|
+
dict.sorted = true;
|
296
|
+
|
297
|
+
return dict;
|
298
|
+
}
|
299
|
+
|
300
|
+
dict_t prune_dict(dict_t dict, bool sorted)
|
301
|
+
{
|
302
|
+
U32 len = 0, size = 0, null_count = 0;
|
303
|
+
char* against = NULL;
|
304
|
+
|
305
|
+
for(U32 i = 0; i != dict.count; ++i)
|
306
|
+
{
|
307
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
308
|
+
{
|
309
|
+
if(dict.drows[i].words[j] == NULL) continue;
|
310
|
+
against = dict.drows[i].words[j];
|
311
|
+
|
312
|
+
for(U32 k = 0; k != dict.drows[i].count; ++k)
|
313
|
+
{
|
314
|
+
if(dict.drows[i].words[k] == NULL) continue;
|
315
|
+
if(strcmp(against, dict.drows[i].words[k]) == 0 && k != j)
|
316
|
+
{
|
317
|
+
free(dict.drows[i].words[k]);
|
318
|
+
dict.drows[i].words[k] = NULL;
|
319
|
+
}
|
320
|
+
}
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
// sort drows within dict
|
325
|
+
if(sorted) dict = bubble_dict(dict);
|
326
|
+
|
327
|
+
// resize individual drows within dict
|
328
|
+
for(U32 i = 0; i != dict.count; ++i)
|
329
|
+
{
|
330
|
+
null_count = 0;
|
331
|
+
|
332
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
333
|
+
{
|
334
|
+
if(dict.drows[i].words[j] == NULL) ++null_count;
|
335
|
+
}
|
336
|
+
|
337
|
+
if(null_count > 0)
|
338
|
+
{
|
339
|
+
len = dict.drows[i].count - null_count;
|
340
|
+
size = sizeof(char*) * len;
|
341
|
+
|
342
|
+
dict.drows[i].words = (char**)realloc(dict.drows[i].words, size);
|
343
|
+
dict.drows[i].count = len;
|
344
|
+
}
|
345
|
+
}
|
346
|
+
|
347
|
+
if(dict_any_blanks(dict)) dict = prune_dict(dict, sorted);
|
348
|
+
|
349
|
+
return dict;
|
350
|
+
}
|
351
|
+
|
352
|
+
dict_t map_dict(dict_t dict, char* (*f)(char*))
|
353
|
+
{
|
354
|
+
U32 len = 0;
|
355
|
+
char* temp = (char*)malloc(sizeof(char) * SMALL_BUFFER);
|
356
|
+
|
357
|
+
for(U32 i = 0; i != dict.count; ++i)
|
358
|
+
{
|
359
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
360
|
+
{
|
361
|
+
strcpy(temp, (*f)(dict.drows[i].words[j]));
|
362
|
+
len = strlen(temp);
|
363
|
+
|
364
|
+
// only resize if necessary
|
365
|
+
if(len != strlen(dict.drows[i].words[j]))
|
366
|
+
{
|
367
|
+
dict.drows[i].words[j]=(char*)realloc(dict.drows[i].words[j], len);
|
368
|
+
}
|
369
|
+
|
370
|
+
strcpy(dict.drows[i].words[j], temp);
|
371
|
+
}
|
372
|
+
}
|
373
|
+
|
374
|
+
free(temp);
|
375
|
+
|
376
|
+
return dict;
|
377
|
+
}
|
378
|
+
|
379
|
+
dict_t deep_copy_dict(dict_t dict)
|
380
|
+
{
|
381
|
+
dict_t new;
|
382
|
+
|
383
|
+
if(dict.name) new = open_dict_with_name(dict.name);
|
384
|
+
else new = open_dict();
|
385
|
+
|
386
|
+
for(U32 i = 0; i != dict.count; ++i)
|
387
|
+
{
|
388
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
389
|
+
{
|
390
|
+
new = place_word_in_dict_strict(new, dict.drows[i].words[j]);
|
391
|
+
}
|
392
|
+
}
|
393
|
+
|
394
|
+
if(dict.name)
|
395
|
+
{
|
396
|
+
new.name = (char*)malloc(strlen(dict.name) + 1);
|
397
|
+
strcpy(new.name, dict.name);
|
398
|
+
new.name[strlen(dict.name)] = '\0';
|
399
|
+
}
|
400
|
+
|
401
|
+
if(dict.sorted) new = bubble_dict(new);
|
402
|
+
|
403
|
+
return new;
|
404
|
+
}
|
405
|
+
|
406
|
+
bool dict_exclude(dict_t dict, char const* str)
|
407
|
+
{
|
408
|
+
for(U32 i = 0; i != dict.count; ++i)
|
409
|
+
{
|
410
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
411
|
+
{
|
412
|
+
if(strcmp(dict.drows[i].words[j], str) == 0) return false;
|
413
|
+
}
|
414
|
+
}
|
415
|
+
|
416
|
+
return true;
|
417
|
+
}
|
418
|
+
|
419
|
+
bool dict_include(dict_t dict, char const* str)
|
420
|
+
{
|
421
|
+
for(U32 i = 0; i != dict.count; ++i)
|
422
|
+
{
|
423
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
424
|
+
{
|
425
|
+
if(strcmp(dict.drows[i].words[j], str) == 0) return true;
|
426
|
+
}
|
427
|
+
}
|
428
|
+
|
429
|
+
return false;
|
430
|
+
}
|
431
|
+
|
432
|
+
bool dict_any_blanks(dict_t dict)
|
433
|
+
{
|
434
|
+
for(U32 i = 0; i != dict.count; ++i)
|
435
|
+
{
|
436
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
437
|
+
{
|
438
|
+
if(drow_word_blank(dict.drows[i], j)) return true;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
return false;
|
443
|
+
}
|
444
|
+
|
445
|
+
bool dict_valid(dict_t dict, char** error)
|
446
|
+
{
|
447
|
+
U32 count = 0;
|
448
|
+
|
449
|
+
for(U32 i = 0; i != dict.count; ++i)
|
450
|
+
{
|
451
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
452
|
+
{
|
453
|
+
// valid if word excludes a space
|
454
|
+
if(exclude(dict.drows[i].words[j], " ")) ++count;
|
455
|
+
}
|
456
|
+
}
|
457
|
+
|
458
|
+
if(count < MIN_DICT_SIZE)
|
459
|
+
{
|
460
|
+
*error = (char*)malloc(SMALL_BUFFER);
|
461
|
+
sprintf(*error, "too few acceptable entries (%d of %d)",count,
|
462
|
+
MIN_DICT_SIZE);
|
463
|
+
|
464
|
+
return false;
|
465
|
+
}
|
466
|
+
|
467
|
+
if(dict.sorted == false)
|
468
|
+
{
|
469
|
+
*error = (char*)malloc(SMALL_BUFFER);
|
470
|
+
sprintf(*error, "dictionary couldn't be sorted");
|
471
|
+
|
472
|
+
return false;
|
473
|
+
}
|
474
|
+
|
475
|
+
return true;
|
476
|
+
}
|
477
|
+
|
478
|
+
I32 find_drow_of_size_in_dict(dict_t dict, U32 largest)
|
479
|
+
{
|
480
|
+
// sort dict if necessary
|
481
|
+
if(dict.sorted == false) dict = prune_dict(dict, true);
|
482
|
+
|
483
|
+
for(U32 i = 0; i != dict.count; ++i)
|
484
|
+
{
|
485
|
+
if(dict.drows[i].count == largest) return i;
|
486
|
+
}
|
487
|
+
|
488
|
+
return -1;
|
489
|
+
}
|
490
|
+
|
491
|
+
U32 total_dict(dict_t dict)
|
492
|
+
{
|
493
|
+
U32 total = 0;
|
494
|
+
|
495
|
+
for(U32 i = 0; i != dict.count; ++i) total += dict.drows[i].count;
|
496
|
+
|
497
|
+
return total;
|
498
|
+
}
|
499
|
+
|
500
|
+
U32 dict_largest(dict_t dict)
|
501
|
+
{
|
502
|
+
U32 largest = 0;
|
503
|
+
|
504
|
+
for(U32 i = 0; i != dict.count; ++i)
|
505
|
+
{
|
506
|
+
if(i == 0) largest = dict.drows[i].largest;
|
507
|
+
else if(dict.drows[i].largest > largest) largest=dict.drows[i].largest;
|
508
|
+
}
|
509
|
+
|
510
|
+
return largest;
|
511
|
+
}
|
512
|
+
|
513
|
+
char* sample_dict(dict_t dict)
|
514
|
+
{
|
515
|
+
// immediately fail if empty
|
516
|
+
if(dict.count == 0) return NULL;
|
517
|
+
|
518
|
+
U32 max = (dict.count == 1 ? 0 : dict.count - 1);
|
519
|
+
U32 external = (max == 0 ? 0 : motherr(0, max));
|
520
|
+
|
521
|
+
return sample_drow(dict.drows[external]);
|
522
|
+
}
|
523
|
+
|
524
|
+
char* join_dict(dict_t dict, char const* delimiter)
|
525
|
+
{
|
526
|
+
U32 len = 0, del_len = strlen(delimiter);
|
527
|
+
char* string = NULL; char* temp = NULL;
|
528
|
+
|
529
|
+
for(U32 i = 0; i != dict.count; ++i)
|
530
|
+
{
|
531
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
532
|
+
{
|
533
|
+
if(dict.drows[i].words[j] == NULL) continue;
|
534
|
+
else if(string) len = strlen(string) + strlen(dict.drows[i].words[j]);
|
535
|
+
else len = strlen(dict.drows[i].words[j]);
|
536
|
+
|
537
|
+
if(i <= dict.count - 1 && j <= dict.drows[i].count - 1)
|
538
|
+
{ len += del_len; }
|
539
|
+
|
540
|
+
temp = (char*)malloc(len + 1);
|
541
|
+
|
542
|
+
if(string)
|
543
|
+
{
|
544
|
+
strcpy(temp, string);
|
545
|
+
strcat(temp, dict.drows[i].words[j]);
|
546
|
+
}
|
547
|
+
else strcpy(temp, dict.drows[i].words[j]);
|
548
|
+
|
549
|
+
if(i < dict.count - 1 && j <= dict.drows[i].count - 1)
|
550
|
+
{ strcat(temp, delimiter); }
|
551
|
+
|
552
|
+
temp[len] = '\0';
|
553
|
+
|
554
|
+
if(string) free(string);
|
555
|
+
string = temp; temp = NULL;
|
556
|
+
}
|
557
|
+
}
|
558
|
+
|
559
|
+
return string;
|
560
|
+
}
|
561
|
+
|
562
|
+
void puts_dict(dict_t dict)
|
563
|
+
{
|
564
|
+
fprintf(stdout, "[");
|
565
|
+
|
566
|
+
for(U32 i = 0; i != dict.count; ++i)
|
567
|
+
{
|
568
|
+
puts_drow(dict.drows[i]);
|
569
|
+
|
570
|
+
if(i < dict.count - 1) fprintf(stdout, ",");
|
571
|
+
|
572
|
+
#ifdef SPLIT
|
573
|
+
if(i < dict.count - 1) fprintf(stdout, "\n");
|
574
|
+
#endif
|
575
|
+
}
|
576
|
+
|
577
|
+
fprintf(stdout, "]");
|
578
|
+
}
|
579
|
+
|
580
|
+
dict_t close_dict(dict_t dict)
|
581
|
+
{
|
582
|
+
for(U32 i = 0; i != dict.count; ++i) close_drow(dict.drows[i]);
|
583
|
+
if(dict.drows) { free(dict.drows); dict.drows = NULL; }
|
584
|
+
|
585
|
+
dict.count = 0;
|
586
|
+
if(dict.name) { free(dict.name); dict.name = NULL; }
|
587
|
+
|
588
|
+
return open_dict();
|
589
|
+
}
|
590
|
+
|
591
|
+
void validate_dict(dict_t dict, char const* function_name)
|
592
|
+
{
|
593
|
+
U32 count = 0;
|
594
|
+
|
595
|
+
for(U32 i = 0; i != dict.count; ++i)
|
596
|
+
{
|
597
|
+
for(U32 j = 0; j != dict.drows[i].count; ++j)
|
598
|
+
{
|
599
|
+
// valide if word excludes a space
|
600
|
+
if(exclude(dict.drows[i].words[j], " ")) ++count;
|
601
|
+
}
|
602
|
+
}
|
603
|
+
|
604
|
+
if(count < MIN_DICT_SIZE)
|
605
|
+
{
|
606
|
+
char e[] =
|
607
|
+
"Error in function \"%s\" :\n"
|
608
|
+
" valid dictionary (%d) entry count must be greater than %d\n";
|
609
|
+
fprintf(stderr, e, function_name, count, MIN_DICT_SIZE);
|
610
|
+
exit(EXIT_FAILURE);
|
611
|
+
}
|
612
|
+
|
613
|
+
if(dict.sorted == false)
|
614
|
+
{
|
615
|
+
char e[] =
|
616
|
+
"Error in function \"%s\" :\n"
|
617
|
+
" dictionary is not valid, as it couldn't be properly sorted\n";
|
618
|
+
fprintf(stderr, e, function_name);
|
619
|
+
exit(EXIT_FAILURE);
|
620
|
+
}
|
621
|
+
}
|
622
|
+
|
623
|
+
dict_t split(const char* buffer, const char* delimiters)
|
624
|
+
{
|
625
|
+
char* tok;
|
626
|
+
char* mutable_buffer = (char*)malloc(strlen(buffer) + 1 * sizeof(char));
|
627
|
+
dict_t dict = open_dict();
|
628
|
+
|
629
|
+
// get mutable copy of buffer; a bit slower, but allows for const-ness
|
630
|
+
strcpy(mutable_buffer, buffer);
|
631
|
+
mutable_buffer[strlen(buffer)] = '\0';
|
632
|
+
|
633
|
+
// natively tokenize input string
|
634
|
+
tok = strtok(mutable_buffer, delimiters);
|
635
|
+
while(tok != NULL)
|
636
|
+
{
|
637
|
+
// add word to dict
|
638
|
+
dict = place_word_in_dict(dict, tok);
|
639
|
+
|
640
|
+
// get new tok (if any)
|
641
|
+
tok = strtok(NULL, delimiters);
|
642
|
+
}
|
643
|
+
|
644
|
+
// close mutable buffer
|
645
|
+
free(mutable_buffer);
|
646
|
+
|
647
|
+
return dict;
|
648
|
+
}
|
649
|
+
|
650
|
+
#ifdef DICTMAIN
|
651
|
+
int main(int argc, const char *argv[])
|
652
|
+
{
|
653
|
+
dict_t dict = open_dict();
|
654
|
+
// const char * const words[]= { "the", "quick", "brown", "fox", "jumps",
|
655
|
+
// "over", "the", "lazy", "dog", "dawg" };
|
656
|
+
|
657
|
+
dict = place_words_in_dict_strict(dict, argv, argc);
|
658
|
+
dict = prune_dict(dict, true);
|
659
|
+
|
660
|
+
#ifdef DEBUG
|
661
|
+
fprintf(stdout, "dict.count : %d\n", dict.count);
|
662
|
+
#endif
|
663
|
+
|
664
|
+
puts_dict(dict); fprintf(stdout, "\n");
|
665
|
+
|
666
|
+
close_dict(dict);
|
667
|
+
|
668
|
+
return 0;
|
669
|
+
}
|
670
|
+
#endif
|
data/ext/chinwag/dict.h
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#ifndef __DICT_CO6CSUAJ_H
|
2
|
+
#define __DICT_CO6CSUAJ_H
|
3
|
+
|
4
|
+
#include "chinwag.h"
|
5
|
+
|
6
|
+
// dictionary row utilities
|
7
|
+
drow_t open_drow();
|
8
|
+
drow_t add_word_to_drow(drow_t drow, const char* word);
|
9
|
+
drow_t add_word_to_drow_limit(drow_t drow, const char* word, U32 size);
|
10
|
+
drow_t bubble_drow(drow_t drow);
|
11
|
+
bool drow_word_blank(drow_t drow, U32 i);
|
12
|
+
bool drow_word_present(drow_t drow, U32 i);
|
13
|
+
bool drow_exclude(drow_t drow, char const* str);
|
14
|
+
bool drow_include(drow_t drow, char const* str);
|
15
|
+
char* sample_drow(drow_t drow);
|
16
|
+
void puts_drow(drow_t drow);
|
17
|
+
void close_drow(drow_t drow);
|
18
|
+
|
19
|
+
// dictionary utilities
|
20
|
+
dict_t open_dict();
|
21
|
+
dict_t open_dict_with_name(const char* name);
|
22
|
+
dict_t open_dict_with_tokens(const char* const buffer, const char* delimiters);
|
23
|
+
dict_t open_dict_with_name_and_tokens(const char* name, const char* const buffer, const char* delimiters);
|
24
|
+
dict_t add_drow_to_dict(dict_t dict, drow_t drow);
|
25
|
+
dict_t add_drow_to_dict_strict(dict_t dict, drow_t drow, U32 size);
|
26
|
+
dict_t place_word_in_dict(dict_t dict, const char* word);
|
27
|
+
dict_t place_words_in_dict(dict_t dict, const char* const* words, U32 s);
|
28
|
+
dict_t place_word_in_dict_strict(dict_t dict, const char* word);
|
29
|
+
dict_t place_words_in_dict_strict(dict_t dict, const char* const* words, U32 s);
|
30
|
+
dict_t bubble_dict(dict_t dict);
|
31
|
+
dict_t prune_dict(dict_t dict, bool sorted);
|
32
|
+
dict_t map_dict(dict_t dict, char* (*f)(char*));
|
33
|
+
dict_t deep_copy_dict(dict_t dict);
|
34
|
+
bool dict_exclude(dict_t dict, char const* str);
|
35
|
+
bool dict_include(dict_t dict, char const* str);
|
36
|
+
bool dict_any_blanks(dict_t dict);
|
37
|
+
bool dict_valid(dict_t dict, char** error);
|
38
|
+
I32 find_drow_of_size_in_dict(dict_t dict, U32 largest);
|
39
|
+
U32 total_dict(dict_t dict);
|
40
|
+
U32 dict_largest(dict_t dict);
|
41
|
+
char* sample_dict(dict_t dict);
|
42
|
+
char* join_dict(dict_t dict, char const* delimiter);
|
43
|
+
void puts_dict(dict_t dict);
|
44
|
+
dict_t close_dict(dict_t dict);
|
45
|
+
|
46
|
+
// secondary utilities
|
47
|
+
void validate_dict(dict_t dict, char const* function_name);
|
48
|
+
dict_t split(const char* buffer, const char* delimiters);
|
49
|
+
|
50
|
+
#endif
|