1 /* 2 ============================================================================== 3 4 This file is part of the JUCE library. 5 Copyright (c) 2020 - Raw Material Software Limited 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 26 //============================================================================== 27 /** 28 Wraps a pointer to a null-terminated ASCII character string, and provides 29 various methods to operate on the data. 30 31 A valid ASCII string is assumed to not contain any characters above 127. 32 33 @see CharPointer_UTF8, CharPointer_UTF16, CharPointer_UTF32 34 35 @tags{Core} 36 */ 37 class CharPointer_ASCII final 38 { 39 public: 40 using CharType = char; 41 CharPointer_ASCII(const CharType * rawPointer)42 inline explicit CharPointer_ASCII (const CharType* rawPointer) noexcept 43 : data (const_cast<CharType*> (rawPointer)) 44 { 45 } 46 47 inline CharPointer_ASCII (const CharPointer_ASCII& other) = default; 48 49 inline CharPointer_ASCII operator= (const CharPointer_ASCII other) noexcept 50 { 51 data = other.data; 52 return *this; 53 } 54 55 inline CharPointer_ASCII operator= (const CharType* text) noexcept 56 { 57 data = const_cast<CharType*> (text); 58 return *this; 59 } 60 61 /** This is a pointer comparison, it doesn't compare the actual text. */ 62 inline bool operator== (CharPointer_ASCII other) const noexcept { return data == other.data; } 63 inline bool operator!= (CharPointer_ASCII other) const noexcept { return data != other.data; } 64 inline bool operator<= (CharPointer_ASCII other) const noexcept { return data <= other.data; } 65 inline bool operator< (CharPointer_ASCII other) const noexcept { return data < other.data; } 66 inline bool operator>= (CharPointer_ASCII other) const noexcept { return data >= other.data; } 67 inline bool operator> (CharPointer_ASCII other) const noexcept { return data > other.data; } 68 69 /** Returns the address that this pointer is pointing to. */ getAddress()70 inline CharType* getAddress() const noexcept { return data; } 71 72 /** Returns the address that this pointer is pointing to. */ 73 inline operator const CharType*() const noexcept { return data; } 74 75 /** Returns true if this pointer is pointing to a null character. */ isEmpty()76 inline bool isEmpty() const noexcept { return *data == 0; } 77 78 /** Returns true if this pointer is not pointing to a null character. */ isNotEmpty()79 inline bool isNotEmpty() const noexcept { return *data != 0; } 80 81 /** Returns the unicode character that this pointer is pointing to. */ 82 inline juce_wchar operator*() const noexcept { return (juce_wchar) (uint8) *data; } 83 84 /** Moves this pointer along to the next character in the string. */ 85 inline CharPointer_ASCII operator++() noexcept 86 { 87 ++data; 88 return *this; 89 } 90 91 /** Moves this pointer to the previous character in the string. */ 92 inline CharPointer_ASCII operator--() noexcept 93 { 94 --data; 95 return *this; 96 } 97 98 /** Returns the character that this pointer is currently pointing to, and then 99 advances the pointer to point to the next character. */ getAndAdvance()100 inline juce_wchar getAndAdvance() noexcept { return (juce_wchar) (uint8) *data++; } 101 102 /** Moves this pointer along to the next character in the string. */ 103 CharPointer_ASCII operator++ (int) noexcept 104 { 105 auto temp (*this); 106 ++data; 107 return temp; 108 } 109 110 /** Moves this pointer forwards by the specified number of characters. */ 111 inline void operator+= (const int numToSkip) noexcept 112 { 113 data += numToSkip; 114 } 115 116 inline void operator-= (const int numToSkip) noexcept 117 { 118 data -= numToSkip; 119 } 120 121 /** Returns the character at a given character index from the start of the string. */ 122 inline juce_wchar operator[] (const int characterIndex) const noexcept 123 { 124 return (juce_wchar) (uint8) data [characterIndex]; 125 } 126 127 /** Returns a pointer which is moved forwards from this one by the specified number of characters. */ 128 CharPointer_ASCII operator+ (const int numToSkip) const noexcept 129 { 130 return CharPointer_ASCII (data + numToSkip); 131 } 132 133 /** Returns a pointer which is moved backwards from this one by the specified number of characters. */ 134 CharPointer_ASCII operator- (const int numToSkip) const noexcept 135 { 136 return CharPointer_ASCII (data - numToSkip); 137 } 138 139 /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ write(const juce_wchar charToWrite)140 inline void write (const juce_wchar charToWrite) noexcept 141 { 142 *data++ = (char) charToWrite; 143 } 144 replaceChar(const juce_wchar newChar)145 inline void replaceChar (const juce_wchar newChar) noexcept 146 { 147 *data = (char) newChar; 148 } 149 150 /** Writes a null character to this string (leaving the pointer's position unchanged). */ writeNull()151 inline void writeNull() const noexcept 152 { 153 *data = 0; 154 } 155 156 /** Returns the number of characters in this string. */ length()157 size_t length() const noexcept 158 { 159 return (size_t) strlen (data); 160 } 161 162 /** Returns the number of characters in this string, or the given value, whichever is lower. */ lengthUpTo(const size_t maxCharsToCount)163 size_t lengthUpTo (const size_t maxCharsToCount) const noexcept 164 { 165 return CharacterFunctions::lengthUpTo (*this, maxCharsToCount); 166 } 167 168 /** Returns the number of characters in this string, or up to the given end pointer, whichever is lower. */ lengthUpTo(const CharPointer_ASCII end)169 size_t lengthUpTo (const CharPointer_ASCII end) const noexcept 170 { 171 return CharacterFunctions::lengthUpTo (*this, end); 172 } 173 174 /** Returns the number of bytes that are used to represent this string. 175 This includes the terminating null character. 176 */ sizeInBytes()177 size_t sizeInBytes() const noexcept 178 { 179 return length() + 1; 180 } 181 182 /** Returns the number of bytes that would be needed to represent the given 183 unicode character in this encoding format. 184 */ getBytesRequiredFor(const juce_wchar)185 static size_t getBytesRequiredFor (const juce_wchar) noexcept 186 { 187 return 1; 188 } 189 190 /** Returns the number of bytes that would be needed to represent the given 191 string in this encoding format. 192 The value returned does NOT include the terminating null character. 193 */ 194 template <class CharPointer> getBytesRequiredFor(const CharPointer text)195 static size_t getBytesRequiredFor (const CharPointer text) noexcept 196 { 197 return text.length(); 198 } 199 200 /** Returns a pointer to the null character that terminates this string. */ findTerminatingNull()201 CharPointer_ASCII findTerminatingNull() const noexcept 202 { 203 return CharPointer_ASCII (data + length()); 204 } 205 206 /** Copies a source string to this pointer, advancing this pointer as it goes. */ 207 template <typename CharPointer> writeAll(const CharPointer src)208 void writeAll (const CharPointer src) noexcept 209 { 210 CharacterFunctions::copyAll (*this, src); 211 } 212 213 /** Copies a source string to this pointer, advancing this pointer as it goes. 214 The maxDestBytes parameter specifies the maximum number of bytes that can be written 215 to the destination buffer before stopping. 216 */ 217 template <typename CharPointer> writeWithDestByteLimit(const CharPointer src,const size_t maxDestBytes)218 size_t writeWithDestByteLimit (const CharPointer src, const size_t maxDestBytes) noexcept 219 { 220 return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes); 221 } 222 223 /** Copies a source string to this pointer, advancing this pointer as it goes. 224 The maxChars parameter specifies the maximum number of characters that can be 225 written to the destination buffer before stopping (including the terminating null). 226 */ 227 template <typename CharPointer> writeWithCharLimit(const CharPointer src,const int maxChars)228 void writeWithCharLimit (const CharPointer src, const int maxChars) noexcept 229 { 230 CharacterFunctions::copyWithCharLimit (*this, src, maxChars); 231 } 232 233 /** Compares this string with another one. */ 234 template <typename CharPointer> compare(const CharPointer other)235 int compare (const CharPointer other) const noexcept 236 { 237 return CharacterFunctions::compare (*this, other); 238 } 239 240 /** Compares this string with another one. */ compare(const CharPointer_ASCII other)241 int compare (const CharPointer_ASCII other) const noexcept 242 { 243 return strcmp (data, other.data); 244 } 245 246 /** Compares this string with another one, up to a specified number of characters. */ 247 template <typename CharPointer> compareUpTo(const CharPointer other,const int maxChars)248 int compareUpTo (const CharPointer other, const int maxChars) const noexcept 249 { 250 return CharacterFunctions::compareUpTo (*this, other, maxChars); 251 } 252 253 /** Compares this string with another one, up to a specified number of characters. */ compareUpTo(const CharPointer_ASCII other,const int maxChars)254 int compareUpTo (const CharPointer_ASCII other, const int maxChars) const noexcept 255 { 256 return strncmp (data, other.data, (size_t) maxChars); 257 } 258 259 /** Compares this string with another one. */ 260 template <typename CharPointer> compareIgnoreCase(const CharPointer other)261 int compareIgnoreCase (const CharPointer other) const 262 { 263 return CharacterFunctions::compareIgnoreCase (*this, other); 264 } 265 compareIgnoreCase(const CharPointer_ASCII other)266 int compareIgnoreCase (const CharPointer_ASCII other) const 267 { 268 #if JUCE_MINGW || (JUCE_WINDOWS && JUCE_CLANG) 269 return CharacterFunctions::compareIgnoreCase (*this, other); 270 #elif JUCE_WINDOWS 271 return stricmp (data, other.data); 272 #else 273 return strcasecmp (data, other.data); 274 #endif 275 } 276 277 /** Compares this string with another one, up to a specified number of characters. */ 278 template <typename CharPointer> compareIgnoreCaseUpTo(const CharPointer other,const int maxChars)279 int compareIgnoreCaseUpTo (const CharPointer other, const int maxChars) const noexcept 280 { 281 return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); 282 } 283 284 /** Returns the character index of a substring, or -1 if it isn't found. */ 285 template <typename CharPointer> indexOf(const CharPointer stringToFind)286 int indexOf (const CharPointer stringToFind) const noexcept 287 { 288 return CharacterFunctions::indexOf (*this, stringToFind); 289 } 290 291 /** Returns the character index of a unicode character, or -1 if it isn't found. */ indexOf(const juce_wchar charToFind)292 int indexOf (const juce_wchar charToFind) const noexcept 293 { 294 int i = 0; 295 296 while (data[i] != 0) 297 { 298 if (data[i] == (char) charToFind) 299 return i; 300 301 ++i; 302 } 303 304 return -1; 305 } 306 307 /** Returns the character index of a unicode character, or -1 if it isn't found. */ indexOf(const juce_wchar charToFind,const bool ignoreCase)308 int indexOf (const juce_wchar charToFind, const bool ignoreCase) const noexcept 309 { 310 return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind) 311 : CharacterFunctions::indexOfChar (*this, charToFind); 312 } 313 314 /** Returns true if the first character of this string is whitespace. */ isWhitespace()315 bool isWhitespace() const { return CharacterFunctions::isWhitespace (*data) != 0; } 316 /** Returns true if the first character of this string is a digit. */ isDigit()317 bool isDigit() const { return CharacterFunctions::isDigit (*data) != 0; } 318 /** Returns true if the first character of this string is a letter. */ isLetter()319 bool isLetter() const { return CharacterFunctions::isLetter (*data) != 0; } 320 /** Returns true if the first character of this string is a letter or digit. */ isLetterOrDigit()321 bool isLetterOrDigit() const { return CharacterFunctions::isLetterOrDigit (*data) != 0; } 322 /** Returns true if the first character of this string is upper-case. */ isUpperCase()323 bool isUpperCase() const { return CharacterFunctions::isUpperCase ((juce_wchar) (uint8) *data) != 0; } 324 /** Returns true if the first character of this string is lower-case. */ isLowerCase()325 bool isLowerCase() const { return CharacterFunctions::isLowerCase ((juce_wchar) (uint8) *data) != 0; } 326 327 /** Returns an upper-case version of the first character of this string. */ toUpperCase()328 juce_wchar toUpperCase() const noexcept { return CharacterFunctions::toUpperCase ((juce_wchar) (uint8) *data); } 329 /** Returns a lower-case version of the first character of this string. */ toLowerCase()330 juce_wchar toLowerCase() const noexcept { return CharacterFunctions::toLowerCase ((juce_wchar) (uint8) *data); } 331 332 /** Parses this string as a 32-bit integer. */ getIntValue32()333 int getIntValue32() const noexcept { return atoi (data); } 334 335 /** Parses this string as a 64-bit integer. */ getIntValue64()336 int64 getIntValue64() const noexcept 337 { 338 #if JUCE_LINUX || JUCE_BSD || JUCE_ANDROID || JUCE_MINGW 339 return atoll (data); 340 #elif JUCE_WINDOWS 341 return _atoi64 (data); 342 #else 343 return CharacterFunctions::getIntValue <int64, CharPointer_ASCII> (*this); 344 #endif 345 } 346 347 /** Parses this string as a floating point double. */ getDoubleValue()348 double getDoubleValue() const noexcept { return CharacterFunctions::getDoubleValue (*this); } 349 350 /** Returns the first non-whitespace character in the string. */ findEndOfWhitespace()351 CharPointer_ASCII findEndOfWhitespace() const noexcept { return CharacterFunctions::findEndOfWhitespace (*this); } 352 353 /** Move this pointer to the first non-whitespace character in the string. */ incrementToEndOfWhitespace()354 void incrementToEndOfWhitespace() noexcept { CharacterFunctions::incrementToEndOfWhitespace (*this); } 355 356 /** Returns true if the given unicode character can be represented in this encoding. */ canRepresent(juce_wchar character)357 static bool canRepresent (juce_wchar character) noexcept 358 { 359 return ((unsigned int) character) < (unsigned int) 128; 360 } 361 362 /** Returns true if this data contains a valid string in this encoding. */ isValidString(const CharType * dataToTest,int maxBytesToRead)363 static bool isValidString (const CharType* dataToTest, int maxBytesToRead) 364 { 365 while (--maxBytesToRead >= 0) 366 { 367 if (((signed char) *dataToTest) <= 0) 368 return *dataToTest == 0; 369 370 ++dataToTest; 371 } 372 373 return true; 374 } 375 376 private: 377 CharType* data; 378 }; 379 380 } // namespace juce 381