3 * Copyright (C) 2014-2019 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_STRING_LIST_HPP_INCLUDED
19 #define CARLA_STRING_LIST_HPP_INCLUDED
21 #include "LinkedList.hpp"
23 // -----------------------------------------------------------------------
24 // Helper class to manage the lifetime of a "char**" object
26 class CharStringListPtr
29 CharStringListPtr() noexcept
30 : fCharList(nullptr) {}
32 CharStringListPtr(const char* const* const c
) noexcept
35 CharStringListPtr(const CharStringListPtr
& ptr
) noexcept
41 CharStringListPtr(const LinkedList
<const char*>& list
) noexcept
47 ~CharStringListPtr() noexcept
52 // -------------------------------------------------------------------
54 operator const char* const*() const noexcept
59 CharStringListPtr
& operator=(const char* const* const c
) noexcept
66 CharStringListPtr
& operator=(const CharStringListPtr
& ptr
) noexcept
73 CharStringListPtr
& operator=(const LinkedList
<const char*>& list
) noexcept
80 // -------------------------------------------------------------------
85 if (fCharList
== nullptr)
88 for (int i
=0; fCharList
[i
] != nullptr; ++i
)
89 delete[] fCharList
[i
];
95 void copy(const char* const* const c
) noexcept
97 CARLA_SAFE_ASSERT_RETURN(c
!= nullptr,);
98 CARLA_SAFE_ASSERT_RETURN(fCharList
== nullptr,);
100 std::size_t count
= 0;
101 for (; c
[count
] != nullptr; ++count
) {}
102 CARLA_SAFE_ASSERT_RETURN(count
> 0,);
104 const char** tmpList
;
107 tmpList
= new const char*[count
+1];
108 } CARLA_SAFE_EXCEPTION_RETURN("CharStringListPtr::copy",);
110 tmpList
[count
] = nullptr;
112 for (std::size_t i
=0; i
<count
; ++i
)
114 tmpList
[i
] = carla_strdup_safe(c
[i
]);
115 CARLA_SAFE_ASSERT_BREAK(tmpList
[i
] != nullptr);
121 void copy(const LinkedList
<const char*>& list
) noexcept
123 CARLA_SAFE_ASSERT_RETURN(fCharList
== nullptr,);
125 const std::size_t count(list
.count());
126 CARLA_SAFE_ASSERT_RETURN(count
> 0,);
128 const char** tmpList
;
131 tmpList
= new const char*[count
+1];
132 } CARLA_SAFE_EXCEPTION_RETURN("CharStringListPtr::copy",);
134 tmpList
[count
] = nullptr;
137 for (LinkedList
<const char*>::Itenerator it
= list
.begin2(); it
.valid(); it
.next(), ++i
)
139 tmpList
[i
] = carla_strdup_safe(it
.getValue(nullptr));
140 CARLA_SAFE_ASSERT_BREAK(tmpList
[i
] != nullptr);
142 CARLA_SAFE_ASSERT(i
== count
);
147 // -------------------------------------------------------------------
150 const char* const* fCharList
;
153 // -----------------------------------------------------------------------
156 class CarlaStringList
: public LinkedList
<const char*>
159 CarlaStringList(bool allocateElements
= true) noexcept
160 : LinkedList
<const char*>(),
161 fAllocateElements(allocateElements
) {}
163 CarlaStringList(const CarlaStringList
& list
) noexcept
164 : LinkedList
<const char*>(),
165 fAllocateElements(list
.fAllocateElements
)
167 for (Itenerator it
= list
.begin2(); it
.valid(); it
.next())
168 LinkedList
<const char*>::append(carla_strdup_safe(it
.getValue(nullptr)));
171 ~CarlaStringList() noexcept override
176 // -------------------------------------------------------------------
178 void clear() noexcept
180 if (fAllocateElements
)
182 for (Itenerator it
= begin2(); it
.valid(); it
.next())
184 if (const char* const string
= it
.getValue(nullptr))
189 LinkedList
<const char*>::clear();
192 // -------------------------------------------------------------------
194 bool append(const char* const string
) noexcept
196 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
198 if (const char* const stringDup
= fAllocateElements
? carla_strdup_safe(string
) : string
)
200 if (LinkedList
<const char*>::append(stringDup
))
208 bool appendUnique(const char* const string
) noexcept
210 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
212 if (contains(string
))
215 return append(string
);
218 bool appendAt(const char* const string
, const Itenerator
& it
) noexcept
220 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
222 if (const char* const stringDup
= fAllocateElements
? carla_strdup_safe(string
) : string
)
224 if (LinkedList
<const char*>::appendAt(stringDup
, it
))
232 bool insert(const char* const string
) noexcept
234 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
236 if (const char* const stringDup
= fAllocateElements
? carla_strdup_safe(string
) : string
)
238 if (LinkedList
<const char*>::insert(stringDup
))
246 bool insertAt(const char* const string
, const Itenerator
& it
) noexcept
248 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
250 if (const char* const stringDup
= fAllocateElements
? carla_strdup_safe(string
) : string
)
252 if (LinkedList
<const char*>::insertAt(stringDup
, it
))
260 // -------------------------------------------------------------------
262 const char* getAt(const std::size_t index
) const noexcept
264 CARLA_SAFE_ASSERT_RETURN(fCount
> 0 && index
< fCount
, nullptr);
267 ListHead
* entry
= fQueue
.next
;
269 for (; i
++ != index
; entry
= entry
->next
) {}
271 const Data
* const data(list_entry_const(entry
, Data
, siblings
));
272 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr, nullptr);
277 const char* getFirst() const noexcept
279 CARLA_SAFE_ASSERT_RETURN(fCount
> 0, nullptr);
281 const Data
* const data(list_entry_const(fQueue
.next
, Data
, siblings
));
282 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr, nullptr);
287 const char* getLast() const noexcept
289 CARLA_SAFE_ASSERT_RETURN(fCount
> 0, nullptr);
291 const Data
* const data(list_entry_const(fQueue
.prev
, Data
, siblings
));
292 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr, nullptr);
297 // -------------------------------------------------------------------
299 const char* getAndRemoveFirst() noexcept
301 CARLA_SAFE_ASSERT_RETURN(fCount
> 0, nullptr);
303 const Data
* const data
= list_entry_const(fQueue
.next
, Data
, siblings
);
304 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr, nullptr);
306 const char* const ret
= data
->value
;
308 Itenerator it
= begin2();
309 LinkedList
<const char*>::remove(it
);
314 // -------------------------------------------------------------------
316 bool contains(const char* const string
) noexcept
318 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
323 for (Itenerator it
= begin2(); it
.valid(); it
.next())
325 const char* const stringComp(it
.getValue(nullptr));
326 CARLA_SAFE_ASSERT_CONTINUE(stringComp
!= nullptr);
328 if (std::strcmp(string
, stringComp
) == 0)
335 const char* containsAndReturnString(const char* const string
) noexcept
337 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, nullptr);
342 for (Itenerator it
= begin2(); it
.valid(); it
.next())
344 const char* const stringComp(it
.getValue(nullptr));
345 CARLA_SAFE_ASSERT_CONTINUE(stringComp
!= nullptr);
347 if (std::strcmp(string
, stringComp
) == 0)
354 // -------------------------------------------------------------------
356 void remove(Itenerator
& it
) noexcept
358 if (const char* const string
= it
.getValue(nullptr))
361 LinkedList
<const char*>::remove(it
);
364 bool removeOne(const char* const string
) noexcept
366 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr, false);
368 for (Itenerator it
= begin2(); it
.valid(); it
.next())
370 const char* const stringComp(it
.getValue(nullptr));
371 CARLA_SAFE_ASSERT_CONTINUE(stringComp
!= nullptr);
373 if (std::strcmp(string
, stringComp
) != 0)
377 LinkedList
<const char*>::remove(it
);
384 void removeAll(const char* const string
) noexcept
386 CARLA_SAFE_ASSERT_RETURN(string
!= nullptr,);
388 for (Itenerator it
= begin2(); it
.valid(); it
.next())
390 const char* const stringComp(it
.getValue(nullptr));
391 CARLA_SAFE_ASSERT_CONTINUE(stringComp
!= nullptr);
393 if (std::strcmp(string
, stringComp
) != 0)
397 LinkedList
<const char*>::remove(it
);
401 // -------------------------------------------------------------------
403 CharStringListPtr
toCharStringListPtr() const noexcept
405 return CharStringListPtr(*this);
408 CarlaStringList
& operator=(const char* const* const charStringList
) noexcept
410 CARLA_SAFE_ASSERT_RETURN(! fAllocateElements
, *this);
414 CARLA_SAFE_ASSERT_RETURN(charStringList
!= nullptr, *this);
416 for (int i
=0; charStringList
[i
] != nullptr; ++i
)
418 if (const char* const string
= carla_strdup_safe(charStringList
[i
]))
419 LinkedList
<const char*>::append(string
);
425 CarlaStringList
& operator=(const CarlaStringList
& list
) noexcept
427 CARLA_SAFE_ASSERT_RETURN(! fAllocateElements
, *this);
431 for (Itenerator it
= list
.begin2(); it
.valid(); it
.next())
433 if (const char* const string
= carla_strdup_safe(it
.getValue(nullptr)))
434 LinkedList
<const char*>::append(string
);
441 const bool fAllocateElements
;
443 CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
446 // -----------------------------------------------------------------------
448 #endif // CARLA_STRING_LIST_HPP_INCLUDED