00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "glib.h"
00032
00033
00034 struct _GAllocator
00035 {
00036 gchar *name;
00037 guint16 n_preallocs;
00038 guint is_unused : 1;
00039 guint type : 4;
00040 GAllocator *last;
00041 GMemChunk *mem_chunk;
00042 GList *free_lists;
00043 };
00044
00045 static GAllocator *current_allocator = NULL;
00046 G_LOCK_DEFINE_STATIC (current_allocator);
00047
00048
00049 static void
00050 g_list_validate_allocator (GAllocator *allocator)
00051 {
00052 g_return_if_fail (allocator != NULL);
00053 g_return_if_fail (allocator->is_unused == TRUE);
00054
00055 if (allocator->type != G_ALLOCATOR_LIST)
00056 {
00057 allocator->type = G_ALLOCATOR_LIST;
00058 if (allocator->mem_chunk)
00059 {
00060 g_mem_chunk_destroy (allocator->mem_chunk);
00061 allocator->mem_chunk = NULL;
00062 }
00063 }
00064
00065 if (!allocator->mem_chunk)
00066 {
00067 allocator->mem_chunk = g_mem_chunk_new (allocator->name,
00068 sizeof (GList),
00069 sizeof (GList) * allocator->n_preallocs,
00070 G_ALLOC_ONLY);
00071 allocator->free_lists = NULL;
00072 }
00073
00074 allocator->is_unused = FALSE;
00075 }
00076
00077 void
00078 g_list_push_allocator(GAllocator *allocator)
00079 {
00080 G_LOCK (current_allocator);
00081 g_list_validate_allocator ( allocator );
00082 allocator->last = current_allocator;
00083 current_allocator = allocator;
00084 G_UNLOCK (current_allocator);
00085 }
00086
00087 void
00088 g_list_pop_allocator (void)
00089 {
00090 G_LOCK (current_allocator);
00091 if (current_allocator)
00092 {
00093 GAllocator *allocator;
00094
00095 allocator = current_allocator;
00096 current_allocator = allocator->last;
00097 allocator->last = NULL;
00098 allocator->is_unused = TRUE;
00099 }
00100 G_UNLOCK (current_allocator);
00101 }
00102
00103 GList*
00104 g_list_alloc (void)
00105 {
00106 GList *list;
00107
00108 G_LOCK (current_allocator);
00109 if (!current_allocator)
00110 {
00111 GAllocator *allocator = g_allocator_new ("GLib default GList allocator",
00112 128);
00113 g_list_validate_allocator (allocator);
00114 allocator->last = NULL;
00115 current_allocator = allocator;
00116 }
00117 if (!current_allocator->free_lists)
00118 {
00119 list = g_chunk_new (GList, current_allocator->mem_chunk);
00120 list->data = NULL;
00121 }
00122 else
00123 {
00124 if (current_allocator->free_lists->data)
00125 {
00126 list = current_allocator->free_lists->data;
00127 current_allocator->free_lists->data = list->next;
00128 list->data = NULL;
00129 }
00130 else
00131 {
00132 list = current_allocator->free_lists;
00133 current_allocator->free_lists = list->next;
00134 }
00135 }
00136 G_UNLOCK (current_allocator);
00137 list->next = NULL;
00138 list->prev = NULL;
00139
00140 return list;
00141 }
00142
00143 void
00144 g_list_free (GList *list)
00145 {
00146 if (list)
00147 {
00148 list->data = list->next;
00149 G_LOCK (current_allocator);
00150 list->next = current_allocator->free_lists;
00151 current_allocator->free_lists = list;
00152 G_UNLOCK (current_allocator);
00153 }
00154 }
00155
00156 void
00157 g_list_free_1 (GList *list)
00158 {
00159 if (list)
00160 {
00161 list->data = NULL;
00162 G_LOCK (current_allocator);
00163 list->next = current_allocator->free_lists;
00164 current_allocator->free_lists = list;
00165 G_UNLOCK (current_allocator);
00166 }
00167 }
00168
00169 GList*
00170 g_list_append (GList *list,
00171 gpointer data)
00172 {
00173 GList *new_list;
00174 GList *last;
00175
00176 new_list = g_list_alloc ();
00177 new_list->data = data;
00178
00179 if (list)
00180 {
00181 last = g_list_last (list);
00182
00183 last->next = new_list;
00184 new_list->prev = last;
00185
00186 return list;
00187 }
00188 else
00189 return new_list;
00190 }
00191
00192 GList*
00193 g_list_prepend (GList *list,
00194 gpointer data)
00195 {
00196 GList *new_list;
00197
00198 new_list = g_list_alloc ();
00199 new_list->data = data;
00200
00201 if (list)
00202 {
00203 if (list->prev)
00204 {
00205 list->prev->next = new_list;
00206 new_list->prev = list->prev;
00207 }
00208 list->prev = new_list;
00209 new_list->next = list;
00210 }
00211
00212 return new_list;
00213 }
00214
00215 GList*
00216 g_list_insert (GList *list,
00217 gpointer data,
00218 gint position)
00219 {
00220 GList *new_list;
00221 GList *tmp_list;
00222
00223 if (position < 0)
00224 return g_list_append (list, data);
00225 else if (position == 0)
00226 return g_list_prepend (list, data);
00227
00228 tmp_list = g_list_nth (list, position);
00229 if (!tmp_list)
00230 return g_list_append (list, data);
00231
00232 new_list = g_list_alloc ();
00233 new_list->data = data;
00234
00235 if (tmp_list->prev)
00236 {
00237 tmp_list->prev->next = new_list;
00238 new_list->prev = tmp_list->prev;
00239 }
00240 new_list->next = tmp_list;
00241 tmp_list->prev = new_list;
00242
00243 if (tmp_list == list)
00244 return new_list;
00245 else
00246 return list;
00247 }
00248
00249 GList *
00250 g_list_concat (GList *list1, GList *list2)
00251 {
00252 GList *tmp_list;
00253
00254 if (list2)
00255 {
00256 tmp_list = g_list_last (list1);
00257 if (tmp_list)
00258 tmp_list->next = list2;
00259 else
00260 list1 = list2;
00261 list2->prev = tmp_list;
00262 }
00263
00264 return list1;
00265 }
00266
00267 GList*
00268 g_list_remove (GList *list,
00269 gpointer data)
00270 {
00271 GList *tmp;
00272
00273 tmp = list;
00274 while (tmp)
00275 {
00276 if (tmp->data != data)
00277 tmp = tmp->next;
00278 else
00279 {
00280 if (tmp->prev)
00281 tmp->prev->next = tmp->next;
00282 if (tmp->next)
00283 tmp->next->prev = tmp->prev;
00284
00285 if (list == tmp)
00286 list = list->next;
00287
00288 g_list_free_1 (tmp);
00289
00290 break;
00291 }
00292 }
00293 return list;
00294 }
00295
00296 GList*
00297 g_list_remove_link (GList *list,
00298 GList *link)
00299 {
00300 if (link)
00301 {
00302 if (link->prev)
00303 link->prev->next = link->next;
00304 if (link->next)
00305 link->next->prev = link->prev;
00306
00307 if (link == list)
00308 list = list->next;
00309
00310 link->next = NULL;
00311 link->prev = NULL;
00312 }
00313
00314 return list;
00315 }
00316
00317 GList*
00318 g_list_copy (GList *list)
00319 {
00320 GList *new_list = NULL;
00321
00322 if (list)
00323 {
00324 GList *last;
00325
00326 new_list = g_list_alloc ();
00327 new_list->data = list->data;
00328 last = new_list;
00329 list = list->next;
00330 while (list)
00331 {
00332 last->next = g_list_alloc ();
00333 last->next->prev = last;
00334 last = last->next;
00335 last->data = list->data;
00336 list = list->next;
00337 }
00338 }
00339
00340 return new_list;
00341 }
00342
00343 GList*
00344 g_list_reverse (GList *list)
00345 {
00346 GList *last;
00347
00348 last = NULL;
00349 while (list)
00350 {
00351 last = list;
00352 list = last->next;
00353 last->next = last->prev;
00354 last->prev = list;
00355 }
00356
00357 return last;
00358 }
00359
00360 GList*
00361 g_list_nth (GList *list,
00362 guint n)
00363 {
00364 while ((n-- > 0) && list)
00365 list = list->next;
00366
00367 return list;
00368 }
00369
00370 gpointer
00371 g_list_nth_data (GList *list,
00372 guint n)
00373 {
00374 while ((n-- > 0) && list)
00375 list = list->next;
00376
00377 return list ? list->data : NULL;
00378 }
00379
00380 GList*
00381 g_list_find (GList *list,
00382 gpointer data)
00383 {
00384 while (list)
00385 {
00386 if (list->data == data)
00387 break;
00388 list = list->next;
00389 }
00390
00391 return list;
00392 }
00393
00394 GList*
00395 g_list_find_custom (GList *list,
00396 gpointer data,
00397 GCompareFunc func)
00398 {
00399 g_return_val_if_fail (func != NULL, list);
00400
00401 while (list)
00402 {
00403 if (! func (list->data, data))
00404 return list;
00405 list = list->next;
00406 }
00407
00408 return NULL;
00409 }
00410
00411
00412 gint
00413 g_list_position (GList *list,
00414 GList *link)
00415 {
00416 gint i;
00417
00418 i = 0;
00419 while (list)
00420 {
00421 if (list == link)
00422 return i;
00423 i++;
00424 list = list->next;
00425 }
00426
00427 return -1;
00428 }
00429
00430 gint
00431 g_list_index (GList *list,
00432 gpointer data)
00433 {
00434 gint i;
00435
00436 i = 0;
00437 while (list)
00438 {
00439 if (list->data == data)
00440 return i;
00441 i++;
00442 list = list->next;
00443 }
00444
00445 return -1;
00446 }
00447
00448 GList*
00449 g_list_last (GList *list)
00450 {
00451 if (list)
00452 {
00453 while (list->next)
00454 list = list->next;
00455 }
00456
00457 return list;
00458 }
00459
00460 GList*
00461 g_list_first (GList *list)
00462 {
00463 if (list)
00464 {
00465 while (list->prev)
00466 list = list->prev;
00467 }
00468
00469 return list;
00470 }
00471
00472 guint
00473 g_list_length (GList *list)
00474 {
00475 guint length;
00476
00477 length = 0;
00478 while (list)
00479 {
00480 length++;
00481 list = list->next;
00482 }
00483
00484 return length;
00485 }
00486
00487 void
00488 g_list_foreach (GList *list,
00489 GFunc func,
00490 gpointer user_data)
00491 {
00492 while (list)
00493 {
00494 (*func) (list->data, user_data);
00495 list = list->next;
00496 }
00497 }
00498
00499
00500 GList*
00501 g_list_insert_sorted (GList *list,
00502 gpointer data,
00503 GCompareFunc func)
00504 {
00505 GList *tmp_list = list;
00506 GList *new_list;
00507 gint cmp;
00508
00509 g_return_val_if_fail (func != NULL, list);
00510
00511 if (!list)
00512 {
00513 new_list = g_list_alloc();
00514 new_list->data = data;
00515 return new_list;
00516 }
00517
00518 cmp = (*func) (data, tmp_list->data);
00519
00520 while ((tmp_list->next) && (cmp > 0))
00521 {
00522 tmp_list = tmp_list->next;
00523 cmp = (*func) (data, tmp_list->data);
00524 }
00525
00526 new_list = g_list_alloc();
00527 new_list->data = data;
00528
00529 if ((!tmp_list->next) && (cmp > 0))
00530 {
00531 tmp_list->next = new_list;
00532 new_list->prev = tmp_list;
00533 return list;
00534 }
00535
00536 if (tmp_list->prev)
00537 {
00538 tmp_list->prev->next = new_list;
00539 new_list->prev = tmp_list->prev;
00540 }
00541 new_list->next = tmp_list;
00542 tmp_list->prev = new_list;
00543
00544 if (tmp_list == list)
00545 return new_list;
00546 else
00547 return list;
00548 }
00549
00550 static GList *
00551 g_list_sort_merge (GList *l1,
00552 GList *l2,
00553 GCompareFunc compare_func)
00554 {
00555 GList list, *l, *lprev;
00556
00557 l = &list;
00558 lprev = NULL;
00559
00560 while (l1 && l2)
00561 {
00562 if (compare_func (l1->data, l2->data) < 0)
00563 {
00564 l->next = l1;
00565 l = l->next;
00566 l->prev = lprev;
00567 lprev = l;
00568 l1 = l1->next;
00569 }
00570 else
00571 {
00572 l->next = l2;
00573 l = l->next;
00574 l->prev = lprev;
00575 lprev = l;
00576 l2 = l2->next;
00577 }
00578 }
00579 l->next = l1 ? l1 : l2;
00580 l->next->prev = l;
00581
00582 return list.next;
00583 }
00584
00585 GList*
00586 g_list_sort (GList *list,
00587 GCompareFunc compare_func)
00588 {
00589 GList *l1, *l2;
00590
00591 if (!list)
00592 return NULL;
00593 if (!list->next)
00594 return list;
00595
00596 l1 = list;
00597 l2 = list->next;
00598
00599 while ((l2 = l2->next) != NULL)
00600 {
00601 if ((l2 = l2->next) == NULL)
00602 break;
00603 l1 = l1->next;
00604 }
00605 l2 = l1->next;
00606 l1->next = NULL;
00607
00608 return g_list_sort_merge (g_list_sort (list, compare_func),
00609 g_list_sort (l2, compare_func),
00610 compare_func);
00611 }
00612
00613 GList*
00614 g_list_sort2 (GList *list,
00615 GCompareFunc compare_func)
00616 {
00617 GSList *runs = NULL;
00618 GList *tmp;
00619
00620
00621 if (!list) return NULL;
00622
00623
00624 for (tmp = list; tmp; )
00625 {
00626 GList *tmp2;
00627 for (tmp2 = tmp;
00628 tmp2->next && compare_func (tmp2->data, tmp2->next->data) <= 0;
00629 tmp2 = tmp2->next)
00630 ;
00631 runs = g_slist_append (runs, tmp);
00632 tmp = tmp2->next;
00633 tmp2->next = NULL;
00634 }
00635
00636
00637 while (runs->next)
00638 {
00639
00640 GSList *dst, *src, *dstprev = NULL;
00641 dst = src = runs;
00642 while (src && src->next)
00643 {
00644 dst->data = g_list_sort_merge (src->data,
00645 src->next->data,
00646 compare_func);
00647 dstprev = dst;
00648 dst = dst->next;
00649 src = src->next->next;
00650 }
00651
00652
00653 if (src)
00654 {
00655 dst->data = src->data;
00656 dstprev = dst;
00657 dst = dst->next;
00658 }
00659
00660 dstprev->next = NULL;
00661 g_slist_free (dst);
00662 }
00663
00664
00665
00666
00667 list = runs->data;
00668 g_slist_free (runs);
00669 return list;
00670 }