com_string.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. Copyright (C) 2004-2005 Michael Liebscher <johnnycanuck@users.sourceforge.net>
  3. Copyright (C) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  4. Copyright (C) 1997-2001 Id Software, Inc.
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. */
  17. /*
  18. * com_string.c: Common string functions done in a portable manner.
  19. *
  20. * Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
  21. *
  22. * Acknowledgement:
  23. * Portion of this code was derived from Quake II, and was originally
  24. * written by Id Software, Inc.
  25. *
  26. * Portion of this code was derived from code that was originally
  27. * written by Todd C. Miller.
  28. *
  29. */
  30. #include "../wolfiphone.h"
  31. /*
  32. -----------------------------------------------------------------------------
  33. Function: my_strlcpy -Copies a specified number of characters from a
  34. source string into a buffer.
  35. Parameters: dest -[in/out] Pointer to a buffer into which the function
  36. copies characters
  37. source -[in] Pointer to a NUL-terminated string from which
  38. the function copies characters.
  39. nMaxLength -[in] Specifies the number of bytes to be copied
  40. from the string pointed to by source into the
  41. buffer pointed to by dest.
  42. Returns: Returns strlen( source ); if retval >= nMaxLength, truncation
  43. occurred.
  44. Notes:
  45. At most nMaxLength-1 characters will be copied. Always NUL-
  46. terminates (unless nMaxLength == 0).
  47. -----------------------------------------------------------------------------
  48. */
  49. PUBLIC size_t my_strlcpy( char *dest, const char *source, size_t nMaxLength )
  50. {
  51. char *d = dest;
  52. const char *s = source;
  53. size_t n = nMaxLength;
  54. /* Copy as many bytes as will fit */
  55. if( n != 0 && --n != 0 )
  56. {
  57. do
  58. {
  59. if( (*d++ = *s++) == 0 )
  60. {
  61. break;
  62. }
  63. } while( --n != 0 );
  64. }
  65. /* Not enough room in dest, add NUL and traverse rest of source */
  66. if( n == 0 )
  67. {
  68. if( nMaxLength != 0 )
  69. {
  70. *d = '\0'; /* NUL-terminate dest */
  71. }
  72. while( *s++ )
  73. {
  74. ;
  75. }
  76. }
  77. return( s - source - 1 ); /* count does not include NUL */
  78. }
  79. /*
  80. -----------------------------------------------------------------------------
  81. Function: my_strlcat -Appends one string to another.
  82. Parameters: dest -[in/out] Pointer to a NUL-terminated string. The buffer
  83. must be large enough to contain both strings or else
  84. truncation will occur.
  85. source -[in] Pointer to a NUL-terminated string from which
  86. the function copies characters.
  87. nMaxLength -[in] full size of dest, not space left.
  88. Returns: Returns strlen( source ) + MIN( nMaxLength, strlen( initial dest ) ).
  89. If retval >= nMaxLength, truncation occurred.
  90. Notes:
  91. At most nMaxLength-1 characters will be copied. Always NUL-
  92. terminates (unless nMaxLength <= strlen( dest ) ).
  93. -----------------------------------------------------------------------------
  94. */
  95. PUBLIC size_t my_strlcat( char *dest, const char *source, size_t nMaxLength )
  96. {
  97. char *d = dest;
  98. const char *s = source;
  99. size_t n = nMaxLength;
  100. size_t dlen;
  101. /* Find the end of dest and adjust bytes left but don't go past end */
  102. while( n-- != 0 && *d != '\0' )
  103. {
  104. d++;
  105. }
  106. dlen = d - dest;
  107. n = nMaxLength - dlen;
  108. /* No room left to append string */
  109. if( n == 0 )
  110. {
  111. return( dlen + strlen( s ) );
  112. }
  113. while( *s != '\0' )
  114. {
  115. if( n != 1 )
  116. {
  117. *d++ = *s;
  118. n--;
  119. }
  120. s++;
  121. }
  122. *d = '\0'; /* NUL-terminate string */
  123. return( dlen + (s - source) ); /* count does not include NUL */
  124. }
  125. /*
  126. -----------------------------------------------------------------------------
  127. Function: my_strnicmp -Compare characters of two strings without regard to case.
  128. Parameters: string1, string2 -[in] NUL-terminated strings to compare.
  129. count -[in] Number of characters to compare.
  130. Returns: 0 string1 identical to string2, -1 otherwise.
  131. Notes:
  132. -----------------------------------------------------------------------------
  133. */
  134. PUBLIC int my_strnicmp( const char *string1, const char *string2, size_t count )
  135. {
  136. char c1, c2;
  137. if( ! string1 || ! *string1 ||
  138. ! string2 || ! *string2 )
  139. {
  140. return -1;
  141. }
  142. do
  143. {
  144. c1 = *string1++;
  145. c2 = *string2++;
  146. if( ! count-- )
  147. {
  148. return 0; /* strings are equal until end point */
  149. }
  150. if( c1 != c2 )
  151. {
  152. if( TOUPPER( c1 ) != TOUPPER( c2 ) ) /* Uppercase compare */
  153. {
  154. return -1; /* strings are not equal */
  155. }
  156. }
  157. } while( c1 );
  158. return 0; /* strings are equal */
  159. }
  160. /*
  161. -----------------------------------------------------------------------------
  162. Function: my_stricmp -Perform an uppercase comparison of strings.
  163. Parameters: string1, string2 -[in] NUL-terminated strings to compare.
  164. Returns: 0 string1 identical to string2, -1 otherwise.
  165. Notes:
  166. Calls my_strnicmp, where count is 99999
  167. -----------------------------------------------------------------------------
  168. */
  169. PUBLIC int my_stricmp( const char *string1, const char *string2 )
  170. {
  171. return my_strnicmp( string1, string2, 99999 );
  172. }
  173. /*
  174. -----------------------------------------------------------------------------
  175. Function: my_snprintf -Write formatted data to a string.
  176. Parameters: dest -[out] Storage location for output.
  177. size -[in] Maximum number of characters to store.
  178. format -[in] Format-control string.
  179. ... -[in] Optional arguments.
  180. Returns: Nothing.
  181. Notes: If the format string is longer than 32768 truncation will occur.
  182. Also, if format is longer than dest truncation will occur.
  183. -----------------------------------------------------------------------------
  184. */
  185. PUBLIC void my_snprintf( char *dest, size_t size, const char *format, ... )
  186. {
  187. va_list argptr;
  188. char bigbuffer[ 0x8000 ];
  189. va_start( argptr, format );
  190. (void)vsnprintf( bigbuffer, sizeof( bigbuffer ), format, argptr );
  191. va_end( argptr );
  192. bigbuffer[ sizeof( bigbuffer ) - 1 ] = '\0';
  193. my_strlcpy( dest, bigbuffer, size );
  194. }
  195. /*
  196. -----------------------------------------------------------------------------
  197. Function: my_CopyString -Allocate a duplicate copy of a string, and return
  198. duplicate.
  199. Parameters: in -[in] String to duplicate.
  200. Returns:
  201. Pointer to duplicate string. Caller is responsible for freeing
  202. memory with Z_Free.
  203. Notes:
  204. -----------------------------------------------------------------------------
  205. */
  206. PUBLIC char *my_CopyString( const char *in )
  207. {
  208. char *out;
  209. out = Z_Malloc( strlen( in ) + 1 );
  210. my_strlcpy( out, in, strlen( in ) + 1 );
  211. return out;
  212. }
  213. /*
  214. -----------------------------------------------------------------------------
  215. Function: my_strhash -Create a hash id from string.
  216. Parameters: string -[in] NUL-terminated string.
  217. Returns: Hash id.
  218. Notes:
  219. -----------------------------------------------------------------------------
  220. */
  221. PUBLIC W32 my_strhash( const char *string )
  222. {
  223. W32 hash = *string;
  224. if( hash )
  225. {
  226. for( string += 1; *string != '\0'; ++string )
  227. {
  228. hash = (hash << 5) - hash + *string;
  229. }
  230. }
  231. return hash;
  232. }
  233. /*
  234. -----------------------------------------------------------------------------
  235. Function: my_strupr -Convert a string to uppercase.
  236. Parameters: string -[in/out] NUL-terminated string to capitalize.
  237. Returns:
  238. This functions returns a pointer to the converted string. Because
  239. the modification is done in place, the pointer returned is the same
  240. as the pointer passed as the input argument. No return value is
  241. reserved to indicate an error.
  242. Notes:
  243. -----------------------------------------------------------------------------
  244. */
  245. PUBLIC char *my_strupr( char *string )
  246. {
  247. char *ptr;
  248. if( ! string || ! *string )
  249. {
  250. return string;
  251. }
  252. ptr = string;
  253. do
  254. {
  255. *ptr = TOUPPER( *ptr );
  256. } while( *ptr++ );
  257. return string;
  258. }
  259. /*
  260. -----------------------------------------------------------------------------
  261. Function: my_strlwr -Convert a string to lowercase.
  262. Parameters: string -[in/out] NUL-terminated string to convert to lowercase.
  263. Returns:
  264. This functions returns a pointer to the converted string. Because
  265. the modification is done in place, the pointer returned is the same
  266. as the pointer passed as the input argument. No return value is
  267. reserved to indicate an error.
  268. Notes:
  269. -----------------------------------------------------------------------------
  270. */
  271. PUBLIC char *my_strlwr( char *string )
  272. {
  273. char *ptr;
  274. if( ! string || ! *string )
  275. {
  276. return string;
  277. }
  278. ptr = string;
  279. do
  280. {
  281. *ptr = TOLOWER( *ptr );
  282. } while( *ptr++ );
  283. return string;
  284. }
  285. /*
  286. -----------------------------------------------------------------------------
  287. Function: StringToInteger -Convert string to integer.
  288. Parameters: string -[in] NUL-terminated string to be converted.
  289. error -[out] Error code. See header.
  290. Returns: An integer value.
  291. Notes:
  292. -----------------------------------------------------------------------------
  293. */
  294. PUBLIC SW32 StringToInteger( const char *string, W32 *error )
  295. {
  296. const char *ptr = string;
  297. SW32 temp;
  298. SW32 number = 0;
  299. W32 errortag = 0;
  300. _boolean bNegative = false;
  301. if( ! string || ! *string )
  302. {
  303. *error = SCE_NULL_VALUE;
  304. return 0;
  305. }
  306. if( *ptr == '-' )
  307. {
  308. bNegative = true;
  309. ptr++;
  310. }
  311. while( *ptr && ISNUMERIC( *ptr ) )
  312. {
  313. temp = number;
  314. number = (number * 10) + *ptr - '0';
  315. if( number < temp )
  316. {
  317. errortag &= SCE_BUFFER_OVERFLOW;
  318. }
  319. ptr++;
  320. }
  321. if( *ptr )
  322. {
  323. errortag &= SCE_NON_NUMERIC;
  324. }
  325. if( bNegative )
  326. {
  327. number = -number;
  328. }
  329. *error = errortag;
  330. return number;
  331. }
  332. /*
  333. -----------------------------------------------------------------------------
  334. Function: StringToFloat -Convert string to float.
  335. Parameters: string -[in] NUL-terminated string to be converted.
  336. error -[out] Error code. See header.
  337. Returns: A float value.
  338. Notes:
  339. -----------------------------------------------------------------------------
  340. */
  341. PUBLIC double StringToFloat( const char *string, W32 *error )
  342. {
  343. const char *ptr = string;
  344. double number = 0;
  345. SW32 exponent = 0;
  346. W32 expError;
  347. _boolean bNegative = false;
  348. *error = 0;
  349. if( ! string || ! *string )
  350. {
  351. *error &= SCE_NULL_VALUE;
  352. return 0;
  353. }
  354. if( *ptr == '-' )
  355. {
  356. bNegative = true;
  357. ptr++;
  358. }
  359. else if( *ptr == '+' )
  360. {
  361. ptr++;
  362. }
  363. while( *ptr && ISNUMERIC( *ptr ) )
  364. {
  365. number = (number * 10) + (double)(*ptr - '0');
  366. ptr++;
  367. }
  368. if( *ptr == '.' )
  369. {
  370. ptr++;
  371. while( *ptr && ISNUMERIC( *ptr ) )
  372. {
  373. number = (number * 10) + (double)(*ptr - '0');
  374. exponent--;
  375. ptr++;
  376. }
  377. }
  378. if( TOLOWER( *ptr ) == 'e' )
  379. {
  380. ptr++;
  381. exponent += StringToInteger( ptr, &expError );
  382. }
  383. if( bNegative )
  384. {
  385. number = -number;
  386. }
  387. if( expError )
  388. {
  389. *error |= expError;
  390. }
  391. return (number * pow( 10, exponent ));
  392. }