The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

804 lines
19KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../core/juce_StandardHeader.h"
  19. #if JUCE_MSVC
  20. #pragma warning (push)
  21. #pragma warning (disable: 4514 4996)
  22. #endif
  23. #include <cwctype>
  24. #include <cctype>
  25. #include <ctime>
  26. BEGIN_JUCE_NAMESPACE
  27. #include "juce_CharacterFunctions.h"
  28. #include "juce_String.h"
  29. //==============================================================================
  30. int CharacterFunctions::length (const char* const s) throw()
  31. {
  32. return (int) strlen (s);
  33. }
  34. int CharacterFunctions::length (const juce_wchar* const s) throw()
  35. {
  36. return (int) wcslen (s);
  37. }
  38. void CharacterFunctions::copy (char* dest, const char* src, const int maxChars) throw()
  39. {
  40. strncpy (dest, src, maxChars);
  41. }
  42. void CharacterFunctions::copy (juce_wchar* dest, const juce_wchar* src, int maxChars) throw()
  43. {
  44. wcsncpy (dest, src, maxChars);
  45. }
  46. void CharacterFunctions::copy (juce_wchar* dest, const char* src, const int maxChars) throw()
  47. {
  48. mbstowcs (dest, src, maxChars);
  49. }
  50. void CharacterFunctions::copy (char* dest, const juce_wchar* src, const int maxChars) throw()
  51. {
  52. wcstombs (dest, src, maxChars);
  53. }
  54. int CharacterFunctions::bytesRequiredForCopy (const juce_wchar* src) throw()
  55. {
  56. return (int) wcstombs (0, src, 0);
  57. }
  58. void CharacterFunctions::append (char* dest, const char* src) throw()
  59. {
  60. strcat (dest, src);
  61. }
  62. void CharacterFunctions::append (juce_wchar* dest, const juce_wchar* src) throw()
  63. {
  64. wcscat (dest, src);
  65. }
  66. int CharacterFunctions::compare (const char* const s1, const char* const s2) throw()
  67. {
  68. return strcmp (s1, s2);
  69. }
  70. int CharacterFunctions::compare (const juce_wchar* s1, const juce_wchar* s2) throw()
  71. {
  72. jassert (s1 != 0 && s2 != 0);
  73. return wcscmp (s1, s2);
  74. }
  75. int CharacterFunctions::compare (const char* const s1, const char* const s2, const int maxChars) throw()
  76. {
  77. jassert (s1 != 0 && s2 != 0);
  78. return strncmp (s1, s2, maxChars);
  79. }
  80. int CharacterFunctions::compare (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw()
  81. {
  82. jassert (s1 != 0 && s2 != 0);
  83. return wcsncmp (s1, s2, maxChars);
  84. }
  85. int CharacterFunctions::compare (const juce_wchar* s1, const char* s2) throw()
  86. {
  87. jassert (s1 != 0 && s2 != 0);
  88. for (;;)
  89. {
  90. const int diff = (int) (*s1 - (juce_wchar) (unsigned char) *s2);
  91. if (diff != 0)
  92. return diff;
  93. else if (*s1 == 0)
  94. break;
  95. ++s1;
  96. ++s2;
  97. }
  98. return 0;
  99. }
  100. int CharacterFunctions::compare (const char* s1, const juce_wchar* s2) throw()
  101. {
  102. return -compare (s2, s1);
  103. }
  104. int CharacterFunctions::compareIgnoreCase (const char* const s1, const char* const s2) throw()
  105. {
  106. jassert (s1 != 0 && s2 != 0);
  107. #if JUCE_WINDOWS
  108. return stricmp (s1, s2);
  109. #else
  110. return strcasecmp (s1, s2);
  111. #endif
  112. }
  113. int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2) throw()
  114. {
  115. jassert (s1 != 0 && s2 != 0);
  116. #if JUCE_WINDOWS
  117. return _wcsicmp (s1, s2);
  118. #else
  119. for (;;)
  120. {
  121. if (*s1 != *s2)
  122. {
  123. const int diff = toUpperCase (*s1) - toUpperCase (*s2);
  124. if (diff != 0)
  125. return diff < 0 ? -1 : 1;
  126. }
  127. else if (*s1 == 0)
  128. break;
  129. ++s1;
  130. ++s2;
  131. }
  132. return 0;
  133. #endif
  134. }
  135. int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const char* s2) throw()
  136. {
  137. jassert (s1 != 0 && s2 != 0);
  138. for (;;)
  139. {
  140. if (*s1 != *s2)
  141. {
  142. const int diff = toUpperCase (*s1) - toUpperCase (*s2);
  143. if (diff != 0)
  144. return diff < 0 ? -1 : 1;
  145. }
  146. else if (*s1 == 0)
  147. break;
  148. ++s1;
  149. ++s2;
  150. }
  151. return 0;
  152. }
  153. int CharacterFunctions::compareIgnoreCase (const char* const s1, const char* const s2, const int maxChars) throw()
  154. {
  155. jassert (s1 != 0 && s2 != 0);
  156. #if JUCE_WINDOWS
  157. return strnicmp (s1, s2, maxChars);
  158. #else
  159. return strncasecmp (s1, s2, maxChars);
  160. #endif
  161. }
  162. int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw()
  163. {
  164. jassert (s1 != 0 && s2 != 0);
  165. #if JUCE_WINDOWS
  166. return _wcsnicmp (s1, s2, maxChars);
  167. #else
  168. while (--maxChars >= 0)
  169. {
  170. if (*s1 != *s2)
  171. {
  172. const int diff = toUpperCase (*s1) - toUpperCase (*s2);
  173. if (diff != 0)
  174. return diff < 0 ? -1 : 1;
  175. }
  176. else if (*s1 == 0)
  177. break;
  178. ++s1;
  179. ++s2;
  180. }
  181. return 0;
  182. #endif
  183. }
  184. const char* CharacterFunctions::find (const char* const haystack, const char* const needle) throw()
  185. {
  186. return strstr (haystack, needle);
  187. }
  188. const juce_wchar* CharacterFunctions::find (const juce_wchar* haystack, const juce_wchar* const needle) throw()
  189. {
  190. return wcsstr (haystack, needle);
  191. }
  192. int CharacterFunctions::indexOfChar (const char* const haystack, const char needle, const bool ignoreCase) throw()
  193. {
  194. if (haystack != 0)
  195. {
  196. int i = 0;
  197. if (ignoreCase)
  198. {
  199. const char n1 = toLowerCase (needle);
  200. const char n2 = toUpperCase (needle);
  201. if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search
  202. {
  203. while (haystack[i] != 0)
  204. {
  205. if (haystack[i] == n1 || haystack[i] == n2)
  206. return i;
  207. ++i;
  208. }
  209. return -1;
  210. }
  211. jassert (n1 == needle);
  212. }
  213. while (haystack[i] != 0)
  214. {
  215. if (haystack[i] == needle)
  216. return i;
  217. ++i;
  218. }
  219. }
  220. return -1;
  221. }
  222. int CharacterFunctions::indexOfChar (const juce_wchar* const haystack, const juce_wchar needle, const bool ignoreCase) throw()
  223. {
  224. if (haystack != 0)
  225. {
  226. int i = 0;
  227. if (ignoreCase)
  228. {
  229. const juce_wchar n1 = toLowerCase (needle);
  230. const juce_wchar n2 = toUpperCase (needle);
  231. if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search
  232. {
  233. while (haystack[i] != 0)
  234. {
  235. if (haystack[i] == n1 || haystack[i] == n2)
  236. return i;
  237. ++i;
  238. }
  239. return -1;
  240. }
  241. jassert (n1 == needle);
  242. }
  243. while (haystack[i] != 0)
  244. {
  245. if (haystack[i] == needle)
  246. return i;
  247. ++i;
  248. }
  249. }
  250. return -1;
  251. }
  252. int CharacterFunctions::indexOfCharFast (const char* const haystack, const char needle) throw()
  253. {
  254. jassert (haystack != 0);
  255. int i = 0;
  256. while (haystack[i] != 0)
  257. {
  258. if (haystack[i] == needle)
  259. return i;
  260. ++i;
  261. }
  262. return -1;
  263. }
  264. int CharacterFunctions::indexOfCharFast (const juce_wchar* const haystack, const juce_wchar needle) throw()
  265. {
  266. jassert (haystack != 0);
  267. int i = 0;
  268. while (haystack[i] != 0)
  269. {
  270. if (haystack[i] == needle)
  271. return i;
  272. ++i;
  273. }
  274. return -1;
  275. }
  276. int CharacterFunctions::getIntialSectionContainingOnly (const char* const text, const char* const allowedChars) throw()
  277. {
  278. return allowedChars == 0 ? 0 : (int) strspn (text, allowedChars);
  279. }
  280. int CharacterFunctions::getIntialSectionContainingOnly (const juce_wchar* const text, const juce_wchar* const allowedChars) throw()
  281. {
  282. if (allowedChars == 0)
  283. return 0;
  284. int i = 0;
  285. for (;;)
  286. {
  287. if (indexOfCharFast (allowedChars, text[i]) < 0)
  288. break;
  289. ++i;
  290. }
  291. return i;
  292. }
  293. int CharacterFunctions::ftime (char* const dest, const int maxChars, const char* const format, const struct tm* const tm) throw()
  294. {
  295. return (int) strftime (dest, maxChars, format, tm);
  296. }
  297. int CharacterFunctions::ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw()
  298. {
  299. return (int) wcsftime (dest, maxChars, format, tm);
  300. }
  301. int CharacterFunctions::getIntValue (const char* const s) throw()
  302. {
  303. return atoi (s);
  304. }
  305. int CharacterFunctions::getIntValue (const juce_wchar* s) throw()
  306. {
  307. #if JUCE_WINDOWS
  308. return _wtoi (s);
  309. #else
  310. int v = 0;
  311. while (isWhitespace (*s))
  312. ++s;
  313. const bool isNeg = *s == '-';
  314. if (isNeg)
  315. ++s;
  316. for (;;)
  317. {
  318. const wchar_t c = *s++;
  319. if (c >= '0' && c <= '9')
  320. v = v * 10 + (int) (c - '0');
  321. else
  322. break;
  323. }
  324. return isNeg ? -v : v;
  325. #endif
  326. }
  327. int64 CharacterFunctions::getInt64Value (const char* s) throw()
  328. {
  329. #if JUCE_LINUX
  330. return atoll (s);
  331. #elif JUCE_WINDOWS
  332. return _atoi64 (s);
  333. #else
  334. int64 v = 0;
  335. while (isWhitespace (*s))
  336. ++s;
  337. const bool isNeg = *s == '-';
  338. if (isNeg)
  339. ++s;
  340. for (;;)
  341. {
  342. const char c = *s++;
  343. if (c >= '0' && c <= '9')
  344. v = v * 10 + (int64) (c - '0');
  345. else
  346. break;
  347. }
  348. return isNeg ? -v : v;
  349. #endif
  350. }
  351. int64 CharacterFunctions::getInt64Value (const juce_wchar* s) throw()
  352. {
  353. #if JUCE_WINDOWS
  354. return _wtoi64 (s);
  355. #else
  356. int64 v = 0;
  357. while (isWhitespace (*s))
  358. ++s;
  359. const bool isNeg = *s == '-';
  360. if (isNeg)
  361. ++s;
  362. for (;;)
  363. {
  364. const juce_wchar c = *s++;
  365. if (c >= '0' && c <= '9')
  366. v = v * 10 + (int64) (c - '0');
  367. else
  368. break;
  369. }
  370. return isNeg ? -v : v;
  371. #endif
  372. }
  373. //==============================================================================
  374. static double juce_mulexp10 (const double value, int exponent) throw()
  375. {
  376. if (exponent == 0)
  377. return value;
  378. if (value == 0)
  379. return 0;
  380. const bool negative = (exponent < 0);
  381. if (negative)
  382. exponent = -exponent;
  383. double result = 1.0, power = 10.0;
  384. for (int bit = 1; exponent != 0; bit <<= 1)
  385. {
  386. if ((exponent & bit) != 0)
  387. {
  388. exponent ^= bit;
  389. result *= power;
  390. if (exponent == 0)
  391. break;
  392. }
  393. power *= power;
  394. }
  395. return negative ? (value / result) : (value * result);
  396. }
  397. template <class CharType>
  398. double juce_atof (const CharType* const original) throw()
  399. {
  400. double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 };
  401. int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 };
  402. int exponent = 0, decPointIndex = 0, digit = 0;
  403. int lastDigit = 0, numSignificantDigits = 0;
  404. bool isNegative = false, digitsFound = false;
  405. const int maxSignificantDigits = 15 + 2;
  406. const CharType* s = original;
  407. while (CharacterFunctions::isWhitespace (*s))
  408. ++s;
  409. switch (*s)
  410. {
  411. case '-': isNegative = true; // fall-through..
  412. case '+': ++s;
  413. }
  414. if (*s == 'n' || *s == 'N' || *s == 'i' || *s == 'I')
  415. return atof (String (original).toUTF8()); // Let the c library deal with NAN and INF
  416. for (;;)
  417. {
  418. if (CharacterFunctions::isDigit (*s))
  419. {
  420. lastDigit = digit;
  421. digit = *s++ - '0';
  422. digitsFound = true;
  423. if (decPointIndex != 0)
  424. exponentAdjustment[1]++;
  425. if (numSignificantDigits == 0 && digit == 0)
  426. continue;
  427. if (++numSignificantDigits > maxSignificantDigits)
  428. {
  429. if (digit > 5)
  430. ++accumulator [decPointIndex];
  431. else if (digit == 5 && (lastDigit & 1) != 0)
  432. ++accumulator [decPointIndex];
  433. if (decPointIndex > 0)
  434. exponentAdjustment[1]--;
  435. else
  436. exponentAdjustment[0]++;
  437. while (CharacterFunctions::isDigit (*s))
  438. {
  439. ++s;
  440. if (decPointIndex == 0)
  441. exponentAdjustment[0]++;
  442. }
  443. }
  444. else
  445. {
  446. const double maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10);
  447. if (accumulator [decPointIndex] > maxAccumulatorValue)
  448. {
  449. result [decPointIndex] = juce_mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex])
  450. + accumulator [decPointIndex];
  451. accumulator [decPointIndex] = 0;
  452. exponentAccumulator [decPointIndex] = 0;
  453. }
  454. accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit;
  455. exponentAccumulator [decPointIndex]++;
  456. }
  457. }
  458. else if (decPointIndex == 0 && *s == '.')
  459. {
  460. ++s;
  461. decPointIndex = 1;
  462. if (numSignificantDigits > maxSignificantDigits)
  463. {
  464. while (CharacterFunctions::isDigit (*s))
  465. ++s;
  466. break;
  467. }
  468. }
  469. else
  470. {
  471. break;
  472. }
  473. }
  474. result[0] = juce_mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0];
  475. if (decPointIndex != 0)
  476. result[1] = juce_mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
  477. if ((*s == 'e' || *s == 'E') && digitsFound)
  478. {
  479. bool negativeExponent = false;
  480. switch (*++s)
  481. {
  482. case '-': negativeExponent = true; // fall-through..
  483. case '+': ++s;
  484. }
  485. while (CharacterFunctions::isDigit (*s))
  486. exponent = (exponent * 10) + (*s++ - '0');
  487. if (negativeExponent)
  488. exponent = -exponent;
  489. }
  490. double r = juce_mulexp10 (result[0], exponent + exponentAdjustment[0]);
  491. if (decPointIndex != 0)
  492. r += juce_mulexp10 (result[1], exponent - exponentAdjustment[1]);
  493. return isNegative ? -r : r;
  494. }
  495. double CharacterFunctions::getDoubleValue (const char* const s) throw()
  496. {
  497. return juce_atof <char> (s);
  498. }
  499. double CharacterFunctions::getDoubleValue (const juce_wchar* const s) throw()
  500. {
  501. return juce_atof <juce_wchar> (s);
  502. }
  503. //==============================================================================
  504. char CharacterFunctions::toUpperCase (const char character) throw()
  505. {
  506. return (char) toupper (character);
  507. }
  508. juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) throw()
  509. {
  510. return towupper (character);
  511. }
  512. void CharacterFunctions::toUpperCase (char* s) throw()
  513. {
  514. #if JUCE_WINDOWS
  515. strupr (s);
  516. #else
  517. while (*s != 0)
  518. {
  519. *s = toUpperCase (*s);
  520. ++s;
  521. }
  522. #endif
  523. }
  524. void CharacterFunctions::toUpperCase (juce_wchar* s) throw()
  525. {
  526. #if JUCE_WINDOWS
  527. _wcsupr (s);
  528. #else
  529. while (*s != 0)
  530. {
  531. *s = toUpperCase (*s);
  532. ++s;
  533. }
  534. #endif
  535. }
  536. bool CharacterFunctions::isUpperCase (const char character) throw()
  537. {
  538. return isupper (character) != 0;
  539. }
  540. bool CharacterFunctions::isUpperCase (const juce_wchar character) throw()
  541. {
  542. #if JUCE_WINDOWS
  543. return iswupper (character) != 0;
  544. #else
  545. return toLowerCase (character) != character;
  546. #endif
  547. }
  548. //==============================================================================
  549. char CharacterFunctions::toLowerCase (const char character) throw()
  550. {
  551. return (char) tolower (character);
  552. }
  553. juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) throw()
  554. {
  555. return towlower (character);
  556. }
  557. void CharacterFunctions::toLowerCase (char* s) throw()
  558. {
  559. #if JUCE_WINDOWS
  560. strlwr (s);
  561. #else
  562. while (*s != 0)
  563. {
  564. *s = toLowerCase (*s);
  565. ++s;
  566. }
  567. #endif
  568. }
  569. void CharacterFunctions::toLowerCase (juce_wchar* s) throw()
  570. {
  571. #if JUCE_WINDOWS
  572. _wcslwr (s);
  573. #else
  574. while (*s != 0)
  575. {
  576. *s = toLowerCase (*s);
  577. ++s;
  578. }
  579. #endif
  580. }
  581. bool CharacterFunctions::isLowerCase (const char character) throw()
  582. {
  583. return islower (character) != 0;
  584. }
  585. bool CharacterFunctions::isLowerCase (const juce_wchar character) throw()
  586. {
  587. #if JUCE_WINDOWS
  588. return iswlower (character) != 0;
  589. #else
  590. return toUpperCase (character) != character;
  591. #endif
  592. }
  593. //==============================================================================
  594. bool CharacterFunctions::isWhitespace (const char character) throw()
  595. {
  596. return character == ' ' || (character <= 13 && character >= 9);
  597. }
  598. bool CharacterFunctions::isWhitespace (const juce_wchar character) throw()
  599. {
  600. return iswspace (character) != 0;
  601. }
  602. bool CharacterFunctions::isDigit (const char character) throw()
  603. {
  604. return (character >= '0' && character <= '9');
  605. }
  606. bool CharacterFunctions::isDigit (const juce_wchar character) throw()
  607. {
  608. return iswdigit (character) != 0;
  609. }
  610. bool CharacterFunctions::isLetter (const char character) throw()
  611. {
  612. return (character >= 'a' && character <= 'z')
  613. || (character >= 'A' && character <= 'Z');
  614. }
  615. bool CharacterFunctions::isLetter (const juce_wchar character) throw()
  616. {
  617. return iswalpha (character) != 0;
  618. }
  619. bool CharacterFunctions::isLetterOrDigit (const char character) throw()
  620. {
  621. return (character >= 'a' && character <= 'z')
  622. || (character >= 'A' && character <= 'Z')
  623. || (character >= '0' && character <= '9');
  624. }
  625. bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) throw()
  626. {
  627. return iswalnum (character) != 0;
  628. }
  629. int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw()
  630. {
  631. unsigned int d = digit - '0';
  632. if (d < (unsigned int) 10)
  633. return (int) d;
  634. d += '0' - 'a';
  635. if (d < (unsigned int) 6)
  636. return (int) d + 10;
  637. d += 'a' - 'A';
  638. if (d < (unsigned int) 6)
  639. return (int) d + 10;
  640. return -1;
  641. }
  642. #if JUCE_MSVC
  643. #pragma warning (pop)
  644. #endif
  645. END_JUCE_NAMESPACE