#include "node.h" #include #include #include NOD_Node *NOD_CreateNode(char *name){ return NOD_CreateNodeEX("Node", name); } NOD_Node *NOD_CreateNodeEX(char* type, char *name){ NOD_Node *node = malloc(sizeof(NOD_Node)); if(node != NULL){ node->name = name; node->type = type; node->parent = NULL; node->childv = NULL; node->childc = 0; } return node; } void NOD_DestroyNode(NOD_Node *node){ if(node != NULL){ /*printf("NOD_Info: Deleting node \"%s\"\n", node->name);*/ /** Cleanup dependencies on this node by its parent */ NOD_NodeUnparent(node); free(node); } } void NOD_DestroyNodeBranch(NOD_Node *node){ if(node != NULL){ for(int i = 0; i < node->childc && node->childv != NULL; i++){ NOD_DestroyNodeBranch(node->childv[i]); } NOD_DestroyNode(node); } } /* You call this by calling NOD_NodeAddChild, see header */ void _nod_add_child(NOD_Node *parent, NOD_Node *child){ if(parent != NULL && child != NULL){ /** Prevent recursion */ if(parent == child){ fprintf(stderr, "NOD_Warning: A node cannot be added to itself.\n"); return; } ///** Don't allow tree-breaking reparenting */ //NOD_Node *tmp_parent = parent->parent; //while(tmp_parent != NULL){ //if(tmp_parent == child){ //fprintf(stderr, "NOD_Warning: Can't add a parent of a node as its child.\n"); //return; //} //tmp_parent = tmp_parent->parent; //} /** Check if child already in vector */ for(int i = 0; i < parent->childc; i++){ if(parent->childv[i] == child){ fprintf(stderr, "NOD_Warning: Adding child \"%s\" already in the vector \"%s\".\n", child->name, parent->name); return; } } /** If it had a parent before, unparent before reparenting */ if(child->parent != NULL && child->parent != parent){ printf("NOD_Info: Reparenting node \"%s\"\n", child->name); NOD_NodeUnparent(child); } /** Create child vector if it hasn't been used */ if(parent->childc <= 0 || parent->childv == NULL){ parent->childv = malloc(sizeof(child)); if(parent->childv != NULL){ parent->childv[0] = child; parent->childc = 1; child->parent = parent; return; } else{ fprintf(stderr, "NOD_Error: Failed to allocate space on \"%s\"for child vector \"%s\"\n", parent->name, child->name); } } /** If there is a blank space, use it */ for(int i = 0; i < parent->childc; i++){ if(parent->childv[i] == NULL){ printf("NOD_Info: Reused blank space for child :D\n"); parent->childv[i] = child; child->parent = parent; return; } } /** If not, reallocate vector to fit the child */ parent->childv = realloc(parent->childv, sizeof(child) *(parent->childc+1)); if(parent->childv != NULL){ parent->childv[parent->childc] = child; parent->childc++; child->parent = parent; } else{ fprintf(stderr, "NOD_Error: Failed to reallocate space on \"%s\"for child vector \"%s\"\n", parent->name, child->name); } } } /* You call this by calling NOD_NodeUnparent, see header */ void _nod_unparent (NOD_Node *node){ if(node != NULL && node->parent != NULL){ NOD_Node *parent = node->parent; for(int i = 0; i < parent->childc; i ++){ if(parent->childv[i] == node){ parent->childv[i] = NULL; /* Free allocated memory if last child */ if(i + 1 == parent->childc){ /*fprintf(stderr, "NOD_Debug: Freeing last child \"%s\" of vector \"%s\"...\n", node->name, parent->name);*/ parent->childv = realloc(parent->childv, sizeof(node) *parent->childc); parent->childc--; } } } node->parent = NULL; } } int get_child_pos(NOD_Node *node){ int count = 0; if(node != NULL && node->parent != NULL){ for(int i = 0; i < node->parent->childc; i++){ if(node->parent->childv[i] == node) return count; count++; } return 0; } return -1; } void nodetree_print_branch(NOD_Node *node, char* level){ if(node != NULL){ for(int i = 0; level[i] != '\0'; i++){ if(level[i] == 'y') printf("│ "); else printf(" "); } if(node->parent != NULL){ if(get_child_pos(node)+1 != node->parent->childc){ printf("├─ "); strcat(level, "y"); } else{ printf("└─ "); strcat(level, "n"); } } printf("%s (%s)\n", node->name, node->type); /** Recurse */ for(int i = 0; i < node->childc; i++){ nodetree_print_branch(node->childv[i], level); } if(node->parent != NULL){ level = (char *)realloc(level, strlen(level) * sizeof(char)); level[strlen(level)-1] = '\0'; } } } /* You call this by calling NOD_PrintNodeTree, see header */ void _nod_print_tree(NOD_Node *node){ if(node != NULL){ char* level = strdup(""); printf("%s (%s)\n", node->name, node->type); for(int i = 0; i < node->childc; i++){ nodetree_print_branch(node->childv[i], level); } free(level); } } /* You call this by calling NOD_NodeChildCount, see header */ int _nod_child_count(NOD_Node *node){ int count = 0; for(int i = 0; i < node->childc; i++){ if(node->childv[i] != NULL) count++; } return count; }