Version
menu_open
Wwise SDK 2023.1.4
AkString.h
Go to the documentation of this file.
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 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 #pragma once
27 
30 
31 template<typename TAlloc, typename T_CHAR>
32 class AkStringData : public TAlloc
33 {
34 public:
35  AkStringData() : pStr(NULL), bOwner(false) {}
36  AkStringData(const T_CHAR* in_pStr) : pStr(in_pStr), bOwner(false) {}
38 
39  void Term()
40  {
41  if (pStr && bOwner)
42  {
43  TAlloc::Free((void*)pStr);
44  bOwner = false;
45  }
46  pStr = nullptr;
47  }
48 
50  {
51  if (!bOwner)
52  pStr = nullptr;
53  }
54 
55 protected:
56  const T_CHAR* pStr;
57  bool bOwner;
58 };
59 
60 template<typename TAlloc, typename T_CHAR>
61 class AkStringImpl : public AkStringData<TAlloc, T_CHAR>
62 {};
63 
64 template<typename TAlloc, typename T_CHAR>
65 class AkString: public AkStringImpl<TAlloc, T_CHAR>
66 {
67 private:
70 
71 public:
72  AkString() : AkStringImpl<TAlloc, T_CHAR>() {}
73 
74  template<typename T_CHAR2>
75  AkString(const T_CHAR2* in_pStr) { tImpl::Set(in_pStr); }
76 
77  AkString(const AkString<TAlloc, T_CHAR>& in_other) { tImpl::Set(in_other.Get()); TAlloc::operator=(in_other); }
78 
79  template<typename TAlloc2, typename T_CHAR2>
80  AkString(const AkString<TAlloc2, T_CHAR2>& in_other) { tImpl::Set(in_other.Get()); TAlloc::operator=(in_other); } // if this does not compile it means that both allocation policies are not compatible.
81 
82  // The default assignment behavior is to not create a local copy, unless it is necessary (due to incompatible string types).
83  // Call AllocCopy() if you want to ensure there is a local copy owned by this AkString.
85  {
86  if (tData::pStr && !tData::bOwner)
87  {
88  const T_CHAR* pRefStr = tData::pStr;
89  AkUInt32 uLen = tImpl::Length();
90  if (uLen > 0)
91  {
92  tData::pStr = (T_CHAR*)TAlloc::Alloc((uLen + 1) * sizeof(T_CHAR));
93  if (tData::pStr == NULL)
94  return AK_InsufficientMemory;
95 
96  AKPLATFORM::AkMemCpy((void*)tData::pStr, (void*)pRefStr, ((uLen + 1) * sizeof(T_CHAR)));
97  tData::bOwner = true;
98  }
99  else
100  {
101  tData::pStr = NULL;
102  }
103  }
104  return AK_Success;
105  }
106 
107  // Transfer memory ownership from in_from to this AkString.
109  {
110  tData::Term();
111 
112  TAlloc::TransferMem((void*&) tData::pStr, in_from, (void*)in_from.tData::pStr);
113  in_from.tData::pStr = nullptr;
114 
115  tData::bOwner = in_from.tData::bOwner;
116  in_from.tData::bOwner = false;
117  }
118 
119  const T_CHAR* Get() const
120  {
121  return tData::pStr;
122  }
123 
125  {
126  tImpl::Set(in_rhs.Get());
127  TAlloc::operator=(in_rhs);
128  return *this;
129  }
130 
131  template<typename TAlloc2, typename T_CHAR2>
133  {
134  tImpl::Set(in_rhs.Get());
135  TAlloc::operator=(in_rhs); // if this does not compile it means that both allocation policies are not compatible.
136  return *this;
137  }
138 
139  template<typename T_CHAR2>
140  AkString& operator=(const T_CHAR2* in_pStr)
141  {
142  tImpl::Set(in_pStr);
143  return *this;
144  }
145 };
146 
147 #ifdef AK_SUPPORT_WCHAR
148 template<typename TAlloc>
149 class AkStringImpl <TAlloc, wchar_t> : public AkStringData<TAlloc, wchar_t>
150 {
151 private:
152  typedef AkStringData<TAlloc, wchar_t> tData;
153 
154 public:
155  AkStringImpl() : AkStringData<TAlloc, wchar_t>() {}
156 
157 protected:
158  AKRESULT Set(const char* in_pStr)
159  {
160  tData::Term();
161 
162  if (in_pStr != NULL)
163  {
164  size_t uLen = strlen(in_pStr);
165  if (uLen > 0)
166  {
167  tData::pStr = (wchar_t*)TAlloc::Alloc((uLen + 1) * sizeof(wchar_t));
168  if (tData::pStr == NULL)
169  return AK_InsufficientMemory;
170 
171  AKPLATFORM::AkCharToWideChar(in_pStr, (AkUInt32)(uLen + 1), const_cast<wchar_t*>(tData::pStr));
172  tData::bOwner = true;
173  }
174  else
175  {
176  tData::pStr = NULL;
177  }
178  }
179 
180  return AK_Success;
181  }
182 
183  AKRESULT Set(const wchar_t* in_pStr)
184  {
185  tData::Term();
186  tData::pStr = in_pStr;
187  return AK_Success;
188  }
189 
190 public:
191  AkUInt32 Length() const
192  {
193  if (tData::pStr == nullptr)
194  return 0;
195 
196  return (AkUInt32)wcslen(tData::pStr);
197  }
198 };
199 #endif
200 
201 template<typename TAlloc>
202 class AkStringImpl <TAlloc, char> : public AkStringData<TAlloc, char>
203 {
204 private:
206 
207 public:
208  AkStringImpl() : AkStringData<TAlloc, char>() {}
209 
210 protected:
211  AKRESULT Set(const wchar_t* in_pStr)
212  {
213  tData::Term();
214 
215  if (in_pStr != NULL)
216  {
217  size_t uLen = wcslen(in_pStr);
218  if (uLen > 0)
219  {
220  tData::pStr = (char*)TAlloc::Alloc((uLen + 1) * sizeof(char));
221  if (tData::pStr == NULL)
222  return AK_InsufficientMemory;
223 
224  AKPLATFORM::AkWideCharToChar(in_pStr, (AkUInt32)(uLen + 1), const_cast<char*>(tData::pStr));
225  tData::bOwner = true;
226  }
227  else
228  {
229  tData::pStr = NULL;
230  }
231  }
232 
233  return AK_Success;
234  }
235 
236  AKRESULT Set(const char* in_pStr)
237  {
238  tData::Term();
239  tData::pStr = in_pStr;
240  return AK_Success;
241  }
242 
243 public:
244  AkUInt32 Length() const
245  {
246  if (tData::pStr == nullptr)
247  return 0;
248 
249  return (AkUInt32)strlen(tData::pStr);
250  }
251 };
252 
254 {
255  AkForceInline void Lock() {}
257 };
258 
259 template<typename TAlloc, typename T_CHAR>
261 {
262  AkUInt32 uLen = in_str.Length();
263  if (uLen > 0)
264  {
265  AK::FNVHash32 hash;
266  return hash.Compute(in_str.Get(), uLen * sizeof(T_CHAR));
267  }
268  return 0;
269 }
270 
271 //
272 // AkDbString - A string reference class that stores a hash to a string in a database. If an identical string is found, the reference count in the database is incremented,
273 // so that we do not store duplicate strings. Database can be made multi thread safe by passing in CAkLock for tLock, or AkNonThreaded if concurrent access is not needed.
274 //
275 template<typename TAlloc, typename T_CHAR, typename tLock = AkNonThreaded>
276 class AkDbString : public TAlloc
277 {
278 public:
281 
282  struct Entry
283  {
284  Entry() : refCount(0) {}
285 
288  };
289 
291 
292  struct Instance : public TAlloc
293  {
295  tLock lock;
296  };
297 
298 public:
299 
300  // Must be called to initialize the database.
301  static AKRESULT InitDB()
302  {
303  if (pInstance == NULL)
304  {
305  pInstance = (Instance*)pInstance->TAlloc::Alloc(sizeof(Instance));
306  AkPlacementNew(pInstance) Instance();
307  return AK_Success;
308  }
309  else
310  return AK_Fail;
311  }
312 
313  // Term the DB.
314  static void TermDB()
315  {
316  if (pInstance != NULL)
317  {
318  pInstance->~Instance();
319  pInstance->TAlloc::Free(pInstance);
320  pInstance = NULL;
321  }
322  }
323 
324  static void UnlockDB() { pInstance->lock.Unlock();}
325  static void LockDB() { pInstance->lock.Lock(); }
326 
327 private:
328 
329  static Instance* pInstance;
330 
331 public:
333  {}
334 
335  AkDbString(const tThis& in_fromDbStr) : m_uHash(0) { Aquire(in_fromDbStr.m_uHash); }
336 
337  // Construct from AkString
338  template<typename TAlloc2, typename T_CHAR2>
339  AkDbString(const AkString<TAlloc2, T_CHAR2>& in_fromStr) : m_uHash(0) { Aquire(in_fromStr); }
340 
341  tThis& operator=(const tThis& in_rhs)
342  {
343  Aquire(in_rhs.m_uHash);
344  return *this;
345  }
346 
347  // Assign from AkString
348  template<typename TAlloc2, typename T_CHAR2>
350  {
351  Aquire(in_rhs);
352  return *this;
353  }
354 
355  // Assign from char string
356  template<typename T_CHAR2>
357  tThis& operator=(const T_CHAR2* in_rhs)
358  {
359  const AkString<TAlloc, T_CHAR2>& convert = in_rhs;
360  Aquire(convert);
361  return *this;
362  }
363 
365  {
366  Release();
367  }
368 
369  const T_CHAR* Get() const
370  {
371  if (m_uHash != 0)
372  {
373  Entry* pEntry = pInstance->table.Exists(m_uHash);
374  AKASSERT(pEntry != NULL);
375  return pEntry->str.Get();
376  }
377  return NULL;
378  }
379 
380 protected:
381 
382  template<typename TAlloc2, typename T_CHAR2>
384  {
385  AKRESULT res = AK_Success;
386 
387  Release();
388 
389  if (in_str.Get() != NULL)
390  {
391  m_uHash = AkHash(in_str);
392 
393  LockDB();
394  {
395  Entry* pEntry = pInstance->table.Set(m_uHash);
396  if (pEntry != NULL)
397  {
398  pEntry->refCount++;
399 
400  if (pEntry->str.Get() == NULL)
401  {
402  pEntry->str = in_str;
403  pEntry->str.AllocCopy();
404 
405  if (pEntry->str.Get() == NULL) // Allocation failure
406  {
407  pInstance->table.Unset(m_uHash);
408  m_uHash = 0;
409  res = AK_Fail;
410  }
411  }
412  }
413  else
414  {
415  m_uHash = 0;
416  res = AK_Fail;
417  }
418  }
419  UnlockDB();
420  }
421 
422  return res;
423  }
424 
425  // in_uHash must have come from another AkDbString, and therefore already exist in the DB.
427  {
428  AKRESULT res = AK_Success;
429 
430  Release();
431 
432  if (in_uHash != 0)
433  {
434  m_uHash = in_uHash;
435  LockDB();
436  {
437  Entry* pEntry = pInstance->table.Exists(m_uHash);
438  AKASSERT(pEntry != NULL);
439 
440  pEntry->refCount++;
441  AKASSERT(pEntry->str.Get() != NULL);
442  }
443  UnlockDB();
444  }
445 
446  return res;
447  }
448 
449  void Release()
450  {
451  if (m_uHash != 0)
452  {
453  LockDB();
454  {
455  tStringTable& table = pInstance->table;
456  typename tStringTable::IteratorEx it = table.FindEx(m_uHash);
457  AKASSERT(it != table.End());//<- Check that DbString was properly constructed.
458  Entry& entry = (*it).item;
459  AKASSERT(entry.refCount > 0);
460 
461  entry.refCount--;
462  if (entry.refCount == 0)
463  {
464  table.Erase(it);
465  }
466  }
467  UnlockDB();
468 
469  m_uHash = 0;
470  }
471  }
472 
474 
475 };
476 
477 template<typename TAlloc, typename T_CHAR, typename tLock>
~AkStringData()
Definition: AkString.h:37
Definition: AkString.h:283
@ AK_Fail
The operation failed.
Definition: AkTypes.h:134
AkString & operator=(const AkString< TAlloc, T_CHAR > &in_rhs)
Definition: AkString.h:124
tThis & operator=(const AkString< TAlloc2, T_CHAR2 > &in_rhs)
Definition: AkString.h:349
Iterator End()
Definition: AkHashList.h:279
tString str
Definition: AkString.h:286
AKRESULT Set(const char *in_pStr)
Definition: AkString.h:236
const T_CHAR * Get() const
Definition: AkString.h:369
void Transfer(AkString< TAlloc, T_CHAR > &in_from)
Definition: AkString.h:108
AkStringData(const T_CHAR *in_pStr)
Definition: AkString.h:36
AKSOUNDENGINE_API void Free(AkMemPoolId in_poolId, void *in_pMemAddress)
AkInt32 refCount
Definition: AkString.h:287
tStringTable table
Definition: AkString.h:294
AkDbString()
Definition: AkString.h:332
AKRESULT
Standard function call result.
Definition: AkTypes.h:131
AkString(const T_CHAR2 *in_pStr)
Definition: AkString.h:75
AKRESULT Aquire(const AkString< TAlloc2, T_CHAR2 > &in_str)
Definition: AkString.h:383
AkString< TAlloc, T_CHAR > tString
Definition: AkString.h:280
AkHashList< AkUInt32, Entry, TAlloc > tStringTable
Definition: AkString.h:290
AkString & operator=(const T_CHAR2 *in_pStr)
Definition: AkString.h:140
IteratorEx Erase(const IteratorEx &in_rIter)
Definition: AkHashList.h:494
#define NULL
Definition: AkTypes.h:46
@ AK_Success
The operation was successful.
Definition: AkTypes.h:133
int32_t AkInt32
Signed 32-bit integer.
AkUInt32 Length() const
Definition: AkString.h:244
AkUInt32 m_uHash
Definition: AkString.h:473
AKSOUNDENGINE_API void Term()
AkStringData()
Definition: AkString.h:35
#define AkPlacementNew(_memory)
Definition: AkObject.h:49
static AkForceInline AkUInt32 AkHash(const AkString< TAlloc, T_CHAR > &in_str)
Definition: AkString.h:260
#define AKASSERT(Condition)
Definition: AkAssert.h:67
AkForceInline void Unlock()
Definition: AkString.h:256
AkForceInline void AkMemCpy(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper for memcpy/memmove/memset.
static void UnlockDB()
Definition: AkString.h:324
AkDbString< TAlloc, T_CHAR, tLock > tThis
Definition: AkString.h:279
const T_CHAR * Get() const
Definition: AkString.h:119
AkString(const AkString< TAlloc, T_CHAR > &in_other)
Definition: AkString.h:77
void ClearReference()
Definition: AkString.h:49
void Release()
Definition: AkString.h:449
~AkDbString()
Definition: AkString.h:364
static void TermDB()
Definition: AkString.h:314
static void LockDB()
Definition: AkString.h:325
AkForceInline void Lock()
Definition: AkString.h:255
AKRESULT Aquire(AkUInt32 in_uHash)
Definition: AkString.h:426
AKRESULT Set(const wchar_t *in_pStr)
Definition: AkString.h:211
IteratorEx FindEx(T_KEY in_Key)
Definition: AkHashList.h:307
AkString & operator=(const AkString< TAlloc2, T_CHAR2 > &in_rhs)
Definition: AkString.h:132
AkForceInline AkInt32 AkCharToWideChar(const char *in_pszAnsiString, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
AKRESULT AllocCopy()
Definition: AkString.h:84
tThis & operator=(const tThis &in_rhs)
Definition: AkString.h:341
uint32_t AkUInt32
Unsigned 32-bit integer.
Entry()
Definition: AkString.h:284
HashParams::HashType Compute(const void *in_pData, typename HashParams::SizeType in_dataSize)
Definition: AkFNVHash.h:105
@ AK_InsufficientMemory
Memory error.
Definition: AkTypes.h:161
AkForceInline AkInt32 AkWideCharToChar(const wchar_t *in_pszUnicodeString, AkUInt32 in_uiOutBufferSize, char *io_pszAnsiString)
String conversion helper.
bool bOwner
Definition: AkString.h:57
void Term()
Definition: AkString.h:39
AkDbString(const AkString< TAlloc2, T_CHAR2 > &in_fromStr)
Definition: AkString.h:339
AkDbString(const tThis &in_fromDbStr)
Definition: AkString.h:335
#define AkForceInline
Definition: AkTypes.h:63
AkString()
Definition: AkString.h:72
static AKRESULT InitDB()
Definition: AkString.h:301
AkString(const AkString< TAlloc2, T_CHAR2 > &in_other)
Definition: AkString.h:80
tThis & operator=(const T_CHAR2 *in_rhs)
Definition: AkString.h:357
const T_CHAR * pStr
Definition: AkString.h:56

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise