113 lines
2.1 KiB
C
113 lines
2.1 KiB
C
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include <unistd.h>
|
|
|
|
#define DICTIONARY "/usr/share/dict/words"
|
|
|
|
struct trie {
|
|
struct trie *children[26];
|
|
uint8_t terminal;
|
|
};
|
|
|
|
void new_trie(struct trie *tree) {
|
|
uint8_t idx = 0;
|
|
|
|
for(; idx < 26; idx += 1) {
|
|
tree->children[idx] = NULL;
|
|
}
|
|
|
|
tree->terminal = 0;
|
|
}
|
|
|
|
void trie_insert(struct trie *tree, const char *str, uint8_t len) {
|
|
struct trie *node = tree;
|
|
uint8_t idx = 0;
|
|
|
|
for(; idx < len; idx += 1) {
|
|
uint8_t pos = tolower(str[idx]) - 'a';
|
|
|
|
if(node->children[pos] == NULL) {
|
|
void *mem = malloc(sizeof(struct trie));
|
|
|
|
if(mem == NULL) {
|
|
fprintf(stderr, "could not allocate memory: %s\n", strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
node->children[pos] = mem;
|
|
new_trie(node->children[pos]);
|
|
}
|
|
|
|
node = node->children[pos];
|
|
}
|
|
|
|
node->terminal = 1;
|
|
}
|
|
|
|
uint8_t trie_has(struct trie *tree, const char *str, uint8_t len) {
|
|
struct trie *node = tree;
|
|
uint8_t idx = 0;
|
|
|
|
for(; idx < len; idx += 1) {
|
|
uint8_t pos = tolower(str[idx]) - 'a';
|
|
|
|
if(node->children[pos] == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
node = node->children[pos];
|
|
}
|
|
|
|
return node->terminal;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
struct trie dict;
|
|
new_trie(&dict);
|
|
|
|
int fd = open(DICTIONARY, O_RDONLY);
|
|
|
|
if(fd < 0) {
|
|
fprintf(stderr, "could not open %s: %s\n", DICTIONARY, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
ssize_t bytes = 0;
|
|
char buf[1024] = { 0 };
|
|
char word[128] = { 0 };
|
|
uint8_t len = 0;
|
|
|
|
while((bytes = read(fd, buf, sizeof(buf))) > 0) {
|
|
ssize_t idx = 0;
|
|
|
|
for(; idx < bytes; idx += 1) {
|
|
if(buf[idx] == '\n') {
|
|
trie_insert(&dict, word, len);
|
|
len = 0;
|
|
bzero(word, sizeof(word));
|
|
} else if(len < sizeof(word)) {
|
|
word[len] = buf[idx];
|
|
len += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bytes < 0) {
|
|
fprintf(stderr, "could not read from %s: %s\n", DICTIONARY, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
const char *check = "paladin";
|
|
|
|
if(argc > 1) {
|
|
check = argv[1];
|
|
}
|
|
|
|
return !trie_has(&dict, check, strlen(check));
|
|
}
|