00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00099
00100
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
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)
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
00421
00422 static void
00423 iterNext(GIterator *iter) {
00424 iter->index++;
00425
00426 if (iter->type == GCONT_PTR_ARRAY)
00427 ;
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 ;
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 }