/*-
* Copyright (c) 2018 The UbixOS Project.
* All rights reserved.
*
* This was developed by Christopher W. Olsen for the UbixOS Project.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice, this list of
* conditions, the following disclaimer and the list of authors.
* 2) Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions, the following disclaimer and the list of authors in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <lib/kmalloc.h>
#include <lib/kern_trie.h>
struct Trie *new_trieNode() {
struct Trie *node = (struct Trie *) kmalloc(sizeof(struct Trie));
node->isLeaf = 0;
for (int i = 0; i < CHAR_SIZE; i++)
node->character[i] = NULL;
return (node);
}
// Insert Trie
void insert_trieNode(struct Trie **head, char* str, void *e) {
// start from root node
struct Trie* curr = *head;
while (*str) {
// create a new node if path doesn't exists
if (curr->character[*str - 'a'] == NULL) {
curr->character[*str - 'a'] = new_trieNode();
}
// go to next node
curr = curr->character[*str - 'a'];
// move to next character
str++;
}
curr->e = e;
// mark current node as leaf
curr->isLeaf = 1;
}
struct Trie *search_trieNode(struct Trie *head, char *str) {
// return 0 if Trie is empty
if (head == NULL || str == NULL)
return (0);
struct Trie *curr = head;
while (*str) {
// go to next node
curr = curr->character[*str - 'a'];
// if string is invalid (reached end of path in Trie)
if (curr == NULL)
return (0);
// move to next character
str++;
}
// if current node is a leaf and we have reached the
// end of the string, return 1
return (curr);
}
// Recursive function to delete a string in Trie
int delete_trieNode(struct Trie **curr, char *str) {
// return if Trie is empty
if (*curr == NULL)
return (0);
// if we have not reached the end of the string
if (*str) {
// recurse for the node corresponding to next character in
// the string and if it returns 1, delete current node
// (if it is non-leaf)
if (*curr != NULL && (*curr)->character[*str - 'a'] != NULL && deletion(&((*curr)->character[*str - 'a']), str + 1) && (*curr)->isLeaf == 0) {
if (!haveChildren(*curr)) {
free(*curr);
(*curr) = NULL;
return (1);
}
else {
return (0);
}
}
}
// if we have reached the end of the string
if (*str == '\0' && (*curr)->isLeaf) {
// if current node is a leaf node and don't have any children
if (!haveChildren(*curr)) {
free(*curr); // delete current node
(*curr) = NULL;
return (1); // delete non-leaf parent nodes
}
// if current node is a leaf node and have children
else {
// mark current node as non-leaf node (DON'T DELETE IT)
(*curr)->isLeaf = 0;
return (0); // don't delete its parent nodes
}
}
return (0);
}
// returns 1 if given node has any children
int haveChildren(struct Trie* curr) {
for (int i = 0; i < CHAR_SIZE; i++)
if (curr->character[i])
return (1); // child found
return (0);
}