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)
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(tries)
if(CMAKE_BUILD_TYPE STREQUAL Release)
add_compile_options(-O3 -flto)
endif()
add_executable(lander src/main.cpp)
target_link_libraries(lander Crow ternarytrie)
add_executable(lander src/main.cpp src/tries/ternarytrie.c)

View File

@ -1,10 +1,11 @@
# =====CONFIG=====
BUILD_DIR := ./build
SRC_DIR := ./src
INCLUDE_DIR := ./include
TEST_DIR := test
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=====

View File

@ -1,16 +1,23 @@
#ifndef 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.
*
* 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 <stddef.h>
#include <string.h>
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const char charset[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const size_t charset_len = sizeof(charset) - 1;
// Length of randomly generated keys
@ -24,11 +31,7 @@ static const size_t charset_len = sizeof(charset) - 1;
*/
typedef struct ttrie TernaryTrie;
typedef enum entry_type {
Redirect,
Paste,
Unknown
} EntryType;
typedef enum entry_type { Redirect, Paste, Unknown } EntryType;
typedef struct entry {
EntryType type;
@ -42,7 +45,7 @@ Entry *entry_new(EntryType type, const char *string);
*
* @return a pointer to an empty Trie struct
*/
TernaryTrie* ternarytrie_init();
TernaryTrie *ternarytrie_init();
/**
* Populate trie with entries stored in the given file.
@ -51,14 +54,14 @@ TernaryTrie* ternarytrie_init();
* @param file_path path to file containing entries
* @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.
*
* @param trie which should be freed
*/
void ternarytrie_free(TernaryTrie* trie);
void ternarytrie_free(TernaryTrie *trie);
/**
* Search for an entry in the trie.
@ -67,17 +70,18 @@ void ternarytrie_free(TernaryTrie* trie);
* @param key key representing the entry
* @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.
*
* @param trie
* @param key key to represent entry with
* @param entry entry to add
* @return true if the trie was changed by this operation, false if it was already present
* @param entry entry to add
* @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.
@ -94,9 +98,10 @@ char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure);
*
* @param trie
* @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.
@ -104,6 +109,6 @@ bool ternarytrie_remove(TernaryTrie* trie, const char *key);
* @param 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include "ternarytrie.h"
#include "ternarytrie_node.c"
@ -10,7 +10,7 @@
typedef struct ttrie {
TernaryTrieNode *root;
size_t size;
char* file_path;
char *file_path;
pthread_rwlock_t lock;
} TernaryTrie;
@ -20,7 +20,7 @@ typedef struct ttrie {
* @return pointer to the empty TernaryTrie
*/
TernaryTrie *ternarytrie_init() {
TernaryTrie *trie = calloc(1, sizeof(TernaryTrie));
TernaryTrie *trie = (TernaryTrie *)calloc(1, sizeof(TernaryTrie));
trie->root = ttnode_init();
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);
EntryType entry_type_from_char(char c) {
switch(c) {
case '0': return Redirect;
case '1': return Paste;
default: return Unknown;
switch (c) {
case '0':
return Redirect;
case '1':
return Paste;
default:
return Unknown;
}
}
char entry_type_to_char(EntryType et) {
switch (et) {
case Redirect: return '0';
case Paste: return '1';
default: return '\0';
case Redirect:
return '0';
case Paste:
return '1';
default:
return '\0';
}
}
Entry *entry_new(EntryType type, const char *string) {
Entry *entry = malloc(sizeof(Entry));
Entry *entry = (Entry *)malloc(sizeof(Entry));
entry->type = type;
if (string != NULL) {
entry->string = my_strdup(string);
entry->string = strdup(string);
} else {
entry->string = NULL;
}
@ -70,9 +75,9 @@ Entry *entry_new(EntryType type, const char *string) {
}
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
if (fp == NULL) {
@ -161,8 +166,7 @@ SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *key) {
} while (1);
if ((*child_ptr)->type == 2) {
if (key[i] != DELIMITER &&
strcmp(key + i, (*child_ptr)->ptr.string) == 0) {
if (key[i] != DELIMITER && strcmp(key + i, (*child_ptr)->ptr.string) == 0) {
out.child = *child_ptr;
out.parent = *node_ptr;
}
@ -188,11 +192,11 @@ Entry *ternarytrie_search(TernaryTrie *trie, const char *key) {
pthread_rwlock_rdlock(&trie->lock);
SearchResult res = ternarytrie_search_node(trie, key);
Entry *return_value = NULL;
if (res.child != NULL) {
return_value = res.child->entry;
return_value = res.child->entry;
}
pthread_rwlock_unlock(&trie->lock);
@ -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
* 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
if (string[0] == DELIMITER) {
if (trie->root->type == 0) {
@ -291,7 +296,8 @@ bool ternarytrie_add_internal(TernaryTrie *trie, const char *string, Entry *entr
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;
if (trie->file_path != NULL) {
@ -333,13 +339,13 @@ bool ternarytrie_add(TernaryTrie *trie, const char *key, Entry *entry) {
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);
// Generate random key
bool ok = false;
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';
// 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;
}
/**
* Remove the given string from a TernaryTrie.
*

View File

@ -3,7 +3,6 @@
#include <stdlib.h>
#include "ternarytrie.h"
#include "common.c"
/**
* 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
*/
TernaryTrieInnerNode *ttinode_init(char c) {
TernaryTrieInnerNode *node = calloc(1, sizeof(TernaryTrieInnerNode));
TernaryTrieInnerNode *node =
(TernaryTrieInnerNode *)calloc(1, sizeof(TernaryTrieInnerNode));
node->key = c;
return node;
@ -66,7 +66,9 @@ TernaryTrieInnerNode *ttinode_init(char c) {
*
* @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
@ -120,7 +122,7 @@ void ttnode_free(TernaryTrieNode *node) {
void ttnode_set_string(TernaryTrieNode *node, const char *string) {
node->type = 2;
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);
}