1 /* 2 ============================================================================== 3 4 This file is part of the Water library. 5 Copyright (c) 2016 ROLI Ltd. 6 Copyright (C) 2017 Filipe Coelho <falktx@falktx.com> 7 8 Permission is granted to use this software under the terms of the ISC license 9 http://www.isc.org/downloads/software-support-policy/isc-license/ 10 11 Permission to use, copy, modify, and/or distribute this software for any 12 purpose with or without fee is hereby granted, provided that the above 13 copyright notice and this permission notice appear in all copies. 14 15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD 16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, 18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 21 OF THIS SOFTWARE. 22 23 ============================================================================== 24 */ 25 26 #ifndef WATER_STRINGARRAY_H_INCLUDED 27 #define WATER_STRINGARRAY_H_INCLUDED 28 29 #include "String.h" 30 #include "../containers/Array.h" 31 32 namespace water { 33 34 //============================================================================== 35 /** 36 A special array for holding a list of strings. 37 38 @see String, StringPairArray 39 */ 40 class StringArray 41 { 42 public: 43 //============================================================================== 44 /** Creates an empty string array */ 45 StringArray() noexcept; 46 47 /** Creates a copy of another string array */ 48 StringArray (const StringArray&); 49 50 #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS 51 StringArray (StringArray&&) noexcept; 52 #endif 53 54 /** Creates an array containing a single string. */ 55 explicit StringArray (const String& firstValue); 56 57 /** Creates an array from a raw array of strings. 58 @param strings an array of strings to add 59 @param numberOfStrings how many items there are in the array 60 */ 61 StringArray (const String* strings, int numberOfStrings); 62 63 /** Creates a copy of an array of string literals. 64 @param strings an array of strings to add. Null pointers in the array will be 65 treated as empty strings 66 @param numberOfStrings how many items there are in the array 67 */ 68 StringArray (const char* const* strings, int numberOfStrings); 69 70 /** Creates a copy of a null-terminated array of string literals. 71 72 Each item from the array passed-in is added, until it encounters a null pointer, 73 at which point it stops. 74 */ 75 explicit StringArray (const char* const* strings); 76 77 /** Destructor. */ 78 ~StringArray(); 79 80 /** Copies the contents of another string array into this one */ 81 StringArray& operator= (const StringArray&); 82 83 #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS 84 StringArray& operator= (StringArray&&) noexcept; 85 #endif 86 87 /** Swaps the contents of this and another StringArray. */ 88 void swapWith (StringArray&) noexcept; 89 90 //============================================================================== 91 /** Compares two arrays. 92 Comparisons are case-sensitive. 93 @returns true only if the other array contains exactly the same strings in the same order 94 */ 95 bool operator== (const StringArray&) const noexcept; 96 97 /** Compares two arrays. 98 Comparisons are case-sensitive. 99 @returns false if the other array contains exactly the same strings in the same order 100 */ 101 bool operator!= (const StringArray&) const noexcept; 102 103 //============================================================================== 104 /** Returns the number of strings in the array */ size()105 inline int size() const noexcept { return strings.size(); } 106 107 /** Returns true if the array is empty, false otherwise. */ isEmpty()108 inline bool isEmpty() const noexcept { return size() == 0; } 109 110 /** Returns one of the strings from the array. 111 112 If the index is out-of-range, an empty string is returned. 113 114 Obviously the reference returned shouldn't be stored for later use, as the 115 string it refers to may disappear when the array changes. 116 */ 117 const String& operator[] (int index) const noexcept; 118 119 /** Returns a reference to one of the strings in the array. 120 This lets you modify a string in-place in the array, but you must be sure that 121 the index is in-range. 122 */ 123 String& getReference (int index) noexcept; 124 125 /** Returns a pointer to the first String in the array. 126 This method is provided for compatibility with standard C++ iteration mechanisms. 127 */ begin()128 inline String* begin() const noexcept { return strings.begin(); } 129 130 /** Returns a pointer to the String which follows the last element in the array. 131 This method is provided for compatibility with standard C++ iteration mechanisms. 132 */ end()133 inline String* end() const noexcept { return strings.end(); } 134 135 /** Searches for a string in the array. 136 137 The comparison will be case-insensitive if the ignoreCase parameter is true. 138 139 @returns true if the string is found inside the array 140 */ 141 bool contains (StringRef stringToLookFor, 142 bool ignoreCase = false) const; 143 144 /** Searches for a string in the array. 145 146 The comparison will be case-insensitive if the ignoreCase parameter is true. 147 148 @param stringToLookFor the string to try to find 149 @param ignoreCase whether the comparison should be case-insensitive 150 @param startIndex the first index to start searching from 151 @returns the index of the first occurrence of the string in this array, 152 or -1 if it isn't found. 153 */ 154 int indexOf (StringRef stringToLookFor, 155 bool ignoreCase = false, 156 int startIndex = 0) const; 157 158 //============================================================================== 159 /** Appends a string at the end of the array. */ 160 bool add (const String& stringToAdd); 161 162 #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS 163 /** Appends a string at the end of the array. */ 164 bool add (String&& stringToAdd); 165 #endif 166 167 /** Inserts a string into the array. 168 169 This will insert a string into the array at the given index, moving 170 up the other elements to make room for it. 171 If the index is less than zero or greater than the size of the array, 172 the new string will be added to the end of the array. 173 */ 174 bool insert (int index, const String& stringToAdd); 175 176 /** Adds a string to the array as long as it's not already in there. 177 The search can optionally be case-insensitive. 178 179 @return true if the string has been added, false otherwise. 180 */ 181 bool addIfNotAlreadyThere (const String& stringToAdd, bool ignoreCase = false); 182 183 /** Replaces one of the strings in the array with another one. 184 185 If the index is higher than the array's size, the new string will be 186 added to the end of the array; if it's less than zero nothing happens. 187 */ 188 void set (int index, const String& newString); 189 190 /** Appends some strings from another array to the end of this one. 191 192 @param other the array to add 193 @param startIndex the first element of the other array to add 194 @param numElementsToAdd the maximum number of elements to add (if this is 195 less than zero, they are all added) 196 */ 197 void addArray (const StringArray& other, 198 int startIndex = 0, 199 int numElementsToAdd = -1); 200 201 /** Merges the strings from another array into this one. 202 This will not add a string that already exists. 203 204 @param other the array to add 205 @param ignoreCase ignore case when merging 206 */ 207 void mergeArray (const StringArray& other, 208 bool ignoreCase = false); 209 210 /** Breaks up a string into tokens and adds them to this array. 211 212 This will tokenise the given string using whitespace characters as the 213 token delimiters, and will add these tokens to the end of the array. 214 @returns the number of tokens added 215 @see fromTokens 216 */ 217 int addTokens (StringRef stringToTokenise, bool preserveQuotedStrings); 218 219 /** Breaks up a string into tokens and adds them to this array. 220 221 This will tokenise the given string (using the string passed in to define the 222 token delimiters), and will add these tokens to the end of the array. 223 224 @param stringToTokenise the string to tokenise 225 @param breakCharacters a string of characters, any of which will be considered 226 to be a token delimiter. 227 @param quoteCharacters if this string isn't empty, it defines a set of characters 228 which are treated as quotes. Any text occurring 229 between quotes is not broken up into tokens. 230 @returns the number of tokens added 231 @see fromTokens 232 */ 233 int addTokens (StringRef stringToTokenise, 234 StringRef breakCharacters, 235 StringRef quoteCharacters); 236 237 /** Breaks up a string into lines and adds them to this array. 238 239 This breaks a string down into lines separated by \\n or \\r\\n, and adds each line 240 to the array. Line-break characters are omitted from the strings that are added to 241 the array. 242 */ 243 int addLines (StringRef stringToBreakUp); 244 245 /** Returns an array containing the tokens in a given string. 246 247 This will tokenise the given string using whitespace characters as the 248 token delimiters, and return the parsed tokens as an array. 249 @see addTokens 250 */ 251 static StringArray fromTokens (StringRef stringToTokenise, 252 bool preserveQuotedStrings); 253 254 /** Returns an array containing the tokens in a given string. 255 256 This will tokenise the given string using the breakCharacters string to define 257 the token delimiters, and will return the parsed tokens as an array. 258 259 @param stringToTokenise the string to tokenise 260 @param breakCharacters a string of characters, any of which will be considered 261 to be a token delimiter. 262 @param quoteCharacters if this string isn't empty, it defines a set of characters 263 which are treated as quotes. Any text occurring 264 between quotes is not broken up into tokens. 265 @see addTokens 266 */ 267 static StringArray fromTokens (StringRef stringToTokenise, 268 StringRef breakCharacters, 269 StringRef quoteCharacters); 270 271 /** Returns an array containing the lines in a given string. 272 273 This breaks a string down into lines separated by \\n or \\r\\n, and returns an 274 array containing these lines. Line-break characters are omitted from the strings that 275 are added to the array. 276 */ 277 static StringArray fromLines (StringRef stringToBreakUp); 278 279 //============================================================================== 280 /** Removes all elements from the array. */ 281 void clear(); 282 283 /** Removes all elements from the array without freeing the array's allocated storage. 284 @see clear 285 */ 286 void clearQuick(); 287 288 /** Removes a string from the array. 289 If the index is out-of-range, no action will be taken. 290 */ 291 void remove (int index); 292 293 /** Finds a string in the array and removes it. 294 This will remove all occurrences of the given string from the array. 295 The comparison may be case-insensitive depending on the ignoreCase parameter. 296 */ 297 void removeString (StringRef stringToRemove, 298 bool ignoreCase = false); 299 300 /** Removes a range of elements from the array. 301 302 This will remove a set of elements, starting from the given index, 303 and move subsequent elements down to close the gap. 304 305 If the range extends beyond the bounds of the array, it will 306 be safely clipped to the size of the array. 307 308 @param startIndex the index of the first element to remove 309 @param numberToRemove how many elements should be removed 310 */ 311 void removeRange (int startIndex, int numberToRemove); 312 313 /** Removes any duplicated elements from the array. 314 315 If any string appears in the array more than once, only the first occurrence of 316 it will be retained. 317 318 @param ignoreCase whether to use a case-insensitive comparison 319 */ 320 void removeDuplicates (bool ignoreCase); 321 322 /** Removes empty strings from the array. 323 @param removeWhitespaceStrings if true, strings that only contain whitespace 324 characters will also be removed 325 */ 326 void removeEmptyStrings (bool removeWhitespaceStrings = true); 327 328 /** Deletes any whitespace characters from the starts and ends of all the strings. */ 329 void trim(); 330 331 /** Adds numbers to the strings in the array, to make each string unique. 332 333 This will add numbers to the ends of groups of similar strings. 334 e.g. if there are two "moose" strings, they will become "moose (1)" and "moose (2)" 335 336 @param ignoreCaseWhenComparing whether the comparison used is case-insensitive 337 @param appendNumberToFirstInstance whether the first of a group of similar strings 338 also has a number appended to it. 339 @param preNumberString when adding a number, this string is added before the number. 340 If you pass nullptr, a default string will be used, which adds 341 brackets around the number. 342 @param postNumberString this string is appended after any numbers that are added. 343 If you pass nullptr, a default string will be used, which adds 344 brackets around the number. 345 */ 346 void appendNumbersToDuplicates (bool ignoreCaseWhenComparing, 347 bool appendNumberToFirstInstance, 348 CharPointer_UTF8 preNumberString = CharPointer_UTF8 (nullptr), 349 CharPointer_UTF8 postNumberString = CharPointer_UTF8 (nullptr)); 350 351 //============================================================================== 352 /** Joins the strings in the array together into one string. 353 354 This will join a range of elements from the array into a string, separating 355 them with a given string. 356 357 e.g. joinIntoString (",") will turn an array of "a" "b" and "c" into "a,b,c". 358 359 @param separatorString the string to insert between all the strings 360 @param startIndex the first element to join 361 @param numberOfElements how many elements to join together. If this is less 362 than zero, all available elements will be used. 363 */ 364 String joinIntoString (StringRef separatorString, 365 int startIndex = 0, 366 int numberOfElements = -1) const; 367 368 //============================================================================== 369 /** Sorts the array into alphabetical order. 370 @param ignoreCase if true, the comparisons used will be case-sensitive. 371 */ 372 void sort (bool ignoreCase); 373 374 /** Sorts the array using extra language-aware rules to do a better job of comparing 375 words containing spaces and numbers. 376 @see String::compareNatural() 377 */ 378 void sortNatural(); 379 380 //============================================================================== 381 /** Increases the array's internal storage to hold a minimum number of elements. 382 383 Calling this before adding a large known number of elements means that 384 the array won't have to keep dynamically resizing itself as the elements 385 are added, and it'll therefore be more efficient. 386 */ 387 void ensureStorageAllocated (int minNumElements); 388 389 /** Reduces the amount of storage being used by the array. 390 391 Arrays typically allocate slightly more storage than they need, and after 392 removing elements, they may have quite a lot of unused space allocated. 393 This method will reduce the amount of allocated storage to a minimum. 394 */ 395 void minimiseStorageOverheads(); 396 397 /** This is the array holding the actual strings. This is public to allow direct access 398 to array methods that may not already be provided by the StringArray class. 399 */ 400 Array<String> strings; 401 }; 402 403 } 404 405 #endif // WATER_STRINGARRAY_H_INCLUDED 406