Automatically set parent family in individual, when adding child to the family.
[familia.git] / src / memory_stack.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 /*#include "utf8tools.h"*/
6
7 #include "storage/storage.h"
8 #include "storage/individual.h"
9 #include "storage/family.h"
10
11 #include "memory_stack.h"
12
13 #include "debug.h"
14
15 struct familia_memory_stack * memory_stack = NULL;
16
17 /**
18  * Structure holding ID key - object pair.
19  */
20 struct familia_memory_stack_object {
21         /** Unique identifier parsed from the file */
22         char * xref_key;
23
24         /** Pointer to the loaded object */
25         void * object;
26 };
27
28 /**
29  * Structure holding relations between parser and program internals
30  */
31 struct familia_memory_stack {
32         /** Loaded objects from the parser */
33         struct familia_memory_stack_object  ** objects;
34
35         /** Number of objects */
36         unsigned int objects_no;
37 };
38
39 void familia_memory_stack_init()
40 {
41         struct familia_storage * storage = familia_storage_get_current();
42
43         assert(memory_stack == NULL);
44         memory_stack = (struct familia_memory_stack*)malloc(sizeof(struct familia_memory_stack));
45
46         assert(storage != NULL);
47 }
48
49 void familia_memory_stack_dump()
50 {
51         unsigned int i;
52
53         assert(memory_stack != NULL);
54
55         fprintf(stderr, " --------------------------- ----------------- \n");
56         for (i = 0; i < memory_stack->objects_no; i++) {
57                 fprintf(stderr, "| %25s | %15s |\n", 
58                         memory_stack->objects[i]->xref_key,
59                         memory_stack->objects[i]->object ? "initialized" : "empty");
60         }
61 }
62
63 void familia_memory_stack_free()
64 {
65         if (memory_stack) {
66                 unsigned int i;
67                 for (i = 0; i < memory_stack->objects_no; i++) {
68                         free(memory_stack->objects[i]->xref_key);
69                         memory_stack->objects[i]->xref_key = NULL;
70
71                         /* We do not remove object in each element, because it
72                          * is a pointer to stored in storage memory object
73                          */
74
75                         free(memory_stack->objects[i]);
76                         memory_stack->objects[i] = NULL;
77                 }
78                 memory_stack->objects_no = 0;
79         
80                 free(memory_stack);
81                 memory_stack = NULL;
82         }
83 }
84
85 /**
86  * Adds the given object to the memory stack
87  * @param xref_key string under which the object will be found.
88  * @param object object which will be added to the memory stack
89  */
90 void _familia_memory_stack_add(char * xref_key, void * object)
91 {
92         struct familia_memory_stack_object ** tmp = NULL;
93         struct familia_memory_stack_object * element = NULL;
94         unsigned int size = 0;
95         int xref_length = 0;
96
97         xref_length = strlen(xref_key);
98         size = memory_stack->objects_no + 1;
99
100         tmp = realloc(memory_stack->objects,
101                 (size) * sizeof(struct familia_memory_stack_object *));
102
103         if (tmp) {
104                 memory_stack->objects = tmp;
105                 element = malloc(sizeof(struct familia_memory_stack_object));
106
107                 if (element) {
108                         element->xref_key = (char *)calloc(xref_length + 1, sizeof(char));
109                         strncpy(element->xref_key, xref_key, xref_length);
110                         element->object = object;
111                 }
112
113                 memory_stack->objects[memory_stack->objects_no++] = element;
114         }
115         else {
116                 debug("Failed adding parser stack element!");
117         }
118 }
119
120
121 /**
122  * Returns object stored under xref_key of the given type in the memory stack.
123  * @param xref_key string under which the object will be found.
124  * @return pointer to the found object. NULL if it was not found
125  */
126 void * _familia_memory_stack_get(char *xref_key)
127 {
128         unsigned int i;
129         for (i = 0; i < memory_stack->objects_no; i++) {
130                 if (strcmp(memory_stack->objects[i]->xref_key, xref_key) == 0) {
131                         return memory_stack->objects[i]->object;
132                 }
133         }
134
135         return NULL;
136 }
137
138 /**
139  * Creates new object stored under xref_key of the given type in the memory stack.
140  * This method always returns pointer to the newly created object.
141  * NULL is returned when there was a problem with allocating memory.
142  * @param xref_key string under which the object will be found. It should be
143  *        unique and its the user's order to make it unique.
144  * @param object_type type of the stored object
145  * @return pointer to the newly created object. NULL on memory allocation error.
146  */
147 void * _familia_memory_stack_create(char *xref_key, enum familia_storage_type type)
148 {
149         void * object = NULL;
150         struct familia_storage * storage = NULL;
151
152         storage = familia_storage_get_current();
153
154         switch(type) {
155         case FS_INDIVIDUAL:
156                 object = familia_individual_new();
157                 familia_storage_add_individual(storage, object);
158                 break;
159         case FS_FAMILY:
160                 object = familia_family_new();
161                 familia_storage_add_family(storage, object);
162                 break;
163         }
164
165         _familia_memory_stack_add(xref_key, object);
166
167         return object;
168 }
169
170 void * familia_memory_stack_find(char *xref_key, enum familia_storage_type type)
171 {
172         void * object = NULL;
173         object = _familia_memory_stack_get(xref_key);
174
175         if (!object) {
176                 object = _familia_memory_stack_create(xref_key, type);
177         }
178
179         return object;
180 }