Team Fortress 2 Source Code as on 22/4/2020
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.

589 lines
21 KiB

  1. //===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifndef TIER1_STRTOOLS_H
  9. #define TIER1_STRTOOLS_H
  10. #include "tier0/basetypes.h"
  11. #ifdef _WIN32
  12. #pragma once
  13. #elif POSIX
  14. #include <ctype.h>
  15. #include <wchar.h>
  16. #include <math.h>
  17. #include <wctype.h>
  18. #endif
  19. #include <string.h>
  20. #include <stdlib.h>
  21. // 3d memcpy. Copy (up-to) 3 dimensional data with arbitrary source and destination
  22. // strides. Optimizes to just a single memcpy when possible. For 2d data, set numslices to 1.
  23. void CopyMemory3D( void *pDestAdr, void const *pSrcAdr,
  24. int nNumCols, int nNumRows, int nNumSlices, // dimensions of copy
  25. int nSrcBytesPerRow, int nSrcBytesPerSlice, // strides for source.
  26. int nDestBytesPerRow, int nDestBytesPerSlice // strides for dest
  27. );
  28. template< class T, class I > class CUtlMemory;
  29. template< class T, class A > class CUtlVector;
  30. //-----------------------------------------------------------------------------
  31. // Portable versions of standard string functions
  32. //-----------------------------------------------------------------------------
  33. void _V_memset ( void *dest, int fill, int count );
  34. void _V_memcpy ( void *dest, const void *src, int count );
  35. void _V_memmove ( void *dest, const void *src, int count );
  36. int _V_memcmp ( const void *m1, const void *m2, int count );
  37. int _V_strlen ( const char *str );
  38. void _V_strcpy ( char *dest, const char *src );
  39. char* _V_strrchr ( const char *s, char c );
  40. int _V_strcmp ( const char *s1, const char *s2 );
  41. int _V_wcscmp ( const wchar_t *s1, const wchar_t *s2 );
  42. int _V_stricmp ( const char *s1, const char *s2 );
  43. char* _V_strstr ( const char *s1, const char *search );
  44. char* _V_strupr ( char *start );
  45. char* _V_strlower ( char *start );
  46. int _V_wcslen ( const wchar_t *pwch );
  47. wchar_t* _V_wcslower (const char* file, int line, wchar_t *start);
  48. wchar_t* _V_wcsupr (const char* file, int line, wchar_t *start);
  49. #ifdef POSIX
  50. inline char *strupr( char *start )
  51. {
  52. char *str = start;
  53. while( str && *str )
  54. {
  55. *str = (char)toupper(*str);
  56. str++;
  57. }
  58. return start;
  59. }
  60. inline char *strlwr( char *start )
  61. {
  62. char *str = start;
  63. while( str && *str )
  64. {
  65. *str = (char)tolower(*str);
  66. str++;
  67. }
  68. return start;
  69. }
  70. inline wchar_t *_wcslwr( wchar_t *start )
  71. {
  72. wchar_t *str = start;
  73. while( str && *str )
  74. {
  75. *str = (wchar_t)towlower(static_cast<wint_t>(*str));
  76. str++;
  77. }
  78. return start;
  79. };
  80. inline wchar_t *_wcsupr( wchar_t *start )
  81. {
  82. wchar_t *str = start;
  83. while( str && *str )
  84. {
  85. *str = (wchar_t)towupper(static_cast<wint_t>(*str));
  86. str++;
  87. }
  88. return start;
  89. };
  90. #endif // POSIX
  91. // there are some users of these via tier1 templates in used in tier0. but tier0 can't depend on vstdlib which means in tier0 we always need the inlined ones
  92. #if ( !defined( TIER0_DLL_EXPORT ) )
  93. #if !defined( _DEBUG ) && defined( _PS3 )
  94. #include "tier1/strtools_inlines.h"
  95. // To avoid cross-prx calls, making the V_* fucntions that don't do anything but debug checks and call through to the non V_* function
  96. // go ahead and call the non-V_* functions directly.
  97. #define V_memset(dest, fill, count) memset ((dest), (fill), (count))
  98. #define V_memcpy(dest, src, count) memcpy ((dest), (src), (count))
  99. #define V_memmove(dest, src, count) memmove ((dest), (src), (count))
  100. #define V_memcmp(m1, m2, count) memcmp ((m1), (m2), (count))
  101. #define V_strcpy(dest, src) strcpy ((dest), (src))
  102. #define V_strcmp(s1, s2) strcmp ((s1), (s2))
  103. #define V_strupr(start) strupr ((start))
  104. #define V_strlower(start) strlwr ((start))
  105. #define V_wcslen(pwch) wcslen ((pwch))
  106. // To avoid cross-prx calls, using inline versions of these custom functions:
  107. #define V_strlen(str) _V_strlen_inline ((str))
  108. #define V_strrchr(s, c) _V_strrchr_inline ((s), (c))
  109. #define V_wcscmp(s1, s2) _V_wcscmp_inline ((s1), (s2))
  110. #define V_stricmp(s1, s2 ) _V_stricmp_inline ((s1), (s2) )
  111. #define V_strstr(s1, search ) _V_strstr_inline ((s1), (search) )
  112. #else
  113. #define V_memset(dest, fill, count) _V_memset ((dest), (fill), (count))
  114. #define V_memcpy(dest, src, count) _V_memcpy ((dest), (src), (count))
  115. #define V_memmove(dest, src, count) _V_memmove ((dest), (src), (count))
  116. #define V_memcmp(m1, m2, count) _V_memcmp ((m1), (m2), (count))
  117. #define V_strlen(str) _V_strlen ((str))
  118. #define V_strcpy(dest, src) _V_strcpy ((dest), (src))
  119. #define V_strrchr(s, c) _V_strrchr ((s), (c))
  120. #define V_strcmp(s1, s2) _V_strcmp ((s1), (s2))
  121. #define V_wcscmp(s1, s2) _V_wcscmp ((s1), (s2))
  122. #define V_stricmp(s1, s2 ) _V_stricmp ((s1), (s2) )
  123. #define V_strstr(s1, search ) _V_strstr ((s1), (search) )
  124. #define V_strupr(start) _V_strupr ((start))
  125. #define V_strlower(start) _V_strlower ((start))
  126. #define V_wcslen(pwch) _V_wcslen ((pwch))
  127. #endif
  128. #else
  129. inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); }
  130. inline void V_memcpy (void *dest, const void *src, int count) { memcpy( dest, src, count ); }
  131. inline void V_memmove (void *dest, const void *src, int count) { memmove( dest, src, count ); }
  132. inline int V_memcmp (const void *m1, const void *m2, int count){ return memcmp( m1, m2, count ); }
  133. inline int V_strlen (const char *str) { return (int) strlen ( str ); }
  134. inline void V_strcpy (char *dest, const char *src) { strcpy( dest, src ); }
  135. inline int V_wcslen(const wchar_t *pwch) { return (int)wcslen(pwch); }
  136. inline char* V_strrchr (const char *s, char c) { return (char*)strrchr( s, c ); }
  137. inline int V_strcmp (const char *s1, const char *s2) { return strcmp( s1, s2 ); }
  138. inline int V_wcscmp (const wchar_t *s1, const wchar_t *s2) { return wcscmp( s1, s2 ); }
  139. inline int V_stricmp( const char *s1, const char *s2 ) { return stricmp( s1, s2 ); }
  140. inline char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); }
  141. #ifndef COMPILER_PS3
  142. inline char* V_strupr (char *start) { return strupr( start ); }
  143. inline char* V_strlower (char *start) { return strlwr( start ); }
  144. inline wchar_t* V_wcsupr (wchar_t *start) { return _wcsupr( start ); }
  145. #endif
  146. #endif
  147. int V_strncmp (const char *s1, const char *s2, int count);
  148. int V_strcasecmp (const char *s1, const char *s2);
  149. int V_strncasecmp (const char *s1, const char *s2, int n);
  150. int V_strnicmp (const char *s1, const char *s2, int n);
  151. int V_atoi (const char *str);
  152. int64 V_atoi64(const char *str);
  153. uint64 V_atoui64(const char *str);
  154. float V_atof (const char *str);
  155. char* V_stristr( char* pStr, const char* pSearch );
  156. const char* V_stristr( const char* pStr, const char* pSearch );
  157. const char* V_strnistr( const char* pStr, const char* pSearch, int n );
  158. const char* V_strnchr( const char* pStr, char c, int n );
  159. // returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found
  160. const char *StringAfterPrefix ( const char *str, const char *prefix );
  161. const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix );
  162. inline bool StringHasPrefix ( const char *str, const char *prefix ) { return StringAfterPrefix ( str, prefix ) != NULL; }
  163. inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; }
  164. // Normalizes a float string in place.
  165. // (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible)
  166. void V_normalizeFloatString( char* pFloat );
  167. inline bool V_isspace(int c)
  168. {
  169. // The standard white-space characters are the following: space, tab, carriage-return, newline, vertical tab, and form-feed. In the C locale, V_isspace() returns true only for the standard white-space characters.
  170. //return c == ' ' || c == 9 /*horizontal tab*/ || c == '\r' || c == '\n' || c == 11 /*vertical tab*/ || c == '\f';
  171. // codes of whitespace symbols: 9 HT, 10 \n, 11 VT, 12 form feed, 13 \r, 32 space
  172. // easy to understand version, validated:
  173. // return ((1 << (c-1)) & 0x80001F00) != 0 && ((c-1)&0xE0) == 0;
  174. // 5% faster on Core i7, 35% faster on Xbox360, no branches, validated:
  175. #ifdef _X360
  176. return ((1 << (c-1)) & 0x80001F00 & ~(-int((c-1)&0xE0))) != 0;
  177. #else
  178. // this is 11% faster on Core i7 than the previous, VC2005 compiler generates a seemingly unbalanced search tree that's faster
  179. switch(c)
  180. {
  181. case ' ':
  182. case 9:
  183. case '\r':
  184. case '\n':
  185. case 11:
  186. case '\f':
  187. return true;
  188. default:
  189. return false;
  190. }
  191. #endif
  192. }
  193. // These are versions of functions that guarantee NULL termination.
  194. //
  195. // maxLen is the maximum number of bytes in the destination string.
  196. // pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen.
  197. //
  198. // This means the last parameter can usually be a sizeof() of a string.
  199. void V_strncpy( char *pDest, const char *pSrc, int maxLen );
  200. int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ) FMTFUNCTION( 3, 4 );
  201. void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
  202. int V_snwprintf( wchar_t *pDest, int maxLenInNumWideCharacters, const wchar_t *pFormat, ... );
  203. #define COPY_ALL_CHARACTERS -1
  204. char *V_strncat(char *, const char *, size_t maxLenInBytes, int max_chars_to_copy=COPY_ALL_CHARACTERS );
  205. wchar_t *V_wcsncat(wchar_t *, const wchar_t *, int maxLenInBytes, int max_chars_to_copy=COPY_ALL_CHARACTERS );
  206. char *V_strnlwr(char *, size_t);
  207. // UNDONE: Find a non-compiler-specific way to do this
  208. #ifdef _WIN32
  209. #ifndef _VA_LIST_DEFINED
  210. #ifdef _M_ALPHA
  211. struct va_list
  212. {
  213. char *a0; /* pointer to first homed integer argument */
  214. int offset; /* byte offset of next parameter */
  215. };
  216. #else // !_M_ALPHA
  217. typedef char * va_list;
  218. #endif // !_M_ALPHA
  219. #define _VA_LIST_DEFINED
  220. #endif // _VA_LIST_DEFINED
  221. #elif POSIX
  222. #include <stdarg.h>
  223. #endif
  224. #ifdef _WIN32
  225. #define CORRECT_PATH_SEPARATOR '\\'
  226. #define CORRECT_PATH_SEPARATOR_S "\\"
  227. #define INCORRECT_PATH_SEPARATOR '/'
  228. #define INCORRECT_PATH_SEPARATOR_S "/"
  229. #elif POSIX || defined( _PS3 )
  230. #define CORRECT_PATH_SEPARATOR '/'
  231. #define CORRECT_PATH_SEPARATOR_S "/"
  232. #define INCORRECT_PATH_SEPARATOR '\\'
  233. #define INCORRECT_PATH_SEPARATOR_S "\\"
  234. #endif
  235. int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params );
  236. int V_vsnprintfRet( char *pDest, int maxLen, const char *pFormat, va_list params, bool *pbTruncated );
  237. // Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes )
  238. char *V_pretifymem( float value, int digitsafterdecimal = 2, bool usebinaryonek = false );
  239. // Prints out a pretified integer with comma separators (eg, 7,233,270,000)
  240. char *V_pretifynum( int64 value );
  241. // Functions for converting hexidecimal character strings back into binary data etc.
  242. //
  243. // e.g.,
  244. // int output;
  245. // V_hextobinary( "ffffffff", 8, &output, sizeof( output ) );
  246. // would make output == 0xfffffff or -1
  247. // Similarly,
  248. // char buffer[ 9 ];
  249. // V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) );
  250. // would put "ffffffff" into buffer (note null terminator!!!)
  251. void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes );
  252. void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize );
  253. // Tools for working with filenames
  254. // Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator)
  255. void V_FileBase( const char *in, char *out,int maxlen );
  256. // Remove the final characters of ppath if it's '\' or '/'.
  257. void V_StripTrailingSlash( char *ppath );
  258. // Remove any extension from in and return resulting string in out
  259. void V_StripExtension( const char *in, char *out, int outLen );
  260. // Make path end with extension if it doesn't already have an extension
  261. void V_DefaultExtension( char *path, const char *extension, int pathStringLength );
  262. // Strips any current extension from path and ensures that extension is the new extension.
  263. // NOTE: extension string MUST include the . character
  264. void V_SetExtension( char *path, const char *extension, int pathStringLength );
  265. // Removes any filename from path ( strips back to previous / or \ character )
  266. void V_StripFilename( char *path );
  267. // Remove the final directory from the path
  268. bool V_StripLastDir( char *dirName, int maxlen );
  269. // Returns a pointer to the unqualified file name (no path) of a file name
  270. const char * V_UnqualifiedFileName( const char * in );
  271. char * V_UnqualifiedFileName( char * in );
  272. // Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary
  273. void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize );
  274. // Copy out the path except for the stuff after the final pathseparator
  275. bool V_ExtractFilePath( const char *path, char *dest, int destSize );
  276. // Copy out the file extension into dest
  277. void V_ExtractFileExtension( const char *path, char *dest, int destSize );
  278. const char *V_GetFileExtension( const char * path );
  279. // returns a pointer to just the filename part of the path
  280. // (everything after the last path seperator)
  281. const char *V_GetFileName( const char * path );
  282. // This removes "./" and "../" from the pathname. pFilename should be a full pathname.
  283. // Returns false if it tries to ".." past the root directory in the drive (in which case
  284. // it is an invalid path).
  285. bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR );
  286. // If pPath is a relative path, this function makes it into an absolute path
  287. // using the current working directory as the base, or pStartingDir if it's non-NULL.
  288. // Returns false if it runs out of room in the string, or if pPath tries to ".." past the root directory.
  289. void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir = NULL );
  290. // Creates a relative path given two full paths
  291. // The first is the full path of the file to make a relative path for.
  292. // The second is the full path of the directory to make the first file relative to
  293. // Returns false if they can't be made relative (on separate drives, for example)
  294. bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen );
  295. // Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc.
  296. void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath );
  297. // Adds a path separator to the end of the string if there isn't one already. Returns false if it would run out of space.
  298. void V_AppendSlash( char *pStr, int strSize );
  299. // Returns true if the path is an absolute path.
  300. bool V_IsAbsolutePath( const char *pPath );
  301. // Scans pIn and replaces all occurences of pMatch with pReplaceWith.
  302. // Writes the result to pOut.
  303. // Returns true if it completed successfully.
  304. // If it would overflow pOut, it fills as much as it can and returns false.
  305. bool V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith,
  306. char *pOut, int outLen, bool bCaseSensitive=false );
  307. // Split the specified string on the specified separator.
  308. // Returns a list of strings separated by pSeparator.
  309. // You are responsible for freeing the contents of outStrings (call outStrings.PurgeAndDeleteElements).
  310. void V_SplitString( const char *pString, const char *pSeparator, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
  311. // Just like V_SplitString, but it can use multiple possible separators.
  312. void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
  313. // Returns false if the buffer is not large enough to hold the working directory name.
  314. bool V_GetCurrentDirectory( char *pOut, int maxLen );
  315. // Set the working directory thus.
  316. bool V_SetCurrentDirectory( const char *pDirName );
  317. // This function takes a slice out of pStr and stores it in pOut.
  318. // It follows the Python slice convention:
  319. // Negative numbers wrap around the string (-1 references the last character).
  320. // Large numbers are clamped to the end of the string.
  321. void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize );
  322. // Chop off the left nChars of a string.
  323. void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize );
  324. // Chop off the right nChars of a string.
  325. void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize );
  326. // change "special" characters to have their c-style backslash sequence. like \n, \r, \t, ", etc.
  327. // returns a pointer to a newly allocated string, which you must delete[] when finished with.
  328. char *V_AddBackSlashesToSpecialChars( char const *pSrc );
  329. // Force slashes of either type to be = separator character
  330. void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR );
  331. // This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash.
  332. void V_FixDoubleSlashes( char *pStr );
  333. // Convert multibyte to wchar + back
  334. // Specify -1 for nInSize for null-terminated string
  335. void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize );
  336. void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize );
  337. // buffer-safe strcat
  338. inline void V_strcat( char *dest, const char *src, int maxLenInBytes )
  339. {
  340. V_strncat( dest, src, maxLenInBytes, COPY_ALL_CHARACTERS );
  341. }
  342. // buffer-safe strcat
  343. inline void V_wcscat( wchar_t *dest, const wchar_t *src, int maxLenInBytes )
  344. {
  345. V_wcsncat( dest, src, maxLenInBytes, COPY_ALL_CHARACTERS );
  346. }
  347. // Convert from a string to an array of integers.
  348. void V_StringToIntArray( int *pVector, int count, const char *pString );
  349. // Convert from a string to a 4 byte color value.
  350. void V_StringToColor32( color32 *color, const char *pString );
  351. // Convert \r\n (Windows linefeeds) to \n (Unix linefeeds).
  352. void V_TranslateLineFeedsToUnix( char *pStr );
  353. //-----------------------------------------------------------------------------
  354. // generic unique name helper functions
  355. //-----------------------------------------------------------------------------
  356. // returns -1 if no match, nDefault if pName==prefix, and N if pName==prefix+N
  357. inline int V_IndexAfterPrefix( const char *pName, const char *prefix, int nDefault = 0 )
  358. {
  359. if ( !pName || !prefix )
  360. return -1;
  361. const char *pIndexStr = StringAfterPrefix( pName, prefix );
  362. if ( !pIndexStr )
  363. return -1;
  364. if ( !*pIndexStr )
  365. return nDefault;
  366. return atoi( pIndexStr );
  367. }
  368. // returns startindex if none found, 2 if "prefix" found, and n+1 if "prefixn" found
  369. template < class NameArray >
  370. int V_GenerateUniqueNameIndex( const char *prefix, const NameArray &nameArray, int startindex = 0 )
  371. {
  372. if ( !prefix )
  373. return 0;
  374. int freeindex = startindex;
  375. int nNames = nameArray.Count();
  376. for ( int i = 0; i < nNames; ++i )
  377. {
  378. int index = V_IndexAfterPrefix( nameArray[ i ], prefix, 1 ); // returns -1 if no match, 0 for exact match, N for
  379. if ( index >= freeindex )
  380. {
  381. // TODO - check that there isn't more junk after the index in pElementName
  382. freeindex = index + 1;
  383. }
  384. }
  385. return freeindex;
  386. }
  387. template < class NameArray >
  388. bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const NameArray &nameArray )
  389. {
  390. if ( name == NULL || memsize == 0 )
  391. return false;
  392. if ( prefix == NULL )
  393. {
  394. name[ 0 ] = '\0';
  395. return false;
  396. }
  397. int prefixLength = V_strlen( prefix );
  398. if ( prefixLength + 1 > memsize )
  399. {
  400. name[ 0 ] = '\0';
  401. return false;
  402. }
  403. int i = V_GenerateUniqueNameIndex( prefix, nameArray );
  404. if ( i <= 0 )
  405. {
  406. V_strncpy( name, prefix, memsize );
  407. return true;
  408. }
  409. int newlen = prefixLength + ( int )log10( ( float )i ) + 1;
  410. if ( newlen + 1 > memsize )
  411. {
  412. V_strncpy( name, prefix, memsize );
  413. return false;
  414. }
  415. V_snprintf( name, memsize, "%s%d", prefix, i );
  416. return true;
  417. }
  418. extern bool V_StringToBin( const char*pString, void *pBin, uint nBinSize );
  419. extern bool V_BinToString( char*pString, void *pBin, uint nBinSize );
  420. template<typename T>
  421. struct BinString_t
  422. {
  423. BinString_t(){}
  424. BinString_t( const char *pStr )
  425. {
  426. V_strncpy( m_string, pStr, sizeof(m_string) );
  427. ToBin();
  428. }
  429. BinString_t( const T & that )
  430. {
  431. m_bin = that;
  432. ToString();
  433. }
  434. bool ToBin()
  435. {
  436. return V_StringToBin( m_string, &m_bin, sizeof( m_bin ) );
  437. }
  438. void ToString()
  439. {
  440. V_BinToString( m_string, &m_bin, sizeof( m_bin ) );
  441. }
  442. T m_bin;
  443. char m_string[sizeof(T)*2+2]; // 0-terminated string representing the binary data in hex
  444. };
  445. template <typename T>
  446. inline BinString_t<T> MakeBinString( const T& that )
  447. {
  448. return BinString_t<T>( that );
  449. }
  450. #if defined(_PS3) || defined(POSIX)
  451. #define PRI_WS_FOR_WS L"%ls"
  452. #define PRI_WS_FOR_S "%ls"
  453. #define PRI_S_FOR_WS L"%s"
  454. #define PRI_S_FOR_S "%s"
  455. #else
  456. #define PRI_WS_FOR_WS L"%s"
  457. #define PRI_WS_FOR_S "%S"
  458. #define PRI_S_FOR_WS L"%S"
  459. #define PRI_S_FOR_S "%s"
  460. #endif
  461. namespace AsianWordWrap
  462. {
  463. // Functions used by Asian language line wrapping to determine if a character can end a line, begin a line, or be broken up when repeated (eg: "...")
  464. bool CanEndLine( wchar_t wcCandidate );
  465. bool CanBeginLine( wchar_t wcCandidate );
  466. bool CanBreakRepeated( wchar_t wcCandidate );
  467. // Used to determine if we can break a line between the first two characters passed; calls the above functions on each character
  468. bool CanBreakAfter( const wchar_t* wsz );
  469. }
  470. // We use this function to determine where it is permissible to break lines
  471. // of text while wrapping them. On most platforms, the native iswspace() function
  472. // returns FALSE for the "non-breaking space" characters 0x00a0 and 0x202f, and so we don't
  473. // break on them. On the 360, however, iswspace returns TRUE for them. So, on that
  474. // platform, we work around it by defining this wrapper which returns false
  475. // for &nbsp; and calls through to the library function for everything else.
  476. int isbreakablewspace( wchar_t ch );
  477. #endif // TIER1_STRTOOLS_H