return (ft_strcmp(a->name, b->name));
}
-union u_part_spec
+typedef union u_part_spec
{
char *name;
const t_part *part;
-};
-
-typedef struct s_part_spec
-{
- int is_string_tag;
- union u_part_spec spec;
-} t_part_spec;
-
-const char *get_name_from_spec(t_part_spec spec)
-{
- if (spec.is_string_tag)
- return (spec.spec.name);
- return (spec.spec.part->name);
-}
-
-const t_part *get_part_from_spec(t_part_spec spec)
-{
- if (spec.is_string_tag)
- return (NULL);
- return (spec.spec.part);
-}
+} t_part_spec;
int cmp_strings_void(const void *a_v, const void *b_v)
{
return ;
}
+void free_part_with_used_names(t_part *part)
+{
+ if (!part)
+ return ;
+ free(part->name);
+ ft_vec_free(&part->nodes, free_node);
+ ft_vec_free(&part->mosfets, NULL);
+ ft_dict_free(&part->used_parts, free_string_void, free_string_void);
+ ft_dict_free(&part->io_to_node, free_string_void, NULL);
+ return ;
+}
+
+void free_part_with_used_names_void(void *part)
+{
+ free_part_with_used_names(part);
+ return ;
+}
+
int write_used_part(t_part *part, const t_parse_tree_node *part_reference)
{
char *specific_name;
t_part_spec part_spec;
specific_name = ft_strdup(ft_cget_child_deep(part_reference, 3, 0, 0, 0)->token.str);
- part_spec.is_string_tag = 1;
- part_spec.spec.name = ft_strdup(ft_cget_child_deep(part_reference, 3, 2, 0, 0)->token.str);
- if (specific_name && part_spec.spec.name
+ part_spec.name = ft_strdup(ft_cget_child_deep(part_reference, 3, 2, 0, 0)->token.str);
+ if (specific_name && part_spec.name
&& ft_dict_insert(&part->used_parts, &specific_name, &part_spec) == success)
return (0);
free(specific_name);
- free(part_spec.spec.name);
+ free(part_spec.name);
return (1);
}
typedef t_rbtree t_catalog;
return (ft_rbtree_insert(part_catalog, part) != success);
}
+// This works because part name is the first member of a part and there can
+// be no padding before the first member of a struct
+//
+// Thinking about it this is an easy way to use rbtrees as dicts...
+t_part *access_catalog(t_catalog *part_catalog, const char *part_name)
+{
+ return (ft_rbtree_search(part_catalog, &part_name));
+}
+
void free_catalog(t_catalog *part_catalog)
{
ft_rbtree_free(part_catalog, free_part_void);
return (0);
}
+void free_unchanged_part_of_catalog(t_rbtree_traversal *traversal, t_catalog *part_catalog)
+{
+ t_part *part;
+
+ part = ft_rbtree_traverse(traversal);
+ while (part)
+ {
+ ft_rbtree_delete(part_catalog, part, free_part_with_used_names_void);
+ part = ft_rbtree_traverse(traversal);
+ }
+ return ;
+}
+
+// The following is exactly what one should not do - using the implementation details
+// instead of the interface
+//
+// I first wanted to create the FETs as static consts (as per the Norm).
+// But they are not possible to initialize because the nodes hold pointers to mosfets.
+//
+// So I had to do static var. But I did not want to allocate any space for that,
+// because I would need to clean the memory for Valgrind not to cry.
+//
+// So I am doing this thing... Because of the challenge of adhering to the Norm (to the interesting part).
+static const char *const g_gate_str = "gate";
+static const char *const g_drain_str = "drain";
+static const char *const g_source_str = "source";
+static const char g_p_name[] = "p";
+static const char g_n_name[] = "n";
+
+// IO needs to hold node id instead of pointer
+#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_node *))
+#define G_COMPLETE_SIZE_OF_FET_PART (sizeof(t_part) + 3 * (sizeof(t_node)) + sizeof(t_id) + sizeof(t_mosfet) + 3 * G_SIZE_OF_IO_NODE)
+
+void init_fet_nodes(t_part *fet, t_node *nodes, t_id *mosfet)
+{
+ size_t i = 0;
+ t_node *node;
+
+ fet->nodes.capacity = 3;
+ fet->nodes.size = 0;
+ fet->nodes.el_size = sizeof(t_node);
+ fet->nodes.vec = nodes;
+ while (i < 3)
+ {
+ node = add_node(&fet->nodes, floating);
+ node->connected_gates.capacity = 1;
+ node->connected_gates.vec = mosfet;
+ node->connected.capacity = 1;
+ node->connected.vec = mosfet;
+ ++i;
+ }
+ return ;
+}
+
+void init_fet_mosfet(t_part *fet, t_mosfet *mosfet, t_type type)
+{
+ if (type == p)
+ fet->name = (char *)g_p_name;
+ else
+ fet->name = (char *)g_n_name;
+ fet->mosfets.capacity = 1;
+ fet->mosfets.size = 0;
+ fet->mosfets.el_size = sizeof(t_mosfet);
+ fet->mosfets.vec = mosfet;
+ add_mosfet(&fet->mosfets, type, (t_position){.x = 0, .y = 0}, RIGHT);
+ return ;
+}
+
+void init_fet_single_io(t_part *fet, t_rbtree_node *io_node, t_node *node, t_terminal terminal)
+{
+ t_mosfet *mosfet;
+
+ mosfet = node->connected.vec;
+ io_node->tree = &fet->io_to_node.tree;
+ io_node->parent = NULL;
+ io_node->is_black = 1;
+ io_node->left = NULL;
+ io_node->right = NULL;
+ ft_memcpy((char *)&io_node->data + sizeof(char *), &node, sizeof(t_node *));
+ if (terminal == source)
+ {
+ bind_fet_node(&fet->nodes, mosfet, node, source);
+ ft_memcpy(&io_node->data, &g_source_str, sizeof(char *));
+ }
+ else if (terminal == gate)
+ {
+ bind_fet_node(&fet->nodes, mosfet, node, gate);
+ ft_memcpy(&io_node->data, &g_gate_str, sizeof(char *));
+ }
+ else
+ {
+ bind_fet_node(&fet->nodes, mosfet, node, drain);
+ ft_memcpy(&io_node->data, &g_drain_str, sizeof(char *));
+ }
+}
+
+void build_tree(t_part *fet, t_rbtree_node *left, t_rbtree_node *root, t_rbtree_node *right)
+{
+ root->left = left;
+ root->right = right;
+ right->parent = root;
+ left->parent = root;
+ fet->io_to_node.tree.root = root;
+ return ;
+}
+
+void init_fet_io(t_part *fet, t_rbtree_node *io_node_source)
+{
+ t_rbtree_node *const io_node_gate = (t_rbtree_node *)((char *)io_node_source + G_SIZE_OF_IO_NODE);
+ t_rbtree_node *const io_node_drain = (t_rbtree_node *)((char *)io_node_gate + G_SIZE_OF_IO_NODE);
+ const int source_gate_cmp = cmp_strings_void(&g_source_str, &g_gate_str);
+ const int gate_drain_cmp = cmp_strings_void(&g_gate_str, &g_drain_str);
+ const int drain_source_cmp = cmp_strings_void(&g_drain_str, &g_source_str);
+
+ ft_dict_init(&fet->io_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void);
+ init_fet_single_io(fet, io_node_source, ft_vec_access(&fet->nodes, 0), source);
+ init_fet_single_io(fet, io_node_gate, ft_vec_access(&fet->nodes, 1), gate);
+ init_fet_single_io(fet, io_node_drain, ft_vec_access(&fet->nodes, 2), drain);
+ if (drain_source_cmp < 0 && source_gate_cmp < 0)
+ build_tree(fet, io_node_drain, io_node_source, io_node_gate);
+ else if (source_gate_cmp < 0 && gate_drain_cmp < 0)
+ build_tree(fet, io_node_source, io_node_gate, io_node_drain);
+ else if (gate_drain_cmp < 0 && drain_source_cmp < 0)
+ build_tree(fet, io_node_gate, io_node_drain, io_node_source);
+ else if (drain_source_cmp > 0 && source_gate_cmp > 0)
+ build_tree(fet, io_node_gate, io_node_source, io_node_drain);
+ else if (source_gate_cmp > 0 && gate_drain_cmp > 0)
+ build_tree(fet, io_node_drain, io_node_gate, io_node_source);
+ else if (gate_drain_cmp > 0 && drain_source_cmp > 0)
+ build_tree(fet, io_node_source, io_node_drain, io_node_gate);
+ return ;
+}
+
+void initialize_fet_part(t_part *fet, t_type type)
+{
+ t_node *const nodes = (t_node *)((char *)fet + sizeof(t_part));
+ t_id *const mosfet_id = (t_id *)((char *)nodes + 3 * sizeof(t_node));
+ t_mosfet *const mosfet = (t_mosfet *)((char *)mosfet_id + sizeof(t_id));
+ t_rbtree_node *const io_nodes = (t_rbtree_node *)((char *)mosfet + sizeof(t_mosfet));
+
+ init_fet_nodes(fet, nodes, mosfet_id);
+ init_fet_mosfet(fet, mosfet, type);
+ init_fet_io(fet, io_nodes);
+}
+
+const t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name)
+{
+ static char memory_for_fets[2 * G_COMPLETE_SIZE_OF_FET_PART];
+ static t_part *nfet_part = NULL;
+ static t_part *pfet_part = NULL;
+
+ if (nfet_part == NULL)
+ {
+ nfet_part = (t_part *)memory_for_fets;
+ initialize_fet_part(nfet_part, n);
+ pfet_part = (t_part *)(memory_for_fets + G_COMPLETE_SIZE_OF_FET_PART);
+ initialize_fet_part(pfet_part, p);
+ }
+ if (!ft_strcmp(part_name, "n"))
+ return (nfet_part);
+ if (!ft_strcmp(part_name, "p"))
+ return (pfet_part);
+ return (access_catalog(parts_catalog, part_name));
+}
+
+int rebind_names_to_parts(t_catalog *parts_catalog)
+{
+ t_rbtree_traversal parts_traversal;
+ t_dict_traversal used_parts_traversal;
+ t_part *part;
+ t_part_spec *part_spec;
+ char *part_name;
+
+ if (ft_rbtree_traversal_init(&parts_traversal, parts_catalog, inorder) != success)
+ return (1);
+ part = ft_rbtree_traverse(&parts_traversal);
+ while (part)
+ {
+ if (ft_dict_traversal_init(&used_parts_traversal, &part->used_parts) != success)
+ {
+ free_unchanged_part_of_catalog(&parts_traversal, parts_catalog);
+ return (1);
+ }
+ part_spec = ft_dict_traverse(&used_parts_traversal);
+ while (part_spec)
+ {
+ part_name = part_spec->name;
+ part_spec->part = get_part_from_name(parts_catalog, part_name);
+ free(part_name);
+ if (!part_spec->part)
+ {
+ free_unchanged_part_of_catalog(&parts_traversal, parts_catalog);
+ part_spec = ft_dict_traverse(&used_parts_traversal);
+ while (part_spec)
+ {
+ free(part_spec->name);
+ part_spec = ft_dict_traverse(&used_parts_traversal);
+ }
+ return (1);
+ }
+ part_spec = ft_dict_traverse(&used_parts_traversal);
+ }
+ part = ft_rbtree_traverse(&parts_traversal);
+ }
+ return (0);
+}
+
int construct_new_graph(t_parse_tree_node *parse_tree, __attribute__((unused)) t_vec *nodes, __attribute__((unused)) t_vec *mosfets)
{
t_catalog part_catalog;
init_catalog(&part_catalog);
extract_used_names(&part_catalog, parse_tree);
+ rebind_names_to_parts(&part_catalog);
//build_graphs(&part_catalog, parse_tree);
//transfer_main(&part_catalog, nodes, mosfets);
free_catalog(&part_catalog);