diff options
Diffstat (limited to 'dictionary.c')
-rw-r--r-- | dictionary.c | 171 |
1 files changed, 168 insertions, 3 deletions
diff --git a/dictionary.c b/dictionary.c index 0d953d9..a0c8f72 100644 --- a/dictionary.c +++ b/dictionary.c @@ -1,15 +1,28 @@ #include "jdtalk.h" +/** + * Initializes a dictionary + * @return Empty initialized Dictionary structure + */ struct Dictionary *dictionary_new() { struct Dictionary *dict; + dict = malloc(1 * sizeof(*dict)); + if (!dict) { + perror("Unable to initialize new dictionary"); + exit(1); + } dict->words = malloc(DICT_INITIAL_SIZE * sizeof(**dict->words)); + if (!dict->words) { + perror("Unable to initialize array of dictionary words"); + exit(1); + } dict->nelem_alloc = DICT_INITIAL_SIZE; dict->nelem_inuse = 0; return dict; } -void dictionary_append(struct Dictionary **dict, char *s, unsigned type) { +void dictionary_grow_as_needed(struct Dictionary **dict) { if ((*dict)->nelem_inuse + 1 > (*dict)->nelem_alloc) { struct Word **tmp; (*dict)->nelem_alloc += DICT_INITIAL_SIZE; @@ -20,18 +33,74 @@ void dictionary_append(struct Dictionary **dict, char *s, unsigned type) { } (*dict)->words = tmp; } +} + +void dictionary_alloc_word_record(struct Dictionary **dict) { (*dict)->words[(*dict)->nelem_inuse] = malloc(1 * sizeof(**(*dict)->words)); + if (!(*dict)->words[(*dict)->nelem_inuse]) { + perror("Unable to allocate dictionary word list record"); + exit(1); + } +} + +void dictionary_new_word(struct Dictionary **dict, char *s, unsigned type) { (*dict)->words[(*dict)->nelem_inuse]->word = strdup(s); + if (!(*dict)->words[(*dict)->nelem_inuse]->word) { + perror("Unable to allocate dictionary word in list"); + exit(1); + } (*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; +} + +struct Dictionary *dictionary_of(struct Dictionary **src, unsigned type) { + struct Dictionary *dest; + dest = dictionary_new(); + dictionary_grow_as_needed(&dest); + for (size_t i = 0, x = 0; i < (*src)->nelem_inuse; i++) { + if ((*src)->words[i]->type != type) + continue; + dictionary_alloc_word_record(&dest); + dest->words[x] = malloc(sizeof(**(*src)->words)); + dest->words[x] = (*src)->words[i]; + dest->nelem_inuse++; + x++; + } + return dest; +} + +/** + * Add a word to the dictionary + * + * @param dict pointer to dictionary + * @param s string to append to word list + * @param type type of word (WT_NOUN, WT_VERB, WT_ADVERB, WT_ADJECTIVE) + */ +void dictionary_append(struct Dictionary **dict, char *s, unsigned type) { + dictionary_grow_as_needed(dict); + dictionary_alloc_word_record(dict); + dictionary_new_word(dict, s, type); (*dict)->nelem_inuse++; } +/** + * Extract words from a file and append them to a Dictionary + * structure with a specific type + * + * @param fp raw dictionary file handle + * @param dict pointer to Dictionary structure + * @param type type of words in raw dictionary file + * @return 0=success or value of errno on failure + */ int dictionary_read(FILE *fp, struct Dictionary **dict, unsigned type) { char *buf; buf = malloc(DICT_WORD_SIZE_MAX * sizeof(char)); + if (!buf) { + perror("Unable to allocate buffer for dictionary_read"); + exit(1); + } while ((fgets(buf, DICT_WORD_SIZE_MAX - 1, fp) != NULL)) { if (errno) { return errno; @@ -44,6 +113,11 @@ int dictionary_read(FILE *fp, struct Dictionary **dict, unsigned type) { return 0; } +/** + * Consume all dictionary files + * + * @return fully populated dictionary of words + */ struct Dictionary *dictionary_populate() { FILE *fp; struct Dictionary *dict; @@ -55,6 +129,7 @@ struct Dictionary *dictionary_populate() { NULL, }; + // Types of words expected by files[] array const unsigned files_type[] = { WT_NOUN, WT_ADJECTIVE, @@ -62,7 +137,10 @@ struct Dictionary *dictionary_populate() { WT_VERB, }; + // Initialize the dictionary dict = dictionary_new(); + + // Consume each dictionary in files[] for (size_t i = 0; files[i] != NULL; i++) { char *datadir; char filename[PATH_MAX]; @@ -80,18 +158,92 @@ struct Dictionary *dictionary_populate() { fprintf(stderr, "Unable to open dictionary: %s", filename); exit(1); } + + // Append the contents of file[i] to dictionary dictionary_read(fp, &dict, files_type[i]); fclose(fp); } return dict; } +/** + * Get the types of a word + * @param dict pointer to dictionary + * @param s dictionary word to search for + * @return a string containing the word types (i.e. n,a,d,v) + */ +char *dictionary_word_formats(struct Dictionary *dict, char *s) { + static char buf[OUTPUT_SIZE_MAX]; + buf[0] = '\0'; + + for (size_t i = 0; i < dict->nelem_inuse; i++) { + if (strcmp(dict->words[i]->word, s) != 0) { + continue; + } + switch (dict->words[i]->type) { + case WT_NOUN: + strcat(buf, "n"); + break; + case WT_ADJECTIVE: + strcat(buf, "a"); + break; + case WT_ADVERB: + strcat(buf, "d"); + break; + case WT_VERB: + strcat(buf, "v"); + break; + default: + strcat(buf, "x"); + break; + } + } + if (!strlen(buf)) { + return NULL; + } + return buf; +} + +/** + * Search dictionary for a word + * + * int result; + * + * // "beef" exists and is a verb + * result = dictionary_contains(dict, "beef", WT_VERB); + * // 1 + * + * // "beef" exists and is a noun + * result = dictionary_contains(dict, "beef", WT_NOUN); + * // 1 + * + * // "beef" is not an adjective + * result = dictionary_contains(dict, "beef", WT_ADJECTIVE); + * // 0 + * + * // "Beef" does not exist as written (case sensitive search) + * result = dictionary_contains(dict, "Beef", WT_NOUN); + * // 0 + * + * // "Beef" exists (case insensitive search) and is a noun + * result = dictionary_contains(dict, "Beef", WT_NOUN | WT_ICASE); + * // 1 + * + * // "Beef" exists (case insensitive search), matching any type of word + * result = dictionary_contains(dict, "Beef", WT_ANY | WT_ICASE); + * // 1 + * + * @param dict pointer to populated dictionary + * @param s pointer to pattern string + * @param type type of word (WT_NOUN, WT_VERB, WT_ADVERB, WT_ADJECTIVE) || (WT_ANY, WT_ICASE) + * @return 0=not found, !0=found + */ int dictionary_contains(struct Dictionary *dict, const char *s, unsigned type) { int result; unsigned icase; - icase = type & WT_ICASE; - type &= 0x7f; + icase = type & WT_ICASE; // Determine case-sensitivity of the search function + type &= 0x7f; // Strip case-insensitive flag from type result = 0; for (size_t i = 0; i < dict->nelem_inuse; i++) { @@ -118,6 +270,15 @@ int dictionary_contains(struct Dictionary *dict, const char *s, unsigned type) { return result; } +/** + * Produce a random word from the dictionary of type + * + * When type is WT_ANY, a random word irrespective of type will be produced + * + * @param dict pointer to dictionary + * @param type type of word to produce + * @return pointer to dictionary word + */ char *dictionary_word(struct Dictionary *dict, unsigned type) { struct Word *word; while (1) { @@ -129,6 +290,10 @@ char *dictionary_word(struct Dictionary *dict, unsigned type) { } } +/** + * Free a dictionary + * @param dict pointer to dictionary + */ void dictionary_free(struct Dictionary *dict) { for (size_t i = 0; i < dict->nelem_inuse; i++) { free(dict->words[i]->word); |