pelib  2.0.0
include/pelib/map.c
Go to the documentation of this file.
00001 /*
00002  * map.c
00003  *
00004  *  Created on: 5 Sep 2011
00005  *  Copyright 2011 Nicolas Melot
00006  *
00007  * This file is part of pelib.
00008  * 
00009  *     pelib is free software: you can redistribute it and/or modify
00010  *     it under the terms of the GNU General Public License as published by
00011  *     the Free Software Foundation, either version 3 of the License, or
00012  *     (at your option) any later version.
00013  * 
00014  *     pelib is distributed in the hope that it will be useful,
00015  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *     GNU General Public License for more details.
00018  * 
00019  *     You should have received a copy of the GNU General Public License
00020  *     along with pelib. If not, see <http://www.gnu.org/licenses/>.
00021  * 
00022  */
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <assert.h>
00027 #include <string.h>
00028 
00029 #if !(defined MAP_KEY_T && defined MAP_VALUE_T)
00030 #error Using generic map without a type
00031 #endif
00032 
00033 /*
00034 #define PAIR_KEY_T MAP_KEY_T
00035 #define PAIR_VALUE_T MAP_VALUE_T
00036 #include "pelib/pair.c"
00037 */
00038 
00039 /*
00040 #define ITERATOR_T pair_t(MAP_KEY_T, MAP_VALUE_T)
00041 #include "pelib/iterator.c"
00042 */
00043 
00044 #if 10
00045 #define debug(var) printf("[%s:%s:%d] %s = \"%s\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL)
00046 #define debug_addr(var) printf("[%s:%s:%d] %s = \"%p\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL)
00047 #define debug_int(var) printf("[%s:%s:%d] %s = \"%d\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL)
00048 #define debug_size_t(var) printf("[%s:%s:%d] %s = \"%zu\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL)
00049 #else
00050 #define debug(var)
00051 #define debug_addr(var)
00052 #define debug_int(var)
00053 #define debug_size_t(var)
00054 #endif
00055 
00056 static map_t(MAP_KEY_T, MAP_VALUE_T) *stuff;
00057 
00058 map_t(MAP_KEY_T, MAP_VALUE_T)*
00059 pelib_alloc_struct(map_t(MAP_KEY_T, MAP_VALUE_T))()
00060 {
00061         map_t(MAP_KEY_T, MAP_VALUE_T)* map;
00062 
00063         map = malloc(sizeof(map_t(MAP_KEY_T, MAP_VALUE_T)));
00064         assert(map != NULL);
00065 
00066         return map;
00067 }
00068 
00069 map_t(MAP_KEY_T, MAP_VALUE_T)*
00070 pelib_alloc(map_t(MAP_KEY_T, MAP_VALUE_T))()
00071 {
00072         map_t(MAP_KEY_T, MAP_VALUE_T)* map;
00073 
00074         map = malloc(sizeof(map_t(MAP_KEY_T, MAP_VALUE_T)));
00075         assert(map != NULL);
00076 
00077         return map;
00078 }
00079 
00080 int
00081 pelib_init(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T)* map)
00082 {
00083         map->first = NULL;
00084         map->middle = NULL;
00085         map->last = NULL;
00086 
00087         return 1;
00088 }
00089 
00090 #define pelib_map_insert_element(key, value) PELIB_CONCAT_3(pelib_, map(key, value), _insert_element)
00091 static
00092 int
00093 pelib_map_insert_element(MAP_KEY_T, MAP_VALUE_T)(map_t(MAP_KEY_T, MAP_VALUE_T) *map, iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *elem)
00094 {
00095         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *current = map->first, *previous = NULL;
00096 
00097         // If there is at least one element, then browse the list until we find the right spot
00098         // Otherwise, place the element as first and last, that is first and last pointers point
00099         // the the element and next and previous pointers of this element point to nothing.
00100         if(current != NULL)
00101         {
00102                 // browse the list until we reach the end or until we find the last element lower 
00103                 // than the element to insert
00104                 while(current != NULL && pelib_compare(MAP_KEY_T)(elem->value.key, current->value.key) > 0)
00105                 {
00106                         previous = current;
00107                         current = current->next;
00108                 }
00109 
00110                 /* Comment out the next block if you want to implement a multimap */
00111                 if(current != 0 && pelib_compare(MAP_KEY_T)(elem->value.key, current->value.key) == 0)
00112                 {
00113                         return 0;
00114                 }
00115 
00116                 // Insert element
00117                 elem->previous = previous;
00118                 elem->next = current;
00119                 if(previous != NULL)
00120                 {
00121                         previous->next = elem;
00122                 }
00123 
00124                 // Update tail if the element is insert last
00125                 // Otherwise update next element's pointer to
00126                 // previous element (the newly inserted one)
00127                 if(current == NULL)
00128                 {
00129                         map->last = elem;
00130                 }
00131                 else
00132                 {
00133                         if(current == map->first)
00134                         {
00135                                 map->first = elem;
00136                         }
00137                         current->previous = elem;
00138                 }
00139         }
00140         else
00141         {
00142                 elem->next = NULL;
00143                 elem->previous = NULL;
00144                 map->first = elem;
00145                 map->last = elem;
00146         }
00147 
00148         return 1;
00149 }
00150 
00151 int
00152 pelib_map_insert(MAP_KEY_T, MAP_VALUE_T)(map_t(MAP_KEY_T, MAP_VALUE_T)* map, pair_t(MAP_KEY_T, MAP_VALUE_T) value)
00153 {
00154         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *new = pelib_alloc(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)))();
00155         pelib_init(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)))(new);
00156         pelib_copy(pair_t(MAP_KEY_T, MAP_VALUE_T))(value, &new->value);
00157         if(!pelib_map_insert_element(MAP_KEY_T, MAP_VALUE_T)(map, new))
00158         {
00159                 pelib_free(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)))(new);
00160                 return 0;
00161         }
00162         else
00163         {
00164                 return 1;
00165         }
00166 }
00167 
00168 int
00169 pelib_copy(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T) src, map_t(MAP_KEY_T, MAP_VALUE_T)* dst)
00170 {
00171         size_t i;
00172 
00173         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *elem = src.last;
00174         while(elem != NULL)
00175         {
00176                 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *cpy = pelib_alloc(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)))();
00177                 pelib_copy(pair_t(MAP_KEY_T, MAP_VALUE_T))(elem->value, &cpy->value);
00178                 pelib_map_insert_element(MAP_KEY_T, MAP_VALUE_T)(dst, cpy);
00179                 elem = elem->previous;
00180         }
00181 
00182         return 0;
00183 }
00184 
00185 #define map_length_debug printf("[PELIB:%s:%s:%d] i = %d\n", __FILE__, __FUNCTION__, __LINE__, i);
00186 #define map_length_pre_debug printf("[PELIB:%s:%s:%d] length = %d\n", __FILE__, __FUNCTION__, __LINE__, pelib_map_length(MAP_KEY_T, MAP_VALUE_T)(&map));
00187 char*
00188 pelib_string(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T) map)
00189 {
00190         char *str, *grow, *elem;
00191         size_t i;
00192         str = malloc(3 * sizeof(char));
00193         sprintf(str, "[");
00194 
00195         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *el = map.first;
00196         while(el != NULL && el->next != NULL)
00197         {
00198                 elem = pelib_string(pair_t(MAP_KEY_T, MAP_VALUE_T))(el->value);
00199                 grow = malloc((strlen(str) + 1) * sizeof(char));
00200                 sprintf(grow, "%s", str);
00201 
00202                 free(str);
00203                 str = malloc(strlen(grow) + 1 + strlen(elem) + 1);
00204                 sprintf(str, "%s%s:", grow, elem);
00205                 free(elem);
00206                 free(grow);
00207                 el = el->next;
00208         }
00209         while(el != NULL)
00210         {
00211                 elem = pelib_string(pair_t(MAP_KEY_T, MAP_VALUE_T))(el->value);
00212                 grow = malloc((strlen(str) + 1) * sizeof(char));
00213                 sprintf(grow, "%s", str);
00214 
00215                 free(str);
00216                 str = malloc(strlen(grow) + 1 + strlen(elem) + 1);
00217                 sprintf(str, "%s%s", grow, elem);
00218                 free(elem);
00219                 free(grow);
00220 
00221                 el = el->next;
00222         }
00223 
00224         grow = malloc((strlen(str) + 1) * sizeof(char));
00225         sprintf(grow, "%s", str);
00226         sprintf(str, "%s]", grow);
00227         free(grow);
00228 
00229         return str;
00230 }
00231 
00232 char*
00233 pelib_string_detail(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T) map, int level)
00234 {
00235         if(level == 0)
00236         {
00237                 return pelib_string(map_t(MAP_KEY_T, MAP_VALUE_T))(map);
00238         }
00239         else
00240         {
00241                 // Bring it on
00242                 char *str, *grow, *elem;
00243                 size_t i;
00244                 str = malloc(3 * sizeof(char));
00245                 sprintf(str, "[");
00246                 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *el = map.first;
00247                 
00248                 while(el != NULL && el->next != NULL)
00249                 {
00250                         elem = pelib_string_detail(pair_t(MAP_KEY_T, MAP_VALUE_T))(el->value, level);
00251                         grow = malloc((strlen(str) + 1) * sizeof(char));
00252                         sprintf(grow, "%s", str);
00253 
00254                         free(str);
00255                         str = malloc(strlen(grow) + 1 + strlen(elem) + 1);
00256                         sprintf(str, "%s%s:", grow, elem);
00257                         free(elem);
00258                         free(grow);
00259                 }
00260                 while(el != NULL)
00261                 {
00262                         elem = pelib_string_detail(pair_t(MAP_KEY_T, MAP_VALUE_T))(el->value, level);
00263                         grow = malloc((strlen(str) + 1) * sizeof(char));
00264                         sprintf(grow, "%s", str);
00265 
00266                         free(str);
00267                         str = malloc(strlen(grow) + 1 + strlen(elem) + 1);
00268                         sprintf(str, "%s%s", grow, elem);
00269                         free(elem);
00270                         free(grow);
00271                 }
00272 
00273                 grow = malloc((strlen(str) + 1) * sizeof(char));
00274                 sprintf(grow, "%s", str);
00275                 sprintf(str, "%s]", grow);
00276                 free(grow);
00277 
00278                 return str;
00279         }
00280 }
00281 
00282 FILE*
00283 pelib_printf(map_t(MAP_KEY_T, MAP_VALUE_T))(FILE* stream, map_t(MAP_KEY_T, MAP_VALUE_T) map)
00284 {
00285         char * str;
00286         str = pelib_string(map_t(MAP_KEY_T, MAP_VALUE_T))(map);
00287 
00288         fprintf(stream, "%s\n", str);
00289         free(str);
00290 
00291         return stream;
00292 }
00293 
00294 FILE*
00295 pelib_printf_detail(map_t(MAP_KEY_T, MAP_VALUE_T))(FILE* stream, map_t(MAP_KEY_T, MAP_VALUE_T) map, int level)
00296 {
00297         char * str;
00298         str = pelib_string_detail(map_t(MAP_KEY_T, MAP_VALUE_T))(map, level);
00299 
00300         fprintf(stream, "%s\n", str);
00301         free(str);
00302 
00303         return stream;
00304 }
00305 
00306 int
00307 pelib_destroy(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T) map)
00308 {
00309         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *elem = map.first;
00310         while(elem != NULL)
00311         {
00312                 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *current = elem;
00313                 elem = elem->next;
00314                 pelib_destroy(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)))(*current);
00315         }
00316         return 1;
00317 }
00318 
00319 int
00320 pelib_free_buffer(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T)* map)
00321 {
00322         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *elem = map->first;
00323         while(elem != NULL)
00324         {
00325                 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *current = elem;
00326                 elem = elem->next;
00327                 pelib_free(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)))(current);                
00328         }
00329         return 1;
00330 }
00331 
00332 int
00333 pelib_free_struct(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T)* map)
00334 {
00335         free(map);
00336         return 1;
00337 }
00338 
00339 int
00340 pelib_free(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T)* map)
00341 {
00342         pelib_free_buffer(map_t(MAP_KEY_T, MAP_VALUE_T))(map);
00343         pelib_free_struct(map_t(MAP_KEY_T, MAP_VALUE_T))(map);
00344         return 1;
00345 }
00346 
00347 int
00348 pelib_compare(map_t(MAP_KEY_T, MAP_VALUE_T))(map_t(MAP_KEY_T, MAP_VALUE_T) a1, map_t(MAP_KEY_T, MAP_VALUE_T) a2)
00349 {
00350         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *e1 = a1.first;
00351         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *e2 = a2.first;
00352 
00353         while(e1 != NULL && e2 != NULL && pelib_compare(pair_t(MAP_KEY_T, MAP_VALUE_T))(e1->value, e2->value) == 0)
00354         {
00355                 e1 = e1->next;
00356                 e2 = e2->next;
00357         }
00358 
00359         if(e1 == NULL && e2 != NULL)
00360         {
00361                 return 1;
00362         }
00363         else if(e1 != NULL && e2 == NULL)
00364         {
00365                 return -1;
00366         }
00367         else return pelib_compare(pair_t(MAP_KEY_T, MAP_VALUE_T))(e1->value, e2->value);
00368 }
00369 
00370 /* Returns the first element in map */
00371 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T))*
00372 pelib_map_begin(MAP_KEY_T, MAP_VALUE_T)(map_t(MAP_KEY_T, MAP_VALUE_T) *map)
00373 {
00374         return map->first;
00375 }
00376 
00377 /* Returns the first element in map */
00378 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T))*
00379 pelib_map_end(MAP_KEY_T, MAP_VALUE_T)(map_t(MAP_KEY_T, MAP_VALUE_T) *map)
00380 {
00381         return NULL;
00382 }
00383 
00384 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T))*
00385 pelib_map_next(MAP_KEY_T, MAP_VALUE_T)(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *i)
00386 {
00387         return pelib_iterator_next(pair_t(MAP_KEY_T, MAP_VALUE_T))(i);
00388 }
00389 
00390 pair_t(MAP_KEY_T, MAP_VALUE_T)
00391 pelib_map_read(MAP_KEY_T, MAP_VALUE_T)(iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *i)
00392 {
00393         return pelib_iterator_read(pair_t(MAP_KEY_T, MAP_VALUE_T))(i);
00394 }
00395 
00396 iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T))*
00397 pelib_map_find(MAP_KEY_T, MAP_VALUE_T)(map_t(MAP_KEY_T, MAP_VALUE_T) *map, MAP_KEY_T key)
00398 {
00399         map_iterator_t(MAP_KEY_T, MAP_VALUE_T) *i;
00400         for(i = pelib_map_begin(MAP_KEY_T, MAP_VALUE_T)(map); i != pelib_map_end(MAP_KEY_T, MAP_VALUE_T)(map); i = pelib_map_next(MAP_KEY_T, MAP_VALUE_T)(i))
00401         {
00402                 MAP_KEY_T elem_key = pelib_map_read(MAP_KEY_T, MAP_VALUE_T)(i).key;
00403                 if(pelib_compare(MAP_KEY_T)(key, elem_key) == 0)
00404                 {
00405                         return i;
00406                 }
00407         }
00408 
00409         return NULL;
00410 }
00411 
00412 size_t
00413 pelib_map_size(MAP_KEY_T, MAP_VALUE_T)(map_t(MAP_KEY_T, MAP_VALUE_T) *map)
00414 {
00415         size_t size = 0;
00416         iterator_t(pair_t(MAP_KEY_T, MAP_VALUE_T)) *i;
00417 
00418         // Iterate from the beginning until we find the end
00419         for(i = pelib_map_begin(MAP_KEY_T, MAP_VALUE_T)(map); i != pelib_map_end(MAP_KEY_T, MAP_VALUE_T)(map); i = pelib_map_next(MAP_KEY_T, MAP_VALUE_T)(i), size++);
00420 
00421         return size;
00422 }
00423 
00424 #undef MAP_KEY_T
00425 #undef MAP_VALUE_T
00426