stringFunctions.cpp
Engine/source/core/strings/stringFunctions.cpp
Public Typedefs
char
nat_char
Public Functions
int
compare_left(const nat_char * a, const nat_char * b)
int
dItoa(int n, char s)
bool
dStrEndsWith(const char * str1, const char * str2)
Check if one string ends with another.
bool
char *
dStrichr(char * str, char ch)
char *
dStripPath(const char * filename)
Strip the path from the input filename.
char *
dStrlwr(char * str)
int
dStrrev(char * str)
bool
dStrStartsWith(const char * str1, const char * str2)
Check if one string starts with another.
char *
dStrupr(char * str)
int
int
Detailed Description
Public Typedefs
typedef char nat_char
Public Functions
compare_left(const nat_char * a, const nat_char * b)
compare_right(const nat_char * a, const nat_char * b)
dItoa(int n, char s)
dPrintf(const char * format, ... )
dSprintf(char * buffer, U32 bufferSize, const char * format, ... )
dSscanf(const char * buffer, const char * format, ... )
dStrcatl(char * dst, dsize_t dstSize, ... )
dStrcmp(const UTF16 * str1, const UTF16 * str2)
dStrcpyl(char * dst, dsize_t dstSize, ... )
dStrdup_r(const char * src, const char * fileName, dsize_t lineNumber)
dStrEndsWith(const char * str1, const char * str2)
Check if one string ends with another.
dStrEqual(const char * str1, const char * str2)
Safe form of dStrcmp: checks both strings for NULL before comparing.
dStrichr(char * str, char ch)
dStrichr(const char * str, char ch)
dStripPath(const char * filename)
Strip the path from the input filename.
dStristr(char * str1, const char * str2)
dStristr(const char * str1, const char * str2)
dStrlcat(char * dst, const char * src, dsize_t dstSize)
dStrlcpy(char * dst, const char * src, dsize_t dstSize)
dStrlwr(char * str)
dStrnatcasecmp(const nat_char * a, const nat_char * b)
dStrnatcmp(const nat_char * a, const nat_char * b)
dStrrev(char * str)
dStrStartsWith(const char * str1, const char * str2)
Check if one string starts with another.
dStrupr(char * str)
dVprintf(const char * format, va_list arglist)
dVsprintf(char * buffer, U32 bufferSize, const char * format, va_list arglist)
nat_isdigit(nat_char a)
nat_isspace(nat_char a)
nat_toupper(nat_char a)
strnatcmp0(const nat_char * a, const nat_char * b, S32 fold_case)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include <stdarg.h> 25#include <stdio.h> 26 27#include "core/strings/stringFunctions.h" 28#include "platform/platform.h" 29 30 31#if defined(TORQUE_OS_WIN) 32// This standard function is not defined when compiling with VC7... 33#define vsnprintf _vsnprintf 34#endif 35 36 37//----------------------------------------------------------------------------- 38 39// Original code from: http://sourcefrog.net/projects/natsort/ 40// Somewhat altered here. 41//TODO: proper UTF8 support; currently only working for single-byte characters 42 43/* -*- mode: c; c-file-style: "k&r" -*- 44 45 strnatcmp.c -- Perform 'natural order' comparisons of strings in C. 46 Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net> 47 48 This software is provided 'as-is', without any express or implied 49 warranty. In no event will the authors be held liable for any damages 50 arising from the use of this software. 51 52 Permission is granted to anyone to use this software for any purpose, 53 including commercial applications, and to alter it and redistribute it 54 freely, subject to the following restrictions: 55 56 1. The origin of this software must not be misrepresented; you must not 57 claim that you wrote the original software. If you use this software 58 in a product, an acknowledgment in the product documentation would be 59 appreciated but is not required. 60 2. Altered source versions must be plainly marked as such, and must not be 61 misrepresented as being the original software. 62 3. This notice may not be removed or altered from any source distribution. 63*/ 64 65 66/* partial change history: 67 * 68 * 2004-10-10 mbp: Lift out character type dependencies into macros. 69 * 70 * Eric Sosman pointed out that ctype functions take a parameter whose 71 * value must be that of an unsigned int, even on platforms that have 72 * negative chars in their default char type. 73 */ 74 75typedef char nat_char; 76 77/* These are defined as macros to make it easier to adapt this code to 78 * different characters types or comparison functions. */ 79static inline int 80nat_isdigit( nat_char a ) 81{ 82 return dIsdigit( a ); 83} 84 85 86static inline int 87nat_isspace( nat_char a ) 88{ 89 return dIsspace( a ); 90} 91 92 93static inline nat_char 94nat_toupper( nat_char a ) 95{ 96 return dToupper( a ); 97} 98 99 100 101static S32 102compare_right(const nat_char* a, const nat_char* b) 103{ 104 S32 bias = 0; 105 106 /* The longest run of digits wins. That aside, the greatest 107 value wins, but we can't know that it will until we've scanned 108 both numbers to know that they have the same magnitude, so we 109 remember it in BIAS. */ 110 for (;; a++, b++) { 111 if (!nat_isdigit(*a) && !nat_isdigit(*b)) 112 break; 113 else if (!nat_isdigit(*a)) 114 return -1; 115 else if (!nat_isdigit(*b)) 116 return +1; 117 else if (*a < *b) { 118 if (!bias) 119 bias = -1; 120 } else if (*a > *b) { 121 if (!bias) 122 bias = +1; 123 } else if (!*a && !*b) 124 return bias; 125 } 126 127 return bias; 128} 129 130 131static int 132compare_left(const nat_char* a, const nat_char* b) 133{ 134 /* Compare two left-aligned numbers: the first to have a 135 different value wins. */ 136 for (;; a++, b++) { 137 if (!nat_isdigit(*a) && !nat_isdigit(*b)) 138 break; 139 else if (!nat_isdigit(*a)) 140 return -1; 141 else if (!nat_isdigit(*b)) 142 return +1; 143 else if (*a < *b) 144 return -1; 145 else if (*a > *b) 146 return +1; 147 } 148 149 return 0; 150} 151 152 153static S32 strnatcmp0(const nat_char* a, const nat_char* b, S32 fold_case) 154{ 155 S32 ai, bi; 156 nat_char ca, cb; 157 S32 fractional, result; 158 159 ai = bi = 0; 160 while (1) { 161 ca = a[ai]; cb = b[bi]; 162 163 /* skip over leading spaces or zeros */ 164 while (nat_isspace(ca)) 165 ca = a[++ai]; 166 167 while (nat_isspace(cb)) 168 cb = b[++bi]; 169 170 /* process run of digits */ 171 if (nat_isdigit(ca) && nat_isdigit(cb)) { 172 fractional = (ca == '0' || cb == '0'); 173 174 if (fractional) { 175 if ((result = compare_left(a+ai, b+bi)) != 0) 176 return result; 177 } else { 178 if ((result = compare_right(a+ai, b+bi)) != 0) 179 return result; 180 } 181 } 182 183 if (!ca && !cb) { 184 /* The strings compare the same. Perhaps the caller 185 will want to call strcmp to break the tie. */ 186 return 0; 187 } 188 189 if (fold_case) { 190 ca = nat_toupper(ca); 191 cb = nat_toupper(cb); 192 } 193 194 if (ca < cb) 195 return -1; 196 else if (ca > cb) 197 return +1; 198 199 ++ai; ++bi; 200 } 201} 202 203 204S32 dStrnatcmp(const nat_char* a, const nat_char* b) { 205 return strnatcmp0(a, b, 0); 206} 207 208 209/* Compare, recognizing numeric string and ignoring case. */ 210S32 dStrnatcasecmp(const nat_char* a, const nat_char* b) { 211 return strnatcmp0(a, b, 1); 212} 213 214//------------------------------------------------------------------------------ 215// non-standard string functions 216 217char *dStrdup_r(const char *src, const char *fileName, dsize_t lineNumber) 218{ 219 dsize_t bufferLen = dStrlen(src) + 1; 220 char *buffer = (char *) dMalloc_r(bufferLen, fileName, lineNumber); 221 dStrcpy(buffer, src, bufferLen); 222 return buffer; 223} 224 225char* dStrichr( char* str, char ch ) 226{ 227 AssertFatal( str != NULL, "dStrichr - NULL string" ); 228 229 if( !ch ) 230 return dStrchr( str, ch ); 231 232 char c = dToupper( ch ); 233 while( *str ) 234 { 235 if( dToupper( *str ) == c ) 236 return str; 237 238 ++ str; 239 } 240 241 return NULL; 242} 243 244const char* dStrichr( const char* str, char ch ) 245{ 246 AssertFatal( str != NULL, "dStrichr - NULL string" ); 247 248 if( !ch ) 249 return dStrchr( str, ch ); 250 251 char c = dToupper( ch ); 252 while( *str ) 253 { 254 if( dToupper( *str ) == c ) 255 return str; 256 257 ++ str; 258 } 259 260 return NULL; 261} 262 263// concatenates a list of src's onto the end of dst 264// the list of src's MUST be terminated by a NULL parameter 265// dStrcatl(dst, sizeof(dst), src1, src2, NULL); 266char* dStrcatl(char *dst, dsize_t dstSize, ...) 267{ 268 const char* src = NULL; 269 char *p = dst; 270 271 AssertFatal(dstSize > 0, "dStrcatl: destination size is set zero"); 272 dstSize--; // leave room for string termination 273 274 // find end of dst 275 while (dstSize && *p++) 276 dstSize--; 277 278 va_list args; 279 va_start(args, dstSize); 280 281 // concatenate each src to end of dst 282 while ( (src = va_arg(args, const char*)) != NULL ) 283 { 284 while( dstSize && *src ) 285 { 286 *p++ = *src++; 287 dstSize--; 288 } 289 } 290 291 va_end(args); 292 293 // make sure the string is terminated 294 *p = 0; 295 296 return dst; 297} 298 299 300// copy a list of src's into dst 301// the list of src's MUST be terminated by a NULL parameter 302// dStrccpyl(dst, sizeof(dst), src1, src2, NULL); 303char* dStrcpyl(char *dst, dsize_t dstSize, ...) 304{ 305 const char* src = NULL; 306 char *p = dst; 307 308 AssertFatal(dstSize > 0, "dStrcpyl: destination size is set zero"); 309 dstSize--; // leave room for string termination 310 311 va_list args; 312 va_start(args, dstSize); 313 314 // concatenate each src to end of dst 315 while ( (src = va_arg(args, const char*)) != NULL ) 316 { 317 while( dstSize && *src ) 318 { 319 *p++ = *src++; 320 dstSize--; 321 } 322 } 323 324 va_end(args); 325 326 // make sure the string is terminated 327 *p = 0; 328 329 return dst; 330} 331 332 333S32 dStrcmp(const UTF16 *str1, const UTF16 *str2) 334{ 335#if defined(TORQUE_OS_WIN) 336 return wcscmp( reinterpret_cast<const wchar_t *>( str1 ), reinterpret_cast<const wchar_t *>( str2 ) ); 337#else 338 S32 ret; 339 const UTF16 *a, *b; 340 a = str1; 341 b = str2; 342 343 while( ((ret = *a - *b) == 0) && *a && *b ) 344 a++, b++; 345 346 return ret; 347#endif 348} 349 350char* dStrupr(char *str) 351{ 352#if defined(TORQUE_OS_WIN) 353 return _strupr(str); 354#else 355 if (str == NULL) 356 return(NULL); 357 358 char* saveStr = str; 359 while (*str) 360 { 361 *str = toupper(*str); 362 str++; 363 } 364 return saveStr; 365#endif 366} 367 368char* dStrlwr(char *str) 369{ 370#if defined(TORQUE_OS_WIN) 371 return _strlwr(str); 372#else 373 if (str == NULL) 374 return(NULL); 375 376 char* saveStr = str; 377 while (*str) 378 { 379 *str = tolower(*str); 380 str++; 381 } 382 return saveStr; 383#endif 384} 385 386//------------------------------------------------------------------------------ 387 388S32 dStrlcat(char *dst, const char *src, dsize_t dstSize) 389{ 390 //TODO: Do other platforms support strlcat in their libc 391#ifdef TORQUE_OS_MAC 392 S32 len = strlcat(dst, src, dstSize); 393 394 AssertWarn(len < dstSize, "Buffer too small in call to dStrlcat!"); 395 396 return len; 397#else //TORQUE_OS_MAC 398 S32 dstLen = dStrlen(dst); 399 S32 srcLen = dStrlen(src); 400 S32 copyLen = srcLen; 401 402 //Check for buffer overflow and don't allow it. Warn on debug so we can fix it 403 AssertWarn(dstLen + copyLen < dstSize, "Buffer too small in call to dStrlcat!"); 404 if (dstLen + copyLen + 1 > dstSize) 405 { 406 copyLen = dstSize - dstLen - 1; 407 } 408 409 //Copy src after dst and null terminate 410 memcpy(dst + dstLen, src, copyLen); 411 dst[dstLen + copyLen] = 0; 412 413 //Return the length of the string we would have generated 414 return dstLen + srcLen; 415#endif //TORQUE_OS_MAC 416} 417 418S32 dStrlcpy(char *dst, const char *src, dsize_t dstSize) 419{ 420 //TODO: Do other platforms support strlcpy in their libc 421#ifdef TORQUE_OS_MAC 422 S32 len = strlcpy(dst, src, dstSize); 423 424 AssertWarn(len < dstSize, "Buffer too small in call to dStrlcpy!"); 425 426 return len; 427#else //TORQUE_OS_MAC 428 S32 srcLen = dStrlen(src); 429 S32 copyLen = srcLen; 430 431 //Check for buffer overflow and don't allow it. Warn on debug so we can fix it 432 AssertWarn(copyLen < dstSize, "Buffer too small in call to dStrlcpy!"); 433 if (srcLen + 1 > dstSize) 434 { 435 copyLen = dstSize - 1; 436 } 437 438 //Copy src and null terminate 439 memcpy(dst, src, copyLen); 440 dst[copyLen] = 0; 441 442 //Return the length of the string we would have generated 443 return srcLen; 444#endif //TORQUE_OS_MAC 445} 446 447//------------------------------------------------------------------------------ 448// standard I/O functions 449 450void dPrintf(const char *format, ...) 451{ 452 va_list args; 453 va_start(args, format); 454 vprintf(format, args); 455 va_end(args); 456} 457 458S32 dVprintf(const char *format, va_list arglist) 459{ 460 return (S32)vprintf(format, arglist); 461} 462 463S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...) 464{ 465 va_list args; 466 va_start(args, format); 467 468 S32 len = vsnprintf(buffer, bufferSize, format, args); 469 va_end(args); 470 471 AssertWarn( len < bufferSize, "Buffer too small in call to dSprintf!" ); 472 473 return (len); 474} 475 476 477S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, va_list arglist) 478{ 479 S32 len = vsnprintf(buffer, bufferSize, format, arglist); 480 481 AssertWarn( len < bufferSize, "Buffer too small in call to dVsprintf!" ); 482 483 return (len); 484} 485 486 487S32 dSscanf(const char *buffer, const char *format, ...) 488{ 489#if defined(TORQUE_OS_WIN) 490 va_list args; 491 va_start(args, format); 492 493 // Boy is this lame. We have to scan through the format string, and find out how many 494 // arguments there are. We'll store them off as void*, and pass them to the sscanf 495 // function through specialized calls. We're going to have to put a cap on the number of args that 496 // can be passed, 8 for the moment. Sigh. 497 static void* sVarArgs[20]; 498 U32 numArgs = 0; 499 500 for (const char* search = format; *search != '\0'; search++) { 501 if (search[0] == '%' && search[1] != '%') 502 numArgs++; 503 } 504 AssertFatal(numArgs <= 20, "Error, too many arguments to lame implementation of dSscanf. Fix implmentation"); 505 506 // Ok, we have the number of arguments... 507 for (U32 i = 0; i < numArgs; i++) 508 sVarArgs[i] = va_arg(args, void*); 509 va_end(args); 510 511 switch (numArgs) { 512 case 0: return 0; 513 case 1: return sscanf(buffer, format, sVarArgs[0]); 514 case 2: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1]); 515 case 3: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2]); 516 case 4: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3]); 517 case 5: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4]); 518 case 6: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5]); 519 case 7: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6]); 520 case 8: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7]); 521 case 9: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8]); 522 case 10: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9]); 523 case 11: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10]); 524 case 12: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11]); 525 case 13: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12]); 526 case 14: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13]); 527 case 15: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14]); 528 case 16: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15]); 529 case 17: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16]); 530 case 18: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16], sVarArgs[17]); 531 case 19: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16], sVarArgs[17], sVarArgs[18]); 532 case 20: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16], sVarArgs[17], sVarArgs[18], sVarArgs[19]); 533 } 534 return 0; 535#else 536 va_list args; 537 va_start(args, format); 538 S32 res = vsscanf(buffer, format, args); 539 va_end(args); 540 return res; 541#endif 542} 543 544/// Safe form of dStrcmp: checks both strings for NULL before comparing 545bool dStrEqual(const char* str1, const char* str2) 546{ 547 if (!str1 || !str2) 548 return false; 549 else 550 return (String::compare(str1, str2) == 0); 551} 552 553/// Check if one string starts with another 554bool dStrStartsWith(const char* str1, const char* str2) 555{ 556 return !dStrnicmp(str1, str2, dStrlen(str2)); 557} 558 559/// Check if one string ends with another 560bool dStrEndsWith(const char* str1, const char* str2) 561{ 562 const char *p = str1 + dStrlen(str1) - dStrlen(str2); 563 return ((p >= str1) && !dStricmp(p, str2)); 564} 565 566/// Strip the path from the input filename 567char* dStripPath(const char* filename) 568{ 569 const char* itr = filename + dStrlen(filename); 570 while(--itr != filename) { 571 if (*itr == '/' || *itr == '\\') { 572 itr++; 573 break; 574 } 575 } 576 return dStrdup(itr); 577} 578 579char* dStristr( char* str1, const char* str2 ) 580{ 581 if( !str1 || !str2 ) 582 return NULL; 583 584 // Slow but at least we have it. 585 586 U32 str2len = strlen( str2 ); 587 while( *str1 ) 588 { 589 if( strncasecmp( str1, str2, str2len ) == 0 ) 590 return str1; 591 592 ++ str1; 593 } 594 595 return NULL; 596} 597 598const char* dStristr( const char* str1, const char* str2 ) 599{ 600 return dStristr( const_cast< char* >( str1 ), str2 ); 601} 602 603int dStrrev(char* str) 604{ 605 int l=<a href="/coding/file/stringfunctions_8h/#stringfunctions_8h_1ab08bdbead2d56aa91fb39c1d4aa3a436">dStrlen</a>(str)-1; //get the string length 606 for(int x=0;x < l;x++,l--) 607 { 608 str[x]^=str[l]; //triple XOR Trick 609 str[l]^=str[x]; //for not using a temp 610 str[x]^=str[l]; 611 } 612 return l; 613} 614 615int dItoa(int n, char s[]) 616{ 617 int i, sign; 618 619 if ((sign = n) < 0) /* record sign */ 620 n = -n; /* make n positive */ 621 i = 0; 622 do { /* generate digits in reverse order */ 623 s[i++] = n % 10 + '0'; /* get next digit */ 624 } while ((n /= 10) > 0); /* delete it */ 625 if (sign < 0) 626 s[i++] = '-'; 627 s[i] = '\0'; 628 dStrrev(s); 629 return dStrlen(s); 630} 631