More generic use of event.
[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         memory_stack->objects = NULL;
46         memory_stack->objects_no = 0;
47
48         assert(storage != NULL);
49 }
50
51 void familia_memory_stack_dump()
52 {
53         unsigned int i;
54
55         assert(memory_stack != NULL);
56
57         fprintf(stderr, " --------------------------- ----------------- \n");
58         for (i = 0; i < memory_stack->objects_no; i++) {
59                 fprintf(stderr, "| %25s | %15s |\n", 
60                         memory_stack->objects[i]->xref_key,
61                         memory_stack->objects[i]->object ? "initialized" : "empty");
62         }
63 }
64
65 void familia_memory_stack_free()
66 {
67         if (memory_stack) {
68                 unsigned int i;
69                 for (i = 0; i < memory_stack->objects_no; i++) {
70                         free(memory_stack->objects[i]->xref_key);
71                         memory_stack->objects[i]->xref_key = NULL;
72
73                         /* We do not remove object in each element, because it
74                          * is a pointer to stored in storage memory object
75                          */
76
77                         free(memory_stack->objects[i]);
78                         memory_stack->objects[i] = NULL;
79                 }
80                 memory_stack->objects_no = 0;
81         
82                 free(memory_stack);
83                 memory_stack = NULL;
84         }
85 }
86
87 /**
88  * Adds the given object to the memory stack
89  * @param xref_key string under which the object will be found.
90  * @param object object which will be added to the memory stack
91  */
92 void _familia_memory_stack_add(char * xref_key, void * object)
93 {
94         struct familia_memory_stack_object ** tmp = NULL;
95         struct familia_memory_stack_object * element = NULL;
96         unsigned int size = 0;
97         int xref_length = 0;
98
99         xref_length = strlen(xref_key);
100         size = memory_stack->objects_no + 1;
101
102         tmp = realloc(memory_stack->objects,
103                 (size) * sizeof(struct familia_memory_stack_object *));
104
105         if (tmp) {
106                 memory_stack->objects = tmp;
107                 element = malloc(sizeof(struct familia_memory_stack_object));
108
109                 if (element) {
110                         element->xref_key = (char *)calloc(xref_length + 1, sizeof(char));
111                         strncpy(element->xref_key, xref_key, xref_length);
112                         element->object = object;
113                 }
114
115                 memory_stack->objects[memory_stack->objects_no++] = element;
116         }
117         else {
118                 debug("Failed adding parser stack element!");
119         }
120 }
121
122
123 /**
124  * Returns object stored under xref_key of the given type in the memory stack.
125  * @param xref_key string under which the object will be found.
126  * @return pointer to the found object. NULL if it was not found
127  */
128 void * _familia_memory_stack_get(char *xref_key)
129 {
130         unsigned int i;
131         for (i = 0; i < memory_stack->objects_no; i++) {
132                 if (strcmp(memory_stack->objects[i]->xref_key, xref_key) == 0) {
133                         return memory_stack->objects[i]->object;
134                 }
135         }
136
137         return NULL;
138 }
139
140 /**
141  * Creates new object stored under xref_key of the given type in the memory stack.
142  * This method always returns pointer to the newly created object.
143  * NULL is returned when there was a problem with allocating memory.
144  * @param xref_key string under which the object will be found. It should be
145  *        unique and its the user's order to make it unique.
146  * @param object_type type of the stored object
147  * @return pointer to the newly created object. NULL on memory allocation error.
148  */
149 void * _familia_memory_stack_create(char *xref_key, enum familia_storage_type type)
150 {
151         void * object = NULL;
152         struct familia_storage * storage = NULL;
153
154         storage = familia_storage_get_current();
155
156         switch(type) {
157         case FS_INDIVIDUAL:
158                 object = familia_individual_new();
159                 familia_storage_add_individual(storage, object);
160                 break;
161         case FS_FAMILY:
162                 object = familia_family_new();
163                 familia_storage_add_family(storage, object);
164                 break;
165         }
166
167         _familia_memory_stack_add(xref_key, object);
168
169         return object;
170 }
171
172 void * familia_memory_stack_find(char *xref_key, enum familia_storage_type type)
173 {
174         void * object = NULL;
175         object = _familia_memory_stack_get(xref_key);
176
177         if (!object) {
178                 object = _familia_memory_stack_create(xref_key, type);
179         }
180
181         return object;
182 }