Audio plugin host https://kx.studio/carla
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.

273 lines
7.2KB

  1. //-----------------------------------------------------------------------------
  2. // Project : SDK Core
  3. //
  4. // Category : Helpers
  5. // Filename : pluginterfaces/base/ustring.cpp
  6. // Created by : Steinberg, 12/2005
  7. // Description : UTF-16 String class
  8. //
  9. //-----------------------------------------------------------------------------
  10. // This file is part of a Steinberg SDK. It is subject to the license terms
  11. // in the LICENSE file found in the top-level directory of this distribution
  12. // and at www.steinberg.net/sdklicenses.
  13. // No part of the SDK, including this file, may be copied, modified, propagated,
  14. // or distributed except according to the terms contained in the LICENSE file.
  15. //-----------------------------------------------------------------------------
  16. #include "ustring.h"
  17. #if WINDOWS
  18. #include <stdio.h>
  19. #pragma warning (disable : 4996)
  20. #elif MAC
  21. #include <CoreFoundation/CoreFoundation.h>
  22. #elif LINUX
  23. #include <cstring>
  24. #include <string>
  25. #include <codecvt>
  26. #include <sstream>
  27. #include <locale>
  28. #include <wctype.h>
  29. #include <wchar.h>
  30. #endif
  31. //------------------------------------------------------------------------
  32. namespace Steinberg {
  33. //------------------------------------------------------------------------
  34. #if LINUX
  35. //------------------------------------------------------------------------
  36. namespace {
  37. using Converter = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>;
  38. //------------------------------------------------------------------------
  39. Converter& converter ()
  40. {
  41. static Converter instance;
  42. return instance;
  43. }
  44. //------------------------------------------------------------------------
  45. } // anonymous
  46. //------------------------------------------------------------------------
  47. #endif // LINUX
  48. //------------------------------------------------------------------------
  49. /** Copy strings of different character width. */
  50. //------------------------------------------------------------------------
  51. template <class TDstChar, class TSrcChar>
  52. void StringCopy (TDstChar* dst, int32 dstSize, const TSrcChar* src, int32 srcSize = -1)
  53. {
  54. int32 count = dstSize;
  55. if (srcSize >= 0 && srcSize < dstSize)
  56. count = srcSize;
  57. for (int32 i = 0; i < count; i++)
  58. {
  59. dst[i] = (TDstChar)src[i];
  60. if (src[i] == 0)
  61. break;
  62. }
  63. dst[dstSize - 1] = 0;
  64. }
  65. //------------------------------------------------------------------------
  66. /** Find length of null-terminated string. */
  67. //------------------------------------------------------------------------
  68. template <class TSrcChar>
  69. int32 StringLength (const TSrcChar* src, int32 srcSize = -1)
  70. {
  71. if (srcSize == 0)
  72. return 0;
  73. int32 length = 0;
  74. while (src[length])
  75. {
  76. length++;
  77. if (srcSize > 0 && length >= srcSize)
  78. break;
  79. }
  80. return length;
  81. }
  82. //------------------------------------------------------------------------
  83. // UString
  84. //------------------------------------------------------------------------
  85. int32 UString::getLength () const
  86. {
  87. return StringLength<char16> (thisBuffer, thisSize);
  88. }
  89. //------------------------------------------------------------------------
  90. UString& UString::assign (const char16* src, int32 srcSize)
  91. {
  92. StringCopy<char16, char16> (thisBuffer, thisSize, src, srcSize);
  93. return *this;
  94. }
  95. //------------------------------------------------------------------------
  96. UString& UString::append (const char16* src, int32 srcSize)
  97. {
  98. int32 length = getLength ();
  99. StringCopy<char16, char16> (thisBuffer + length, thisSize - length, src, srcSize);
  100. return *this;
  101. }
  102. //------------------------------------------------------------------------
  103. const UString& UString::copyTo (char16* dst, int32 dstSize) const
  104. {
  105. StringCopy<char16, char16> (dst, dstSize, thisBuffer, thisSize);
  106. return *this;
  107. }
  108. //------------------------------------------------------------------------
  109. UString& UString::fromAscii (const char* src, int32 srcSize)
  110. {
  111. StringCopy<char16, char> (thisBuffer, thisSize, src, srcSize);
  112. return *this;
  113. }
  114. //------------------------------------------------------------------------
  115. const UString& UString::toAscii (char* dst, int32 dstSize) const
  116. {
  117. StringCopy<char, char16> (dst, dstSize, thisBuffer, thisSize);
  118. return *this;
  119. }
  120. //------------------------------------------------------------------------
  121. bool UString::scanFloat (double& value) const
  122. {
  123. #if WINDOWS
  124. return swscanf ((const wchar_t*)thisBuffer, L"%lf", &value) != -1;
  125. #elif TARGET_API_MAC_CARBON
  126. CFStringRef cfStr = CFStringCreateWithBytes (0, (const UInt8 *)thisBuffer, getLength () * 2, kCFStringEncodingUTF16, false);
  127. if (cfStr)
  128. {
  129. value = CFStringGetDoubleValue (cfStr);
  130. CFRelease (cfStr);
  131. return true;
  132. }
  133. return false;
  134. #elif LINUX
  135. auto str = converter ().to_bytes (thisBuffer);
  136. return sscanf (str.data (), "%lf", &value) == 1;
  137. #else
  138. #warning Implement me
  139. // implement me!
  140. return false;
  141. #endif
  142. }
  143. //------------------------------------------------------------------------
  144. bool UString::printFloat (double value, int32 precision)
  145. {
  146. #if WINDOWS
  147. return swprintf ((wchar_t*)thisBuffer, L"%.*lf", precision, value) != -1;
  148. #elif MAC
  149. bool result = false;
  150. CFStringRef cfStr = CFStringCreateWithFormat (0, 0, CFSTR("%.*lf"), precision, value);
  151. if (cfStr)
  152. {
  153. memset (thisBuffer, 0, thisSize);
  154. CFRange range = {0, CFStringGetLength (cfStr)};
  155. CFStringGetBytes (cfStr, range, kCFStringEncodingUTF16, 0, false, (UInt8*)thisBuffer, thisSize, 0);
  156. CFRelease (cfStr);
  157. return true;
  158. }
  159. return result;
  160. #elif LINUX
  161. auto utf8Buffer = reinterpret_cast<char*> (thisBuffer);
  162. auto len = snprintf (utf8Buffer, thisSize, "%.*lf", precision, value);
  163. if (len > 0)
  164. {
  165. auto utf16Buffer = reinterpret_cast<char16*> (thisBuffer);
  166. utf16Buffer[len] = 0;
  167. while (--len >= 0)
  168. {
  169. utf16Buffer[len] = utf8Buffer[len];
  170. }
  171. return true;
  172. }
  173. return false;
  174. #else
  175. #warning Implement me
  176. // implement me!
  177. return false;
  178. #endif
  179. }
  180. //------------------------------------------------------------------------
  181. bool UString::scanInt (int64& value) const
  182. {
  183. #if WINDOWS
  184. return swscanf ((const wchar_t*)thisBuffer, L"%I64d", &value) != -1;
  185. #elif MAC
  186. CFStringRef cfStr = CFStringCreateWithBytes (0, (const UInt8 *)thisBuffer, getLength () * 2, kCFStringEncodingUTF16, false);
  187. if (cfStr)
  188. {
  189. value = CFStringGetIntValue (cfStr);
  190. CFRelease (cfStr);
  191. return true;
  192. }
  193. return false;
  194. #elif LINUX
  195. auto str = converter ().to_bytes (thisBuffer);
  196. return sscanf (str.data (), "%lld", &value) == 1;
  197. #else
  198. #warning Implement me
  199. // implement me!
  200. return false;
  201. #endif
  202. }
  203. //------------------------------------------------------------------------
  204. bool UString::printInt (int64 value)
  205. {
  206. #if WINDOWS
  207. return swprintf ((wchar_t*)thisBuffer, L"%I64d", value) != -1;
  208. #elif MAC
  209. CFStringRef cfStr = CFStringCreateWithFormat (0, 0, CFSTR("%lld"), value);
  210. if (cfStr)
  211. {
  212. memset (thisBuffer, 0, thisSize);
  213. CFRange range = {0, CFStringGetLength (cfStr)};
  214. CFStringGetBytes (cfStr, range, kCFStringEncodingUTF16, 0, false, (UInt8*)thisBuffer, thisSize, 0);
  215. CFRelease (cfStr);
  216. return true;
  217. }
  218. return false;
  219. #elif LINUX
  220. auto utf8Buffer = reinterpret_cast<char*> (thisBuffer);
  221. auto len = snprintf (utf8Buffer, thisSize, "%lld", value);
  222. if (len > 0)
  223. {
  224. auto utf16Buffer = reinterpret_cast<char16*> (thisBuffer);
  225. utf16Buffer[len] = 0;
  226. while (--len >= 0)
  227. {
  228. utf16Buffer[len] = utf8Buffer[len];
  229. }
  230. return true;
  231. }
  232. return false;
  233. #else
  234. #warning Implement me
  235. // implement me!
  236. return false;
  237. #endif
  238. }
  239. } // namespace Steinberg