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.
9 #include <StringList.h>
13 #include <StringPrivate.h>
14 #include <TypeConstants.h>
18 compare_private_data(const void* a
, const void* b
)
20 return BString::Private::StringFromData(*(char**)a
).Compare(
21 BString::Private::StringFromData(*(char**)b
));
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
)
43 BStringList::BStringList(const BStringList
& other
)
45 fStrings(other
.fStrings
)
47 _IncrementRefCounts();
51 BStringList::~BStringList()
53 _DecrementRefCounts();
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())
65 char* privateData
= BString::Private(string
).Data();
66 if (!fStrings
.AddItem(privateData
, index
))
69 BString::Private::IncrementDataRefCount(privateData
);
75 BStringList::Add(const BString
& _string
)
77 BString
string(_string
);
78 // makes sure the string is shareable
79 if (string
.Length() != _string
.Length())
82 char* privateData
= BString::Private(string
).Data();
83 if (!fStrings
.AddItem(privateData
))
86 BString::Private::IncrementDataRefCount(privateData
);
92 BStringList::Add(const BStringList
& list
, int32 index
)
94 if (!fStrings
.AddList(&list
.fStrings
, index
))
97 list
._IncrementRefCounts();
103 BStringList::Add(const BStringList
& list
)
105 if (!fStrings
.AddList(&list
.fStrings
))
108 list
._IncrementRefCounts();
114 BStringList::Remove(const BString
& string
, bool ignoreCase
)
117 int32 count
= fStrings
.CountItems();
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) {
130 for (int32 i
= count
- 1; i
>= 0; i
--) {
131 if (string
== StringAt(i
)) {
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
;
155 BStringList::Remove(int32 index
)
157 if (index
< 0 || index
>= fStrings
.CountItems())
160 char* privateData
= (char*)fStrings
.RemoveItem(index
);
161 BString
string(BString::Private::StringFromData(privateData
));
162 BString::Private::DecrementDataRefCount(privateData
);
168 BStringList::Remove(int32 index
, int32 count
)
170 int32 stringCount
= fStrings
.CountItems();
171 if (index
< 0 || index
> stringCount
)
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
);
184 BStringList::Replace(int32 index
, const BString
& string
)
186 if (index
< 0 || index
>= fStrings
.CountItems())
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
);
200 BStringList::MakeEmpty()
202 _DecrementRefCounts();
203 fStrings
.MakeEmpty();
208 BStringList::Sort(bool ignoreCase
)
210 fStrings
.SortItems(ignoreCase
211 ? compare_private_data_ignore_case
: compare_private_data
);
216 BStringList::Swap(int32 indexA
, int32 indexB
)
218 return fStrings
.SwapItems(indexA
, indexB
);
223 BStringList::Move(int32 fromIndex
, int32 toIndex
)
225 return fStrings
.MoveItem(fromIndex
, toIndex
);
230 BStringList::StringAt(int32 index
) const
232 return BString::Private::StringFromData((char*)fStrings
.ItemAt(index
));
237 BStringList::First() const
239 return BString::Private::StringFromData((char*)fStrings
.FirstItem());
244 BStringList::Last() const
246 return BString::Private::StringFromData((char*)fStrings
.LastItem());
251 BStringList::IndexOf(const BString
& string
, bool ignoreCase
) const
253 int32 count
= fStrings
.CountItems();
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)
264 for (int32 i
= 0; i
< count
; i
++) {
265 if (string
== StringAt(i
))
275 BStringList::CountStrings() const
277 return fStrings
.CountItems();
282 BStringList::IsEmpty() const
284 return fStrings
.IsEmpty();
289 BStringList::Join(const char* separator
, int32 length
) const
291 return _Join(separator
,
292 length
>= 0 ? strnlen(separator
, length
) : strlen(separator
));
297 BStringList::DoForEach(bool (*func
)(const BString
& string
))
299 int32 count
= fStrings
.CountItems();
300 for (int32 i
= 0; i
< count
; i
++)
306 BStringList::DoForEach(bool (*func
)(const BString
& string
, void* arg2
),
309 int32 count
= fStrings
.CountItems();
310 for (int32 i
= 0; i
< count
; i
++)
311 func(StringAt(i
), arg2
);
316 BStringList::operator=(const BStringList
& other
)
318 if (this != &other
) {
319 _DecrementRefCounts();
320 fStrings
= other
.fStrings
;
321 _IncrementRefCounts();
329 BStringList::operator==(const BStringList
& other
) const
334 int32 count
= fStrings
.CountItems();
335 if (count
!= other
.fStrings
.CountItems())
338 for (int32 i
= 0; i
< count
; i
++) {
339 if (StringAt(i
) != other
.StringAt(i
))
348 BStringList::IsFixedSize() const
355 BStringList::TypeCode() const
357 return B_STRING_LIST_TYPE
;
363 BStringList::AllowsTypeCode(type_code code
) const
365 return code
== B_STRING_LIST_TYPE
;
370 BStringList::FlattenedSize() const
373 int32 count
= CountStrings();
374 for (int32 i
= 0; i
< count
; i
++)
375 size
+= StringAt(i
).Length() + 1;
382 BStringList::Flatten(void* buf
, ssize_t size
) const
384 const char* buffer
= (const char*)buf
;
386 if (size
< FlattenedSize())
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
);
402 BStringList::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
404 if (code
!= B_STRING_LIST_TYPE
)
406 const char* bufferStart
= (const char*)buffer
;
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
)
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
));
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
));
447 BStringList::_Join(const char* separator
, int32 length
) const
449 // handle simple cases (0 or 1 element)
450 int32 count
= CountStrings();
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
463 char* buffer
= result
.LockBuffer(totalLength
);
467 for (int32 i
= 0; i
< count
; i
++) {
468 if (i
> 0 && length
> 0) {
469 memcpy(buffer
, separator
, length
);
473 BString string
= StringAt(i
);
474 memcpy(buffer
, string
.String(), string
.Length());
475 buffer
+= string
.Length();
478 return result
.UnlockBuffer(totalLength
);