AkPlatformFuncs.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  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 <AK/Tools/Common/AkAssert.h>
  22. #include <AK/SoundEngine/Common/AkTypes.h>
  23. #include <stdarg.h>
  24. #include <string.h>
  25. #include <wchar.h>
  26. #include <unistd.h>
  27. #include <sys/mman.h>
  28. #ifndef AK_QNX
  29. #include <sys/syscall.h>
  30. #endif
  31. #include <stdlib.h>
  32. #if defined(AK_SUPPORT_THREADS)
  33. #include <pthread.h>
  34. #endif
  35. #define AK_POSIX_NO_ERR 0
  36. #define AK_POSIX
  37. //-----------------------------------------------------------------------------
  38. // Platform-specific thread properties definition.
  39. //-----------------------------------------------------------------------------
  40. struct AkThreadProperties
  41. {
  42. int nPriority; ///< Thread priority
  43. size_t uStackSize; ///< Thread stack size
  44. int uSchedPolicy; ///< Thread scheduling policy
  45. AkUInt32 dwAffinityMask; ///< Affinity mask
  46. };
  47. //-----------------------------------------------------------------------------
  48. // External variables.
  49. //-----------------------------------------------------------------------------
  50. // g_fFreqRatio is used by time helpers to return time values in milliseconds.
  51. // It is declared and updated by the sound engine.
  52. namespace AK
  53. {
  54. extern AkReal32 g_fFreqRatio;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Defines for POSIX (Mac, iOS, Android)
  58. //-----------------------------------------------------------------------------
  59. #define AK_DECLARE_THREAD_ROUTINE( FuncName ) void* FuncName(void* lpParameter)
  60. #define AK_THREAD_RETURN( _param_ ) return (_param_);
  61. #define AK_THREAD_ROUTINE_PARAMETER lpParameter
  62. #define AK_GET_THREAD_ROUTINE_PARAMETER_PTR(type) reinterpret_cast<type*>( AK_THREAD_ROUTINE_PARAMETER )
  63. #define AK_RETURN_THREAD_OK 0x00000000
  64. #define AK_RETURN_THREAD_ERROR 0x00000001
  65. #define AK_DEFAULT_STACK_SIZE (128*1024)
  66. #if defined(AK_SUPPORT_THREADS)
  67. #define AK_THREAD_DEFAULT_SCHED_POLICY SCHED_FIFO
  68. #define AK_THREAD_PRIORITY_NORMAL (((sched_get_priority_max( SCHED_FIFO ) - sched_get_priority_min( SCHED_FIFO )) / 2) + sched_get_priority_min( SCHED_FIFO ))
  69. #define AK_THREAD_PRIORITY_ABOVE_NORMAL sched_get_priority_max( SCHED_FIFO )
  70. #define AK_THREAD_PRIORITY_BELOW_NORMAL sched_get_priority_min( SCHED_FIFO )
  71. #else
  72. #define AK_THREAD_DEFAULT_SCHED_POLICY 1
  73. #define AK_THREAD_PRIORITY_NORMAL 50
  74. #define AK_THREAD_PRIORITY_ABOVE_NORMAL 99
  75. #define AK_THREAD_PRIORITY_BELOW_NORMAL 1
  76. #endif
  77. #define AK_THREAD_AFFINITY_DEFAULT 0xFFFF
  78. // NULL objects
  79. #define AK_NULL_THREAD 0
  80. #define AK_INFINITE (AK_UINT_MAX)
  81. #define AkMax(x1, x2) (((x1) > (x2))? (x1): (x2))
  82. #define AkMin(x1, x2) (((x1) < (x2))? (x1): (x2))
  83. #define AkClamp(x, min, max) ((x) < (min)) ? (min) : (((x) > (max) ? (max) : (x)))
  84. #pragma GCC visibility push(hidden)
  85. namespace AKPLATFORM
  86. {
  87. #define AkExitThread( _result ) return _result;
  88. // Simple automatic event API
  89. // ------------------------------------------------------------------
  90. #ifndef AK_APPLE
  91. /// Platform Independent Helper
  92. inline void AkClearEvent( AkEvent & out_event )
  93. {
  94. memset(&out_event,0,sizeof(AkEvent));
  95. }
  96. /// Platform Independent Helper
  97. inline AKRESULT AkCreateEvent( AkEvent & out_event )
  98. {
  99. int ret = sem_init(
  100. &out_event,
  101. 0,
  102. 0 );
  103. return ( ret == AK_POSIX_NO_ERR ) ? AK_Success : AK_Fail;
  104. }
  105. /// Platform Independent Helper
  106. inline void AkDestroyEvent( AkEvent & io_event )
  107. {
  108. AKVERIFY( sem_destroy( &io_event ) == AK_POSIX_NO_ERR);
  109. AkClearEvent(io_event);
  110. }
  111. /// Platform Independent Helper
  112. inline void AkWaitForEvent( AkEvent & in_event )
  113. {
  114. AKVERIFY( sem_wait( &in_event ) == AK_POSIX_NO_ERR );
  115. }
  116. /// Platform Independent Helper
  117. inline void AkSignalEvent( AkEvent & in_event )
  118. {
  119. AKVERIFY( sem_post( &in_event ) == AK_POSIX_NO_ERR );
  120. }
  121. /// Platform Independent Helper
  122. AkForceInline void AkClearSemaphore(AkSemaphore& io_semaphore)
  123. {
  124. memset(&io_semaphore, 0, sizeof(AkSemaphore));
  125. }
  126. /// Platform Independent Helper
  127. inline AKRESULT AkCreateSemaphore( AkSemaphore& out_semaphore, AkUInt32 in_initialCount )
  128. {
  129. int ret = sem_init(
  130. &out_semaphore,
  131. 0,
  132. in_initialCount );
  133. return ( ret == AK_POSIX_NO_ERR ) ? AK_Success : AK_Fail;
  134. }
  135. /// Platform Independent Helper
  136. inline void AkDestroySemaphore(AkSemaphore& io_semaphore)
  137. {
  138. AKVERIFY(sem_destroy(&io_semaphore) == AK_POSIX_NO_ERR);
  139. memset(&io_semaphore, 0, sizeof(AkSemaphore));
  140. }
  141. /// Platform Independent Helper - Semaphore wait, aka Operation P. Decrements value of semaphore, and, if the semaphore would be less than 0, waits for the semaphore to be released.
  142. inline void AkWaitForSemaphore(AkSemaphore& in_semaphore)
  143. {
  144. AKVERIFY(sem_wait(&in_semaphore) == AK_POSIX_NO_ERR);
  145. }
  146. /// Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore by an arbitrary count.
  147. inline void AkReleaseSemaphore(AkSemaphore& in_semaphore, AkUInt32 in_count)
  148. {
  149. for (int i=0; i < in_count; i++)
  150. {
  151. AKVERIFY(sem_post(&in_semaphore) == AK_POSIX_NO_ERR);
  152. }
  153. }
  154. #endif
  155. // Virtual Memory
  156. // ------------------------------------------------------------------
  157. AkForceInline void* AllocVM(size_t size, size_t* /*extra*/)
  158. {
  159. void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  160. return ( ( ptr == MAP_FAILED ) || !ptr ) ? NULL : ptr;
  161. }
  162. AkForceInline void FreeVM(void* address, size_t size, size_t /*extra*/, size_t release)
  163. {
  164. if ( release )
  165. munmap( address, release );
  166. }
  167. #if defined(AK_SUPPORT_THREADS)
  168. // Threads
  169. // ------------------------------------------------------------------
  170. /// Platform Independent Helper
  171. inline bool AkIsValidThread( AkThread * in_pThread )
  172. {
  173. return (*in_pThread != AK_NULL_THREAD);
  174. }
  175. /// Platform Independent Helper
  176. inline void AkClearThread( AkThread * in_pThread )
  177. {
  178. *in_pThread = AK_NULL_THREAD;
  179. }
  180. /// Platform Independent Helper
  181. inline void AkCloseThread( AkThread * in_pThread )
  182. {
  183. AKASSERT( in_pThread );
  184. AKASSERT( *in_pThread );
  185. AkClearThread( in_pThread );
  186. }
  187. /// Platform Independent Helper
  188. inline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
  189. {
  190. out_threadProperties.uStackSize = AK_DEFAULT_STACK_SIZE;
  191. out_threadProperties.uSchedPolicy = AK_THREAD_DEFAULT_SCHED_POLICY;
  192. out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
  193. out_threadProperties.dwAffinityMask = AK_THREAD_AFFINITY_DEFAULT;
  194. }
  195. #if !defined(AK_ANDROID) && !defined(AK_LINUX_AOSP)
  196. /// Platform Independent Helper
  197. inline void AkCreateThread(
  198. AkThreadRoutine pStartRoutine, // Thread routine.
  199. void * pParams, // Routine params.
  200. const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
  201. AkThread * out_pThread, // Returned thread handle.
  202. const char * /*in_szThreadName*/ ) // Opt thread name.
  203. {
  204. AKASSERT( out_pThread != NULL );
  205. pthread_attr_t attr;
  206. // Create the attr
  207. AKVERIFY(!pthread_attr_init(&attr));
  208. // Set the stack size
  209. #ifndef AK_EMSCRIPTEN
  210. // Apparently Emscripten doesn't like that we try to specify stack sizes.
  211. AKVERIFY(!pthread_attr_setstacksize(&attr,in_threadProperties.uStackSize));
  212. #endif //AK_EMSCRIPTEN
  213. AKVERIFY(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
  214. // Try to set the thread policy
  215. int sched_policy = in_threadProperties.uSchedPolicy;
  216. if( pthread_attr_setschedpolicy( &attr, sched_policy ) )
  217. {
  218. AKASSERT( !"AKCreateThread invalid sched policy, will automatically set it to FIFO scheduling" );
  219. sched_policy = AK_THREAD_DEFAULT_SCHED_POLICY;
  220. AKVERIFY( !pthread_attr_setschedpolicy( &attr, sched_policy ));
  221. }
  222. // Get the priority for the policy
  223. int minPriority, maxPriority;
  224. minPriority = sched_get_priority_min(sched_policy);
  225. maxPriority = sched_get_priority_max(sched_policy);
  226. // Set the thread priority if valid
  227. AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );
  228. if( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority )
  229. {
  230. sched_param schedParam;
  231. AKVERIFY( !pthread_attr_getschedparam(&attr, &schedParam));
  232. schedParam.sched_priority = in_threadProperties.nPriority;
  233. AKVERIFY( !pthread_attr_setschedparam( &attr, &schedParam ));
  234. }
  235. #ifdef AK_APPLE
  236. int inherit;
  237. pthread_attr_getinheritsched(&attr, &inherit );
  238. pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED );
  239. #endif
  240. // Create the tread
  241. int threadError = pthread_create( out_pThread, &attr, pStartRoutine, pParams);
  242. AKASSERT( threadError == 0 );
  243. AKVERIFY(!pthread_attr_destroy(&attr));
  244. if( threadError != 0 )
  245. {
  246. AkClearThread( out_pThread );
  247. return;
  248. }
  249. // ::CreateThread() return NULL if it fails.
  250. if ( !*out_pThread )
  251. {
  252. AkClearThread( out_pThread );
  253. return;
  254. }
  255. }
  256. #endif
  257. /// Platform Independent Helper
  258. inline void AkWaitForSingleThread( AkThread * in_pThread )
  259. {
  260. AKASSERT( in_pThread );
  261. AKASSERT( *in_pThread );
  262. AKVERIFY(!pthread_join( *in_pThread, NULL ));
  263. }
  264. /// Returns the calling thread's ID.
  265. inline AkThreadID CurrentThread()
  266. {
  267. return pthread_self();
  268. }
  269. #else // AK_SUPPORT_THREADS
  270. inline bool AkIsValidThread( AkThread * in_pThread )
  271. {
  272. return false;
  273. }
  274. inline void AkClearThread( AkThread * in_pThread )
  275. {
  276. }
  277. inline void AkCloseThread( AkThread * in_pThread )
  278. {
  279. }
  280. /// Platform Independent Helper
  281. inline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
  282. {
  283. out_threadProperties.uStackSize = AK_DEFAULT_STACK_SIZE;
  284. out_threadProperties.uSchedPolicy = AK_THREAD_DEFAULT_SCHED_POLICY;
  285. out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
  286. out_threadProperties.dwAffinityMask = AK_THREAD_AFFINITY_DEFAULT;
  287. }
  288. inline void AkCreateThread(
  289. AkThreadRoutine pStartRoutine, // Thread routine.
  290. void * pParams, // Routine params.
  291. const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
  292. AkThread * out_pThread, // Returned thread handle.
  293. const char * /*in_szThreadName*/ ) // Opt thread name.
  294. {
  295. }
  296. /// Platform Independent Helper
  297. inline void AkWaitForSingleThread( AkThread * in_pThread )
  298. {
  299. }
  300. /// Returns the calling thread's ID.
  301. inline AkThreadID CurrentThread()
  302. {
  303. return 1;
  304. }
  305. #endif // AK_SUPPORT_THREADS
  306. /// Platform Independent Helper
  307. inline void AkSleep( AkUInt32 in_ulMilliseconds )
  308. {
  309. // usleep in micro second
  310. usleep( in_ulMilliseconds * 1000 );
  311. }
  312. // Optimized memory functions
  313. // --------------------------------------------------------------------
  314. /// Platform Independent Helper
  315. inline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
  316. {
  317. memcpy( pDest, pSrc, uSize );
  318. }
  319. /// Platform Independent Helper
  320. inline void AkMemMove( void* pDest, const void* pSrc, AkUInt32 uSize )
  321. {
  322. memmove( pDest, pSrc, uSize );
  323. }
  324. /// Platform Independent Helper
  325. inline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
  326. {
  327. memset( pDest, iVal, uSize );
  328. }
  329. /// Platform Independent Helper
  330. inline void UpdatePerformanceFrequency()
  331. {
  332. AkInt64 iFreq;
  333. PerformanceFrequency( &iFreq );
  334. AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
  335. }
  336. /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
  337. inline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
  338. {
  339. return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
  340. }
  341. /// String conversion helper
  342. inline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
  343. AkUInt32 in_uiOutBufferSize,
  344. char* io_pszAnsiString )
  345. {
  346. AKASSERT( io_pszAnsiString != NULL );
  347. io_pszAnsiString[0] = 0;
  348. AkInt32 ConvRet = (AkInt32) wcstombs(io_pszAnsiString, in_pszUnicodeString, in_uiOutBufferSize);
  349. return ConvRet;
  350. }
  351. #ifdef AK_SUPPORT_WCHAR
  352. /// String conversion helper
  353. inline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
  354. AkUInt32 in_uiOutBufferSize,
  355. wchar_t* io_pvUnicodeStringBuffer )
  356. {
  357. AKASSERT( io_pvUnicodeStringBuffer != NULL );
  358. io_pvUnicodeStringBuffer[0] = 0;
  359. AkInt32 ConvRet = (AkInt32) mbstowcs((wchar_t *)io_pvUnicodeStringBuffer, in_pszAnsiString, in_uiOutBufferSize );
  360. return ConvRet;
  361. }
  362. inline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
  363. AkUInt32 in_uiOutBufferSize,
  364. void* io_pvUnicodeStringBuffer )
  365. {
  366. return AkCharToWideChar( in_pszUtf8String, in_uiOutBufferSize, (wchar_t*)io_pvUnicodeStringBuffer );
  367. }
  368. #endif
  369. /// Safe unicode string copy.
  370. inline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
  371. {
  372. size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
  373. wcsncpy( in_pDest, in_pSrc, iSizeCopy );
  374. in_pDest[iSizeCopy] = '\0';
  375. }
  376. /// Safe ansi string copy.
  377. inline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
  378. {
  379. size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
  380. strncpy( in_pDest, in_pSrc, iSizeCopy );
  381. in_pDest[iSizeCopy] = '\0';
  382. }
  383. /// Safe unicode string concatenation.
  384. inline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
  385. {
  386. size_t iAvailableSize = in_uDestMaxNumChars - wcslen( in_pDest ) - 1;
  387. wcsncat( in_pDest, in_pSrc, AkMin( iAvailableSize, wcslen( in_pSrc ) ) );
  388. }
  389. /// Safe ansi string concatenation.
  390. inline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
  391. {
  392. size_t iAvailableSize = in_uDestMaxNumChars - strlen( in_pDest ) - 1;
  393. strncat( in_pDest, in_pSrc, AkMin( iAvailableSize, strlen( in_pSrc ) ) );
  394. }
  395. inline int SafeStrFormat(wchar_t * in_pDest, size_t in_uDestMaxNumChars, const wchar_t* in_pszFmt, ...)
  396. {
  397. va_list args;
  398. va_start(args, in_pszFmt);
  399. int r = vswprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
  400. va_end(args);
  401. return r;
  402. }
  403. inline int SafeStrFormat(char * in_pDest, size_t in_uDestMaxNumChars, const char* in_pszFmt, ...)
  404. {
  405. va_list args;
  406. va_start(args, in_pszFmt);
  407. int r = vsnprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
  408. va_end(args);
  409. return r;
  410. }
  411. /// Get the length, in characters, of a NULL-terminated AkUtf16 string
  412. /// \return The length, in characters, of the specified string (excluding terminating NULL)
  413. inline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
  414. {
  415. size_t len = 0;
  416. while( *in_pStr != 0 )
  417. {
  418. in_pStr++;
  419. len++;
  420. }
  421. return len;
  422. }
  423. #if !defined(AK_ANDROID) && !defined(AK_LINUX_AOSP)
  424. #ifndef AK_OPTIMIZED
  425. /// Output a debug message on the console (Unicode string)
  426. inline void OutputDebugMsg( const wchar_t* in_pszMsg )
  427. {
  428. fputws( in_pszMsg, stderr );
  429. }
  430. /// Output a debug message on the console (Ansi string)
  431. inline void OutputDebugMsg( const char* in_pszMsg )
  432. {
  433. fputs( in_pszMsg, stderr );
  434. }
  435. /// Output a debug message on the console (Unicode string)
  436. template <int MaxSize = 0> // Unused
  437. inline void OutputDebugMsgV( const wchar_t* in_pszFmt, ... )
  438. {
  439. va_list args;
  440. va_start(args, in_pszFmt);
  441. vfwprintf(stderr, in_pszFmt, args);
  442. va_end(args);
  443. }
  444. /// Output a debug message on the console (Ansi string)
  445. template <int MaxSize = 0> // Unused
  446. inline void OutputDebugMsgV( const char* in_pszFmt, ... )
  447. {
  448. va_list args;
  449. va_start(args, in_pszFmt);
  450. vfprintf(stderr, in_pszFmt, args);
  451. va_end(args);
  452. }
  453. #else
  454. inline void OutputDebugMsg( const wchar_t* ){}
  455. inline void OutputDebugMsg( const char* ){}
  456. template <int MaxSize = 0> // Unused
  457. inline void OutputDebugMsgV( const wchar_t* in_pszFmt, ... ){}
  458. template <int MaxSize = 0> // Unused
  459. inline void OutputDebugMsgV( const char* in_pszFmt, ... ){}
  460. #endif
  461. #endif
  462. /// Converts a wchar_t string to an AkOSChar string.
  463. /// \remark On some platforms the AkOSChar string simply points to the same string,
  464. /// on others a new buffer is allocated on the stack using AkAlloca. This means
  465. /// you must make sure that:
  466. /// - The source string stays valid and unmodified for as long as you need the
  467. /// AkOSChar string (for cases where they point to the same string)
  468. /// - The AkOSChar string is used within this scope only -- for example, do NOT
  469. /// return that string from a function (for cases where it is allocated on the stack)
  470. #define CONVERT_WIDE_TO_OSCHAR( _astring_, _oscharstring_ ) \
  471. _oscharstring_ = (AkOSChar*)AkAlloca( (1 + wcslen( _astring_ )) * sizeof(AkOSChar)); \
  472. AKPLATFORM::AkWideCharToChar( _astring_, (AkUInt32)(1 + wcslen(_astring_ )), (AkOSChar*)( _oscharstring_ ) )
  473. /// Converts a char string to an AkOSChar string.
  474. /// \remark On some platforms the AkOSChar string simply points to the same string,
  475. /// on others a new buffer is allocated on the stack using AkAlloca. This means
  476. /// you must make sure that:
  477. /// - The source string stays valid and unmodified for as long as you need the
  478. /// AkOSChar string (for cases where they point to the same string)
  479. /// - The AkOSChar string is used within this scope only -- for example, do NOT
  480. /// return that string from a function (for cases where it is allocated on the stack)
  481. #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _astring_ )
  482. /// Converts a AkOSChar string into wide char string.
  483. /// \remark On some platforms the AkOSChar string simply points to the same string,
  484. /// on others a new buffer is allocated on the stack using AkAlloca. This means
  485. /// you must make sure that:
  486. /// - The source string stays valid and unmodified for as long as you need the
  487. /// AkOSChar string (for cases where they point to the same string)
  488. /// - The AkOSChar string is used within this scope only -- for example, do NOT
  489. /// return that string from a function (for cases where it is allocated on the stack)
  490. #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) \
  491. _wstring_ = (wchar_t*)AkAlloca((1+strlen(_osstring_)) * sizeof(wchar_t)); \
  492. AKPLATFORM::AkCharToWideChar( _osstring_, (AkUInt32)(1 + strlen(_osstring_ )), _wstring_ )
  493. /// Converts a AkOSChar string into char string.
  494. /// \remark On some platforms the AkOSChar string simply points to the same string,
  495. /// on others a new buffer is allocated on the stack using AkAlloca. This means
  496. /// you must make sure that:
  497. /// - The source string stays valid and unmodified for as long as you need the
  498. /// AkOSChar string (for cases where they point to the same string)
  499. /// - The AkOSChar string is used within this scope only -- for example, do NOT
  500. /// return that string from a function (for cases where it is allocated on the stack)
  501. #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) _astring_ = (char*)_osstring_
  502. inline size_t OsStrLen( const AkOSChar* in_pszString )
  503. {
  504. return ( strlen( in_pszString ) );
  505. }
  506. /// AkOSChar version of snprintf().
  507. #define AK_OSPRINTF snprintf
  508. inline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
  509. {
  510. return ( strcmp( in_pszString1, in_pszString2 ) );
  511. }
  512. /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
  513. /// \return
  514. /// - \< 0 if in_pszString1 \< in_pszString2
  515. /// - 0 if the two strings are identical
  516. /// - \> 0 if in_pszString1 \> in_pszString2
  517. /// \remark The comparison is case-sensitive
  518. inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize )
  519. {
  520. return ( strncmp(in_pszString1, in_pszString2, in_MaxCountSize) );
  521. }
  522. /// Detects whether the string represents an absolute path to a file
  523. inline bool IsAbsolutePath(const AkOSChar* in_pszPath, size_t in_pathLen)
  524. {
  525. return in_pathLen >= 1 && in_pszPath[0] == '/';
  526. }
  527. // Use with AkOSChar.
  528. #ifndef AK_PATH_SEPARATOR
  529. #define AK_PATH_SEPARATOR ("/")
  530. #endif
  531. #ifndef AK_LIBRARY_PREFIX
  532. #define AK_LIBRARY_PREFIX ("lib")
  533. #endif
  534. #ifndef AK_DYNAMIC_LIBRARY_EXTENSION
  535. #define AK_DYNAMIC_LIBRARY_EXTENSION (".so")
  536. #endif
  537. #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
  538. #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
  539. }
  540. #pragma GCC visibility pop