xref: /haiku/src/kits/support/List.cpp (revision 9d6d3fcf5fe8308cd020cecf89dede440346f8c4)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		List.cpp
23 //	Author(s):		The Storage kit Team
24 //					Isaac Yonemoto
25 //	Description:	BList class provides storage for pointers.
26 //					Not thread safe.
27 //------------------------------------------------------------------------------
28 
29 
30 // Standard Includes -----------------------------------------------------------
31 #include <List.h>
32 
33 // System Includes -------------------------------------------------------------
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 
39 // helper function
40 static inline
41 void
42 move_items(void** items, int32 offset, int32 count)
43 {
44 	if (count > 0 && offset != 0)
45 		memmove(items + offset, items, count * sizeof(void*));
46 }
47 
48 
49 // constructor
50 BList::BList(int32 count)
51 	  :		 fObjectList(NULL),
52 			 fPhysicalSize(0),
53 			 fItemCount(0),
54 			 fBlockSize(count)
55 {
56 	if (fBlockSize <= 0)
57 		fBlockSize = 1;
58 	Resize(fItemCount);
59 }
60 
61 
62 // copy constructor
63 BList::BList(const BList& anotherList)
64 	  :		 fObjectList(NULL),
65 			 fPhysicalSize(0),
66 			 fItemCount(0),
67 			 fBlockSize(anotherList.fBlockSize)
68 {
69 	*this = anotherList;
70 }
71 
72 
73 // destructor
74 BList::~BList()
75 {
76 	free(fObjectList);
77 }
78 
79 
80 // =
81 BList&
82 BList::operator =(const BList &list)
83 {
84 	fBlockSize = list.fBlockSize;
85 	Resize(list.fItemCount);
86 	memcpy(fObjectList, list.fObjectList, fItemCount * sizeof(void*));
87 	return *this;
88 }
89 
90 
91 // AddItem
92 bool
93 BList::AddItem(void *item, int32 index)
94 {
95 	bool result = (index >= 0 && index <= fItemCount
96 				   && Resize(fItemCount + 1));
97 	if (result) {
98 		move_items(fObjectList + index, 1, fItemCount - index - 1);
99 		fObjectList[index] = item;
100 	}
101 	return result;
102 }
103 
104 
105 // AddItem
106 bool
107 BList::AddItem(void *item)
108 {
109 	bool result = true;
110 	if ((int32)fPhysicalSize > fItemCount) {
111 		fObjectList[fItemCount] = item;
112 		fItemCount++;
113 	} else {
114 		if ((result = Resize(fItemCount + 1)))
115 			fObjectList[fItemCount - 1] = item;
116 	}
117 	return result;
118 }
119 
120 
121 // AddList
122 bool
123 BList::AddList(const BList *list, int32 index)
124 {
125 	bool result = (list && index >= 0 && index <= fItemCount);
126 	if (result && list->fItemCount > 0) {
127 		int32 count = list->fItemCount;
128 		result = Resize(fItemCount + count);
129 		if (result) {
130 			move_items(fObjectList + index, count, fItemCount - index - count);
131 			memcpy(fObjectList + index, list->fObjectList,
132 				   list->fItemCount * sizeof(void *));
133 		}
134 	}
135 	return result;
136 }
137 
138 
139 // AddList
140 bool
141 BList::AddList(const BList *list)
142 {
143 	bool result = (list != NULL);
144 	if (result && list->fItemCount > 0) {
145 		int32 index = fItemCount;
146 		int32 count = list->fItemCount;
147 		result = Resize(fItemCount + count);
148 		if (result) {
149 			memcpy(fObjectList + index, list->fObjectList,
150 				   list->fItemCount * sizeof(void *));
151 		}
152 	}
153 	return result;
154 }
155 
156 
157 // RemoveItem
158 bool
159 BList::RemoveItem(void *item)
160 {
161 	int32 index = IndexOf(item);
162 	bool result = (index >= 0);
163 	if (result)
164 		RemoveItem(index);
165 	return result;
166 }
167 
168 
169 // RemoveItem
170 void *
171 BList::RemoveItem(int32 index)
172 {
173 	void *item = NULL;
174 	if (index >= 0 && index < fItemCount) {
175 		item = fObjectList[index];
176 		move_items(fObjectList + index + 1, -1, fItemCount - index - 1);
177 		Resize(fItemCount - 1);
178 	}
179 	return item;
180 }
181 
182 
183 // RemoveItems
184 bool
185 BList::RemoveItems(int32 index, int32 count)
186 {
187 	bool result = (index >= 0 && index <= fItemCount);
188 	if (result) {
189 		if (index + count > fItemCount)
190 			count = fItemCount - index;
191 		if (count > 0) {
192 			move_items(fObjectList + index + count, -count,
193 					   fItemCount - index - count);
194 			Resize(fItemCount - count);
195 		} else
196 			result = false;
197 	}
198 	return result;
199 }
200 
201 
202 //ReplaceItem
203 bool
204 BList::ReplaceItem(int32 index, void *newItem)
205 {
206 	bool result = false;
207 
208 	if (index >= 0 && index < fItemCount) {
209 		fObjectList[index] = newItem;
210 		result = true;
211 	}
212 	return result;
213 }
214 
215 
216 // MakeEmpty
217 void
218 BList::MakeEmpty()
219 {
220 	Resize(0);
221 }
222 
223 
224 /* Reordering items. */
225 // SortItems
226 void
227 BList::SortItems(int (*compareFunc)(const void *, const void *))
228 {
229 	if (compareFunc)
230 		qsort(fObjectList, fItemCount, sizeof(void *), compareFunc);
231 }
232 
233 
234 //SwapItems
235 bool
236 BList::SwapItems(int32 indexA, int32 indexB)
237 {
238 	bool result = false;
239 
240 	if (indexA >= 0 && indexA < fItemCount
241 		&& indexB >= 0 && indexB < fItemCount) {
242 
243 		void *tmpItem = fObjectList[indexA];
244 		fObjectList[indexA] = fObjectList[indexB];
245 		fObjectList[indexB] = tmpItem;
246 
247 		result = true;
248 	}
249 
250 	return result;
251 }
252 
253 
254 //MoveItem
255   //This moves a list item from posititon a to position b, moving the appropriate block of
256   // list elements to make up for the move.  For example, in the array:
257   // A B C D E F G H I J
258   //  Moveing 1(B)->6(G) would result in this:
259   // A C D E F G B H I J
260 bool
261 BList::MoveItem(int32 fromIndex, int32 toIndex)
262 {
263 	if ((fromIndex >= fItemCount) || (toIndex >= fItemCount) || (fromIndex < 0) || (toIndex < 0))
264 		return false;
265 
266 	if (fromIndex < toIndex)
267 	{
268 		void * tmp_mover = fObjectList[fromIndex];
269 		memmove(fObjectList + fromIndex + 1, fObjectList + fromIndex, (toIndex - fromIndex) * sizeof(void *));
270 		fObjectList[toIndex] = tmp_mover;
271 	}
272 	else if (fromIndex > toIndex)
273 	{
274 		void * tmp_mover = fObjectList[fromIndex];
275 		memmove(fObjectList + toIndex + 1, fObjectList + toIndex, (fromIndex - toIndex) * sizeof(void *));
276 		fObjectList[toIndex] = tmp_mover;
277 	};
278 	return true;
279 }
280 
281 
282 /* Retrieving items. */
283 // ItemAt
284 void *
285 BList::ItemAt(int32 index) const
286 {
287 	void *item = NULL;
288 	if (index >= 0 && index < fItemCount)
289 		item = fObjectList[index];
290 	return item;
291 }
292 
293 
294 // FirstItem
295 void *
296 BList::FirstItem() const
297 {
298 	void *item = NULL;
299 	if (fItemCount > 0)
300 		item = fObjectList[0];
301 	return item;
302 }
303 
304 
305 // ItemAtFast
306 void *
307 BList::ItemAtFast(int32 index) const
308 {
309 	return fObjectList[index];
310 }
311 
312 
313 // Items
314 void *
315 BList::Items() const
316 {
317 	return fObjectList;
318 }
319 
320 
321 // LastItem
322 void *
323 BList::LastItem() const
324 {
325 	void *item = NULL;
326 	if (fItemCount > 0)
327 		item = fObjectList[fItemCount - 1];
328 	return item;
329 }
330 
331 
332 /* Querying the list. */
333 // HasItem
334 bool
335 BList::HasItem(void *item) const
336 {
337 	return (IndexOf(item) >= 0);
338 }
339 
340 
341 // IndexOf
342 int32
343 BList::IndexOf(void *item) const
344 {
345 	for (int32 i = 0; i < fItemCount; i++) {
346 		if (fObjectList[i] == item)
347 			return i;
348 	}
349 	return -1;
350 }
351 
352 
353 // CountItems
354 int32
355 BList::CountItems() const
356 {
357 	return fItemCount;
358 }
359 
360 
361 // IsEmpty
362 bool
363 BList::IsEmpty() const
364 {
365 	return (fItemCount == 0);
366 }
367 
368 
369 /* Iterating over the list. */
370 //iterate a function over the whole list.  If the function outputs a true
371 //value, then the process is terminated.
372 
373 void
374 BList::DoForEach(bool (*func)(void *))
375 {
376 	bool terminate = false; int32 index = 0;		//set terminate condition variables to go.
377 	if (func != NULL)
378 	{
379 		while ((!terminate) && (index < fItemCount))	//check terminate condition.
380 		{
381 			terminate = func(fObjectList[index]);			//reset immediate terminator
382 			index++;									//advance along the list.
383 		};
384 	}
385 
386 }
387 
388 
389 //same as above, except this function takes an argument.
390 void
391 BList::DoForEach(bool (*func)(void *, void*), void * arg)
392 {
393 	bool terminate = false; int32 index = 0;
394 	if (func != NULL)
395 	{
396 		while ((!terminate) && (index < fItemCount))
397 		{
398 			terminate = func(fObjectList[index], arg);
399 			index++;
400 		};
401 	}
402 }
403 
404 
405 // obsolete AddList(BList* list, int32 index) and AddList(BList* list)
406 
407 // AddList
408 extern "C" bool
409 AddList__5BListP5BListl(BList* self, BList* list, int32 index)
410 {
411 	return self->AddList((const BList*)list, index);
412 }
413 
414 
415 // AddList
416 extern "C" bool
417 AddList__5BListP5BList(BList* self, BList* list)
418 {
419 	return self->AddList((const BList*)list);
420 }
421 
422 
423 // FBC
424 void BList::_ReservedList1() {}
425 void BList::_ReservedList2() {}
426 
427 
428 // Resize
429 //
430 // Resizes fObjectList to be large enough to contain count items.
431 // fItemCount is adjusted accordingly.
432 bool
433 BList::Resize(int32 count)
434 {
435 	bool result = true;
436 	// calculate the new physical size
437 	int32 newSize = count;
438 	if (newSize <= 0)
439 		newSize = 1;
440 	newSize = ((newSize - 1) / fBlockSize + 1) * fBlockSize;
441 	// resize if necessary
442 	if ((size_t)newSize != fPhysicalSize) {
443 		void** newObjectList
444 			= (void**)realloc(fObjectList, newSize * sizeof(void*));
445 		if (newObjectList) {
446 			fObjectList = newObjectList;
447 			fPhysicalSize = newSize;
448 		} else
449 			result = false;
450 	}
451 	if (result)
452 		fItemCount = count;
453 	return result;
454 }
455 
456