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 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034 #include <gutenprint/gutenprint.h>
00035 #include "gutenprint-internal.h"
00036 #include <gutenprint/gutenprint-intl-internal.h>
00037 #include <assert.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <string.h>
00041
00043 struct stp_list_item
00044 {
00045 void *data;
00046 struct stp_list_item *prev;
00047 struct stp_list_item *next;
00048 };
00049
00051 struct stp_list
00052 {
00053 int index_cache;
00054 struct stp_list_item *start;
00055 struct stp_list_item *end;
00056 struct stp_list_item *index_cache_node;
00057 int length;
00058 stp_node_freefunc freefunc;
00059 stp_node_copyfunc copyfunc;
00060 stp_node_namefunc namefunc;
00061 stp_node_namefunc long_namefunc;
00062 stp_node_sortfunc sortfunc;
00063 char *name_cache;
00064 struct stp_list_item *name_cache_node;
00065 char *long_name_cache;
00066 struct stp_list_item *long_name_cache_node;
00067 };
00068
00075 static void
00076 set_name_cache(stp_list_t *list,
00077 const char *name,
00078 stp_list_item_t *cache)
00079 {
00080 if (list->name_cache)
00081 stp_free(list->name_cache);
00082 list->name_cache = NULL;
00083 if (name)
00084 list->name_cache = stp_strdup(name);
00085 list->name_cache_node = cache;
00086 }
00087
00094 static void
00095 set_long_name_cache(stp_list_t *list,
00096 const char *long_name,
00097 stp_list_item_t *cache)
00098 {
00099 if (list->long_name_cache)
00100 stp_free(list->long_name_cache);
00101 list->long_name_cache = NULL;
00102 if (long_name)
00103 list->long_name_cache = stp_strdup(long_name);
00104 list->long_name_cache_node = cache;
00105 }
00106
00111 static inline void
00112 clear_cache(stp_list_t *list)
00113 {
00114 list->index_cache = 0;
00115 list->index_cache_node = NULL;
00116 set_name_cache(list, NULL, NULL);
00117 set_long_name_cache(list, NULL, NULL);
00118 }
00119
00120 void
00121 stp_list_node_free_data (void *item)
00122 {
00123 stp_free(item);
00124 stp_deprintf(STP_DBG_LIST, "stp_list_node_free_data destructor\n");
00125 }
00126
00128 #define check_list(List) assert(List != NULL)
00129
00130
00131
00132
00133
00134
00135 stp_list_t *
00136 stp_list_create(void)
00137 {
00138 stp_list_t *list =
00139 stp_malloc(sizeof(stp_list_t));
00140
00141
00142 list->index_cache = 0;
00143 list->length = 0;
00144 list->start = NULL;
00145 list->end = NULL;
00146 list->index_cache_node = NULL;
00147 list->freefunc = NULL;
00148 list->namefunc = NULL;
00149 list->long_namefunc = NULL;
00150 list->sortfunc = NULL;
00151 list->copyfunc = NULL;
00152 list->name_cache = NULL;
00153 list->name_cache_node = NULL;
00154 list->long_name_cache = NULL;
00155 list->long_name_cache_node = NULL;
00156
00157 stp_deprintf(STP_DBG_LIST, "stp_list_head constructor\n");
00158 return list;
00159 }
00160
00161 stp_list_t *
00162 stp_list_copy(const stp_list_t *list)
00163 {
00164 stp_list_t *ret;
00165 stp_node_copyfunc copyfunc = stp_list_get_copyfunc(list);
00166 stp_list_item_t *item = list->start;
00167
00168 check_list(list);
00169
00170 ret = stp_list_create();
00171 stp_list_set_copyfunc(ret, stp_list_get_copyfunc(list));
00172
00173 if (stp_list_get_copyfunc(list))
00174 stp_list_set_freefunc(ret, stp_list_get_freefunc(list));
00175 stp_list_set_namefunc(ret, stp_list_get_namefunc(list));
00176 stp_list_set_long_namefunc(ret, stp_list_get_long_namefunc(list));
00177 stp_list_set_sortfunc(ret, stp_list_get_sortfunc(list));
00178 while (item)
00179 {
00180 void *data = item->data;
00181 if (copyfunc)
00182 stp_list_item_create (ret, NULL, (*copyfunc)(data));
00183 else
00184 stp_list_item_create(ret, NULL, data);
00185 item = stp_list_item_next(item);
00186 }
00187 return ret;
00188 }
00189
00190
00191 int
00192 stp_list_destroy(stp_list_t *list)
00193 {
00194 stp_list_item_t *cur;
00195 stp_list_item_t *next;
00196
00197 check_list(list);
00198 clear_cache(list);
00199 cur = list->start;
00200 while(cur)
00201 {
00202 next = cur->next;
00203 stp_list_item_destroy(list, cur);
00204 cur = next;
00205 }
00206 stp_deprintf(STP_DBG_LIST, "stp_list_head destructor\n");
00207 stp_free(list);
00208
00209 return 0;
00210 }
00211
00212 int
00213 stp_list_get_length(const stp_list_t *list)
00214 {
00215 check_list(list);
00216 return list->length;
00217 }
00218
00219
00220
00221
00222
00223 stp_list_item_t *
00224 stp_list_get_start(const stp_list_t *list)
00225 {
00226 return list->start;
00227 }
00228
00229
00230
00231 stp_list_item_t *
00232 stp_list_get_end(const stp_list_t *list)
00233 {
00234 return list->end;
00235 }
00236
00237
00238 stp_list_item_t *
00239 stp_list_get_item_by_index(const stp_list_t *list, int idx)
00240 {
00241 stp_list_item_t *node = NULL;
00242 int i;
00243 int d = 0;
00244 int c = 0;
00245 check_list(list);
00246
00247 if (idx >= list->length)
00248 return NULL;
00249
00250
00251 if (list->index_cache)
00252 {
00253 if (idx < (list->length/2))
00254 {
00255 if (idx > abs(idx - list->index_cache))
00256 c = 1;
00257 else
00258 d = 0;
00259 }
00260 else
00261 {
00262 if (list->length - 1 - idx >
00263 abs (list->length - 1 - idx - list->index_cache))
00264 c = 1;
00265 else
00266 d = 1;
00267 }
00268 }
00269
00270
00271 if (c)
00272 {
00273 if (idx > list->index_cache)
00274 d = 0;
00275 else
00276 d = 1;
00277 i = list->index_cache;
00278 node = list->index_cache_node;
00279 }
00280 else
00281 {
00282 if (d)
00283 {
00284 i = list->length - 1;
00285 node = list->end;
00286 }
00287 else
00288 {
00289 i = 0;
00290 node = list->start;
00291 }
00292 }
00293
00294 while (node && i != idx)
00295 {
00296 if (d)
00297 {
00298 i--;
00299 node = node->prev;
00300 }
00301 else
00302 {
00303 i++;
00304 node = node->next;
00305 }
00306 }
00307
00308
00309 ((stp_list_t *)list)->index_cache = i;
00310 ((stp_list_t *)list)->index_cache_node = node;
00311
00312 return node;
00313 }
00314
00323 static stp_list_item_t *
00324 stp_list_get_item_by_name_internal(const stp_list_t *list, const char *name)
00325 {
00326 stp_list_item_t *node = list->start;
00327 while (node && strcmp(name, list->namefunc(node->data)))
00328 {
00329 node = node->next;
00330 }
00331 return node;
00332 }
00333
00334
00335
00336 stp_list_item_t *
00337 stp_list_get_item_by_name(const stp_list_t *list, const char *name)
00338 {
00339 stp_list_item_t *node = NULL;
00340 check_list(list);
00341
00342 if (!list->namefunc)
00343 return NULL;
00344
00345 if (list->name_cache && name && list->name_cache_node)
00346 {
00347 const char *new_name;
00348 node = list->name_cache_node;
00349
00350 if (strcmp(name, list->name_cache) == 0 &&
00351 strcmp(name, list->namefunc(node->data)) == 0)
00352 return node;
00353
00354
00355 node = node->next;
00356 if (node)
00357 {
00358 new_name = list->namefunc(node->data);
00359 if (strcmp(name, new_name) == 0)
00360 {
00361 set_name_cache((stp_list_t *) list, new_name, node);
00362 return node;
00363 }
00364 }
00365
00366 node = list->index_cache_node;
00367 if (node)
00368 {
00369 new_name = list->namefunc(node->data);
00370 if (strcmp(name, new_name) == 0)
00371 {
00372 set_name_cache((stp_list_t *) list, new_name, node);
00373 return node;
00374 }
00375 }
00376 }
00377
00378 node = stp_list_get_item_by_name_internal(list, name);
00379
00380 if (node)
00381 set_name_cache((stp_list_t *) list, name, node);
00382
00383 return node;
00384 }
00385
00386
00395 static stp_list_item_t *
00396 stp_list_get_item_by_long_name_internal(const stp_list_t *list,
00397 const char *long_name)
00398 {
00399 stp_list_item_t *node = list->start;
00400 while (node && strcmp(long_name, list->long_namefunc(node->data)))
00401 {
00402 node = node->next;
00403 }
00404 return node;
00405 }
00406
00407
00408
00409 stp_list_item_t *
00410 stp_list_get_item_by_long_name(const stp_list_t *list, const char *long_name)
00411 {
00412 stp_list_item_t *node = NULL;
00413 check_list(list);
00414
00415 if (!list->long_namefunc)
00416 return NULL;
00417
00418 if (list->long_name_cache && long_name && list->long_name_cache_node)
00419 {
00420 const char *new_long_name;
00421 node = list->long_name_cache_node;
00422
00423 if (strcmp(long_name, list->long_name_cache) == 0 &&
00424 strcmp(long_name, list->long_namefunc(node->data)) == 0)
00425 return node;
00426
00427
00428 node = node->next;
00429 if (node)
00430 {
00431 new_long_name = list->long_namefunc(node->data);
00432 if (strcmp(long_name, new_long_name) == 0)
00433 {
00434 set_long_name_cache((stp_list_t*) list, new_long_name, node);
00435 return node;
00436 }
00437 }
00438
00439 node = list->index_cache_node;
00440 if (node)
00441 {
00442 new_long_name = list->long_namefunc(node->data);
00443 if (strcmp(long_name, new_long_name) == 0)
00444 {
00445 set_long_name_cache((stp_list_t *) list, new_long_name, node);
00446 return node;
00447 }
00448 }
00449 }
00450
00451 node = stp_list_get_item_by_long_name_internal(list, long_name);
00452
00453 if (node)
00454 set_long_name_cache((stp_list_t *) list, long_name, node);
00455
00456 return node;
00457 }
00458
00459
00460
00461 void
00462 stp_list_set_freefunc(stp_list_t *list, stp_node_freefunc freefunc)
00463 {
00464 check_list(list);
00465 list->freefunc = freefunc;
00466 }
00467
00468 stp_node_freefunc
00469 stp_list_get_freefunc(const stp_list_t *list)
00470 {
00471 check_list(list);
00472 return list->freefunc;
00473 }
00474
00475
00476 void
00477 stp_list_set_copyfunc(stp_list_t *list, stp_node_copyfunc copyfunc)
00478 {
00479 check_list(list);
00480 list->copyfunc = copyfunc;
00481 }
00482
00483 stp_node_copyfunc
00484 stp_list_get_copyfunc(const stp_list_t *list)
00485 {
00486 check_list(list);
00487 return list->copyfunc;
00488 }
00489
00490
00491 void
00492 stp_list_set_namefunc(stp_list_t *list, stp_node_namefunc namefunc)
00493 {
00494 check_list(list);
00495 list->namefunc = namefunc;
00496 }
00497
00498 stp_node_namefunc
00499 stp_list_get_namefunc(const stp_list_t *list)
00500 {
00501 check_list(list);
00502 return list->namefunc;
00503 }
00504
00505
00506 void
00507 stp_list_set_long_namefunc(stp_list_t *list, stp_node_namefunc long_namefunc)
00508 {
00509 check_list(list);
00510 list->long_namefunc = long_namefunc;
00511 }
00512
00513 stp_node_namefunc
00514 stp_list_get_long_namefunc(const stp_list_t *list)
00515 {
00516 check_list(list);
00517 return list->long_namefunc;
00518 }
00519
00520
00521 void
00522 stp_list_set_sortfunc(stp_list_t *list, stp_node_sortfunc sortfunc)
00523 {
00524 check_list(list);
00525 list->sortfunc = sortfunc;
00526 }
00527
00528 stp_node_sortfunc
00529 stp_list_get_sortfunc(const stp_list_t *list)
00530 {
00531 check_list(list);
00532 return list->sortfunc;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 int
00548 stp_list_item_create(stp_list_t *list,
00549 stp_list_item_t *next,
00550 const void *data)
00551 {
00552 stp_list_item_t *ln;
00553 stp_list_item_t *lnn;
00554
00555 check_list(list);
00556
00557 clear_cache(list);
00558
00559 ln = stp_malloc(sizeof(stp_list_item_t));
00560 ln->prev = ln->next = NULL;
00561
00562 if (data)
00563 ln->data = (void *) data;
00564 else
00565 {
00566 stp_free(ln);
00567 return 1;
00568 }
00569
00570 if (list->sortfunc)
00571 {
00572
00573 lnn = list->end;
00574 while (lnn)
00575 {
00576 if (list->sortfunc(lnn->data, ln->data) <= 0)
00577 break;
00578 lnn = lnn->prev;
00579 }
00580 }
00581 #if 0
00582
00583
00584
00585
00586
00587 else if (stpi_get_debug_level() & STPI_DBG_LIST)
00588 {
00589 if (next)
00590 {
00591 lnn = list->start;
00592 while (lnn)
00593 {
00594 if (lnn == next)
00595 break;
00596 lnn = lnn->prev;
00597 }
00598 }
00599 else
00600 lnn = NULL;
00601 }
00602 #endif
00603 else
00604 lnn = next;
00605
00606
00607
00608
00609 ln->next = lnn;
00610
00611 if (!ln->prev)
00612 {
00613 if (list->start)
00614 ln->prev = list->end;
00615 else
00616 list->start = ln;
00617 list->end = ln;
00618 }
00619
00620
00621
00622 if (!ln->prev && ln->next)
00623 ln->prev = ln->next->prev;
00624
00625 if (list->start == ln->next)
00626 {
00627 list->start = ln;
00628 }
00629
00630
00631 if (ln->next)
00632 ln->next->prev = ln;
00633
00634
00635 if (ln->prev)
00636 ln->prev->next = ln;
00637
00638
00639 list->length++;
00640
00641 stp_deprintf(STP_DBG_LIST, "stp_list_node constructor\n");
00642 return 0;
00643 }
00644
00645
00646 int
00647 stp_list_item_destroy(stp_list_t *list, stp_list_item_t *item)
00648 {
00649 check_list(list);
00650
00651 clear_cache(list);
00652
00653 list->length--;
00654
00655 if (list->freefunc)
00656 list->freefunc((void *) item->data);
00657 if (item->prev)
00658 item->prev->next = item->next;
00659 else
00660 list->start = item->next;
00661 if (item->next)
00662 item->next->prev = item->prev;
00663 else
00664 list->end = item->prev;
00665 stp_free(item);
00666
00667 stp_deprintf(STP_DBG_LIST, "stp_list_node destructor\n");
00668 return 0;
00669 }
00670
00671
00672 stp_list_item_t *
00673 stp_list_item_prev(const stp_list_item_t *item)
00674 {
00675 return item->prev;
00676 }
00677
00678
00679 stp_list_item_t *
00680 stp_list_item_next(const stp_list_item_t *item)
00681 {
00682 return item->next;
00683 }
00684
00685
00686 void *
00687 stp_list_item_get_data(const stp_list_item_t *item)
00688 {
00689 return item->data;
00690 }
00691
00692
00693 int
00694 stp_list_item_set_data(stp_list_item_t *item, void *data)
00695 {
00696 if (data)
00697 {
00698 item->data = data;
00699 return 0;
00700 }
00701 return 1;
00702 }