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.

776 lines
18KB

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