2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
25 * $XConsortium: strlist.c /main/5 1996/10/02 16:53:22 drk $
27 * @(#)strlist.c 1.8 14 Oct 1994 cde_app_builder/src/libAButil
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special
32 * restrictions in a confidential disclosure agreement between
33 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 * document outside HP, IBM, Sun, USL, SCO, or Univel without
35 * Sun's specific written approval. This document and all copies
36 * and derivative works thereof must be returned or destroyed at
39 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
49 #include <ab_private/AB.h>
50 #include <ab_private/istr.h>
51 #include <ab_private/strlist.h>
53 /*****************************************************************
57 *****************************************************************/
59 static int strlistP_grow_array(StringList list, int sizeDiff);
60 static int strlistP_shrink_array(StringList list, int sizeDiff);
61 static int strlistP_build_user_data_array(
68 #define strlistP_add_user_data(_list,_index,_data) \
69 ((((_list)->user_datas == NULL) && ((_data) != NULL))? \
70 strlistP_build_user_data_array(_list, _index, _data) \
72 ((int)((_list)->user_datas[(_index)] = (_data))) \
79 StringList list = (StringList) util_malloc(sizeof(StringListRec));
84 strlist_construct(list);
90 strlist_construct(StringList list)
92 list->num_strings = 0;
93 list->strings_size = 0;
95 list->user_datas = NULL;
97 list->sort_order = STRLIST_SORT_CLIENT_DEF;
98 list->indexes_dirty = TRUE;
104 * Frees the string list and all it's associated memory.
107 strlist_destroy(StringList list)
109 strlist_destruct(list);
116 strlist_destruct(StringList list)
118 return strlist_make_empty(list);
123 strlist_get_sort_order(StringList list)
125 return list->sort_order;
130 strlist_set_sort_order(StringList list, STRLIST_SORT_ORDER new_order)
132 int return_value = 0;
134 if (list->sort_order != new_order)
136 list->indexes_dirty = TRUE;
144 strlist_make_empty(StringList list)
146 int return_value = 0;
148 if (list->strings != NULL)
150 return_value = strlistP_shrink_array(list, list->strings_size);
158 strlist_is_empty(StringList list)
160 return (list->num_strings < 1);
165 strlist_set_is_unique(StringList list, BOOL unique)
167 list->unique = unique;
173 strlist_get_is_unique(StringList list)
180 * Searches the string list for a match.
182 * returns: true, if the string exists. false, if the string doesn't
186 strlist_istr_exists(StringList list, ISTRING istring)
188 return (strlist_get_istr_index(list, istring) >= 0);
193 strlist_set_istr_data(StringList list, ISTRING istring, void *data)
195 int index = strlist_get_istr_index(list, istring);
201 strlistP_add_user_data(list,index,data);
208 strlist_get_istr_data(StringList list, ISTRING istring)
210 int index = strlist_get_istr_index(list, istring);
211 return (index < 0)? NULL:list->user_datas[index];
216 * Returns the index of the given string, or -1 if it doesn't exist
219 strlist_get_istr_index(StringList list, ISTRING string)
223 int num_strings = list->num_strings;
225 for (i = 0; i < num_strings; ++i)
227 if (istr_equal(list->strings[i], string))
240 * Add a string to a string list.
242 * Duplicates the string
244 * returns: 0 if item added successfully ERR_DUPLICATE_KEY if item is
248 strlist_add_istr(StringList list, ISTRING istring, void *clientData)
250 int return_value = 0;
258 int index = strlist_get_istr_index(list, istring);
261 strlistP_add_user_data(list, index, clientData);
267 * Allocate more space
269 if (list->num_strings >= list->strings_size)
271 /* grow the array by 50% (the "opposite" of a binary search) */
272 int new_size = (list->strings_size * 3)/2;
273 int size_inc = new_size - list->strings_size;
274 size_inc = util_max(5,size_inc);
275 rc = strlistP_grow_array(list, size_inc);
285 * save the string (and data)
287 list->strings[list->num_strings] = istr_dup(istring);
288 strlistP_add_user_data(list, list->num_strings, clientData);
289 ++(list->num_strings);
297 strlist_remove_istr(StringList list, ISTRING istring)
299 int index = strlist_get_istr_index(list, istring);
304 return strlist_remove_index(list, index);
309 strlist_remove_index(StringList list, int doomedIndex)
311 #define num_strings (list->num_strings)
312 ISTRING *strings = list->strings;
313 void **user_datas = list->user_datas;
317 if ((doomedIndex < 0) || (doomedIndex >= num_strings))
322 numToMove = (num_strings - doomedIndex - 1);
325 * Destroy this string and collapse the list
327 istr_destroy(strings[doomedIndex]);
330 memmove((void *)(&(strings[doomedIndex])),
331 (void *)&(strings[doomedIndex+1]),
332 sizeof(ISTRING) * numToMove);
333 strings[num_strings-1] = NULL;
337 * Destroy user data and collapse list
339 if (user_datas != NULL)
341 user_datas[doomedIndex] = NULL;
344 memmove((void *)(&(user_datas[doomedIndex])),
345 (void *)&(user_datas[doomedIndex+1]),
346 sizeof(void*) * numToMove);
347 user_datas[num_strings-1] = NULL;
352 * Actually shorten list
362 strlist_get_num_strs(StringList list)
368 return list->num_strings;
373 strlist_get_istr(StringList list, int whichString, void **clientDataOut)
375 if ((list == NULL) || (whichString >= list->num_strings) ||
380 if (clientDataOut != NULL)
383 (list->user_datas == NULL? NULL:list->user_datas[whichString]);
385 return list->strings[whichString];
390 * Only "soft" limit is supported, now
393 strlist_max_size_is_soft(StringList list)
400 strlist_set_max_size_soft(StringList list, int maxSize)
402 int return_value = 0;
403 int sizeDiff = (maxSize - list->strings_size);
407 return_value = strlistP_shrink_array(list, -1 * sizeDiff);
409 else if (sizeDiff > 0)
411 return_value = strlistP_grow_array(list, sizeDiff);
419 strlist_get_max_size(StringList list)
421 return list->strings_size;
426 * Frees any extra memory that may not be needed (multiple strings are
427 * allocated at once, to reduce the number of realloc calls).
430 strlist_shrink_mem_to_fit(StringList list)
432 int return_value = 0;
433 int diff = list->strings_size - list->num_strings;
437 return_value = strlistP_shrink_array(list, diff);
444 /*************************************************************************
446 ** STRING interface **
448 **************************************************************************/
451 strlist_add_str(StringList list, STRING string, void *clientData)
453 int return_value = 0;
454 ISTRING istring = istr_create(string);
455 return_value = strlist_add_istr(list, istring, clientData);
456 istr_destroy(istring);
463 strlist_add_index_str(StringList list, int index, STRING string, void *clientData)
465 int return_value = 0;
466 ISTRING istring = istr_create(string);
467 return_value = strlist_add_index_istr(list, index, istring, clientData);
468 istr_destroy(istring);
471 #endif /* UNIMPLEMENTED */
475 strlist_str_exists(StringList list, STRING string)
478 ISTRING istring = istr_dup_existing(string);
481 doesIt = strlist_istr_exists(list, istring);
482 istr_destroy(istring);
489 strlist_get_str_index(StringList list, STRING string)
492 ISTRING istring = istr_create(string);
495 index = strlist_get_istr_index(list, istring);
496 istr_destroy(istring);
503 strlist_get_str(StringList list, int whichString, void **clientDataOut)
505 return istr_string(strlist_get_istr(list, whichString, clientDataOut));
510 strlist_remove_str(StringList list, STRING string)
512 int return_value = 0;
513 ISTRING istring = istr_dup_existing(string);
516 return_value = strlist_remove_istr(list, istring);
517 istr_destroy(istring);
524 strlist_set_str_data(StringList list, STRING string, void *data)
526 int return_value = 0;
527 ISTRING istring = istr_dup_existing(string);
530 return_value = strlist_set_istr_data(list, istring, data);
531 istr_destroy(istring);
538 strlist_get_str_data(StringList list, STRING string)
540 void *clientData = NULL;
541 ISTRING istring = istr_dup_existing(string);
544 clientData = strlist_get_istr_data(list, istring);
545 istr_destroy(istring);
551 strlist_dup(StringList list)
554 StringList new_list = NULL;
556 new_list = strlist_create();
557 new_list->unique = list->unique;
558 new_list->sort_order = list->sort_order;
559 new_list->indexes_dirty = list->indexes_dirty;
560 for (i=0; i<list->num_strings; i++)
562 strlist_add_istr(new_list, list->strings[i], list->user_datas[i]);
567 /*************************************************************************
569 ** PRIVATE FUNCTIONS **
571 **************************************************************************/
574 strlistP_shrink_array(StringList list, int sizeDiff)
576 int return_value = 0;
577 int new_strings_size = util_max(0, list->strings_size - sizeDiff);
578 ISTRING *new_strings = NULL;
579 void **new_user_datas = NULL;
582 for (i= new_strings_size; i < list->strings_size; ++i)
584 if (list->strings[i] != NULL)
586 istr_destroy(list->strings[i]);
588 list->user_datas[i] = NULL;
591 if (new_strings_size > 0)
593 new_strings = (ISTRING *) realloc(
594 list->strings, new_strings_size * sizeof(ISTRING));
595 new_user_datas = (void **) realloc(
596 list->user_datas, new_strings_size * sizeof(void*));
600 util_free(list->strings); list->strings = NULL;
601 util_free(list->user_datas); list->user_datas= NULL;
604 if ( (new_strings_size > 0)
605 && ((new_strings == NULL) || (new_user_datas == NULL)) )
612 list->strings = new_strings;
613 list->user_datas = new_user_datas;
614 list->strings_size = new_strings_size;
615 if (list->num_strings > list->strings_size)
617 list->num_strings = util_max(0, list->strings_size);
627 strlistP_grow_array(StringList list, int sizeDiff)
629 int return_value = 0;
630 int old_strings_size = list->strings_size;
631 int new_strings_size = list->strings_size + sizeDiff;
632 ISTRING *new_strings = NULL;
633 void **new_user_datas = NULL;
636 new_strings = (ISTRING *)realloc(
637 list->strings, new_strings_size * sizeof(ISTRING));
638 new_user_datas = (void **)realloc(
639 list->user_datas, new_strings_size * sizeof(void *));
640 if ((new_strings == NULL) || (new_user_datas == NULL))
647 list->strings = new_strings;
648 list->user_datas = new_user_datas;
649 list->strings_size = new_strings_size;
653 * Init the new entries to NULL;
655 for (i = old_strings_size; i < new_strings_size; ++i)
657 list->strings[i] = NULL;
658 list->user_datas[i] = NULL;
667 strlistP_build_user_data_array(StringList list, int index, void *data)
669 if (list->user_datas != NULL)
673 list->user_datas = (void **)calloc(sizeof(void*), list->strings_size);
674 if (list->user_datas == NULL)
678 list->user_datas[index] = data;
687 strlist_dump(StringList list)
690 ISTRING istring = NULL;
691 STRING string = NULL;
695 util_printf(0, "NULL string list\n");
698 if (list->strings_size == 0)
700 util_dprintf(0, "empty string list\n");
704 for (i= 0; i < list->strings_size; ++i)
706 istring= list->strings[i];
707 if (istr_verify(istring) < 0)
709 string = "** Invalid ISTRING **";
713 string = util_strsafe(istr_string(istring));
716 util_dprintf(0, "%d[%s]: '%s'",
718 (i >= list->num_strings? " ":"X"),
721 if (list->user_datas != NULL)
723 util_dprintf(0, " 0x%08lx", list->user_datas[i]);
725 util_dprintf(0, "\n");
727 util_dprintf(0, "\n");