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.

276 lines
7.5KB

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