OpenShot Library | libopenshot-audio  0.1.9
juce_StringArray.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
27 {
28 }
29 
31  : strings (other.strings)
32 {
33 }
34 
36  : strings (std::move (other.strings))
37 {
38 }
39 
41  : strings (std::move (other))
42 {
43 }
44 
45 StringArray::StringArray (const String& firstValue)
46 {
47  strings.add (firstValue);
48 }
49 
50 StringArray::StringArray (const String* initialStrings, int numberOfStrings)
51 {
52  strings.addArray (initialStrings, numberOfStrings);
53 }
54 
55 StringArray::StringArray (const char* const* initialStrings)
56 {
57  strings.addNullTerminatedArray (initialStrings);
58 }
59 
60 StringArray::StringArray (const char* const* initialStrings, int numberOfStrings)
61 {
62  strings.addArray (initialStrings, numberOfStrings);
63 }
64 
65 StringArray::StringArray (const wchar_t* const* initialStrings)
66 {
67  strings.addNullTerminatedArray (initialStrings);
68 }
69 
70 StringArray::StringArray (const wchar_t* const* initialStrings, int numberOfStrings)
71 {
72  strings.addArray (initialStrings, numberOfStrings);
73 }
74 
75 StringArray::StringArray (const std::initializer_list<const char*>& stringList)
76 {
77  strings.addArray (stringList);
78 }
79 
81 {
82  strings = other.strings;
83  return *this;
84 }
85 
87 {
88  strings = std::move (other.strings);
89  return *this;
90 }
91 
93 {
94 }
95 
96 bool StringArray::operator== (const StringArray& other) const noexcept
97 {
98  return strings == other.strings;
99 }
100 
101 bool StringArray::operator!= (const StringArray& other) const noexcept
102 {
103  return ! operator== (other);
104 }
105 
106 void StringArray::swapWith (StringArray& other) noexcept
107 {
108  strings.swapWith (other.strings);
109 }
110 
112 {
113  strings.clear();
114 }
115 
117 {
118  strings.clearQuick();
119 }
120 
121 const String& StringArray::operator[] (int index) const noexcept
122 {
123  if (isPositiveAndBelow (index, strings.size()))
124  return strings.getReference (index);
125 
126  static String empty;
127  return empty;
128 }
129 
130 String& StringArray::getReference (int index) noexcept
131 {
132  return strings.getReference (index);
133 }
134 
135 void StringArray::add (String newString)
136 {
137  // NB: the local temp copy is to avoid a dangling pointer if the
138  // argument being passed-in is a reference into this array.
139  strings.add (std::move (newString));
140 }
141 
142 void StringArray::insert (int index, String newString)
143 {
144  // NB: the local temp copy is to avoid a dangling pointer if the
145  // argument being passed-in is a reference into this array.
146  strings.insert (index, std::move (newString));
147 }
148 
149 bool StringArray::addIfNotAlreadyThere (const String& newString, bool ignoreCase)
150 {
151  if (contains (newString, ignoreCase))
152  return false;
153 
154  add (newString);
155  return true;
156 }
157 
158 void StringArray::addArray (const StringArray& otherArray, int startIndex, int numElementsToAdd)
159 {
160  jassert (this != &otherArray); // can't add from our own elements!
161 
162  if (startIndex < 0)
163  {
164  jassertfalse;
165  startIndex = 0;
166  }
167 
168  if (numElementsToAdd < 0 || startIndex + numElementsToAdd > otherArray.size())
169  numElementsToAdd = otherArray.size() - startIndex;
170 
171  while (--numElementsToAdd >= 0)
172  strings.add (otherArray.strings.getReference (startIndex++));
173 }
174 
175 void StringArray::mergeArray (const StringArray& otherArray, bool ignoreCase)
176 {
177  jassert (this != &otherArray); // can't add from our own elements!
178 
179  for (auto& s : otherArray)
180  addIfNotAlreadyThere (s, ignoreCase);
181 }
182 
183 void StringArray::set (int index, String newString)
184 {
185  strings.set (index, std::move (newString));
186 }
187 
188 bool StringArray::contains (StringRef stringToLookFor, bool ignoreCase) const
189 {
190  return indexOf (stringToLookFor, ignoreCase) >= 0;
191 }
192 
193 int StringArray::indexOf (StringRef stringToLookFor, bool ignoreCase, int i) const
194 {
195  if (i < 0)
196  i = 0;
197 
198  auto numElements = size();
199 
200  if (ignoreCase)
201  {
202  for (; i < numElements; ++i)
203  if (strings.getReference(i).equalsIgnoreCase (stringToLookFor))
204  return i;
205  }
206  else
207  {
208  for (; i < numElements; ++i)
209  if (stringToLookFor == strings.getReference (i))
210  return i;
211  }
212 
213  return -1;
214 }
215 
216 void StringArray::move (int currentIndex, int newIndex) noexcept
217 {
218  strings.move (currentIndex, newIndex);
219 }
220 
221 //==============================================================================
222 void StringArray::remove (int index)
223 {
224  strings.remove (index);
225 }
226 
227 void StringArray::removeString (StringRef stringToRemove, bool ignoreCase)
228 {
229  if (ignoreCase)
230  {
231  for (int i = size(); --i >= 0;)
232  if (strings.getReference(i).equalsIgnoreCase (stringToRemove))
233  strings.remove (i);
234  }
235  else
236  {
237  for (int i = size(); --i >= 0;)
238  if (stringToRemove == strings.getReference (i))
239  strings.remove (i);
240  }
241 }
242 
243 void StringArray::removeRange (int startIndex, int numberToRemove)
244 {
245  strings.removeRange (startIndex, numberToRemove);
246 }
247 
248 //==============================================================================
249 void StringArray::removeEmptyStrings (bool removeWhitespaceStrings)
250 {
251  if (removeWhitespaceStrings)
252  {
253  for (int i = size(); --i >= 0;)
254  if (! strings.getReference(i).containsNonWhitespaceChars())
255  strings.remove (i);
256  }
257  else
258  {
259  for (int i = size(); --i >= 0;)
260  if (strings.getReference(i).isEmpty())
261  strings.remove (i);
262  }
263 }
264 
266 {
267  for (auto& s : strings)
268  s = s.trim();
269 }
270 
271 //==============================================================================
272 void StringArray::sort (bool ignoreCase)
273 {
274  if (ignoreCase)
275  std::sort (strings.begin(), strings.end(),
276  [] (const String& a, const String& b) { return a.compareIgnoreCase (b) < 0; });
277  else
278  std::sort (strings.begin(), strings.end());
279 }
280 
282 {
283  std::sort (strings.begin(), strings.end(),
284  [] (const String& a, const String& b) { return a.compareNatural (b) < 0; });
285 }
286 
287 //==============================================================================
288 String StringArray::joinIntoString (StringRef separator, int start, int numberToJoin) const
289 {
290  auto last = (numberToJoin < 0) ? size()
291  : jmin (size(), start + numberToJoin);
292 
293  if (start < 0)
294  start = 0;
295 
296  if (start >= last)
297  return {};
298 
299  if (start == last - 1)
300  return strings.getReference (start);
301 
302  auto separatorBytes = separator.text.sizeInBytes() - sizeof (String::CharPointerType::CharType);
303  auto bytesNeeded = separatorBytes * (size_t) (last - start - 1);
304 
305  for (int i = start; i < last; ++i)
306  bytesNeeded += strings.getReference(i).getCharPointer().sizeInBytes() - sizeof (String::CharPointerType::CharType);
307 
308  String result;
309  result.preallocateBytes (bytesNeeded);
310 
311  auto dest = result.getCharPointer();
312 
313  while (start < last)
314  {
315  auto& s = strings.getReference (start);
316 
317  if (! s.isEmpty())
318  dest.writeAll (s.getCharPointer());
319 
320  if (++start < last && separatorBytes > 0)
321  dest.writeAll (separator.text);
322  }
323 
324  dest.writeNull();
325  return result;
326 }
327 
328 int StringArray::addTokens (StringRef text, const bool preserveQuotedStrings)
329 {
330  return addTokens (text, " \n\r\t", preserveQuotedStrings ? "\"" : "");
331 }
332 
333 int StringArray::addTokens (StringRef text, StringRef breakCharacters, StringRef quoteCharacters)
334 {
335  int num = 0;
336 
337  if (text.isNotEmpty())
338  {
339  for (auto t = text.text;;)
340  {
341  auto tokenEnd = CharacterFunctions::findEndOfToken (t,
342  breakCharacters.text,
343  quoteCharacters.text);
344  strings.add (String (t, tokenEnd));
345  ++num;
346 
347  if (tokenEnd.isEmpty())
348  break;
349 
350  t = ++tokenEnd;
351  }
352  }
353 
354  return num;
355 }
356 
358 {
359  int numLines = 0;
360  auto text = sourceText.text;
361  bool finished = text.isEmpty();
362 
363  while (! finished)
364  {
365  for (auto startOfLine = text;;)
366  {
367  auto endOfLine = text;
368 
369  switch (text.getAndAdvance())
370  {
371  case 0: finished = true; break;
372  case '\n': break;
373  case '\r': if (*text == '\n') ++text; break;
374  default: continue;
375  }
376 
377  strings.add (String (startOfLine, endOfLine));
378  ++numLines;
379  break;
380  }
381  }
382 
383  return numLines;
384 }
385 
386 StringArray StringArray::fromTokens (StringRef stringToTokenise, bool preserveQuotedStrings)
387 {
388  StringArray s;
389  s.addTokens (stringToTokenise, preserveQuotedStrings);
390  return s;
391 }
392 
394  StringRef breakCharacters,
395  StringRef quoteCharacters)
396 {
397  StringArray s;
398  s.addTokens (stringToTokenise, breakCharacters, quoteCharacters);
399  return s;
400 }
401 
403 {
404  StringArray s;
405  s.addLines (stringToBreakUp);
406  return s;
407 }
408 
409 //==============================================================================
410 void StringArray::removeDuplicates (bool ignoreCase)
411 {
412  for (int i = 0; i < size() - 1; ++i)
413  {
414  auto s = strings.getReference(i);
415 
416  for (int nextIndex = i + 1;;)
417  {
418  nextIndex = indexOf (s, ignoreCase, nextIndex);
419 
420  if (nextIndex < 0)
421  break;
422 
423  strings.remove (nextIndex);
424  }
425  }
426 }
427 
429  bool appendNumberToFirstInstance,
430  CharPointer_UTF8 preNumberString,
431  CharPointer_UTF8 postNumberString)
432 {
433  if (preNumberString.getAddress() == nullptr)
434  preNumberString = CharPointer_UTF8 (" (");
435 
436  if (postNumberString.getAddress() == nullptr)
437  postNumberString = CharPointer_UTF8 (")");
438 
439  for (int i = 0; i < size() - 1; ++i)
440  {
441  auto& s = strings.getReference(i);
442  auto nextIndex = indexOf (s, ignoreCase, i + 1);
443 
444  if (nextIndex >= 0)
445  {
446  auto original = s;
447  int number = 0;
448 
449  if (appendNumberToFirstInstance)
450  s = original + String (preNumberString) + String (++number) + String (postNumberString);
451  else
452  ++number;
453 
454  while (nextIndex >= 0)
455  {
456  set (nextIndex, (*this)[nextIndex] + String (preNumberString) + String (++number) + String (postNumberString));
457  nextIndex = indexOf (original, ignoreCase, nextIndex + 1);
458  }
459  }
460  }
461 }
462 
463 void StringArray::ensureStorageAllocated (int minNumElements)
464 {
465  strings.ensureStorageAllocated (minNumElements);
466 }
467 
469 {
470  strings.minimiseStorageOverheads();
471 }
472 
473 } // namespace juce
void addArray(const StringArray &other, int startIndex=0, int numElementsToAdd=-1)
Appends some strings from another array to the end of this one.
static Type findEndOfToken(Type text, BreakType breakCharacters, Type quoteCharacters)
Returns a pointer to the first character in the string which is found in the breakCharacters string...
A simple class for holding temporary references to a string literal or String.
bool operator!=(const StringArray &) const noexcept
Compares two arrays.
bool isNotEmpty() const noexcept
Returns true if the string is not empty.
void appendNumbersToDuplicates(bool ignoreCaseWhenComparing, bool appendNumberToFirstInstance, CharPointer_UTF8 preNumberString=CharPointer_UTF8(nullptr), CharPointer_UTF8 postNumberString=CharPointer_UTF8(nullptr))
Adds numbers to the strings in the array, to make each string unique.
void removeEmptyStrings(bool removeWhitespaceStrings=true)
Removes empty strings from the array.
void remove(int index)
Removes a string from the array.
void removeDuplicates(bool ignoreCase)
Removes any duplicated elements from the array.
int compareNatural(StringRef other, bool isCaseSensitive=false) const noexcept
Compares two strings, taking into account textual characteristics like numbers and spaces...
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
Definition: juce_String.h:1200
bool isEmpty() const noexcept
Returns true if this pointer is pointing to a null character.
int addLines(StringRef stringToBreakUp)
Breaks up a string into lines and adds them to this array.
void move(int currentIndex, int newIndex) noexcept
Moves one of the strings to a different position.
void sortNatural()
Sorts the array using extra language-aware rules to do a better job of comparing words containing spa...
A special array for holding a list of strings.
The JUCE String class!
Definition: juce_String.h:42
void trim()
Deletes any whitespace characters from the starts and ends of all the strings.
String & getReference(int index) noexcept
Returns a reference to one of the strings in the array.
int indexOf(StringRef stringToLookFor, bool ignoreCase=false, int startIndex=0) const
Searches for a string in the array.
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Breaks up a string into tokens and adds them to this array.
void clearQuick()
Removes all elements from the array without freeing the array&#39;s allocated storage.
void minimiseStorageOverheads()
Reduces the amount of storage being used by the array.
void set(int index, String newString)
Replaces one of the strings in the array with another one.
int compareIgnoreCase(const String &other) const noexcept
Case-insensitive comparison with another string.
bool operator==(const StringArray &) const noexcept
Compares two arrays.
void clear()
Removes all elements from the array.
CharType * getAddress() const noexcept
Returns the address that this pointer is pointing to.
void ensureStorageAllocated(int minNumElements)
Increases the array&#39;s internal storage to hold a minimum number of elements.
StringArray() noexcept
Creates an empty string array.
void removeString(StringRef stringToRemove, bool ignoreCase=false)
Finds a string in the array and removes it.
void removeRange(int startIndex, int numberToRemove)
Removes a range of elements from the array.
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Returns an array containing the tokens in a given string.
bool addIfNotAlreadyThere(const String &stringToAdd, bool ignoreCase=false)
Adds a string to the array as long as it&#39;s not already in there.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
void sort(bool ignoreCase)
Sorts the array into alphabetical order.
void preallocateBytes(size_t numBytesNeeded)
Increases the string&#39;s internally allocated storage.
String::CharPointerType text
The text that is referenced.
bool contains(StringRef stringToLookFor, bool ignoreCase=false) const
Searches for a string in the array.
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Joins the strings in the array together into one string.
static StringArray fromLines(StringRef stringToBreakUp)
Returns an array containing the lines in a given string.
void insert(int index, String stringToAdd)
Inserts a string into the array.
~StringArray()
Destructor.
int size() const noexcept
Returns the number of strings in the array.
const String & operator[](int index) const noexcept
Returns one of the strings from the array.
Array< String > strings
This is the array holding the actual strings.
void mergeArray(const StringArray &other, bool ignoreCase=false)
Merges the strings from another array into this one.
StringArray & operator=(const StringArray &)
Copies the contents of another string array into this one.
void swapWith(StringArray &) noexcept
Swaps the contents of this and another StringArray.
void add(String stringToAdd)
Appends a string at the end of the array.
size_t sizeInBytes() const noexcept
Returns the number of bytes that are used to represent this string.
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...