aboutsummaryrefslogtreecommitdiff
path: root/dictionary.c
diff options
context:
space:
mode:
Diffstat (limited to 'dictionary.c')
-rw-r--r--dictionary.c171
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);