Main Page | Data Structures | File List | Data Fields | Globals

gcontainer.c

Go to the documentation of this file.
00001 /*
00002  * luau (Lib Update/Auto-Update): Simple Update Library
00003  * Copyright (C) 2003  David Eklund
00004  *
00005  * - This library is free software; you can redistribute it and/or             -
00006  * - modify it under the terms of the GNU Lesser General Public                -
00007  * - License as published by the Free Software Foundation; either              -
00008  * - version 2.1 of the License, or (at your option) any later version.        -
00009  * -                                                                           -
00010  * - This library is distributed in the hope that it will be useful,           -
00011  * - but WITHOUT ANY WARRANTY; without even the implied warranty of            -
00012  * - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         -
00013  * - Lesser General Public License for more details.                           -
00014  * -                                                                           -
00015  * - You should have received a copy of the GNU Lesser General Public          -
00016  * - License along with this library; if not, write to the Free Software       -
00017  * - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #  include <config.h>
00022 #endif
00023 
00024 #include <glib.h>
00025 
00026 #include "gcontainer.h"
00027 #include "error.h"
00028 #include "util.h"
00029 
00030 static void iterNext(GIterator *iter);
00031 static void iterPrev(GIterator *iter);
00032 
00033 GContainer *
00034 g_container_new(GContType type) {
00035         GContainer *container;
00036         
00037         container = g_malloc(sizeof(GContainer));
00038         container->type = type;
00039         container->len = 0;
00040         
00041         if (type == GCONT_PTR_ARRAY)
00042                 container->data = g_ptr_array_new();
00043         else if (type == GCONT_LIST || type == GCONT_SLIST)
00044                 container->data = NULL;
00045         else {
00046                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00047                 g_free(container);
00048                 container = NULL;
00049         }
00050         
00051         return container;
00052 }
00053 
00054 GContainer *
00055 g_container_new_from_data(GContType type, void *data) {
00056         GContainer *container;
00057         
00058         if (data == NULL)
00059                 return NULL;
00060         
00061         container = g_malloc(sizeof(GContainer));
00062         container->type = type;
00063         container->data = data;
00064 
00065         if (type == GCONT_PTR_ARRAY)
00066                 container->len = ((GPtrArray*)data)->len;
00067         else if (type == GCONT_LIST)
00068                 container->len = g_list_length(data);
00069         else if (type == GCONT_SLIST)
00070                 container->len = g_slist_length(data);
00071         else {
00072                 ERROR("Internal Error: Unrecognized type (%d)", type);
00073                 container->len = 0;
00074         }
00075         
00076         return container;
00077 }
00078 
00079 void
00080 g_container_add(GContainer *container, const gpointer data) {
00081         container->len++;
00082         
00083         if (container->type == GCONT_PTR_ARRAY)
00084                 g_ptr_array_add(container->data, data);
00085         else if (container->type == GCONT_LIST)
00086                 container->data = g_list_append(container->data, data);
00087         else if (container->type == GCONT_SLIST)
00088                 container->data = g_slist_append(container->data, data);
00089         else
00090                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00091 }
00092 
00093 gboolean
00094 g_container_remove(GContainer *container, const gpointer data) {
00095         gboolean result;
00096         int newlen;
00097         
00098         /* Unfortunately here we have to recompute the size after each remove operation for
00099            list and slist types because glib doesn't let us know if the operation was successful
00100            or not */
00101         if (container->type == GCONT_PTR_ARRAY) {
00102                 result = g_ptr_array_remove(container->data, data);
00103                 if (result) container->len--;
00104         } else if (container->type == GCONT_LIST) {
00105                 container->data = g_list_remove(container->data, data);
00106                 newlen = g_list_length(container->data);
00107                 result = (newlen != container->len);
00108                 container->len = newlen;
00109         } else if (container->type == GCONT_SLIST) {
00110                 container->data = g_slist_remove(container->data, data);
00111                 newlen = g_slist_length(container->data);
00112                 result = (newlen != container->len);
00113                 container->len = newlen;
00114         } else {
00115                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00116                 result = FALSE;
00117         }
00118         
00119         return result;
00120 }
00121 
00122 gboolean
00123 g_container_remove_fast(GContainer *container, const gpointer data) {
00124         gboolean result;
00125         
00126         if (container->type == GCONT_PTR_ARRAY) {
00127                 result = g_ptr_array_remove_fast(container->data, data);
00128                 if (result) container->len--;
00129         } else {
00130                 result = g_container_remove(container, data);
00131         }
00132         
00133         return result;
00134 }
00135 
00136 gpointer
00137 g_container_remove_index(GContainer *container, guint index) {
00138         gpointer data;
00139         
00140         if (index >= container->len) {
00141                 ERROR("Index out of bounds");
00142                 return NULL;
00143         }
00144         
00145         container->len--;
00146         
00147         if (container->type == GCONT_PTR_ARRAY)
00148                 data = g_ptr_array_remove_index(container->data, index);
00149         else if (container->type == GCONT_LIST) {
00150                 data = g_list_nth_data(container->data, index);
00151                 container->data = g_list_remove(container->data, data);
00152         } else if (container->type == GCONT_SLIST) {
00153                 data = g_slist_nth_data(container->data, index);
00154                 container->data = g_slist_remove(container->data, data);
00155         } else {
00156                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00157                 data = NULL;
00158         }
00159         
00160         return data;
00161 }
00162 
00163 gpointer
00164 g_container_remove_index_fast(GContainer *container, guint index) {
00165         if (index >= container->len) {
00166                 ERROR("Index out of bounds");
00167                 return NULL;
00168         }
00169         
00170         if (container->type == GCONT_PTR_ARRAY) {
00171                 container->len--;
00172                 return g_ptr_array_remove_index_fast(container->data, index);
00173         } else
00174                 return g_container_remove_index(container, index);
00175 }
00176 
00177 gpointer
00178 g_container_index(const GContainer *container, guint index) {
00179         if (index >= container->len) {
00180                 ERROR("Index out of bounds");
00181                 return NULL;
00182         }
00183         
00184         if (container->type == GCONT_PTR_ARRAY)
00185                 return g_ptr_array_index(((GPtrArray*)container->data), index);
00186         else if (container->type == GCONT_LIST)
00187                 return g_list_nth_data(container->data, index);
00188         else if (container->type == GCONT_SLIST)
00189                 return g_slist_nth_data(container->data, index);
00190         else {
00191                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00192                 return NULL;
00193         }
00194 }
00195 
00196 gboolean
00197 g_container_get_iter(GIterator *iter, const GContainer *container) {
00198         iter->index = 0;
00199         iter->type = container->type;
00200         
00201         if (container->type == GCONT_PTR_ARRAY)
00202                 iter->data.array = (GPtrArray*)container->data;
00203         else if (container->type == GCONT_LIST) {
00204                 iter->data.list.curr = (GList*)container->data;
00205                 iter->data.list.last = g_list_last(container->data);
00206         } else if (container->type == GCONT_SLIST)
00207                 iter->data.slistPtr = container->data;
00208         else {
00209                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00210                 return FALSE;
00211         }
00212         
00213         return TRUE;
00214 }
00215 
00216 gboolean
00217 g_container_get_iter_last(GIterator *iter, const GContainer *container) {
00218         iter->index = container->len;
00219         iter->type = container->type;
00220         
00221         if (container->type == GCONT_PTR_ARRAY)
00222                 iter->data.array = (GPtrArray*)container->data;
00223         else if (container->type == GCONT_LIST) {
00224                 iter->data.list.curr = NULL; 
00225                 iter->data.list.last = g_list_last(container->data);
00226                 /* iter->origList = container->data; */
00227         } else if (container->type == GCONT_SLIST) {
00228                 iter->data.slistPtr = g_slist_last(container->data);
00229         } else {
00230                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00231                 return FALSE;
00232         }
00233         
00234         return TRUE;
00235 }
00236 
00237 gpointer
00238 g_iterator_get(const GIterator *iter) {
00239         if (iter->type == GCONT_PTR_ARRAY)
00240                 return g_ptr_array_index(iter->data.array, iter->index);
00241         else if (iter->type == GCONT_LIST)
00242                 return iter->data.list.curr->data;
00243         else if (iter->type == GCONT_SLIST)
00244                 return iter->data.slistPtr->data;
00245         else {
00246                 ERROR("Internal Error: Unrecognized type (%d)", iter->type);
00247                 return NULL;
00248         }
00249 }
00250 
00251 gpointer
00252 g_iterator_next(GIterator *iter) {
00253         gpointer data = g_iterator_get(iter);
00254         
00255         iterNext(iter);
00256         
00257         return data;
00258 }
00259 
00260 gpointer
00261 g_iterator_prev(GIterator *iter) {
00262         iterPrev(iter);
00263 
00264         return g_iterator_get(iter);
00265 }
00266 
00267 gboolean
00268 g_iterator_hasNext(const GIterator *iter) {
00269         if (iter->type == GCONT_PTR_ARRAY)
00270                 return (iter->index < iter->data.array->len);
00271         else if (iter->type == GCONT_LIST)
00272                 return (iter->data.list.curr != NULL);
00273         else if (iter->type == GCONT_SLIST)
00274                 return (iter->data.slistPtr != NULL);
00275         else {
00276                 ERROR("Internal Error: Unrecognized type (%d)", iter->type);
00277                 return FALSE;
00278         }
00279 }
00280 
00281 gboolean
00282 g_iterator_hasPrev(const GIterator *iter) {
00283         if (iter->type == GCONT_PTR_ARRAY)
00284                 return (iter->index > 0);
00285         else if (iter->type == GCONT_LIST)
00286                 return (iter->data.list.curr != NULL && iter->data.list.curr->prev != NULL) || (iter->data.list.curr == NULL && iter->data.list.last != NULL);
00287         else if (iter->type == GCONT_SLIST) {
00288                 ERROR("Cannot traverse singly linked lists backwards");
00289                 return FALSE;
00290         } else {
00291                 ERROR("Internal Error: Unrecognized type (%d)", iter->type);
00292                 return FALSE;
00293         }
00294 }
00295 
00296 void *
00297 g_container_free(GContainer *container, gboolean freeAssoc) {
00298         void *ret = NULL;
00299         
00300         if (container != NULL) {
00301                 if (freeAssoc) {
00302                         if (container->type == GCONT_PTR_ARRAY)
00303                                 g_ptr_array_free(container->data, TRUE);
00304                         else if (container->type == GCONT_LIST)
00305                                 g_list_free(container->data);
00306                         else if (container->type == GCONT_SLIST)
00307                                 g_slist_free(container->data);
00308                         else
00309                                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00310                 } else {
00311                         ret = container->data;
00312                 }
00313         
00314                 g_free(container);
00315         }
00316         
00317         return ret;
00318 }
00319 
00320 void
00321 g_container_convert(GContType type, GContainer *container) {
00322         GContainer *newCont;
00323         GIterator iter;
00324         gpointer data;
00325         
00326         if (container == NULL) {
00327                 ERROR("Null pointer passed to g_container_convert");
00328                 return;
00329         }
00330         
00331         if (type == container->type) /* don't need to do anything */
00332                 return;
00333         
00334         newCont = g_container_new(type);
00335         
00336         g_container_get_iter(&iter, container);
00337         while (g_iterator_hasNext(&iter)) {
00338                 data = g_iterator_next(&iter);
00339                 g_container_add(newCont, data);
00340         }
00341         
00342         if (container->type == GCONT_PTR_ARRAY)
00343                 g_ptr_array_free(container->data, TRUE);
00344         else if (container->type == GCONT_LIST)
00345                 g_list_free(container->data);
00346         else if (container->type == GCONT_SLIST)
00347                 g_slist_free(container->data);
00348         else
00349                 ERROR("Internal Error: Unrecognized type (%d)", container->type);
00350         
00351         container->data = newCont->data;
00352         container->type = type;
00353         
00354         g_container_free(newCont, FALSE);
00355 }
00356 
00365 void
00366 g_container_copy(GContainer *dest, GContainer *src) {
00367         GIterator iter;
00368         gpointer curr;
00369         
00370         if (dest == NULL || src == NULL) {
00371                 ERROR("Null pointer passed to g_container_copy");
00372         } else {
00373                 g_container_get_iter(&iter, src);
00374                 while (g_iterator_hasNext(&iter)) {
00375                         curr = g_iterator_next(&iter);
00376                         g_container_add(dest, curr);
00377                 }
00378         }
00379 }
00380 
00387 void
00388 g_container_destroy(GContainer *array) {
00389         GIterator iter;
00390         gpointer ptr;
00391         
00392         if (array == NULL) {
00393                 ERROR("Null pointer passed to g_container_destroy");
00394                 return;
00395         }
00396         
00397         g_container_get_iter(&iter, array);
00398         while (g_iterator_hasNext(&iter)) {
00399                 ptr = g_iterator_next(&iter);
00400                 g_free(ptr);
00401         }
00402         
00403         g_container_free(array, TRUE);
00404 }
00405 
00406 void
00407 g_container_destroy_type(GContType type, void *array) {
00408         GContainer *cont;
00409         
00410         if (array == NULL) {
00411                 ERROR("Null pointer passed to g_container_destroy_type");
00412                 return;
00413         }
00414         
00415         cont = g_container_new_from_data(type, array);
00416         g_container_destroy(cont);
00417 }
00418 
00419 
00420 /* -- Non-Interface Methods -- */
00421 
00422 static void
00423 iterNext(GIterator *iter) {
00424         iter->index++;
00425         
00426         if (iter->type == GCONT_PTR_ARRAY)
00427                 /* do nothing */;
00428         else if (iter->type == GCONT_LIST)
00429                 iter->data.list.curr = iter->data.list.curr->next;
00430         else if (iter->type == GCONT_SLIST)
00431                 iter->data.slistPtr = iter->data.slistPtr->next;
00432         else
00433                 ERROR("Internal Error: Unrecognized type (%d)", iter->type);
00434 }
00435 
00436 static void
00437 iterPrev(GIterator *iter) {
00438         iter->index--;
00439         
00440         if (iter->type == GCONT_PTR_ARRAY)
00441                 /* do nothing */;
00442         else if (iter->type == GCONT_LIST) {
00443                 if (iter->data.list.curr == NULL)
00444                         iter->data.list.curr = iter->data.list.last;
00445                 else
00446                         iter->data.list.curr = iter->data.list.curr->prev;
00447         } else if (iter->type == GCONT_SLIST)
00448                 ERROR("g_iterator_prev operation not valid on singly linked lists!");
00449         else
00450                 ERROR("Internal Error: Unrecognized type (%d)", iter->type);
00451 }

Generated on Mon Apr 12 22:17:10 2004 for luau by doxygen 1.3.2