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.

299 lines
9.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4514 4996)
  20. juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) noexcept
  21. {
  22. return (juce_wchar) towupper ((wint_t) character);
  23. }
  24. juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) noexcept
  25. {
  26. return (juce_wchar) towlower ((wint_t) character);
  27. }
  28. bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept
  29. {
  30. #if JUCE_WINDOWS
  31. return iswupper ((wint_t) character) != 0;
  32. #else
  33. return toLowerCase (character) != character;
  34. #endif
  35. }
  36. bool CharacterFunctions::isLowerCase (const juce_wchar character) noexcept
  37. {
  38. #if JUCE_WINDOWS
  39. return iswlower ((wint_t) character) != 0;
  40. #else
  41. return toUpperCase (character) != character;
  42. #endif
  43. }
  44. JUCE_END_IGNORE_WARNINGS_MSVC
  45. //==============================================================================
  46. bool CharacterFunctions::isWhitespace (const char character) noexcept
  47. {
  48. return character == ' ' || (character <= 13 && character >= 9);
  49. }
  50. bool CharacterFunctions::isWhitespace (const juce_wchar character) noexcept
  51. {
  52. return iswspace ((wint_t) character) != 0;
  53. }
  54. bool CharacterFunctions::isDigit (const char character) noexcept
  55. {
  56. return (character >= '0' && character <= '9');
  57. }
  58. bool CharacterFunctions::isDigit (const juce_wchar character) noexcept
  59. {
  60. return iswdigit ((wint_t) character) != 0;
  61. }
  62. bool CharacterFunctions::isLetter (const char character) noexcept
  63. {
  64. return (character >= 'a' && character <= 'z')
  65. || (character >= 'A' && character <= 'Z');
  66. }
  67. bool CharacterFunctions::isLetter (const juce_wchar character) noexcept
  68. {
  69. return iswalpha ((wint_t) character) != 0;
  70. }
  71. bool CharacterFunctions::isLetterOrDigit (const char character) noexcept
  72. {
  73. return (character >= 'a' && character <= 'z')
  74. || (character >= 'A' && character <= 'Z')
  75. || (character >= '0' && character <= '9');
  76. }
  77. bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) noexcept
  78. {
  79. return iswalnum ((wint_t) character) != 0;
  80. }
  81. bool CharacterFunctions::isPrintable (const char character) noexcept
  82. {
  83. return (character >= ' ' && character <= '~');
  84. }
  85. bool CharacterFunctions::isPrintable (const juce_wchar character) noexcept
  86. {
  87. return iswprint ((wint_t) character) != 0;
  88. }
  89. int CharacterFunctions::getHexDigitValue (const juce_wchar digit) noexcept
  90. {
  91. auto d = (unsigned int) (digit - '0');
  92. if (d < (unsigned int) 10)
  93. return (int) d;
  94. d += (unsigned int) ('0' - 'a');
  95. if (d < (unsigned int) 6)
  96. return (int) d + 10;
  97. d += (unsigned int) ('a' - 'A');
  98. if (d < (unsigned int) 6)
  99. return (int) d + 10;
  100. return -1;
  101. }
  102. double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept
  103. {
  104. if (exponent == 0)
  105. return value;
  106. if (value == 0.0)
  107. return 0;
  108. const bool negative = (exponent < 0);
  109. if (negative)
  110. exponent = -exponent;
  111. double result = 1.0, power = 10.0;
  112. for (int bit = 1; exponent != 0; bit <<= 1)
  113. {
  114. if ((exponent & bit) != 0)
  115. {
  116. exponent ^= bit;
  117. result *= power;
  118. if (exponent == 0)
  119. break;
  120. }
  121. power *= power;
  122. }
  123. return negative ? (value / result) : (value * result);
  124. }
  125. juce_wchar CharacterFunctions::getUnicodeCharFromWindows1252Codepage (const uint8 c) noexcept
  126. {
  127. if (c < 0x80 || c >= 0xa0)
  128. return (juce_wchar) c;
  129. static const uint16 lookup[] = { 0x20AC, 0x0007, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
  130. 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0007, 0x017D, 0x0007,
  131. 0x0007, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
  132. 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0007, 0x017E, 0x0178 };
  133. return (juce_wchar) lookup[c - 0x80];
  134. }
  135. //==============================================================================
  136. //==============================================================================
  137. #if JUCE_UNIT_TESTS
  138. #define QUOTE(x) #x
  139. #define STR(value) QUOTE(value)
  140. #define ASYM_STRING_DOUBLE_PAIR(str, value) std::pair<String, double> (STR(str), value)
  141. #define STRING_DOUBLE_PAIR(value) ASYM_STRING_DOUBLE_PAIR(value, value)
  142. #define STRING_DOUBLE_PAIR_COMBOS(value) \
  143. STRING_DOUBLE_PAIR(value), \
  144. STRING_DOUBLE_PAIR(-value), \
  145. ASYM_STRING_DOUBLE_PAIR(+value, value), \
  146. ASYM_STRING_DOUBLE_PAIR(000000 ## value, value), \
  147. ASYM_STRING_DOUBLE_PAIR(+000 ## value, value), \
  148. ASYM_STRING_DOUBLE_PAIR(-0 ## value, -value)
  149. class CharacterFunctionsTests : public UnitTest
  150. {
  151. public:
  152. CharacterFunctionsTests()
  153. : UnitTest ("CharacterFunctions", UnitTestCategories::text)
  154. {}
  155. void runTest() override
  156. {
  157. beginTest ("readDoubleValue");
  158. static const std::pair<String, double> testValues[] =
  159. {
  160. // Integers
  161. STRING_DOUBLE_PAIR_COMBOS (0),
  162. STRING_DOUBLE_PAIR_COMBOS (3),
  163. STRING_DOUBLE_PAIR_COMBOS (4931),
  164. STRING_DOUBLE_PAIR_COMBOS (5000),
  165. STRING_DOUBLE_PAIR_COMBOS (9862097),
  166. // Floating point numbers
  167. STRING_DOUBLE_PAIR_COMBOS (7.000),
  168. STRING_DOUBLE_PAIR_COMBOS (0.2),
  169. STRING_DOUBLE_PAIR_COMBOS (.298630),
  170. STRING_DOUBLE_PAIR_COMBOS (1.118),
  171. STRING_DOUBLE_PAIR_COMBOS (0.9000),
  172. STRING_DOUBLE_PAIR_COMBOS (0.0000001),
  173. STRING_DOUBLE_PAIR_COMBOS (500.0000001),
  174. STRING_DOUBLE_PAIR_COMBOS (9862098.2398604),
  175. // Exponents
  176. STRING_DOUBLE_PAIR_COMBOS (0e0),
  177. STRING_DOUBLE_PAIR_COMBOS (0.e0),
  178. STRING_DOUBLE_PAIR_COMBOS (0.00000e0),
  179. STRING_DOUBLE_PAIR_COMBOS (.0e7),
  180. STRING_DOUBLE_PAIR_COMBOS (0e-5),
  181. STRING_DOUBLE_PAIR_COMBOS (2E0),
  182. STRING_DOUBLE_PAIR_COMBOS (4.E0),
  183. STRING_DOUBLE_PAIR_COMBOS (1.2000000E0),
  184. STRING_DOUBLE_PAIR_COMBOS (1.2000000E6),
  185. STRING_DOUBLE_PAIR_COMBOS (.398e3),
  186. STRING_DOUBLE_PAIR_COMBOS (10e10),
  187. STRING_DOUBLE_PAIR_COMBOS (1.4962e+2),
  188. STRING_DOUBLE_PAIR_COMBOS (3198693.0973e4),
  189. STRING_DOUBLE_PAIR_COMBOS (10973097.2087E-4),
  190. STRING_DOUBLE_PAIR_COMBOS (1.3986e00006),
  191. STRING_DOUBLE_PAIR_COMBOS (2087.3087e+00006),
  192. STRING_DOUBLE_PAIR_COMBOS (6.0872e-00006),
  193. // Too many sig figs. The parsing routine on MinGW gets the last
  194. // significant figure wrong.
  195. STRING_DOUBLE_PAIR_COMBOS (17654321098765432.9),
  196. STRING_DOUBLE_PAIR_COMBOS (183456789012345678.9),
  197. STRING_DOUBLE_PAIR_COMBOS (1934567890123456789.9),
  198. STRING_DOUBLE_PAIR_COMBOS (20345678901234567891.9),
  199. STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000),
  200. STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e3),
  201. STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e100),
  202. STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-5),
  203. STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-40),
  204. STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890),
  205. STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890e-111)
  206. // Limits. DBL_MAX may not exist on Linux.
  207. #if ! JUCE_LINUX
  208. , STRING_DOUBLE_PAIR (DBL_MAX),
  209. STRING_DOUBLE_PAIR (-DBL_MAX),
  210. STRING_DOUBLE_PAIR (DBL_MIN)
  211. #endif
  212. };
  213. for (auto trial : testValues)
  214. {
  215. auto charPtr = trial.first.getCharPointer();
  216. expectEquals (CharacterFunctions::readDoubleValue (charPtr), trial.second);
  217. }
  218. {
  219. String nans[] = { "NaN", "-nan", "+NAN", "1.0E1024", "-1.0E-999", "1.23456789012345678901234567890e123456789"};
  220. for (auto nan : nans)
  221. {
  222. auto charPtr = nan.getCharPointer();
  223. expect (std::isnan (CharacterFunctions::readDoubleValue (charPtr)));
  224. }
  225. }
  226. {
  227. String infs[] = { "Inf", "-inf", "INF"};
  228. for (auto inf : infs)
  229. {
  230. auto charPtr = inf.getCharPointer();
  231. expect (std::isinf (CharacterFunctions::readDoubleValue (charPtr)));
  232. }
  233. }
  234. }
  235. };
  236. static CharacterFunctionsTests characterFunctionsTests;
  237. #endif
  238. } // namespace juce