refactor: don't compile trie as separate library
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
parent
55474b485f
commit
cc8cfaeace
|
@ -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)
|
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -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=====
|
||||||
|
|
|
@ -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,17 +70,18 @@ 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.
|
||||||
*
|
*
|
||||||
* @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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -188,11 +192,11 @@ Entry *ternarytrie_search(TernaryTrie *trie, const char *key) {
|
||||||
pthread_rwlock_rdlock(&trie->lock);
|
pthread_rwlock_rdlock(&trie->lock);
|
||||||
|
|
||||||
SearchResult res = ternarytrie_search_node(trie, key);
|
SearchResult res = ternarytrie_search_node(trie, key);
|
||||||
|
|
||||||
Entry *return_value = NULL;
|
Entry *return_value = NULL;
|
||||||
|
|
||||||
if (res.child != NULL) {
|
if (res.child != NULL) {
|
||||||
return_value = res.child->entry;
|
return_value = res.child->entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_unlock(&trie->lock);
|
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
|
* @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.
|
||||||
*
|
*
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -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)
|
|
|
@ -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);
|
|
||||||
}
|
|
Loading…
Reference in New Issue