LMMS
Loading...
Searching...
No Matches
CharacterFunctions.h
Go to the documentation of this file.
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_CHARACTERFUNCTIONS_H_INCLUDED
27#define WATER_CHARACTERFUNCTIONS_H_INCLUDED
28
29#include "../memory/Memory.h"
30
31#include <algorithm>
32#include <limits>
33#include <sys/types.h>
34
35namespace water {
36
39
40//==============================================================================
50{
51public:
52 //==============================================================================
54 static water_uchar toUpperCase (water_uchar character) noexcept;
56 static water_uchar toLowerCase (water_uchar character) noexcept;
57
59 static bool isUpperCase (water_uchar character) noexcept;
61 static bool isLowerCase (water_uchar character) noexcept;
62
64 static bool isWhitespace (char character) noexcept;
66 static bool isWhitespace (water_uchar character) noexcept;
67
69 static bool isDigit (char character) noexcept;
71 static bool isDigit (water_uchar character) noexcept;
72
74 static bool isLetter (char character) noexcept;
76 static bool isLetter (water_uchar character) noexcept;
77
79 static bool isLetterOrDigit (char character) noexcept;
81 static bool isLetterOrDigit (water_uchar character) noexcept;
82
86 static bool isPrintable (char character) noexcept;
87
91 static bool isPrintable (water_uchar character) noexcept;
92
94 static int getHexDigitValue (water_uchar digit) noexcept;
95
97 static water_uchar getUnicodeCharFromWindows1252Codepage (uint8 windows1252Char) noexcept;
98
99 //==============================================================================
104 template <typename CharPointerType>
105 static double readDoubleValue (CharPointerType& text) noexcept
106 {
107 double result[3] = { 0 }, accumulator[2] = { 0 };
108 int exponentAdjustment[2] = { 0 }, exponentAccumulator[2] = { -1, -1 };
109 int exponent = 0, decPointIndex = 0, digit = 0;
110 int lastDigit = 0, numSignificantDigits = 0;
111 bool isNegative = false, digitsFound = false;
112 const int maxSignificantDigits = 15 + 2;
113
114 text = text.findEndOfWhitespace();
115 water_uchar c = *text;
116
117 switch (c)
118 {
119 case '-': isNegative = true; // fall-through..
120 case '+': c = *++text;
121 }
122
123 switch (c)
124 {
125 case 'n':
126 case 'N':
127 if ((text[1] == 'a' || text[1] == 'A') && (text[2] == 'n' || text[2] == 'N'))
128 return std::numeric_limits<double>::quiet_NaN();
129 break;
130
131 case 'i':
132 case 'I':
133 if ((text[1] == 'n' || text[1] == 'N') && (text[2] == 'f' || text[2] == 'F'))
134 return std::numeric_limits<double>::infinity();
135 break;
136 }
137
138 for (;;)
139 {
140 if (text.isDigit())
141 {
142 lastDigit = digit;
143 digit = (int) text.getAndAdvance() - '0';
144 digitsFound = true;
145
146 if (decPointIndex != 0)
147 exponentAdjustment[1]++;
148
149 if (numSignificantDigits == 0 && digit == 0)
150 continue;
151
152 if (++numSignificantDigits > maxSignificantDigits)
153 {
154 if (digit > 5)
155 ++accumulator [decPointIndex];
156 else if (digit == 5 && (lastDigit & 1) != 0)
157 ++accumulator [decPointIndex];
158
159 if (decPointIndex > 0)
160 exponentAdjustment[1]--;
161 else
162 exponentAdjustment[0]++;
163
164 while (text.isDigit())
165 {
166 ++text;
167 if (decPointIndex == 0)
168 exponentAdjustment[0]++;
169 }
170 }
171 else
172 {
173 const double maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10);
174 if (accumulator [decPointIndex] > maxAccumulatorValue)
175 {
176 result [decPointIndex] = mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex])
177 + accumulator [decPointIndex];
178 accumulator [decPointIndex] = 0;
179 exponentAccumulator [decPointIndex] = 0;
180 }
181
182 accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit;
183 exponentAccumulator [decPointIndex]++;
184 }
185 }
186 else if (decPointIndex == 0 && *text == '.')
187 {
188 ++text;
189 decPointIndex = 1;
190
191 if (numSignificantDigits > maxSignificantDigits)
192 {
193 while (text.isDigit())
194 ++text;
195 break;
196 }
197 }
198 else
199 {
200 break;
201 }
202 }
203
204 result[0] = mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0];
205
206 if (decPointIndex != 0)
207 result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
208
209 c = *text;
210 if ((c == 'e' || c == 'E') && digitsFound)
211 {
212 bool negativeExponent = false;
213
214 switch (*++text)
215 {
216 case '-': negativeExponent = true; // fall-through..
217 case '+': ++text;
218 }
219
220 while (text.isDigit())
221 exponent = (exponent * 10) + ((int) text.getAndAdvance() - '0');
222
223 if (negativeExponent)
224 exponent = -exponent;
225 }
226
227 double r = mulexp10 (result[0], exponent + exponentAdjustment[0]);
228 if (decPointIndex != 0)
229 r += mulexp10 (result[1], exponent - exponentAdjustment[1]);
230
231 return isNegative ? -r : r;
232 }
233
235 template <typename CharPointerType>
236 static double getDoubleValue (CharPointerType text) noexcept
237 {
238 return readDoubleValue (text);
239 }
240
241 //==============================================================================
243 template <typename IntType, typename CharPointerType>
244 static IntType getIntValue (const CharPointerType text) noexcept
245 {
246 IntType v = 0;
247 CharPointerType s (text.findEndOfWhitespace());
248
249 const bool isNeg = *s == '-';
250 if (isNeg)
251 ++s;
252
253 for (;;)
254 {
255 const water_uchar c = s.getAndAdvance();
256
257 if (c >= '0' && c <= '9')
258 v = v * 10 + (IntType) (c - '0');
259 else
260 break;
261 }
262
263 return isNeg ? -v : v;
264 }
265
266 template <typename ResultType>
268 {
269 template <typename CharPointerType>
270 static ResultType parse (CharPointerType t) noexcept
271 {
272 ResultType result = 0;
273
274 while (! t.isEmpty())
275 {
276 const int hexValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
277
278 if (hexValue >= 0)
279 result = (result << 4) | hexValue;
280 }
281
282 return result;
283 }
284 };
285
286 //==============================================================================
289 template <typename CharPointerType>
290 static size_t lengthUpTo (CharPointerType text, const size_t maxCharsToCount) noexcept
291 {
292 size_t len = 0;
293
294 while (len < maxCharsToCount && text.getAndAdvance() != 0)
295 ++len;
296
297 return len;
298 }
299
302 template <typename CharPointerType>
303 static size_t lengthUpTo (CharPointerType start, const CharPointerType end) noexcept
304 {
305 size_t len = 0;
306
307 while (start < end && start.getAndAdvance() != 0)
308 ++len;
309
310 return len;
311 }
312
314 template <typename DestCharPointerType, typename SrcCharPointerType>
315 static void copyAll (DestCharPointerType& dest, SrcCharPointerType src) noexcept
316 {
317 while (water_uchar c = src.getAndAdvance())
318 dest.write (c);
319
320 dest.writeNull();
321 }
322
325 template <typename DestCharPointerType, typename SrcCharPointerType>
326 static size_t copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src, size_t maxBytesToWrite) noexcept
327 {
328 typename DestCharPointerType::CharType const* const startAddress = dest.getAddress();
329 ssize_t maxBytes = (ssize_t) maxBytesToWrite;
330 maxBytes -= sizeof (typename DestCharPointerType::CharType); // (allow for a terminating null)
331
332 for (;;)
333 {
334 const water_uchar c = src.getAndAdvance();
335 const size_t bytesNeeded = DestCharPointerType::getBytesRequiredFor (c);
336
337 maxBytes -= bytesNeeded;
338 if (c == 0 || maxBytes < 0)
339 break;
340
341 dest.write (c);
342 }
343
344 dest.writeNull();
345
346 return (size_t) getAddressDifference (dest.getAddress(), startAddress)
347 + sizeof (typename DestCharPointerType::CharType);
348 }
349
352 template <typename DestCharPointerType, typename SrcCharPointerType>
353 static void copyWithCharLimit (DestCharPointerType& dest, SrcCharPointerType src, int maxChars) noexcept
354 {
355 while (--maxChars > 0)
356 {
357 const water_uchar c = src.getAndAdvance();
358 if (c == 0)
359 break;
360
361 dest.write (c);
362 }
363
364 dest.writeNull();
365 }
366
368 static inline int compare (water_uchar char1, water_uchar char2) noexcept
369 {
370 if (int diff = static_cast<int> (char1) - static_cast<int> (char2))
371 return diff < 0 ? -1 : 1;
372
373 return 0;
374 }
375
377 template <typename CharPointerType1, typename CharPointerType2>
378 static int compare (CharPointerType1 s1, CharPointerType2 s2) noexcept
379 {
380 for (;;)
381 {
382 const water_uchar c1 = s1.getAndAdvance();
383
384 if (int diff = compare (c1, s2.getAndAdvance()))
385 return diff;
386
387 if (c1 == 0)
388 break;
389 }
390
391 return 0;
392 }
393
395 template <typename CharPointerType1, typename CharPointerType2>
396 static int compareUpTo (CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
397 {
398 while (--maxChars >= 0)
399 {
400 const water_uchar c1 = s1.getAndAdvance();
401
402 if (int diff = compare (c1, s2.getAndAdvance()))
403 return diff;
404
405 if (c1 == 0)
406 break;
407 }
408
409 return 0;
410 }
411
413 static inline int compareIgnoreCase (water_uchar char1, water_uchar char2) noexcept
414 {
415 return char1 != char2 ? compare (toUpperCase (char1), toUpperCase (char2)) : 0;
416 }
417
419 template <typename CharPointerType1, typename CharPointerType2>
420 static int compareIgnoreCase (CharPointerType1 s1, CharPointerType2 s2) noexcept
421 {
422 for (;;)
423 {
424 const water_uchar c1 = s1.getAndAdvance();
425
426 if (int diff = compareIgnoreCase (c1, s2.getAndAdvance()))
427 return diff;
428
429 if (c1 == 0)
430 break;
431 }
432
433 return 0;
434 }
435
437 template <typename CharPointerType1, typename CharPointerType2>
438 static int compareIgnoreCaseUpTo (CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
439 {
440 while (--maxChars >= 0)
441 {
442 const water_uchar c1 = s1.getAndAdvance();
443
444 if (int diff = compareIgnoreCase (c1, s2.getAndAdvance()))
445 return diff;
446
447 if (c1 == 0)
448 break;
449 }
450
451 return 0;
452 }
453
457 template <typename CharPointerType1, typename CharPointerType2>
458 static int indexOf (CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
459 {
460 int index = 0;
461 const int substringLength = (int) substringToLookFor.length();
462
463 for (;;)
464 {
465 if (textToSearch.compareUpTo (substringToLookFor, substringLength) == 0)
466 return index;
467
468 if (textToSearch.getAndAdvance() == 0)
469 return -1;
470
471 ++index;
472 }
473 }
474
479 template <typename CharPointerType1, typename CharPointerType2>
480 static CharPointerType1 find (CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
481 {
482 const int substringLength = (int) substringToLookFor.length();
483
484 while (textToSearch.compareUpTo (substringToLookFor, substringLength) != 0
485 && ! textToSearch.isEmpty())
486 ++textToSearch;
487
488 return textToSearch;
489 }
490
495 template <typename CharPointerType>
496 static CharPointerType find (CharPointerType textToSearch, const water_uchar charToLookFor) noexcept
497 {
498 for (;; ++textToSearch)
499 {
500 const water_uchar c = *textToSearch;
501
502 if (c == charToLookFor || c == 0)
503 break;
504 }
505
506 return textToSearch;
507 }
508
513 template <typename CharPointerType1, typename CharPointerType2>
514 static int indexOfIgnoreCase (CharPointerType1 haystack, const CharPointerType2 needle) noexcept
515 {
516 int index = 0;
517 const int needleLength = (int) needle.length();
518
519 for (;;)
520 {
521 if (haystack.compareIgnoreCaseUpTo (needle, needleLength) == 0)
522 return index;
523
524 if (haystack.getAndAdvance() == 0)
525 return -1;
526
527 ++index;
528 }
529 }
530
534 template <typename Type>
535 static int indexOfChar (Type text, const water_uchar charToFind) noexcept
536 {
537 int i = 0;
538
539 while (! text.isEmpty())
540 {
541 if (text.getAndAdvance() == charToFind)
542 return i;
543
544 ++i;
545 }
546
547 return -1;
548 }
549
554 template <typename Type>
555 static int indexOfCharIgnoreCase (Type text, water_uchar charToFind) noexcept
556 {
557 charToFind = CharacterFunctions::toLowerCase (charToFind);
558 int i = 0;
559
560 while (! text.isEmpty())
561 {
562 if (text.toLowerCase() == charToFind)
563 return i;
564
565 ++text;
566 ++i;
567 }
568
569 return -1;
570 }
571
576 template <typename Type>
577 static Type findEndOfWhitespace (Type text) noexcept
578 {
579 while (text.isWhitespace())
580 ++text;
581
582 return text;
583 }
584
588 template <typename Type, typename BreakType>
589 static Type findEndOfToken (Type text, const BreakType breakCharacters, const Type quoteCharacters)
590 {
591 water_uchar currentQuoteChar = 0;
592
593 while (! text.isEmpty())
594 {
595 const water_uchar c = text.getAndAdvance();
596
597 if (currentQuoteChar == 0 && breakCharacters.indexOf (c) >= 0)
598 {
599 --text;
600 break;
601 }
602
603 if (quoteCharacters.indexOf (c) >= 0)
604 {
605 if (currentQuoteChar == 0)
606 currentQuoteChar = c;
607 else if (currentQuoteChar == c)
608 currentQuoteChar = 0;
609 }
610 }
611
612 return text;
613 }
614
615private:
616 static double mulexp10 (const double value, int exponent) noexcept;
617};
618
619}
620
621#endif // WATER_CHARACTERFUNCTIONS_H_INCLUDED
Definition CharacterFunctions.h:50
static water_uchar toUpperCase(water_uchar character) noexcept
Definition CharacterFunctions.cpp:34
static int getHexDigitValue(water_uchar digit) noexcept
Definition CharacterFunctions.cpp:116
static int compareUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
Definition CharacterFunctions.h:396
static bool isLetterOrDigit(char character) noexcept
Definition CharacterFunctions.cpp:94
static int indexOf(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Definition CharacterFunctions.h:458
static bool isDigit(char character) noexcept
Definition CharacterFunctions.cpp:73
static bool isLetter(char character) noexcept
Definition CharacterFunctions.cpp:83
static bool isPrintable(char character) noexcept
Definition CharacterFunctions.cpp:106
static int compareIgnoreCase(water_uchar char1, water_uchar char2) noexcept
Definition CharacterFunctions.h:413
static int compareIgnoreCaseUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
Definition CharacterFunctions.h:438
static int compare(CharPointerType1 s1, CharPointerType2 s2) noexcept
Definition CharacterFunctions.h:378
static double getDoubleValue(CharPointerType text) noexcept
Definition CharacterFunctions.h:236
static water_uchar toLowerCase(water_uchar character) noexcept
Definition CharacterFunctions.cpp:39
static double readDoubleValue(CharPointerType &text) noexcept
Definition CharacterFunctions.h:105
static int indexOfChar(Type text, const water_uchar charToFind) noexcept
Definition CharacterFunctions.h:535
static int indexOfIgnoreCase(CharPointerType1 haystack, const CharPointerType2 needle) noexcept
Definition CharacterFunctions.h:514
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Definition CharacterFunctions.h:480
static CharPointerType find(CharPointerType textToSearch, const water_uchar charToLookFor) noexcept
Definition CharacterFunctions.h:496
static bool isLowerCase(water_uchar character) noexcept
Definition CharacterFunctions.cpp:53
static int compare(water_uchar char1, water_uchar char2) noexcept
Definition CharacterFunctions.h:368
static bool isUpperCase(water_uchar character) noexcept
Definition CharacterFunctions.cpp:44
static void copyAll(DestCharPointerType &dest, SrcCharPointerType src) noexcept
Definition CharacterFunctions.h:315
static int indexOfCharIgnoreCase(Type text, water_uchar charToFind) noexcept
Definition CharacterFunctions.h:555
static void copyWithCharLimit(DestCharPointerType &dest, SrcCharPointerType src, int maxChars) noexcept
Definition CharacterFunctions.h:353
static size_t lengthUpTo(CharPointerType start, const CharPointerType end) noexcept
Definition CharacterFunctions.h:303
static Type findEndOfToken(Type text, const BreakType breakCharacters, const Type quoteCharacters)
Definition CharacterFunctions.h:589
static int compareIgnoreCase(CharPointerType1 s1, CharPointerType2 s2) noexcept
Definition CharacterFunctions.h:420
static Type findEndOfWhitespace(Type text) noexcept
Definition CharacterFunctions.h:577
static double mulexp10(const double value, int exponent) noexcept
Definition CharacterFunctions.cpp:133
static size_t lengthUpTo(CharPointerType text, const size_t maxCharsToCount) noexcept
Definition CharacterFunctions.h:290
static bool isWhitespace(char character) noexcept
Definition CharacterFunctions.cpp:63
static water_uchar getUnicodeCharFromWindows1252Codepage(uint8 windows1252Char) noexcept
Definition CharacterFunctions.cpp:161
static size_t copyWithDestByteLimit(DestCharPointerType &dest, SrcCharPointerType src, size_t maxBytesToWrite) noexcept
Definition CharacterFunctions.h:326
static IntType getIntValue(const CharPointerType text) noexcept
Definition CharacterFunctions.h:244
struct huft * t
Definition inflate.c:943
unsigned v[N_MAX]
Definition inflate.c:1584
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
static PuglViewHint int value
Definition pugl.h:1708
virtual ASIOError start()=0
Definition AudioSampleBuffer.h:33
int getAddressDifference(Type1 *pointer1, Type2 *pointer2) noexcept
Definition Memory.h:62
unsigned int uint32
Definition water.h:98
unsigned char uint8
Definition water.h:90
uint32 water_uchar
Definition CharacterFunctions.h:38
static bool diff(const std::string fn1, const std::string fn2)
Definition playertest.cpp:161
Definition CharacterFunctions.h:268
static ResultType parse(CharPointerType t) noexcept
Definition CharacterFunctions.h:270
const char * text
Definition swell-functions.h:167
return c
Definition crypt.c:175
int r
Definition crypt.c:458
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()