refactor: don't compile trie as separate library
ci/woodpecker/push/woodpecker Pipeline was successful Details

trie-skips
Jef Roosens 2022-11-27 20:20:09 +01:00
parent 55474b485f
commit cc8cfaeace
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
7 changed files with 65 additions and 107 deletions

View File

@ -1,16 +1,15 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(lander C CXX) project(lander C CXX)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
include_directories(crow/include tries/include) include_directories(crow/include include)
add_subdirectory(crow) add_subdirectory(crow)
add_subdirectory(tries)
if(CMAKE_BUILD_TYPE STREQUAL Release) if(CMAKE_BUILD_TYPE STREQUAL Release)
add_compile_options(-O3 -flto) add_compile_options(-O3 -flto)
endif() endif()
add_executable(lander src/main.cpp) add_executable(lander src/main.cpp src/tries/ternarytrie.c)
target_link_libraries(lander Crow ternarytrie)

View File

@ -1,10 +1,11 @@
# =====CONFIG===== # =====CONFIG=====
BUILD_DIR := ./build BUILD_DIR := ./build
SRC_DIR := ./src SRC_DIR := ./src
INCLUDE_DIR := ./include
TEST_DIR := test TEST_DIR := test
CORES != nproc CORES != nproc
SRCS := $(shell find '$(SRC_DIR)' -iname '*.cpp') SRCS := $(shell find '$(SRC_DIR)' '$(INCLUDE_DIR)' \( -iname '*.cpp' -or -iname '*.c' -or -iname '*.h' \))
# =====RECIPES===== # =====RECIPES=====

View File

@ -1,16 +1,23 @@
#ifndef AD3_TERNARYTRIE #ifndef AD3_TERNARYTRIE
#define AD3_TERNARYTRIE #define AD3_TERNARYTRIE
#define ALPHABET_SIZE 256
#define DELIMITER '\0'
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
/** /**
* The implementation of a Ternary Trie. * The implementation of a Ternary Trie.
* *
* Each node should be represented by a binary tree in order to reduce the memory usage. * Each node should be represented by a binary tree in order to reduce the
* memory usage.
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const char charset[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const size_t charset_len = sizeof(charset) - 1; static const size_t charset_len = sizeof(charset) - 1;
// Length of randomly generated keys // Length of randomly generated keys
@ -24,11 +31,7 @@ static const size_t charset_len = sizeof(charset) - 1;
*/ */
typedef struct ttrie TernaryTrie; typedef struct ttrie TernaryTrie;
typedef enum entry_type { typedef enum entry_type { Redirect, Paste, Unknown } EntryType;
Redirect,
Paste,
Unknown
} EntryType;
typedef struct entry { typedef struct entry {
EntryType type; EntryType type;
@ -42,7 +45,7 @@ Entry *entry_new(EntryType type, const char *string);
* *
* @return a pointer to an empty Trie struct * @return a pointer to an empty Trie struct
*/ */
TernaryTrie* ternarytrie_init(); TernaryTrie *ternarytrie_init();
/** /**
* Populate trie with entries stored in the given file. * Populate trie with entries stored in the given file.
@ -51,14 +54,14 @@ TernaryTrie* ternarytrie_init();
* @param file_path path to file containing entries * @param file_path path to file containing entries
* @return amount of entries added; -1 if an error occured * @return amount of entries added; -1 if an error occured
*/ */
int ternarytrie_populate(TernaryTrie* trie, const char* file_path); int ternarytrie_populate(TernaryTrie *trie, const char *file_path);
/** /**
* De-allocate a trie by freeing the memory occupied by this trie. * De-allocate a trie by freeing the memory occupied by this trie.
* *
* @param trie which should be freed * @param trie which should be freed
*/ */
void ternarytrie_free(TernaryTrie* trie); void ternarytrie_free(TernaryTrie *trie);
/** /**
* Search for an entry in the trie. * Search for an entry in the trie.
@ -67,7 +70,7 @@ void ternarytrie_free(TernaryTrie* trie);
* @param key key representing the entry * @param key key representing the entry
* @return pointer to entry; NULL if not found * @return pointer to entry; NULL if not found
*/ */
Entry *ternarytrie_search(TernaryTrie* trie, const char* key); Entry *ternarytrie_search(TernaryTrie *trie, const char *key);
/** /**
* Add a string to this trie. * Add a string to this trie.
@ -75,9 +78,10 @@ Entry *ternarytrie_search(TernaryTrie* trie, const char* key);
* @param trie * @param trie
* @param key key to represent entry with * @param key key to represent entry with
* @param entry entry to add * @param entry entry to add
* @return true if the trie was changed by this operation, false if it was already present * @return true if the trie was changed by this operation, false if it was
* already present
*/ */
bool ternarytrie_add(TernaryTrie* trie, const char* key, Entry *entry); bool ternarytrie_add(TernaryTrie *trie, const char *key, Entry *entry);
/** /**
* Add an entry by generating a random string as the key. * Add an entry by generating a random string as the key.
@ -94,9 +98,10 @@ char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure);
* *
* @param trie * @param trie
* @param key key representing entry * @param key key representing entry
* @return true if the entry was present and has been removed, false if it was not present * @return true if the entry was present and has been removed, false if it was
* not present
*/ */
bool ternarytrie_remove(TernaryTrie* trie, const char *key); bool ternarytrie_remove(TernaryTrie *trie, const char *key);
/** /**
* Returns the number of entries in this trie. * Returns the number of entries in this trie.
@ -104,6 +109,6 @@ bool ternarytrie_remove(TernaryTrie* trie, const char *key);
* @param trie * @param trie
* @return the number of entries in this trie * @return the number of entries in this trie
*/ */
size_t ternarytrie_size(TernaryTrie* trie); size_t ternarytrie_size(TernaryTrie *trie);
#endif //AD3_TERNARYTRIE #endif // AD3_TERNARYTRIE

View File

@ -1,8 +1,8 @@
#include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <pthread.h>
#include "ternarytrie.h" #include "ternarytrie.h"
#include "ternarytrie_node.c" #include "ternarytrie_node.c"
@ -10,7 +10,7 @@
typedef struct ttrie { typedef struct ttrie {
TernaryTrieNode *root; TernaryTrieNode *root;
size_t size; size_t size;
char* file_path; char *file_path;
pthread_rwlock_t lock; pthread_rwlock_t lock;
} TernaryTrie; } TernaryTrie;
@ -20,7 +20,7 @@ typedef struct ttrie {
* @return pointer to the empty TernaryTrie * @return pointer to the empty TernaryTrie
*/ */
TernaryTrie *ternarytrie_init() { TernaryTrie *ternarytrie_init() {
TernaryTrie *trie = calloc(1, sizeof(TernaryTrie)); TernaryTrie *trie = (TernaryTrie *)calloc(1, sizeof(TernaryTrie));
trie->root = ttnode_init(); trie->root = ttnode_init();
pthread_rwlock_init(&trie->lock, NULL); pthread_rwlock_init(&trie->lock, NULL);
@ -40,28 +40,33 @@ void ternarytrie_free(TernaryTrie *trie) {
bool ternarytrie_add_internal(TernaryTrie *trie, const char *key, Entry *entry); bool ternarytrie_add_internal(TernaryTrie *trie, const char *key, Entry *entry);
EntryType entry_type_from_char(char c) { EntryType entry_type_from_char(char c) {
switch(c) { switch (c) {
case '0': return Redirect; case '0':
case '1': return Paste; return Redirect;
default: return Unknown; case '1':
return Paste;
default:
return Unknown;
} }
} }
char entry_type_to_char(EntryType et) { char entry_type_to_char(EntryType et) {
switch (et) { switch (et) {
case Redirect: return '0'; case Redirect:
case Paste: return '1'; return '0';
default: return '\0'; case Paste:
return '1';
default:
return '\0';
} }
} }
Entry *entry_new(EntryType type, const char *string) { Entry *entry_new(EntryType type, const char *string) {
Entry *entry = malloc(sizeof(Entry)); Entry *entry = (Entry *)malloc(sizeof(Entry));
entry->type = type; entry->type = type;
if (string != NULL) { if (string != NULL) {
entry->string = my_strdup(string); entry->string = strdup(string);
} else { } else {
entry->string = NULL; entry->string = NULL;
} }
@ -70,9 +75,9 @@ Entry *entry_new(EntryType type, const char *string) {
} }
int ternarytrie_populate(TernaryTrie *trie, const char *file_path) { int ternarytrie_populate(TernaryTrie *trie, const char *file_path) {
trie->file_path = my_strdup(file_path); trie->file_path = strdup(file_path);
FILE* fp = fopen(file_path, "r"); FILE *fp = fopen(file_path, "r");
// TODO properly handle this // TODO properly handle this
if (fp == NULL) { if (fp == NULL) {
@ -161,8 +166,7 @@ SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *key) {
} while (1); } while (1);
if ((*child_ptr)->type == 2) { if ((*child_ptr)->type == 2) {
if (key[i] != DELIMITER && if (key[i] != DELIMITER && strcmp(key + i, (*child_ptr)->ptr.string) == 0) {
strcmp(key + i, (*child_ptr)->ptr.string) == 0) {
out.child = *child_ptr; out.child = *child_ptr;
out.parent = *node_ptr; out.parent = *node_ptr;
} }
@ -208,7 +212,8 @@ Entry *ternarytrie_search(TernaryTrie *trie, const char *key) {
* @return true if the string wasn't present in the trie and thus added, false * @return true if the string wasn't present in the trie and thus added, false
* otherwise * otherwise
*/ */
bool ternarytrie_add_internal(TernaryTrie *trie, const char *string, Entry *entry) { bool ternarytrie_add_internal(TernaryTrie *trie, const char *string,
Entry *entry) {
// Edge case for empty string // Edge case for empty string
if (string[0] == DELIMITER) { if (string[0] == DELIMITER) {
if (trie->root->type == 0) { if (trie->root->type == 0) {
@ -291,7 +296,8 @@ bool ternarytrie_add_internal(TernaryTrie *trie, const char *string, Entry *entr
return true; return true;
} }
bool ternarytrie_add_persistent(TernaryTrie *trie, const char *key, Entry *entry) { bool ternarytrie_add_persistent(TernaryTrie *trie, const char *key,
Entry *entry) {
bool return_value = false; bool return_value = false;
if (trie->file_path != NULL) { if (trie->file_path != NULL) {
@ -333,13 +339,13 @@ bool ternarytrie_add(TernaryTrie *trie, const char *key, Entry *entry) {
return return_value; return return_value;
} }
char* ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure) { char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure) {
pthread_rwlock_wrlock(&trie->lock); pthread_rwlock_wrlock(&trie->lock);
// Generate random key // Generate random key
bool ok = false; bool ok = false;
int key_length = secure ? RANDOM_KEY_LENGTH_LONG : RANDOM_KEY_LENGTH_SHORT; int key_length = secure ? RANDOM_KEY_LENGTH_LONG : RANDOM_KEY_LENGTH_SHORT;
char *key = malloc(key_length + 1); char *key = (char *)malloc(key_length + 1);
key[key_length] = '\0'; key[key_length] = '\0';
// We naively generate new keys until we find a key that isn't in the trie // We naively generate new keys until we find a key that isn't in the trie
@ -368,7 +374,6 @@ char* ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure) {
return return_value; return return_value;
} }
/** /**
* Remove the given string from a TernaryTrie. * Remove the given string from a TernaryTrie.
* *

View File

@ -3,7 +3,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "ternarytrie.h" #include "ternarytrie.h"
#include "common.c"
/** /**
* Represents a node of the binary tree contained within each non-leaf * Represents a node of the binary tree contained within each non-leaf
@ -55,7 +54,8 @@ void ttnode_free(TernaryTrieNode *node);
* @return pointer to newly allocated struct * @return pointer to newly allocated struct
*/ */
TernaryTrieInnerNode *ttinode_init(char c) { TernaryTrieInnerNode *ttinode_init(char c) {
TernaryTrieInnerNode *node = calloc(1, sizeof(TernaryTrieInnerNode)); TernaryTrieInnerNode *node =
(TernaryTrieInnerNode *)calloc(1, sizeof(TernaryTrieInnerNode));
node->key = c; node->key = c;
return node; return node;
@ -66,7 +66,9 @@ TernaryTrieInnerNode *ttinode_init(char c) {
* *
* @return pointer to newly allocated struct * @return pointer to newly allocated struct
*/ */
TernaryTrieNode *ttnode_init() { return calloc(1, sizeof(TernaryTrieNode)); } TernaryTrieNode *ttnode_init() {
return (TernaryTrieNode *)calloc(1, sizeof(TernaryTrieNode));
}
/** /**
* Free a TernaryTrieInnerNode and its underlying tree structure. This should * Free a TernaryTrieInnerNode and its underlying tree structure. This should
@ -120,7 +122,7 @@ void ttnode_free(TernaryTrieNode *node) {
void ttnode_set_string(TernaryTrieNode *node, const char *string) { void ttnode_set_string(TernaryTrieNode *node, const char *string) {
node->type = 2; node->type = 2;
node->size = strlen(string); node->size = strlen(string);
node->ptr.string = my_strdup(string); node->ptr.string = strdup(string);
} }
/** /**

View File

@ -1,12 +0,0 @@
cmake_minimum_required(VERSION 3.20)
project(ternarytrie C)
set(CMAKE_C_STANDARD 17)
add_library(ternarytrie STATIC src/ternarytrie.c)
target_include_directories(
ternarytrie PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
target_compile_options(ternarytrie PRIVATE -O3 -flto)

View File

@ -1,42 +0,0 @@
#define ALPHABET_SIZE 256
#define DELIMITER '\0'
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#include <stdlib.h>
#include <string.h>
/**
* Own implementation of strdup, heavily inspired by the glibc source code.
*
* This is neccessary because subGIT does not seem to have a strdup
* implementation available for use.
*
* @param s string to duplicate
* @return pointer to the newly allocated string
*/
char *my_strdup(const char *s) {
size_t len = strlen(s);
char *new = malloc(len + 1);
new[len] = DELIMITER;
return (char *)memcpy(new, s, len);
}
/**
* Own implementation of strndup, heavily inspired by the glibc source code.
*
* This is neccessary because subGIT does not seem to have a strndup
* implementation available for use.
*
* @param s string to duplicate
* @return pointer to the newly allocated string
*/
char *my_strndup(const char *s, size_t n) {
size_t string_len = strlen(s);
size_t len = MAX(string_len, n);
char *new = (char *)malloc(len + 1);
new[len] = DELIMITER;
return (char *)memcpy(new, s, len);
}