OpenIndiana and Solaris port
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Basic / List.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /*
24  * $XConsortium: List.cc /main/4 1996/08/06 09:18:55 rcs $
25  *
26  * Copyright (c) 1992 HaL Computer Systems, Inc.  All rights reserved.
27  * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
28  * States.  Use of a copyright notice is precautionary only and does not
29  * imply publication or disclosure.
30  * 
31  * This software contains confidential information and trade secrets of HaL
32  * Computer Systems, Inc.  Use, disclosure, or reproduction is prohibited
33  * without the prior express written permission of HaL Computer Systems, Inc.
34  * 
35  *                         RESTRICTED RIGHTS LEGEND
36  * Use, duplication, or disclosure by the Government is subject to
37  * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
38  * Technical Data and Computer Software clause at DFARS 252.227-7013.
39  *                        HaL Computer Systems, Inc.
40  *                  1315 Dell Avenue, Campbell, CA  95008
41  * 
42  */
43
44 #define C_List
45 #define L_Basic
46
47 #include "Prelude.h"
48
49
50 #ifdef USL
51
52 strcasecmp(register const char *s1,
53            register const char *s2)
54 {
55     register int c1, c2;
56
57     while (*s1 && *s2) {
58         c1 = isupper(*s1) ? tolower(*s1) : *s1;
59         c2 = isupper(*s2) ? tolower(*s2) : *s2;
60         if (c1 != c2)
61             return (c1 - c2);
62         s1++;
63         s2++;
64     }
65     return (int) (*s1 - *s2);
66 }
67
68 #endif
69
70
71 // /////////////////////////////////////////////////////////////////
72 // class constructor
73 // /////////////////////////////////////////////////////////////////
74
75 List::List (int initial_size, int increment, grow_method_t method,
76             bool delete_elements)
77 : f_dtor_delete_elements (delete_elements)
78 {
79   assert (initial_size >= 0);
80   f_length = 0;
81   f_internal_length = initial_size;
82   f_grow_method = method;
83   if (increment == 0)
84     f_increment = initial_size;
85   else
86     f_increment = increment;
87   assert (f_increment > 0);
88   f_list_element = (FolioObject **)
89     malloc (sizeof (FolioObject *) * initial_size);
90 }
91
92
93 // /////////////////////////////////////////////////////////////////
94 // class destructor
95 // /////////////////////////////////////////////////////////////////
96
97 List::~List()
98 {
99   if (f_dtor_delete_elements)
100     remove_all (TRUE);
101   free ((char *) f_list_element);
102 }
103
104 // /////////////////////////////////////////////////////////////////
105 // check_space - create more space for elements if necessary
106 // /////////////////////////////////////////////////////////////////
107
108 void
109 List::check_space (int num_additions)
110 {
111   if (f_length + num_additions > f_internal_length)
112     {
113       // Loop until internal_length has grown large enough. 
114       while (f_length + num_additions > f_internal_length)
115         {
116           switch (f_grow_method)
117             {
118               case GROW_ADD:
119               f_internal_length = f_internal_length + f_increment;
120               break;
121               case GROW_MULTIPLY:
122               f_internal_length = f_internal_length * f_increment;
123               break;
124               default:
125               abort ();         // harsh!
126             }
127         }
128
129       f_list_element =
130         (FolioObject **) realloc ((char *) f_list_element,
131                                   sizeof (FolioObject *) * f_internal_length);
132     }
133 }    
134
135
136 // /////////////////////////////////////////////////////////////////
137 // append - append an element to the list
138 // /////////////////////////////////////////////////////////////////
139
140 void
141 List::append (FolioObject &element)
142 {
143   check_space();
144
145   /* -------- Add the element. -------- */
146   if (&element == NULL)
147     abort();
148   f_list_element[f_length] = &element;
149   f_length++;
150   notify (APPENDED, (void *)(size_t) (f_length - 1));
151 }
152
153
154 // /////////////////////////////////////////////////////////////////
155 // remove - remove an element from the list 
156 // /////////////////////////////////////////////////////////////////
157
158 void
159 List::remove (FolioObject &element)
160 {
161   /* -------- Look for the element in the list -------- */
162   int location = find (element);
163
164   if (location != -1)
165     remove (location);
166 }
167
168
169 // /////////////////////////////////////////////////////////////////
170 // remove - remove an element from the list 
171 // /////////////////////////////////////////////////////////////////
172
173 void
174 List::remove (unsigned int location)
175 {
176   // NOTE: check bounds 
177   // Shift the array back and overwrite deleted element.
178   f_length--;
179   for (int i = location; i < f_length; i++)
180     f_list_element[i] = f_list_element[i+1];
181 }
182
183
184 // /////////////////////////////////////////////////////////////////
185 // insert - insert an element in the list
186 // /////////////////////////////////////////////////////////////////
187
188 void
189 List::insert (unsigned int location, FolioObject *element)
190 {
191   check_space();
192
193   if (location > f_length)
194     abort();
195  
196   // Shift the array forward to make room for new insertion.
197   for (unsigned int i = f_length; i > location; i--)
198     f_list_element[i] = f_list_element[i-1];
199
200   // Insert the new element in the list.
201   f_list_element[location] = element;
202   f_length++;
203   notify (INSERTED, (void *)(size_t) location);
204 }
205
206
207 // /////////////////////////////////////////////////////////////////
208 // find - find an element in a list
209 // /////////////////////////////////////////////////////////////////
210
211 int
212 List::find (FolioObject &element)
213 {
214   /* -------- Search through the list, looking for element. -------- */
215   register int i;
216
217   for (i = 0; i < f_length; i++)
218     if (f_list_element[i] == &element)
219       return (i);
220
221   return (-1);
222 }
223
224
225 // /////////////////////////////////////////////////////////////////
226 // copy
227 // /////////////////////////////////////////////////////////////////
228
229 List *
230 List::copy() const
231 {
232     // copy the contents of the list into a new one 
233
234     // NOTE: use length() instead of f_length because it may be more general
235     List *retlist = new List(length());
236     for (unsigned int i = 0 ; i < length(); i++)
237       retlist->append((*this)[i]);
238
239     return retlist ;
240 }
241
242
243 // /////////////////////////////////////////////////////////////////
244 // remove_all - remove all the elements from the list
245 // /////////////////////////////////////////////////////////////////
246
247 void
248 List::remove_all (bool)
249 {
250   unsigned short length = f_length;
251   // Set length to 0, in case object dtor tries to mess with the list. 
252   f_length = 0;
253   // Reverse order delete is important for Long_Lived objects!! 
254   while (length)
255     delete f_list_element[--length];
256 }
257
258
259 /*
260
261   NOTE: Here's how to make the list use less space per list:
262
263   Make length an internal_length shorts.
264
265   change grow_method to a bit field of length 1.
266   change increment to a bit field of length 7.
267
268   if grow_method is multiple, use the increment as a literal.
269   if grow_method is add, use a static lookup table based on
270   the increment value.
271
272 */
273