refactor: rename TernaryTrie to Trie
	
		
			
	
		
	
	
		
			
				
	
				ci/woodpecker/push/woodpecker Pipeline was successful
				
					Details
				
			
		
	
				
					
				
			
				
	
				ci/woodpecker/push/woodpecker Pipeline was successful
				
					Details
				
			
		
	
							parent
							
								
									cc8cfaeace
								
							
						
					
					
						commit
						4bcdd5c4d9
					
				| 
						 | 
					@ -12,4 +12,4 @@ if(CMAKE_BUILD_TYPE STREQUAL Release)
 | 
				
			||||||
    add_compile_options(-O3 -flto)
 | 
					    add_compile_options(-O3 -flto)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(lander src/main.cpp src/tries/ternarytrie.c)
 | 
					add_executable(lander src/main.cpp src/trie.c)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ static const size_t charset_len = sizeof(charset) - 1;
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You can (and should) redefine this in your c-file with the concrete fields.
 | 
					 * You can (and should) redefine this in your c-file with the concrete fields.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct ttrie TernaryTrie;
 | 
					typedef struct ttrie Trie;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum entry_type { Redirect, Paste, Unknown } EntryType;
 | 
					typedef enum entry_type { Redirect, Paste, Unknown } EntryType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,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();
 | 
					Trie *trie_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Populate trie with entries stored in the given file.
 | 
					 * Populate trie with entries stored in the given file.
 | 
				
			||||||
| 
						 | 
					@ -54,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 trie_populate(Trie *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 trie_free(Trie *trie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Search for an entry in the trie.
 | 
					 * Search for an entry in the trie.
 | 
				
			||||||
| 
						 | 
					@ -70,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 *trie_search(Trie *trie, const char *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Add a string to this trie.
 | 
					 * Add a string to this trie.
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ Entry *ternarytrie_search(TernaryTrie *trie, const char *key);
 | 
				
			||||||
 * @return true if the trie was changed by this operation, false if it was
 | 
					 * @return true if the trie was changed by this operation, false if it was
 | 
				
			||||||
 * already present
 | 
					 * already present
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool ternarytrie_add(TernaryTrie *trie, const char *key, Entry *entry);
 | 
					bool trie_add(Trie *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.
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ bool ternarytrie_add(TernaryTrie *trie, const char *key, Entry *entry);
 | 
				
			||||||
 * @param secure whether to generate a longer, more secure random key
 | 
					 * @param secure whether to generate a longer, more secure random key
 | 
				
			||||||
 * @return the generated key
 | 
					 * @return the generated key
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure);
 | 
					char *trie_add_random(Trie *trie, Entry *entry, bool secure);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Remove an entry from this trie given its key.
 | 
					 * Remove an entry from this trie given its key.
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure);
 | 
				
			||||||
 * @return true if the entry was present and has been removed, false if it was
 | 
					 * @return true if the entry was present and has been removed, false if it was
 | 
				
			||||||
 * not present
 | 
					 * not present
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool ternarytrie_remove(TernaryTrie *trie, const char *key);
 | 
					bool trie_remove(Trie *trie, const char *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Returns the number of entries in this trie.
 | 
					 * Returns the number of entries in this trie.
 | 
				
			||||||
| 
						 | 
					@ -109,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 trie_size(Trie *trie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // AD3_TERNARYTRIE
 | 
					#endif // AD3_TERNARYTRIE
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/main.cpp
								
								
								
								
							
							
						
						
									
										20
									
								
								src/main.cpp
								
								
								
								
							| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
#include "crow.h"
 | 
					#include "crow.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#include "ternarytrie.h"
 | 
					#include "trie.h"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const std::string index_page = R"(
 | 
					static const std::string index_page = R"(
 | 
				
			||||||
| 
						 | 
					@ -31,10 +31,10 @@ static const std::string index_page = R"(
 | 
				
			||||||
    return crow::response(crow::status::UNAUTHORIZED);                         \
 | 
					    return crow::response(crow::status::UNAUTHORIZED);                         \
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
crow::response add_redirect(std::string base_url, TernaryTrie *trie,
 | 
					crow::response add_redirect(std::string base_url, Trie *trie,
 | 
				
			||||||
                            const char *url, bool secure) {
 | 
					                            const char *url, bool secure) {
 | 
				
			||||||
  Entry *new_entry = entry_new(Redirect, url);
 | 
					  Entry *new_entry = entry_new(Redirect, url);
 | 
				
			||||||
  char *key = ternarytrie_add_random(trie, new_entry, secure);
 | 
					  char *key = trie_add_random(trie, new_entry, secure);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (key == NULL) {
 | 
					  if (key == NULL) {
 | 
				
			||||||
    return crow::response(crow::status::INTERNAL_SERVER_ERROR);
 | 
					    return crow::response(crow::status::INTERNAL_SERVER_ERROR);
 | 
				
			||||||
| 
						 | 
					@ -61,10 +61,10 @@ bool store_paste(const char *key, const char *body) {
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
crow::response add_paste(std::string base_url, TernaryTrie *trie,
 | 
					crow::response add_paste(std::string base_url, Trie *trie,
 | 
				
			||||||
                         const char *body, bool secure) {
 | 
					                         const char *body, bool secure) {
 | 
				
			||||||
  Entry *new_entry = entry_new(Paste, "");
 | 
					  Entry *new_entry = entry_new(Paste, "");
 | 
				
			||||||
  char *key = ternarytrie_add_random(trie, new_entry, secure);
 | 
					  char *key = trie_add_random(trie, new_entry, secure);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (key == NULL) {
 | 
					  if (key == NULL) {
 | 
				
			||||||
    return crow::response(crow::status::INTERNAL_SERVER_ERROR);
 | 
					    return crow::response(crow::status::INTERNAL_SERVER_ERROR);
 | 
				
			||||||
| 
						 | 
					@ -88,14 +88,14 @@ int main() {
 | 
				
			||||||
  ENV(base_url, "LANDER_BASE_URL");
 | 
					  ENV(base_url, "LANDER_BASE_URL");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize trie and populate from data file
 | 
					  // Initialize trie and populate from data file
 | 
				
			||||||
  TernaryTrie *trie = ternarytrie_init();
 | 
					  Trie *trie = trie_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::string file_path = "lander.data";
 | 
					  std::string file_path = "lander.data";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::cout << "Populating trie from file '" << file_path << "'..."
 | 
					  std::cout << "Populating trie from file '" << file_path << "'..."
 | 
				
			||||||
            << std::endl;
 | 
					            << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int count = ternarytrie_populate(trie, file_path.c_str());
 | 
					  int count = trie_populate(trie, file_path.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (count == -1) {
 | 
					  if (count == -1) {
 | 
				
			||||||
    std::cout << "An error occured while populating the trie." << std::endl;
 | 
					    std::cout << "An error occured while populating the trie." << std::endl;
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ int main() {
 | 
				
			||||||
  CROW_ROUTE(app, "/<string>")
 | 
					  CROW_ROUTE(app, "/<string>")
 | 
				
			||||||
      .methods(crow::HTTPMethod::Get)(
 | 
					      .methods(crow::HTTPMethod::Get)(
 | 
				
			||||||
          [trie](crow::response &res, std::string key) {
 | 
					          [trie](crow::response &res, std::string key) {
 | 
				
			||||||
            Entry *entry = ternarytrie_search(trie, key.c_str());
 | 
					            Entry *entry = trie_search(trie, key.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (entry != NULL) {
 | 
					            if (entry != NULL) {
 | 
				
			||||||
              if (entry->type == Redirect) {
 | 
					              if (entry->type == Redirect) {
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ int main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Entry *new_entry = entry_new(Redirect, req.body.c_str());
 | 
					            Entry *new_entry = entry_new(Redirect, req.body.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bool added = ternarytrie_add(trie, key.c_str(), new_entry);
 | 
					            bool added = trie_add(trie, key.c_str(), new_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!added) {
 | 
					            if (!added) {
 | 
				
			||||||
              return crow::response(crow::status::CONFLICT);
 | 
					              return crow::response(crow::status::CONFLICT);
 | 
				
			||||||
| 
						 | 
					@ -194,7 +194,7 @@ int main() {
 | 
				
			||||||
            AUTH();
 | 
					            AUTH();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Entry *new_entry = entry_new(Paste, "");
 | 
					            Entry *new_entry = entry_new(Paste, "");
 | 
				
			||||||
            bool added = ternarytrie_add(trie, key.c_str(), new_entry);
 | 
					            bool added = trie_add(trie, key.c_str(), new_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!added) {
 | 
					            if (!added) {
 | 
				
			||||||
              return crow::response(crow::status::CONFLICT);
 | 
					              return crow::response(crow::status::CONFLICT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,23 +4,23 @@
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ternarytrie.h"
 | 
					#include "trie.h"
 | 
				
			||||||
#include "ternarytrie_node.c"
 | 
					#include "trie_node.c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct ttrie {
 | 
					typedef struct ttrie {
 | 
				
			||||||
  TernaryTrieNode *root;
 | 
					  TrieNode *root;
 | 
				
			||||||
  size_t size;
 | 
					  size_t size;
 | 
				
			||||||
  char *file_path;
 | 
					  char *file_path;
 | 
				
			||||||
  pthread_rwlock_t lock;
 | 
					  pthread_rwlock_t lock;
 | 
				
			||||||
} TernaryTrie;
 | 
					} Trie;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allocate and initialize an empty TernaryTrie
 | 
					 * Allocate and initialize an empty Trie
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return pointer to the empty TernaryTrie
 | 
					 * @return pointer to the empty Trie
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
TernaryTrie *ternarytrie_init() {
 | 
					Trie *trie_init() {
 | 
				
			||||||
  TernaryTrie *trie = (TernaryTrie *)calloc(1, sizeof(TernaryTrie));
 | 
					  Trie *trie = calloc(1, sizeof(Trie));
 | 
				
			||||||
  trie->root = ttnode_init();
 | 
					  trie->root = ttnode_init();
 | 
				
			||||||
  pthread_rwlock_init(&trie->lock, NULL);
 | 
					  pthread_rwlock_init(&trie->lock, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,12 +32,12 @@ TernaryTrie *ternarytrie_init() {
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param trie trie to free
 | 
					 * @param trie trie to free
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ternarytrie_free(TernaryTrie *trie) {
 | 
					void trie_free(Trie *trie) {
 | 
				
			||||||
  ttnode_free(trie->root);
 | 
					  ttnode_free(trie->root);
 | 
				
			||||||
  free(trie);
 | 
					  free(trie);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ternarytrie_add_internal(TernaryTrie *trie, const char *key, Entry *entry);
 | 
					bool trie_add_internal(Trie *trie, const char *key, Entry *entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EntryType entry_type_from_char(char c) {
 | 
					EntryType entry_type_from_char(char c) {
 | 
				
			||||||
  switch (c) {
 | 
					  switch (c) {
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ char entry_type_to_char(EntryType et) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Entry *entry_new(EntryType type, const char *string) {
 | 
					Entry *entry_new(EntryType type, const char *string) {
 | 
				
			||||||
  Entry *entry = (Entry *)malloc(sizeof(Entry));
 | 
					  Entry *entry = malloc(sizeof(Entry));
 | 
				
			||||||
  entry->type = type;
 | 
					  entry->type = type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (string != NULL) {
 | 
					  if (string != NULL) {
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ Entry *entry_new(EntryType type, const char *string) {
 | 
				
			||||||
  return entry;
 | 
					  return entry;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ternarytrie_populate(TernaryTrie *trie, const char *file_path) {
 | 
					int trie_populate(Trie *trie, const char *file_path) {
 | 
				
			||||||
  trie->file_path = strdup(file_path);
 | 
					  trie->file_path = strdup(file_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FILE *fp = fopen(file_path, "r");
 | 
					  FILE *fp = fopen(file_path, "r");
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ int ternarytrie_populate(TernaryTrie *trie, const char *file_path) {
 | 
				
			||||||
    buffer[j] = '\0';
 | 
					    buffer[j] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    entry = entry_new(type, buffer + i + 3);
 | 
					    entry = entry_new(type, buffer + i + 3);
 | 
				
			||||||
    ternarytrie_add_internal(trie, buffer, entry);
 | 
					    trie_add_internal(trie, buffer, entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    entries++;
 | 
					    entries++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -127,11 +127,11 @@ int ternarytrie_populate(TernaryTrie *trie, const char *file_path) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct searchresult {
 | 
					typedef struct searchresult {
 | 
				
			||||||
  TernaryTrieNode *parent;
 | 
					  TrieNode *parent;
 | 
				
			||||||
  TernaryTrieNode *child;
 | 
					  TrieNode *child;
 | 
				
			||||||
} SearchResult;
 | 
					} SearchResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *key) {
 | 
					SearchResult trie_search_node(Trie *trie, const char *key) {
 | 
				
			||||||
  SearchResult out = {NULL, NULL};
 | 
					  SearchResult out = {NULL, NULL};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Edge case for empty string
 | 
					  // Edge case for empty string
 | 
				
			||||||
| 
						 | 
					@ -144,8 +144,8 @@ SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *key) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t i = 0;
 | 
					  size_t i = 0;
 | 
				
			||||||
  TernaryTrieNode **node_ptr = &(trie->root);
 | 
					  TrieNode **node_ptr = &(trie->root);
 | 
				
			||||||
  TernaryTrieNode **child_ptr;
 | 
					  TrieNode **child_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  do {
 | 
					  do {
 | 
				
			||||||
    child_ptr = ttnode_search(*node_ptr, key[i], false);
 | 
					    child_ptr = ttnode_search(*node_ptr, key[i], false);
 | 
				
			||||||
| 
						 | 
					@ -188,10 +188,10 @@ SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *key) {
 | 
				
			||||||
 * @param string string to look up
 | 
					 * @param string string to look up
 | 
				
			||||||
 * @return true if the string is present in the trie, false otherwise
 | 
					 * @return true if the string is present in the trie, false otherwise
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
Entry *ternarytrie_search(TernaryTrie *trie, const char *key) {
 | 
					Entry *trie_search(Trie *trie, const char *key) {
 | 
				
			||||||
  pthread_rwlock_rdlock(&trie->lock);
 | 
					  pthread_rwlock_rdlock(&trie->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SearchResult res = ternarytrie_search_node(trie, key);
 | 
					  SearchResult res = trie_search_node(trie, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Entry *return_value = NULL;
 | 
					  Entry *return_value = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,14 +205,14 @@ Entry *ternarytrie_search(TernaryTrie *trie, const char *key) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Add the given string to the TernaryTrie.
 | 
					 * Add the given string to the Trie.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param trie trie to add string to
 | 
					 * @param trie trie to add string to
 | 
				
			||||||
 * @param string string to add
 | 
					 * @param string string to add
 | 
				
			||||||
 * @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,
 | 
					bool trie_add_internal(Trie *trie, const char *string,
 | 
				
			||||||
                              Entry *entry) {
 | 
					                              Entry *entry) {
 | 
				
			||||||
  // Edge case for empty string
 | 
					  // Edge case for empty string
 | 
				
			||||||
  if (string[0] == DELIMITER) {
 | 
					  if (string[0] == DELIMITER) {
 | 
				
			||||||
| 
						 | 
					@ -228,8 +228,8 @@ bool ternarytrie_add_internal(TernaryTrie *trie, const char *string,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t i = 0;
 | 
					  size_t i = 0;
 | 
				
			||||||
  TernaryTrieNode **node_ptr = &(trie->root);
 | 
					  TrieNode **node_ptr = &(trie->root);
 | 
				
			||||||
  TernaryTrieNode **new_node_ptr;
 | 
					  TrieNode **new_node_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  do {
 | 
					  do {
 | 
				
			||||||
    new_node_ptr = ttnode_search(*node_ptr, string[i], true);
 | 
					    new_node_ptr = ttnode_search(*node_ptr, string[i], true);
 | 
				
			||||||
| 
						 | 
					@ -256,7 +256,7 @@ bool ternarytrie_add_internal(TernaryTrie *trie, const char *string,
 | 
				
			||||||
    // The next node in the string's path doesn't exist yet, so we add it to the
 | 
					    // The next node in the string's path doesn't exist yet, so we add it to the
 | 
				
			||||||
    // trie
 | 
					    // trie
 | 
				
			||||||
    if (*node_ptr == NULL) {
 | 
					    if (*node_ptr == NULL) {
 | 
				
			||||||
      TernaryTrieNode *new_node = ttnode_init();
 | 
					      TrieNode *new_node = ttnode_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // If there's a remaining part of the string, we add it to the leaf
 | 
					      // If there's a remaining part of the string, we add it to the leaf
 | 
				
			||||||
      if (string[i] != DELIMITER) {
 | 
					      if (string[i] != DELIMITER) {
 | 
				
			||||||
| 
						 | 
					@ -296,7 +296,7 @@ bool ternarytrie_add_internal(TernaryTrie *trie, const char *string,
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ternarytrie_add_persistent(TernaryTrie *trie, const char *key,
 | 
					bool trie_add_persistent(Trie *trie, const char *key,
 | 
				
			||||||
                                Entry *entry) {
 | 
					                                Entry *entry) {
 | 
				
			||||||
  bool return_value = false;
 | 
					  bool return_value = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -304,7 +304,7 @@ bool ternarytrie_add_persistent(TernaryTrie *trie, const char *key,
 | 
				
			||||||
    // Easiest way to make sure we don't add duplicate entries
 | 
					    // Easiest way to make sure we don't add duplicate entries
 | 
				
			||||||
    // We use an internal function that doesn't require a read lock, as we're
 | 
					    // We use an internal function that doesn't require a read lock, as we're
 | 
				
			||||||
    // already inside a write lock
 | 
					    // already inside a write lock
 | 
				
			||||||
    if (ternarytrie_search_node(trie, key).child != NULL) {
 | 
					    if (trie_search_node(trie, key).child != NULL) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,26 +326,26 @@ bool ternarytrie_add_persistent(TernaryTrie *trie, const char *key,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // This function *should* always return true. Otherwise, the function would've
 | 
					  // This function *should* always return true. Otherwise, the function would've
 | 
				
			||||||
  // exited because the string was found in the trie.
 | 
					  // exited because the string was found in the trie.
 | 
				
			||||||
  return ternarytrie_add_internal(trie, key, entry);
 | 
					  return trie_add_internal(trie, key, entry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ternarytrie_add(TernaryTrie *trie, const char *key, Entry *entry) {
 | 
					bool trie_add(Trie *trie, const char *key, Entry *entry) {
 | 
				
			||||||
  pthread_rwlock_wrlock(&trie->lock);
 | 
					  pthread_rwlock_wrlock(&trie->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool return_value = ternarytrie_add_persistent(trie, key, entry);
 | 
					  bool return_value = trie_add_persistent(trie, key, entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pthread_rwlock_unlock(&trie->lock);
 | 
					  pthread_rwlock_unlock(&trie->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return return_value;
 | 
					  return return_value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure) {
 | 
					char *trie_add_random(Trie *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 = (char *)malloc(key_length + 1);
 | 
					  char *key = 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
 | 
				
			||||||
| 
						 | 
					@ -356,10 +356,10 @@ char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure) {
 | 
				
			||||||
      key[i] = charset[rand() % charset_len];
 | 
					      key[i] = charset[rand() % charset_len];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ok = ternarytrie_search_node(trie, key).child == NULL;
 | 
					    ok = trie_search_node(trie, key).child == NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool res = ternarytrie_add_persistent(trie, key, entry);
 | 
					  bool res = trie_add_persistent(trie, key, entry);
 | 
				
			||||||
  char *return_value;
 | 
					  char *return_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (res) {
 | 
					  if (res) {
 | 
				
			||||||
| 
						 | 
					@ -375,18 +375,18 @@ char *ternarytrie_add_random(TernaryTrie *trie, Entry *entry, bool secure) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Remove the given string from a TernaryTrie.
 | 
					 * Remove the given string from a Trie.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param trie trie to remove string from
 | 
					 * @param trie trie to remove string from
 | 
				
			||||||
 * @param string string to remove
 | 
					 * @param string string to remove
 | 
				
			||||||
 * @return true if the string was in the trie and thus removed, false otherwise
 | 
					 * @return true if the string was in the trie and thus removed, false otherwise
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool ternarytrie_remove(TernaryTrie *trie, const char *string) {
 | 
					bool trie_remove(Trie *trie, const char *string) {
 | 
				
			||||||
  pthread_rwlock_wrlock(&trie->lock);
 | 
					  pthread_rwlock_wrlock(&trie->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool return_value = false;
 | 
					  bool return_value = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SearchResult res = ternarytrie_search_node(trie, string);
 | 
					  SearchResult res = trie_search_node(trie, string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (res.child == NULL) {
 | 
					  if (res.child == NULL) {
 | 
				
			||||||
    goto end;
 | 
					    goto end;
 | 
				
			||||||
| 
						 | 
					@ -439,4 +439,4 @@ end:
 | 
				
			||||||
 * @param trie trie to return size for
 | 
					 * @param trie trie to return size for
 | 
				
			||||||
 * @return size of the trie
 | 
					 * @return size of the trie
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
size_t ternarytrie_size(TernaryTrie *trie) { return trie->size; }
 | 
					size_t trie_size(Trie *trie) { return trie->size; }
 | 
				
			||||||
| 
						 | 
					@ -2,21 +2,21 @@
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ternarytrie.h"
 | 
					#include "trie.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents a node of the binary tree contained within each non-leaf
 | 
					 * Represents a node of the binary tree contained within each non-leaf
 | 
				
			||||||
 * TernaryTrieNode.
 | 
					 * TrieNode.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct ttinode {
 | 
					typedef struct ttinode {
 | 
				
			||||||
  struct ttinode *left;
 | 
					  struct ttinode *left;
 | 
				
			||||||
  struct ttinode *right;
 | 
					  struct ttinode *right;
 | 
				
			||||||
  struct ttnode *next;
 | 
					  struct ttnode *next;
 | 
				
			||||||
  char key;
 | 
					  char key;
 | 
				
			||||||
} TernaryTrieInnerNode;
 | 
					} TrieInnerNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents a node inside a TernaryTrie. A node can be in one of three states:
 | 
					 * Represents a node inside a Trie. A node can be in one of three states:
 | 
				
			||||||
 * - Internal node: a node that's part of a path to a leaf node. This node will
 | 
					 * - Internal node: a node that's part of a path to a leaf node. This node will
 | 
				
			||||||
 *   always have a size greater than one, and an initialized root.
 | 
					 *   always have a size greater than one, and an initialized root.
 | 
				
			||||||
 * - Leaf: a node solely used to represent a string ending there. Its size is 0,
 | 
					 * - Leaf: a node solely used to represent a string ending there. Its size is 0,
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ typedef struct ttinode {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct ttnode {
 | 
					typedef struct ttnode {
 | 
				
			||||||
  union {
 | 
					  union {
 | 
				
			||||||
    TernaryTrieInnerNode *root;
 | 
					    TrieInnerNode *root;
 | 
				
			||||||
    char *string;
 | 
					    char *string;
 | 
				
			||||||
  } ptr;
 | 
					  } ptr;
 | 
				
			||||||
  Entry *entry;
 | 
					  Entry *entry;
 | 
				
			||||||
| 
						 | 
					@ -41,43 +41,40 @@ typedef struct ttnode {
 | 
				
			||||||
  // 0, 1: size of underlying binary tree
 | 
					  // 0, 1: size of underlying binary tree
 | 
				
			||||||
  // 2: length of string
 | 
					  // 2: length of string
 | 
				
			||||||
  uint8_t size;
 | 
					  uint8_t size;
 | 
				
			||||||
} TernaryTrieNode;
 | 
					} TrieNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Required for recursively freeing tree structure
 | 
					// Required for recursively freeing tree structure
 | 
				
			||||||
void ttnode_free(TernaryTrieNode *node);
 | 
					void ttnode_free(TrieNode *node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allocate and initialize a new TernaryTrieInnerNode representing a given
 | 
					 * Allocate and initialize a new TrieInnerNode representing a given
 | 
				
			||||||
 * character.
 | 
					 * character.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param c character to represent
 | 
					 * @param c character to represent
 | 
				
			||||||
 * @return pointer to newly allocated struct
 | 
					 * @return pointer to newly allocated struct
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
TernaryTrieInnerNode *ttinode_init(char c) {
 | 
					TrieInnerNode *ttinode_init(char c) {
 | 
				
			||||||
  TernaryTrieInnerNode *node =
 | 
					  TrieInnerNode *node = calloc(1, sizeof(TrieInnerNode));
 | 
				
			||||||
      (TernaryTrieInnerNode *)calloc(1, sizeof(TernaryTrieInnerNode));
 | 
					 | 
				
			||||||
  node->key = c;
 | 
					  node->key = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return node;
 | 
					  return node;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allocate and initialize a new TernaryTrieNode.
 | 
					 * Allocate and initialize a new TrieNode.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return pointer to newly allocated struct
 | 
					 * @return pointer to newly allocated struct
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
TernaryTrieNode *ttnode_init() {
 | 
					TrieNode *ttnode_init() { return calloc(1, sizeof(TrieNode)); }
 | 
				
			||||||
  return (TernaryTrieNode *)calloc(1, sizeof(TernaryTrieNode));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Free a TernaryTrieInnerNode and its underlying tree structure. This should
 | 
					 * Free a TrieInnerNode and its underlying tree structure. This should
 | 
				
			||||||
 * usually only be called on the root of a binary tree to free the entire
 | 
					 * usually only be called on the root of a binary tree to free the entire
 | 
				
			||||||
 * structure.
 | 
					 * structure.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param node node whose tree to free
 | 
					 * @param node node whose tree to free
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ttinode_free_cascade(TernaryTrieInnerNode *node) {
 | 
					void ttinode_free_cascade(TrieInnerNode *node) {
 | 
				
			||||||
  if (node->left != NULL) {
 | 
					  if (node->left != NULL) {
 | 
				
			||||||
    ttinode_free_cascade(node->left);
 | 
					    ttinode_free_cascade(node->left);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -94,11 +91,11 @@ void ttinode_free_cascade(TernaryTrieInnerNode *node) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Free a TernaryTrieNode and its underlying tree structure.
 | 
					 * Free a TrieNode and its underlying tree structure.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param node node to free
 | 
					 * @param node node to free
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ttnode_free(TernaryTrieNode *node) {
 | 
					void ttnode_free(TrieNode *node) {
 | 
				
			||||||
  if (node->type == 2) {
 | 
					  if (node->type == 2) {
 | 
				
			||||||
    free(node->ptr.string);
 | 
					    free(node->ptr.string);
 | 
				
			||||||
  } else if (node->size != 0) {
 | 
					  } else if (node->size != 0) {
 | 
				
			||||||
| 
						 | 
					@ -119,7 +116,7 @@ void ttnode_free(TernaryTrieNode *node) {
 | 
				
			||||||
 * @param node node to add string to
 | 
					 * @param node node to add string to
 | 
				
			||||||
 * @param string string to add
 | 
					 * @param string string to add
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ttnode_set_string(TernaryTrieNode *node, const char *string) {
 | 
					void ttnode_set_string(TrieNode *node, const char *string) {
 | 
				
			||||||
  node->type = 2;
 | 
					  node->type = 2;
 | 
				
			||||||
  node->size = strlen(string);
 | 
					  node->size = strlen(string);
 | 
				
			||||||
  node->ptr.string = strdup(string);
 | 
					  node->ptr.string = strdup(string);
 | 
				
			||||||
| 
						 | 
					@ -127,8 +124,8 @@ void ttnode_set_string(TernaryTrieNode *node, const char *string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This function performs a lookup in the underlying binary tree of the given
 | 
					 * This function performs a lookup in the underlying binary tree of the given
 | 
				
			||||||
 * TernaryTrieNode. If found, the return value is a pointer to the memory
 | 
					 * TrieNode. If found, the return value is a pointer to the memory
 | 
				
			||||||
 * location where the TernaryTrieInnerNode representing the given character
 | 
					 * location where the TrieInnerNode representing the given character
 | 
				
			||||||
 * stores its `next` field. If not found, the return value is NULL, unless
 | 
					 * stores its `next` field. If not found, the return value is NULL, unless
 | 
				
			||||||
 * `create` is true.
 | 
					 * `create` is true.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -138,12 +135,12 @@ void ttnode_set_string(TernaryTrieNode *node, const char *string) {
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param node node to perform lookup in. If node is a full leaf, the return
 | 
					 * @param node node to perform lookup in. If node is a full leaf, the return
 | 
				
			||||||
 * value will always be NULL, regardless of the value of create.
 | 
					 * value will always be NULL, regardless of the value of create.
 | 
				
			||||||
 * @param create whether to create the TernaryTrieInnerNode if it isn't present
 | 
					 * @param create whether to create the TrieInnerNode if it isn't present
 | 
				
			||||||
 * yet. If this is set to true, the function will never return NULL unless the
 | 
					 * yet. If this is set to true, the function will never return NULL unless the
 | 
				
			||||||
 * node represents a leaf with a string, because the struct and therefore the
 | 
					 * node represents a leaf with a string, because the struct and therefore the
 | 
				
			||||||
 * address is created if it doesn't exist yet.
 | 
					 * address is created if it doesn't exist yet.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
TernaryTrieNode **ttnode_search(TernaryTrieNode *node, const char c,
 | 
					TrieNode **ttnode_search(TrieNode *node, const char c,
 | 
				
			||||||
                                bool create) {
 | 
					                                bool create) {
 | 
				
			||||||
  // Full leafs will always return NULL
 | 
					  // Full leafs will always return NULL
 | 
				
			||||||
  if (node->type == 2) {
 | 
					  if (node->type == 2) {
 | 
				
			||||||
| 
						 | 
					@ -162,8 +159,8 @@ TernaryTrieNode **ttnode_search(TernaryTrieNode *node, const char c,
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TernaryTrieInnerNode *parent = node->ptr.root;
 | 
					  TrieInnerNode *parent = node->ptr.root;
 | 
				
			||||||
  TernaryTrieInnerNode *child;
 | 
					  TrieInnerNode *child;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Iterate through the tree until we either find the character or realize it's
 | 
					  // Iterate through the tree until we either find the character or realize it's
 | 
				
			||||||
  // not present in the tree
 | 
					  // not present in the tree
 | 
				
			||||||
| 
						 | 
					@ -189,7 +186,7 @@ TernaryTrieNode **ttnode_search(TernaryTrieNode *node, const char c,
 | 
				
			||||||
  // If create is true, we create the new node so that we can still return a
 | 
					  // If create is true, we create the new node so that we can still return a
 | 
				
			||||||
  // non-NULL pointer.
 | 
					  // non-NULL pointer.
 | 
				
			||||||
  if (create) {
 | 
					  if (create) {
 | 
				
			||||||
    TernaryTrieInnerNode *new_node = ttinode_init(c);
 | 
					    TrieInnerNode *new_node = ttinode_init(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c < parent->key) {
 | 
					    if (c < parent->key) {
 | 
				
			||||||
      parent->left = new_node;
 | 
					      parent->left = new_node;
 | 
				
			||||||
| 
						 | 
					@ -211,8 +208,8 @@ TernaryTrieNode **ttnode_search(TernaryTrieNode *node, const char c,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param node node to split
 | 
					 * @param node node to split
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ttnode_split(TernaryTrieNode *node) {
 | 
					void ttnode_split(TrieNode *node) {
 | 
				
			||||||
  TernaryTrieNode *new_node = ttnode_init();
 | 
					  TrieNode *new_node = ttnode_init();
 | 
				
			||||||
  char key = node->ptr.string[0];
 | 
					  char key = node->ptr.string[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // There's a chance the remaining string was only 1 character, meaning the new
 | 
					  // There's a chance the remaining string was only 1 character, meaning the new
 | 
				
			||||||
| 
						 | 
					@ -233,16 +230,16 @@ void ttnode_split(TernaryTrieNode *node) {
 | 
				
			||||||
  node->ptr.string = NULL;
 | 
					  node->ptr.string = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize node's binary tree with the correct character
 | 
					  // Initialize node's binary tree with the correct character
 | 
				
			||||||
  TernaryTrieNode **node_ptr = ttnode_search(node, key, true);
 | 
					  TrieNode **node_ptr = ttnode_search(node, key, true);
 | 
				
			||||||
  *node_ptr = new_node;
 | 
					  *node_ptr = new_node;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Remove the given character from a TernaryTrieInnerNode's subtree. The
 | 
					 * Remove the given character from a TrieInnerNode's subtree. The
 | 
				
			||||||
 * function assumes the character is indeed in the subtree.
 | 
					 * function assumes the character is indeed in the subtree.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ttinode_remove(TernaryTrieInnerNode *node, const char c) {
 | 
					void ttinode_remove(TrieInnerNode *node, const char c) {
 | 
				
			||||||
  TernaryTrieInnerNode **to_remove_ptr = &node;
 | 
					  TrieInnerNode **to_remove_ptr = &node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // We use pointers to pointers here so we can later free the removed node
 | 
					  // We use pointers to pointers here so we can later free the removed node
 | 
				
			||||||
  // without having to know what its parent is
 | 
					  // without having to know what its parent is
 | 
				
			||||||
| 
						 | 
					@ -253,11 +250,11 @@ void ttinode_remove(TernaryTrieInnerNode *node, const char c) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If the node isn't a leaf, we have to replace it with another
 | 
					  // If the node isn't a leaf, we have to replace it with another
 | 
				
			||||||
  if ((*to_remove_ptr)->left != NULL || (*to_remove_ptr)->right != NULL) {
 | 
					  if ((*to_remove_ptr)->left != NULL || (*to_remove_ptr)->right != NULL) {
 | 
				
			||||||
    TernaryTrieInnerNode *to_replace = *to_remove_ptr;
 | 
					    TrieInnerNode *to_replace = *to_remove_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Replace with its only right child
 | 
					    // Replace with its only right child
 | 
				
			||||||
    if (to_replace->left == NULL) {
 | 
					    if (to_replace->left == NULL) {
 | 
				
			||||||
      TernaryTrieInnerNode *to_remove = to_replace->right;
 | 
					      TrieInnerNode *to_remove = to_replace->right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      to_replace->key = to_remove->key;
 | 
					      to_replace->key = to_remove->key;
 | 
				
			||||||
      to_replace->next = to_remove->next;
 | 
					      to_replace->next = to_remove->next;
 | 
				
			||||||
| 
						 | 
					@ -268,7 +265,7 @@ void ttinode_remove(TernaryTrieInnerNode *node, const char c) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Replace with its only left child
 | 
					    // Replace with its only left child
 | 
				
			||||||
    else if (to_replace->right == NULL) {
 | 
					    else if (to_replace->right == NULL) {
 | 
				
			||||||
      TernaryTrieInnerNode *to_remove = to_replace->left;
 | 
					      TrieInnerNode *to_remove = to_replace->left;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      to_replace->key = to_remove->key;
 | 
					      to_replace->key = to_remove->key;
 | 
				
			||||||
      to_replace->next = to_remove->next;
 | 
					      to_replace->next = to_remove->next;
 | 
				
			||||||
| 
						 | 
					@ -279,8 +276,8 @@ void ttinode_remove(TernaryTrieInnerNode *node, const char c) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Node has two children, so replace with successor
 | 
					    // Node has two children, so replace with successor
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      TernaryTrieInnerNode *to_remove_parent = to_replace;
 | 
					      TrieInnerNode *to_remove_parent = to_replace;
 | 
				
			||||||
      TernaryTrieInnerNode *to_remove = to_replace->right;
 | 
					      TrieInnerNode *to_remove = to_replace->right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      while (to_remove->left != NULL) {
 | 
					      while (to_remove->left != NULL) {
 | 
				
			||||||
        to_remove_parent = to_remove;
 | 
					        to_remove_parent = to_remove;
 | 
				
			||||||
| 
						 | 
					@ -307,14 +304,14 @@ void ttinode_remove(TernaryTrieInnerNode *node, const char c) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Remove the given character from a TernaryTrieNode, respecting the rules
 | 
					 * Remove the given character from a TrieNode, respecting the rules
 | 
				
			||||||
 * of a binary search tree. This function assumes the character is in the search
 | 
					 * of a binary search tree. This function assumes the character is in the search
 | 
				
			||||||
 * tree.
 | 
					 * tree.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param node node to remove character from
 | 
					 * @param node node to remove character from
 | 
				
			||||||
 * @param c character to remove
 | 
					 * @param c character to remove
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ttnode_remove(TernaryTrieNode *node, const char c) {
 | 
					void ttnode_remove(TrieNode *node, const char c) {
 | 
				
			||||||
  ttinode_remove(node->ptr.root, c);
 | 
					  ttinode_remove(node->ptr.root, c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  node->size--;
 | 
					  node->size--;
 | 
				
			||||||
		Loading…
	
		Reference in New Issue