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.

300 lines
9.5KB

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