#ifndef AD3_TERNARYTRIE #define AD3_TERNARYTRIE #define DELIMITER '\0' // The compiler aligns structs to be multiple of 8 bytes. Therefore, we have a // few "free" bytes that are allocated whether we use them or not, so we might // as, hence the seemingly weird number. This is the largest number we can use // where the size of TernaryTrieNode is still 32 bytes. // // NOTE: Should not be higher than 254 or stuff will break. #define TRIE_MAX_SKIP_SIZE 13 /** * The implementation of a Ternary Trie. * * Each node should be represented by a binary tree in order to reduce the * memory usage. */ #include #include #include #include static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const size_t charset_len = sizeof(charset) - 1; // Length of randomly generated keys #define RANDOM_KEY_LENGTH_SHORT 4 #define RANDOM_KEY_LENGTH_LONG 16 /** * Type definition for the struct representing the current Trie. * * You can (and should) redefine this in your c-file with the concrete fields. */ typedef struct ttrie Trie; typedef enum trie_exit_code { Ok = 0, NotFound, AlreadyPresent, FileError } TrieExitCode; /** * Allocate & initialize a new trie, and populate it with the data from the * given data file. * * @return 0 if everything was successful, non-zero otherwise */ TrieExitCode trie_init(Trie **trie_ptr, const char *file_path); /** * De-allocate a trie by freeing the memory occupied by this trie. * * @param trie which should be freed */ void trie_free(Trie *trie); /** * Search for an entry in the trie. * * @param trie * @param entry_ptr pointer to Entry will be stored here, if found * @param key key representing the entry * @return 0 if the search was successful, 1 if not found */ TrieExitCode trie_search(Trie *trie, void **data_ptr, const char *key); /** * Add a string to this trie. * * @param trie * @param key key to represent entry with * @param entry entry to add * @return 0 if added, 1 if already in trie, something else if other errors */ TrieExitCode trie_add(Trie *trie, const char *key, void *data, uint64_t data_len); /** * Same as trie_add, but copy the data instead of taking over ownership of the * pointer. * * @param trie * @param key key to represent entry with * @param entry entry to add * @return 0 if added, 1 if already in trie, something else if other errors */ TrieExitCode trie_add_copy(Trie *trie, const char *key, void *data, uint64_t data_len); /** * Add an entry by generating a random string as the key. * * @param trie * @param entry entry to add * @param secure whether to generate a longer, more secure random key * @return pointer to the generated key. This pointer is safe to use after * unlocking the trie, and should be freed manually. */ TrieExitCode trie_add_random(Trie *trie, char **key_ptr, void *data, uint64_t data_len, bool secure); /** * Remove an entry from this trie given its key. * * @param trie * @param key key representing entry * @return true if the entry was present and has been removed, false if it was * not present */ bool trie_remove(Trie *trie, const char *key); /** * Returns the number of entries in this trie. * * @param trie * @return the number of entries in this trie */ uint64_t trie_size(Trie *trie); /* * Acquire a read lock on the trie. * * @return 0 if successful, non-zero otherwise (return value of * pthread_rwlock_rdlock) */ int trie_rlock(Trie *trie); /* * Acquire a write lock on the trie. * * @return 0 if successful, non-zero otherwise (return value of * pthread_rwlock_wrlock) */ int trie_wlock(Trie *trie); /* * Release the lock on a trie after having acquired it beforehand. * * @return 0 if successful, non-zero otherwise (return value of * pthread_rwlock_unlock) */ int trie_unlock(Trie *trie); #endif // AD3_TERNARYTRIE