AkVariantBase.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  1. /*******************************************************************************
  2. The content of this file includes portions of the AUDIOKINETIC Wwise Technology
  3. released in source code form as part of the SDK installer package.
  4. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. #pragma once
  21. #include <stdint.h>
  22. #include <string>
  23. #if (defined(_HAS_CXX17) && _HAS_CXX17)
  24. #include <string_view>
  25. #endif
  26. #include "AkGuid.h"
  27. #include <AK/SoundEngine/Common/AkTypes.h>
  28. namespace AK
  29. {
  30. namespace WwiseAuthoringAPI
  31. {
  32. enum AkVariantTypeBase
  33. {
  34. AkVariantType_none = 0,
  35. AkVariantType_uint8,
  36. AkVariantType_uint16,
  37. AkVariantType_uint32,
  38. AkVariantType_uint64,
  39. AkVariantType_int8,
  40. AkVariantType_int16,
  41. AkVariantType_int32,
  42. AkVariantType_int64,
  43. AkVariantType_real32,
  44. AkVariantType_real64,
  45. AkVariantType_bool,
  46. AkVariantType_string,
  47. AkVariantType_wstring,
  48. AkVariantType_guid
  49. };
  50. // Do not use AkVariantBase directly, you must inherit from it.
  51. class AkVariantBase
  52. {
  53. private:
  54. static const int k_iExampleGuidLen = 38;
  55. // Constructors and destructor are protected to prevent accidental leak when deleting the class with the wrong type.
  56. // The class is not using a virtual destructor on purpose to avoid having a vtable.
  57. protected:
  58. inline ~AkVariantBase()
  59. {
  60. Clear();
  61. }
  62. inline AkVariantBase()
  63. {
  64. Nullify();
  65. }
  66. inline AkVariantBase(const AkVariantBase& other)
  67. {
  68. Nullify();
  69. CopyFrom(other);
  70. }
  71. inline AkVariantBase(AkVariantBase&& other)
  72. {
  73. Nullify();
  74. CopyFrom(other);
  75. }
  76. inline AkVariantBase(uint8_t in_val) { m_uint8 = in_val; m_eType = AkVariantType_uint8; }
  77. inline AkVariantBase(uint16_t in_val) { m_uint16 = in_val; m_eType = AkVariantType_uint16; }
  78. inline AkVariantBase(uint32_t in_val) { m_uint32 = in_val; m_eType = AkVariantType_uint32; }
  79. inline AkVariantBase(uint64_t in_val) { m_uint64 = in_val; m_eType = AkVariantType_uint64; }
  80. inline AkVariantBase(int8_t in_val) { m_uint8 = in_val; m_eType = AkVariantType_int8; }
  81. inline AkVariantBase(int16_t in_val) { m_uint16 = in_val; m_eType = AkVariantType_int16; }
  82. inline AkVariantBase(int32_t in_val) { m_uint32 = in_val; m_eType = AkVariantType_int32; }
  83. inline AkVariantBase(int64_t in_val) { m_uint64 = in_val; m_eType = AkVariantType_int64; }
  84. inline AkVariantBase(float in_val) { m_real32 = in_val; m_eType = AkVariantType_real32; }
  85. inline AkVariantBase(double in_val) { m_real64 = in_val; m_eType = AkVariantType_real64; }
  86. inline AkVariantBase(bool in_val) { m_boolean = in_val; m_eType = AkVariantType_bool; }
  87. inline AkVariantBase(const AkGuid& in_val)
  88. {
  89. m_data = new AkGuid();
  90. memcpy(m_data, &in_val, sizeof(AkGuid));
  91. m_eType = AkVariantType_guid;
  92. }
  93. #ifdef GUID_DEFINED
  94. inline AkVariantBase(const GUID& in_val)
  95. {
  96. m_data = new AkGuid();
  97. memcpy(m_data, &in_val, sizeof(AkGuid));
  98. m_eType = AkVariantType_guid;
  99. }
  100. #endif
  101. inline AkVariantBase(const wchar_t* in_val)
  102. {
  103. m_data = new std::wstring(in_val);
  104. m_eType = AkVariantType_wstring;
  105. }
  106. inline AkVariantBase(const std::wstring& in_val)
  107. : AkVariantBase(in_val.c_str())
  108. {
  109. }
  110. inline AkVariantBase(const char* in_val)
  111. {
  112. m_data = new std::string(in_val);
  113. m_eType = AkVariantType_string;
  114. }
  115. inline AkVariantBase(const std::string& in_val)
  116. : AkVariantBase(in_val.c_str())
  117. {
  118. }
  119. #if (defined(_HAS_CXX17) && _HAS_CXX17) || defined(AK_APPLE) || defined(AK_LINUX)
  120. inline AkVariantBase(const std::string_view& in_val)
  121. {
  122. m_data = new std::string(in_val);
  123. m_eType = AkVariantType_string;
  124. }
  125. #endif
  126. void Nullify()
  127. {
  128. m_uint64 = 0;
  129. m_eType = AkVariantType_none;
  130. }
  131. public:
  132. // Assignment ----------------------------------------------------------------------------
  133. inline AkVariantBase& operator=(const AkVariantBase& in_val)
  134. {
  135. Clear();
  136. CopyFrom(in_val);
  137. return *this;
  138. }
  139. inline AkVariantBase& operator=(const AkGuid& in_val)
  140. {
  141. Clear();
  142. AkGuid*guid = new AkGuid();
  143. memcpy(guid, &in_val, sizeof(AkGuid));
  144. m_eType = AkVariantType_guid;
  145. return *this;
  146. }
  147. inline AkVariantBase& operator=(const wchar_t* in_val)
  148. {
  149. Clear();
  150. m_data = new std::wstring(in_val);
  151. m_eType = AkVariantType_wstring;
  152. return *this;
  153. }
  154. inline AkVariantBase& operator=(const std::wstring& in_val)
  155. {
  156. Clear();
  157. m_data = new std::wstring(in_val);
  158. m_eType = AkVariantType_wstring;
  159. return *this;
  160. }
  161. inline AkVariantBase& operator=(const char* in_val)
  162. {
  163. Clear();
  164. m_data = new std::string(in_val);
  165. m_eType = AkVariantType_string;
  166. return *this;
  167. }
  168. inline AkVariantBase& operator=(const std::string& in_val)
  169. {
  170. Clear();
  171. m_data = new std::string(in_val);
  172. m_eType = AkVariantType_string;
  173. return *this;
  174. }
  175. // Helpers ----------------------------------------------------------------------------
  176. inline bool IsString() const
  177. {
  178. return (m_eType == AkVariantType_string);
  179. }
  180. inline bool IsGuid() const
  181. {
  182. return (m_eType == AkVariantType_guid);
  183. }
  184. inline bool IsWString() const
  185. {
  186. return (m_eType == AkVariantType_wstring);
  187. }
  188. inline const std::wstring& GetWString() const
  189. {
  190. AKASSERT(m_eType == AkVariantType_wstring && "AkVariant: illegal typecast");
  191. return *static_cast<const std::wstring*>(m_data);
  192. }
  193. const std::string& GetString() const
  194. {
  195. if (m_eType == AkVariantType_guid)
  196. {
  197. // Safeguard to prevent a crash in case a guid (and nothing else) is provided as a string to a
  198. // function that does not support guids (which would pass schema validation and crash here).
  199. static const std::string empty;
  200. return empty;
  201. }
  202. AKASSERT(m_eType == AkVariantType_string && "AkVariant: illegal typecast");
  203. return *static_cast<const std::string*>(m_data);
  204. }
  205. inline const AkGuid& GetGuid() const
  206. {
  207. AKASSERT(m_eType == AkVariantType_guid && "AkVariant: illegal typecast");
  208. return *static_cast<const AkGuid*>(m_data);
  209. }
  210. #define _SET_VALUE( _member_, _value_, _type_ ) { \
  211. Clear(); \
  212. (_member_) = (_value_); \
  213. m_eType = _type_; \
  214. return *this; \
  215. }
  216. inline AkVariantBase& operator=(int64_t in_val)
  217. {
  218. _SET_VALUE(m_int64, in_val, AkVariantType_int64)
  219. }
  220. inline AkVariantBase& operator=(int32_t in_val)
  221. {
  222. _SET_VALUE(m_int32, in_val, AkVariantType_int32)
  223. }
  224. inline AkVariantBase& operator=(int16_t in_val)
  225. {
  226. _SET_VALUE(m_int16, in_val, AkVariantType_int16)
  227. }
  228. inline AkVariantBase& operator=(int8_t in_val)
  229. {
  230. _SET_VALUE(m_int8, in_val, AkVariantType_int8)
  231. }
  232. inline AkVariantBase& operator=(uint64_t in_val)
  233. {
  234. _SET_VALUE(m_uint64, in_val, AkVariantType_uint64)
  235. }
  236. inline AkVariantBase& operator=(uint32_t in_val)
  237. {
  238. _SET_VALUE(m_uint32, in_val, AkVariantType_uint32)
  239. }
  240. inline AkVariantBase& operator=(uint16_t in_val)
  241. {
  242. _SET_VALUE(m_uint16, in_val, AkVariantType_uint16)
  243. }
  244. inline AkVariantBase& operator=(uint8_t in_val)
  245. {
  246. _SET_VALUE(m_uint8, in_val, AkVariantType_uint8)
  247. }
  248. inline AkVariantBase& operator=(double in_val)
  249. {
  250. _SET_VALUE(m_real64, in_val, AkVariantType_real64)
  251. }
  252. inline AkVariantBase& operator=(float in_val)
  253. {
  254. _SET_VALUE(m_real32, in_val, AkVariantType_real32)
  255. }
  256. inline AkVariantBase& operator=(bool in_val)
  257. {
  258. _SET_VALUE(m_boolean, in_val, AkVariantType_bool)
  259. }
  260. inline bool operator==(const AkVariantBase& rhs) const
  261. {
  262. if (m_eType != rhs.m_eType)
  263. return false;
  264. switch (m_eType)
  265. {
  266. case AkVariantType_uint8: return m_uint8 == rhs.m_uint8;
  267. case AkVariantType_uint16: return m_uint16 == rhs.m_uint16;
  268. case AkVariantType_uint32: return m_uint32 == rhs.m_uint32;
  269. case AkVariantType_uint64: return m_uint64 == rhs.m_uint64;
  270. case AkVariantType_int8: return m_int8 == rhs.m_int8;
  271. case AkVariantType_int16: return m_int16 == rhs.m_int16;
  272. case AkVariantType_int32: return m_int32 == rhs.m_int32;
  273. case AkVariantType_int64: return m_int64 == rhs.m_int64;
  274. case AkVariantType_real32: return m_real32 == rhs.m_real32;
  275. case AkVariantType_real64: return m_real64 == rhs.m_real64;
  276. case AkVariantType_bool: return m_boolean == rhs.m_boolean;
  277. case AkVariantType_string: return GetString().compare(rhs.GetString()) == 0;
  278. case AkVariantType_wstring: return GetWString().compare(rhs.GetWString()) == 0;
  279. case AkVariantType_guid: return GetGuid() == rhs.GetGuid();
  280. default:
  281. AKASSERT(false && "Trying to convert an AkVariant that doesn't contain a basic type");
  282. }
  283. return false;
  284. }
  285. // Typecast ----------------------------------------------------------------------------
  286. inline operator bool() const
  287. {
  288. switch (m_eType)
  289. {
  290. case AkVariantType_bool: return m_boolean;
  291. default: break;
  292. }
  293. AKASSERT(false && "AkVariantBase: illegal typecast");
  294. return 0;
  295. }
  296. inline operator int64_t() const
  297. {
  298. switch (m_eType)
  299. {
  300. case AkVariantType_int8: return static_cast<int64_t>(m_int8);
  301. case AkVariantType_int16: return static_cast<int64_t>(m_int16);
  302. case AkVariantType_int32: return static_cast<int64_t>(m_int32);
  303. case AkVariantType_int64: return m_int64;
  304. default: break;
  305. }
  306. AKASSERT(false && "AkVariantBase: illegal typecast");
  307. return 0;
  308. }
  309. #ifdef AK_LINUX
  310. inline operator long long() const
  311. {
  312. // Prevents conversion ambiguity when using an AkVariant parameter with GMock on Linux
  313. return static_cast<int64_t>(*this);
  314. }
  315. #endif
  316. template<typename T> T ToEnum() const
  317. {
  318. return static_cast<T>(static_cast<int32_t>(*this));
  319. }
  320. inline operator int32_t() const
  321. {
  322. switch (m_eType)
  323. {
  324. case AkVariantType_int8: return static_cast<int32_t>(m_int8);
  325. case AkVariantType_int16: return static_cast<int32_t>(m_int16);
  326. case AkVariantType_int32: return m_int32;
  327. case AkVariantType_uint8: return static_cast<int32_t>(m_uint8);
  328. case AkVariantType_uint16: return static_cast<int32_t>(m_uint16);
  329. default: break;
  330. }
  331. AKASSERT(false && "AkVariantBase: illegal typecast");
  332. return 0;
  333. }
  334. inline operator uint32_t() const
  335. {
  336. switch (m_eType)
  337. {
  338. case AkVariantType_int8: return static_cast<uint32_t>(m_int8);
  339. case AkVariantType_int16: return static_cast<uint32_t>(m_int16);
  340. case AkVariantType_int32: return static_cast<uint32_t>(m_int32);
  341. case AkVariantType_uint8: return static_cast<uint32_t>(m_uint8);
  342. case AkVariantType_uint16: return static_cast<uint32_t>(m_uint16);
  343. case AkVariantType_uint32: return m_uint32;
  344. default: break;
  345. }
  346. AKASSERT(false && "AkVariantBase: illegal typecast");
  347. return 0;
  348. }
  349. inline operator uint64_t() const
  350. {
  351. switch (m_eType)
  352. {
  353. case AkVariantType_int8: return static_cast<uint64_t>(m_int8);
  354. case AkVariantType_int16: return static_cast<uint64_t>(m_int16);
  355. case AkVariantType_int32: return static_cast<uint64_t>(m_int32);
  356. case AkVariantType_int64: return static_cast<uint64_t>(m_int64);
  357. case AkVariantType_uint8: return static_cast<uint64_t>(m_uint8);
  358. case AkVariantType_uint16: return static_cast<uint64_t>(m_uint16);
  359. case AkVariantType_uint32: return static_cast<uint64_t>(m_uint32);
  360. case AkVariantType_uint64: return m_uint64;
  361. default: break;
  362. }
  363. AKASSERT(false && "AkVariantBase: illegal typecast");
  364. return 0;
  365. }
  366. inline operator double() const
  367. {
  368. switch (m_eType)
  369. {
  370. case AkVariantType_int8: return static_cast<double>(m_int8);
  371. case AkVariantType_int16: return static_cast<double>(m_int16);
  372. case AkVariantType_int32: return static_cast<double>(m_int32);
  373. case AkVariantType_int64: return static_cast<double>(m_int64);
  374. case AkVariantType_uint8: return static_cast<double>(m_uint8);
  375. case AkVariantType_uint16: return static_cast<double>(m_uint16);
  376. case AkVariantType_uint32: return static_cast<double>(m_uint32);
  377. case AkVariantType_uint64: return static_cast<double>(m_uint64);
  378. case AkVariantType_real32: return static_cast<double>(m_real32);
  379. case AkVariantType_real64: return m_real64;
  380. default: break;
  381. }
  382. AKASSERT(false && "AkVariantBase: illegal typecast");
  383. return 0;
  384. }
  385. inline operator AkGuid() const
  386. {
  387. if (m_eType == AkVariantType_guid)
  388. return *static_cast<const AkGuid*>(m_data);
  389. AKASSERT(false && "AkVariantBase: illegal typecast");
  390. return AkGuid();
  391. }
  392. inline operator std::wstring() const
  393. {
  394. if(m_eType == AkVariantType_wstring )
  395. return *static_cast<const std::wstring*>(m_data);
  396. AKASSERT(false && "AkVariantBase: illegal typecast");
  397. return std::wstring();
  398. }
  399. inline operator std::string() const
  400. {
  401. if (m_eType == AkVariantType_string)
  402. return *static_cast<const std::string*>(m_data);
  403. AKASSERT(false && "AkVariantBase: illegal typecast");
  404. return std::string();
  405. }
  406. // Helpers ----------------------------------------------------------------------------
  407. inline bool IsNumber() const
  408. {
  409. return (m_eType >= AkVariantType_int8 && m_eType <= AkVariantType_int64)
  410. || (m_eType >= AkVariantType_uint8 && m_eType <= AkVariantType_uint64)
  411. || (m_eType >= AkVariantType_real32 && m_eType <= AkVariantType_real64);
  412. }
  413. inline bool IsEmpty() const
  414. {
  415. return (m_eType == AkVariantType_none);
  416. }
  417. inline bool IsBool() const
  418. {
  419. return (m_eType == AkVariantType_bool);
  420. }
  421. private:
  422. static inline uint8_t CharToUInt(char c)
  423. {
  424. if (c >= '0' && c <= '9')
  425. return (uint8_t)(c - '0');
  426. else if (c >= 'a' && c <= 'f')
  427. return (uint8_t)(c - 'a') + 10;
  428. else if (c >= 'A' && c <= 'F')
  429. return (uint8_t)(c - 'A') + 10;
  430. else
  431. return (uint8_t)-1;
  432. }
  433. static inline char UIntToChar(uint8_t by)
  434. {
  435. if (by < 0xa)
  436. return '0' + by;
  437. else
  438. return 'A' + (by - 10);
  439. }
  440. public:
  441. static bool StrToAkGuid(const std::string& in_str, AkGuid& out_guid)
  442. {
  443. const char* psz = in_str.c_str();
  444. const size_t len = strlen(psz);
  445. // GUID must have format: 01234567-ABCD-0123-abcd-01234567ABCD, with MANDATORY brackets around
  446. if (len != k_iExampleGuidLen)
  447. return false;
  448. const bool brackets = psz[0] == '{' && psz[len - 1] == '}';
  449. if (!brackets)
  450. return false;
  451. psz += 1;
  452. // Note: we must convert the string into this struct
  453. // uint32_t data1;
  454. // uint16_t data2;
  455. // uint16_t data3;
  456. // uint8_t data4[8];
  457. // We only support little endian for now!
  458. uint8_t* pby = (uint8_t*)&out_guid;
  459. // Convert into uint32
  460. for (int i = 0; i < 4; i++) // 01234567
  461. {
  462. uint8_t u1 = CharToUInt(*psz++);
  463. uint8_t u2 = CharToUInt(*psz++);
  464. if (u1 == (uint8_t)-1 || u2 == (uint8_t)-1)
  465. return false;
  466. pby[3 - i] = (u1 << 4) | u2; // store backward as little endian
  467. }
  468. if (*psz != '-')
  469. return false;
  470. ++psz; // -
  471. pby += 4;
  472. // Convert into uint16
  473. for (int i = 0; i < 2; i++) // ABCD
  474. {
  475. uint8_t u1 = CharToUInt(*psz++);
  476. uint8_t u2 = CharToUInt(*psz++);
  477. if (u1 == (uint8_t)-1 || u2 == (uint8_t)-1)
  478. return false;
  479. pby[1 - i] = (u1 << 4) | u2;
  480. }
  481. if (*psz != '-')
  482. return false;
  483. ++psz; // -
  484. pby += 2;
  485. // Convert into uint16
  486. for (int i = 0; i < 2; i++) // 0123
  487. {
  488. uint8_t u1 = CharToUInt(*psz++);
  489. uint8_t u2 = CharToUInt(*psz++);
  490. if (u1 == (uint8_t)-1 || u2 == (uint8_t)-1)
  491. return false;
  492. pby[1 - i] = (u1 << 4) | u2;
  493. }
  494. if (*psz != '-')
  495. return false;
  496. ++psz; // -
  497. pby += 2;
  498. // Convert into uint8[2]
  499. for (int i = 0; i < 2; i++) // abcd
  500. {
  501. uint8_t u1 = CharToUInt(*psz++);
  502. uint8_t u2 = CharToUInt(*psz++);
  503. if (u1 == (uint8_t)-1 || u2 == (uint8_t)-1)
  504. return false;
  505. *pby++ = (u1 << 4) | u2;
  506. }
  507. if (*psz != '-')
  508. return false;
  509. ++psz; // -
  510. // Convert into uint8[6]
  511. for (int i = 0; i < 6; i++) // 01234567ABCD
  512. {
  513. uint8_t u1 = CharToUInt(*psz++);
  514. uint8_t u2 = CharToUInt(*psz++);
  515. if (u1 == (uint8_t)-1 || u2 == (uint8_t)-1)
  516. return false;
  517. *pby++ = (u1 << 4) | u2;
  518. }
  519. return true;
  520. }
  521. static void AkGuidToStr(const AkGuid& in_guid, std::string& out_str)
  522. {
  523. uint8_t* pby = (uint8_t*)&in_guid;
  524. if (out_str.size() < (k_iExampleGuidLen))
  525. out_str.resize(k_iExampleGuidLen);
  526. char* psz = (char*)&out_str[0];
  527. *psz++ = '{';
  528. // Note: we must convert the string into this struct
  529. // uint32_t data1;
  530. // uint16_t data2;
  531. // uint16_t data3;
  532. // uint8_t data4[8];
  533. // We only support little endian for now!
  534. // Convert uint32
  535. for (int i = 0; i < 4; ++i)
  536. {
  537. *psz++ = UIntToChar(pby[3 - i] >> 4);
  538. *psz++ = UIntToChar(pby[3 - i] & 0xf);
  539. }
  540. pby += 4;
  541. *psz++ = '-';
  542. // Convert uint16
  543. for (int i = 0; i < 2; ++i)
  544. {
  545. *psz++ = UIntToChar(pby[1 - i] >> 4);
  546. *psz++ = UIntToChar(pby[1 - i] & 0xf);
  547. }
  548. pby += 2;
  549. *psz++ = '-';
  550. // Convert uint16
  551. for (int i = 0; i < 2; ++i)
  552. {
  553. *psz++ = UIntToChar(pby[1 - i] >> 4);
  554. *psz++ = UIntToChar(pby[1 - i] & 0xf);
  555. }
  556. pby += 2;
  557. *psz++ = '-';
  558. // Convert uint8[2]
  559. for (int i = 0; i < 2; ++i)
  560. {
  561. *psz++ = UIntToChar(pby[i] >> 4);
  562. *psz++ = UIntToChar(pby[i] & 0xf);
  563. }
  564. pby += 2;
  565. *psz++ = '-';
  566. // Convert uint8[6]
  567. for (int i = 0; i < 6; ++i)
  568. {
  569. *psz++ = UIntToChar(pby[i] >> 4);
  570. *psz++ = UIntToChar(pby[i] & 0xf);
  571. }
  572. *psz++ = '}';
  573. }
  574. private:
  575. void Clear()
  576. {
  577. switch (m_eType)
  578. {
  579. case AkVariantType_string:
  580. delete static_cast<std::string*>(m_data);
  581. break;
  582. case AkVariantType_wstring:
  583. delete static_cast<std::wstring*>(m_data);
  584. break;
  585. case AkVariantType_guid:
  586. delete static_cast<AkGuid*>(m_data);
  587. break;
  588. }
  589. }
  590. void CopyFrom(const AkVariantBase& in_var)
  591. {
  592. m_eType = in_var.m_eType;
  593. switch (in_var.m_eType)
  594. {
  595. case AkVariantType_uint8:
  596. m_uint8 = in_var.m_uint8;
  597. break;
  598. case AkVariantType_uint16:
  599. m_uint16 = in_var.m_uint16;
  600. break;
  601. case AkVariantType_uint32:
  602. m_uint32 = in_var.m_uint32;
  603. break;
  604. case AkVariantType_uint64:
  605. m_uint64 = in_var.m_uint64;
  606. break;
  607. case AkVariantType_int8:
  608. m_int8 = in_var.m_int8;
  609. break;
  610. case AkVariantType_int16:
  611. m_int16 = in_var.m_int16;
  612. break;
  613. case AkVariantType_int32:
  614. m_int32 = in_var.m_int32;
  615. break;
  616. case AkVariantType_int64:
  617. m_int64 = in_var.m_int64;
  618. break;
  619. case AkVariantType_real32:
  620. m_real32 = in_var.m_real32;
  621. break;
  622. case AkVariantType_real64:
  623. m_real64 = in_var.m_real64;
  624. break;
  625. case AkVariantType_bool:
  626. m_boolean = in_var.m_boolean;
  627. break;
  628. case AkVariantType_string:
  629. m_data = new std::string(*static_cast<const std::string*>(in_var.m_data));
  630. break;
  631. case AkVariantType_wstring:
  632. m_data = new std::wstring(*static_cast<const std::wstring*>(in_var.m_data));
  633. break;
  634. case AkVariantType_guid:
  635. m_data = new AkGuid();
  636. memcpy(m_data, in_var.m_data, sizeof(AkGuid));
  637. break;
  638. default:
  639. break;
  640. }
  641. }
  642. public:
  643. int GetType() const
  644. {
  645. return m_eType;
  646. }
  647. bool GetBoolean() const
  648. {
  649. AKASSERT(m_eType == AkVariantType_bool && "AkVariant: illegal typecast");
  650. return m_boolean;
  651. }
  652. int8_t GetInt8() const
  653. {
  654. AKASSERT(m_eType == AkVariantType_int8 && "AkVariant: illegal typecast");
  655. return m_int8;
  656. }
  657. int16_t GetInt16() const
  658. {
  659. AKASSERT(m_eType == AkVariantType_int16 && "AkVariant: illegal typecast");
  660. return m_int16;
  661. }
  662. int32_t GetInt32() const
  663. {
  664. AKASSERT(m_eType == AkVariantType_int32 && "AkVariant: illegal typecast");
  665. return m_int32;
  666. }
  667. int64_t GetInt64() const
  668. {
  669. AKASSERT(m_eType == AkVariantType_int64 && "AkVariant: illegal typecast");
  670. return m_int64;
  671. }
  672. uint8_t GetUInt8() const
  673. {
  674. AKASSERT(m_eType == AkVariantType_uint8 && "AkVariant: illegal typecast");
  675. return m_uint8;
  676. }
  677. uint16_t GetUInt16() const
  678. {
  679. AKASSERT(m_eType == AkVariantType_uint16 && "AkVariant: illegal typecast");
  680. return m_uint16;
  681. }
  682. uint32_t GetUInt32() const
  683. {
  684. AKASSERT(m_eType == AkVariantType_uint32 && "AkVariant: illegal typecast");
  685. return m_uint32;
  686. }
  687. uint64_t GetUInt64() const
  688. {
  689. AKASSERT(m_eType == AkVariantType_uint64 && "AkVariant: illegal typecast");
  690. return m_uint64;
  691. }
  692. float GetReal32() const
  693. {
  694. AKASSERT(m_eType == AkVariantType_real32 && "AkVariant: illegal typecast");
  695. return m_real32;
  696. }
  697. double GetReal64() const
  698. {
  699. AKASSERT(m_eType == AkVariantType_real64 && "AkVariant: illegal typecast");
  700. return m_real64;
  701. }
  702. // Implicit interface supporting conversion to rapidjson. Does not require rapidjson dependencies
  703. // if the function is not called.
  704. template<typename RapidJsonValueType, typename RapidJsonAllocator, typename RapidJsonSizeType>
  705. bool toRapidJsonValue(RapidJsonValueType out_rapidJson, RapidJsonAllocator in_allocator) const
  706. {
  707. switch (m_eType)
  708. {
  709. case AkVariantType_none: out_rapidJson.SetNull(); break;
  710. case AkVariantType_bool: out_rapidJson.SetBool(m_boolean); break;
  711. case AkVariantType_int8: out_rapidJson.SetInt(m_int8); break;
  712. case AkVariantType_int16: out_rapidJson.SetInt(m_int16); break;
  713. case AkVariantType_int32: out_rapidJson.SetInt(m_int32); break;
  714. case AkVariantType_int64: out_rapidJson.SetInt64(m_int64); break;
  715. case AkVariantType_uint8: out_rapidJson.SetUint(m_uint8); break;
  716. case AkVariantType_uint16: out_rapidJson.SetUint(m_uint16); break;
  717. case AkVariantType_uint32: out_rapidJson.SetUint(m_uint32); break;
  718. case AkVariantType_uint64: out_rapidJson.SetUint64(m_uint64); break;
  719. case AkVariantType_real32: out_rapidJson.SetDouble(m_real32); break;
  720. case AkVariantType_real64: out_rapidJson.SetDouble(m_real64); break;
  721. case AkVariantType_guid:
  722. {
  723. std::string str;
  724. AkVariantBase::AkGuidToStr(*static_cast<const AkGuid*>(m_data), str);
  725. out_rapidJson.SetString(str.c_str(), static_cast<RapidJsonSizeType>(str.length()), in_allocator);
  726. }
  727. break;
  728. default:
  729. return false;
  730. }
  731. return true;
  732. }
  733. protected:
  734. int m_eType;
  735. union
  736. {
  737. uint8_t m_uint8;
  738. uint16_t m_uint16;
  739. uint32_t m_uint32;
  740. uint64_t m_uint64;
  741. int8_t m_int8;
  742. int16_t m_int16;
  743. int32_t m_int32;
  744. int64_t m_int64;
  745. float m_real32;
  746. double m_real64;
  747. bool m_boolean;
  748. void* m_data;
  749. };
  750. };
  751. }
  752. }