Table of Contents

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