//----------------------------------------------------------------------------- // Copyright (c) 2013 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "console/console.h" #include "string/stringUnit.h" #include "string/stringTable.h" #include "stringUnit_ScriptBinding.h" namespace StringUnit { static char _returnBuffer[4096]; StringTableEntry getStringTableUnit(const char* string, U32 index, const char* set) { return StringTable->insert( getUnit( string, index, set ) ); } const char* getUnit(const char* string, U32 index, const char* set) { U32 sz; while(index--) { if(!*string) return ""; sz = dStrcspn(string, set); if (string[sz] == 0) return ""; string += (sz + 1); } sz = dStrcspn(string, set); if (sz == 0) return ""; AssertFatal( sz + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); char *ret = &_returnBuffer[0]; dStrncpy(ret, string, sz); ret[sz] = '\0'; return ret; } const char* getUnits(const char* string, S32 startIndex, S32 endIndex, const char* set) { // [neo, 5/11/2007 - #2998] // Range check if( startIndex > endIndex ) return ""; S32 sz; S32 index = startIndex; while(index--) { if(!*string) return ""; sz = dStrcspn(string, set); if (string[sz] == 0) return ""; string += (sz + 1); } const char *startString = string; while(startIndex <= endIndex--) { sz = dStrcspn(string, set); string += sz; if (*string == 0) break; string++; } if(!*string) string++; // [neo, 5/11/2007 - #2998] // Another case of the U32 wrapping from 0 to boom! If totalSize < 0 it will // wrap to somewhere around U32 max and that is a lot for dStrncpy to overrun! //U32 totalSize = (U32(string - startString)); S32 totalSize = (S32)(string - startString); AssertFatal( totalSize < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); if( totalSize > 0 ) { char *ret = &_returnBuffer[0]; dStrncpy(ret, startString, totalSize - 1); ret[totalSize-1] = '\0'; return ret; } return ""; } U32 getUnitCount(const char *string, const char *set) { U32 count = 0; U8 last = 0; while(*string) { last = *string++; for(U32 i =0; set[i]; i++) { if(last == set[i]) { count++; last = 0; break; } } } if(last) count++; return count; } const char* setUnit(const char *string, U32 index, const char *replace, const char *set) { U32 sz; const char *start = string; AssertFatal( dStrlen(string) + dStrlen(replace) + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); char *ret = &_returnBuffer[0]; ret[0] = '\0'; U32 padCount = 0; while(index--) { sz = dStrcspn(string, set); if(string[sz] == 0) { string += sz; padCount = index + 1; break; } else string += (sz + 1); } // copy first chunk sz = (U32)(string-start); dStrncpy(ret, start, sz); for(U32 i = 0; i < padCount; i++) ret[sz++] = set[0]; // replace this unit ret[sz] = '\0'; dStrcat(ret, replace); // copy remaining chunks sz = dStrcspn(string, set); // skip chunk we're replacing if(!sz && !string[sz]) return ret; string += sz; dStrcat(ret, string); return ret; } const char* removeUnit(const char *string, U32 index, const char *set) { U32 sz; const char *start = string; AssertFatal( dStrlen(string) + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); char *ret = &_returnBuffer[0]; ret[0] = '\0'; while(index--) { sz = dStrcspn(string, set); // if there was no unit out there... return the original string if(string[sz] == 0) return start; else string += (sz + 1); } // copy first chunk sz = (U32)(string-start); dStrncpy(ret, start, sz); ret[sz] = 0; // copy remaining chunks sz = dStrcspn(string, set); // skip chunk we're removing if(string[sz] == 0) { // if that was the last... if(string != start) { ret[string - start - 1] = 0; // then kill any trailing delimiter } return ret; // and bail } string += sz + 1; // skip the extra field delimiter dStrcat(ret, string); return ret; } };