bin/pc: Mark non-returning function as void
[haiku.git] / src / kits / support / StringList.cpp
blobfe6e138ac01916e7d9fa0b56a28075961bfe3f4c
1 /*
2 * Copyright 2011-2013, Ingo Weinhold, ingo_weinhold@gmx.de
3 * Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
5 * Distributed under the terms of the MIT License.
6 */
9 #include <StringList.h>
11 #include <algorithm>
13 #include <StringPrivate.h>
14 #include <TypeConstants.h>
17 static int
18 compare_private_data(const void* a, const void* b)
20 return BString::Private::StringFromData(*(char**)a).Compare(
21 BString::Private::StringFromData(*(char**)b));
25 static int
26 compare_private_data_ignore_case(const void* a, const void* b)
28 return BString::Private::StringFromData(*(char**)a).ICompare(
29 BString::Private::StringFromData(*(char**)b));
33 // #pragma mark - BStringList
36 BStringList::BStringList(int32 count)
38 fStrings(count)
43 BStringList::BStringList(const BStringList& other)
45 fStrings(other.fStrings)
47 _IncrementRefCounts();
51 BStringList::~BStringList()
53 _DecrementRefCounts();
57 bool
58 BStringList::Add(const BString& _string, int32 index)
60 BString string(_string);
61 // makes sure the string is shareable
62 if (string.Length() != _string.Length())
63 return false;
65 char* privateData = BString::Private(string).Data();
66 if (!fStrings.AddItem(privateData, index))
67 return false;
69 BString::Private::IncrementDataRefCount(privateData);
70 return true;
74 bool
75 BStringList::Add(const BString& _string)
77 BString string(_string);
78 // makes sure the string is shareable
79 if (string.Length() != _string.Length())
80 return false;
82 char* privateData = BString::Private(string).Data();
83 if (!fStrings.AddItem(privateData))
84 return false;
86 BString::Private::IncrementDataRefCount(privateData);
87 return true;
91 bool
92 BStringList::Add(const BStringList& list, int32 index)
94 if (!fStrings.AddList(&list.fStrings, index))
95 return false;
97 list._IncrementRefCounts();
98 return true;
102 bool
103 BStringList::Add(const BStringList& list)
105 if (!fStrings.AddList(&list.fStrings))
106 return false;
108 list._IncrementRefCounts();
109 return true;
113 bool
114 BStringList::Remove(const BString& string, bool ignoreCase)
116 bool result = false;
117 int32 count = fStrings.CountItems();
119 if (ignoreCase) {
120 int32 length = string.Length();
122 for (int32 i = count - 1; i >= 0; i--) {
123 BString element(StringAt(i));
124 if (length == element.Length() && string.ICompare(element) == 0) {
125 Remove(i);
126 result = true;
129 } else {
130 for (int32 i = count - 1; i >= 0; i--) {
131 if (string == StringAt(i)) {
132 Remove(i);
133 result = true;
138 return result;
142 bool
143 BStringList::Remove(const BStringList& list, bool ignoreCase)
145 bool removedAnything = false;
146 int32 stringCount = list.CountStrings();
147 for (int32 i = 0; i < stringCount; i++)
148 removedAnything |= Remove(list.StringAt(i), ignoreCase);
150 return removedAnything;
154 BString
155 BStringList::Remove(int32 index)
157 if (index < 0 || index >= fStrings.CountItems())
158 return BString();
160 char* privateData = (char*)fStrings.RemoveItem(index);
161 BString string(BString::Private::StringFromData(privateData));
162 BString::Private::DecrementDataRefCount(privateData);
163 return string;
167 bool
168 BStringList::Remove(int32 index, int32 count)
170 int32 stringCount = fStrings.CountItems();
171 if (index < 0 || index > stringCount)
172 return false;
174 int32 end = index + std::min(stringCount - index, count);
175 for (int32 i = index; i < end; i++)
176 BString::Private::DecrementDataRefCount((char*)fStrings.ItemAt(i));
178 fStrings.RemoveItems(index, end - index);
179 return true;
183 bool
184 BStringList::Replace(int32 index, const BString& string)
186 if (index < 0 || index >= fStrings.CountItems())
187 return false;
189 BString::Private::DecrementDataRefCount((char*)fStrings.ItemAt(index));
191 char* privateData = BString::Private(string).Data();
192 BString::Private::IncrementDataRefCount(privateData);
193 fStrings.ReplaceItem(index, privateData);
195 return true;
199 void
200 BStringList::MakeEmpty()
202 _DecrementRefCounts();
203 fStrings.MakeEmpty();
207 void
208 BStringList::Sort(bool ignoreCase)
210 fStrings.SortItems(ignoreCase
211 ? compare_private_data_ignore_case : compare_private_data);
215 bool
216 BStringList::Swap(int32 indexA, int32 indexB)
218 return fStrings.SwapItems(indexA, indexB);
222 bool
223 BStringList::Move(int32 fromIndex, int32 toIndex)
225 return fStrings.MoveItem(fromIndex, toIndex);
229 BString
230 BStringList::StringAt(int32 index) const
232 return BString::Private::StringFromData((char*)fStrings.ItemAt(index));
236 BString
237 BStringList::First() const
239 return BString::Private::StringFromData((char*)fStrings.FirstItem());
243 BString
244 BStringList::Last() const
246 return BString::Private::StringFromData((char*)fStrings.LastItem());
250 int32
251 BStringList::IndexOf(const BString& string, bool ignoreCase) const
253 int32 count = fStrings.CountItems();
255 if (ignoreCase) {
256 int32 length = string.Length();
258 for (int32 i = 0; i < count; i++) {
259 BString element(StringAt(i));
260 if (length == element.Length() && string.ICompare(element) == 0)
261 return i;
263 } else {
264 for (int32 i = 0; i < count; i++) {
265 if (string == StringAt(i))
266 return i;
270 return -1;
274 int32
275 BStringList::CountStrings() const
277 return fStrings.CountItems();
281 bool
282 BStringList::IsEmpty() const
284 return fStrings.IsEmpty();
288 BString
289 BStringList::Join(const char* separator, int32 length) const
291 return _Join(separator,
292 length >= 0 ? strnlen(separator, length) : strlen(separator));
296 void
297 BStringList::DoForEach(bool (*func)(const BString& string))
299 int32 count = fStrings.CountItems();
300 for (int32 i = 0; i < count; i++)
301 func(StringAt(i));
305 void
306 BStringList::DoForEach(bool (*func)(const BString& string, void* arg2),
307 void* arg2)
309 int32 count = fStrings.CountItems();
310 for (int32 i = 0; i < count; i++)
311 func(StringAt(i), arg2);
315 BStringList&
316 BStringList::operator=(const BStringList& other)
318 if (this != &other) {
319 _DecrementRefCounts();
320 fStrings = other.fStrings;
321 _IncrementRefCounts();
324 return *this;
328 bool
329 BStringList::operator==(const BStringList& other) const
331 if (this == &other)
332 return true;
334 int32 count = fStrings.CountItems();
335 if (count != other.fStrings.CountItems())
336 return false;
338 for (int32 i = 0; i < count; i++) {
339 if (StringAt(i) != other.StringAt(i))
340 return false;
343 return true;
347 bool
348 BStringList::IsFixedSize() const
350 return false;
354 type_code
355 BStringList::TypeCode() const
357 return B_STRING_LIST_TYPE;
362 bool
363 BStringList::AllowsTypeCode(type_code code) const
365 return code == B_STRING_LIST_TYPE;
369 ssize_t
370 BStringList::FlattenedSize() const
372 ssize_t size = 0;
373 int32 count = CountStrings();
374 for (int32 i = 0; i < count; i++)
375 size += StringAt(i).Length() + 1;
377 return size;
381 status_t
382 BStringList::Flatten(void* buf, ssize_t size) const
384 const char* buffer = (const char*)buf;
386 if (size < FlattenedSize())
387 return B_NO_MEMORY;
389 int32 count = CountStrings();
390 for (int32 i = 0; i < count; i++) {
391 BString item = StringAt(i);
392 ssize_t storeSize = item.Length() + 1;
393 memcpy((void*)buffer, (const void*)item.String(), storeSize);
394 buffer += storeSize;
397 return B_OK;
401 status_t
402 BStringList::Unflatten(type_code code, const void* buffer, ssize_t size)
404 if (code != B_STRING_LIST_TYPE)
405 return B_ERROR;
406 const char* bufferStart = (const char*)buffer;
408 MakeEmpty();
410 off_t offset = 0;
411 while (offset < size) {
412 const char* string = bufferStart + offset;
413 size_t restSize = size - offset;
414 size_t read = strnlen(string, restSize);
415 if (read == restSize)
416 return B_BAD_VALUE;
418 if (!Add(string))
419 return B_NO_MEMORY;
420 offset += read + 1;
423 return B_OK;
427 void
428 BStringList::_IncrementRefCounts() const
430 int32 count = fStrings.CountItems();
431 for (int32 i = 0; i < count; i++) {
432 BString::Private::IncrementDataRefCount((char*)fStrings.ItemAt(i));
437 void
438 BStringList::_DecrementRefCounts() const
440 int32 count = fStrings.CountItems();
441 for (int32 i = 0; i < count; i++)
442 BString::Private::DecrementDataRefCount((char*)fStrings.ItemAt(i));
446 BString
447 BStringList::_Join(const char* separator, int32 length) const
449 // handle simple cases (0 or 1 element)
450 int32 count = CountStrings();
451 if (count == 0)
452 return BString();
453 if (count == 1)
454 return StringAt(0);
456 // determine the total length
457 int32 totalLength = length * (count - 1);
458 for (int32 i = 0; i < count; i++)
459 totalLength += StringAt(i).Length();
461 // compose the result string
462 BString result;
463 char* buffer = result.LockBuffer(totalLength);
464 if (buffer == NULL)
465 return result;
467 for (int32 i = 0; i < count; i++) {
468 if (i > 0 && length > 0) {
469 memcpy(buffer, separator, length);
470 buffer += length;
473 BString string = StringAt(i);
474 memcpy(buffer, string.String(), string.Length());
475 buffer += string.Length();
478 return result.UnlockBuffer(totalLength);