stringUnit.cpp
Engine/source/core/strings/stringUnit.cpp
Namespaces:
namespace
These functions are used for chunking up strings by delimiter.
Detailed Description
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 "core/strings/stringFunctions.h" 25#include "core/strings/stringUnit.h" 26#include "console/console.h" 27 28namespace StringUnit 29{ 30 static char _returnBuffer[ 2048 ]; 31 32 const char *getUnit(const char *string, U32 index, const char *set, char* buffer, U32 bufferSize) 33 { 34 if( !buffer ) 35 { 36 buffer = _returnBuffer; 37 bufferSize = sizeof( _returnBuffer ); 38 } 39 40 AssertFatal( bufferSize, "StringUnit::getUnit - bufferSize cannot be zero!" ); 41 if( !bufferSize ) 42 return ""; 43 44 buffer[0] = 0; 45 46 U32 sz; 47 while(index--) 48 { 49 if(!*string) 50 return buffer; 51 52 sz = dStrcspn(string, set); 53 if (string[sz] == 0) 54 return buffer; 55 56 string += (sz + 1); 57 } 58 sz = dStrcspn(string, set); 59 if (sz == 0) 60 return buffer; 61 62 AssertWarn( sz + 1 < bufferSize, "Size of returned string too large for return buffer" ); 63 sz = getMin( sz, bufferSize - 1 ); 64 65 dStrncpy(buffer, string, sz); 66 buffer[sz] = '\0'; 67 return buffer; 68 } 69 70 const char *getUnits(const char *string, S32 startIndex, S32 endIndex, const char *set) 71 { 72 if( startIndex > endIndex ) 73 return ""; 74 75 S32 sz; 76 S32 index = startIndex; 77 while(index--) 78 { 79 if(!*string) 80 return ""; 81 sz = dStrcspn(string, set); 82 if (string[sz] == 0) 83 return ""; 84 string += (sz + 1); 85 } 86 const char *startString = string; 87 88 for( U32 i = startIndex; i <= endIndex && *string; i ++ ) 89 { 90 sz = dStrcspn(string, set); 91 string += sz; 92 93 if( i < endIndex ) 94 string ++; 95 } 96 97 S32 totalSize = ( S32 )( string - startString ); 98 AssertWarn( totalSize + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); 99 totalSize = getMin( totalSize, S32( sizeof( _returnBuffer ) - 1 ) ); 100 101 if( totalSize > 0 ) 102 { 103 char *ret = &_returnBuffer[0]; 104 dStrncpy( ret, startString, totalSize ); 105 ret[ totalSize ] = '\0'; 106 107 return ret; 108 } 109 110 return ""; 111 } 112 113 U32 getUnitCount(const char *string, const char *set) 114 { 115 U32 count = 0; 116 U8 last = 0; 117 while(*string) 118 { 119 last = *string++; 120 121 for(U32 i =0; set[i]; i++) 122 { 123 if(last == set[i]) 124 { 125 count++; 126 last = 0; 127 break; 128 } 129 } 130 } 131 if(last) 132 count++; 133 return count; 134 } 135 136 137 const char* setUnit(const char *string, U32 index, const char *replace, const char *set) 138 { 139 U32 sz; 140 const char *start = string; 141 142 AssertFatal( dStrlen(string) + dStrlen(replace) + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); 143 144 char *ret = &_returnBuffer[0]; 145 ret[0] = '\0'; 146 U32 padCount = 0; 147 148 while(index--) 149 { 150 sz = dStrcspn(string, set); 151 if(string[sz] == 0) 152 { 153 string += sz; 154 padCount = index + 1; 155 break; 156 } 157 else 158 string += (sz + 1); 159 } 160 // copy first chunk 161 sz = string-start; 162 dStrncpy(ret, start, sz); 163 for(U32 i = 0; i < padCount; i++) 164 ret[sz++] = set[0]; 165 166 // replace this unit 167 ret[sz] = '\0'; 168 dStrcat(ret, replace, 2048); 169 170 // copy remaining chunks 171 sz = dStrcspn(string, set); // skip chunk we're replacing 172 if(!sz && !string[sz]) 173 return ret; 174 175 string += sz; 176 dStrcat(ret, string, 2048); 177 return ret; 178 } 179 180 181 const char* removeUnit(const char *string, U32 index, const char *set) 182 { 183 U32 sz; 184 const char *start = string; 185 AssertFatal( dStrlen(string) + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" ); 186 187 char *ret = &_returnBuffer[0]; 188 ret[0] = '\0'; 189 190 while(index--) 191 { 192 sz = dStrcspn(string, set); 193 // if there was no unit out there... return the original string 194 if(string[sz] == 0) 195 return start; 196 else 197 string += (sz + 1); 198 } 199 // copy first chunk 200 sz = string-start; 201 dStrncpy(ret, start, sz); 202 ret[sz] = 0; 203 204 // copy remaining chunks 205 sz = dStrcspn(string, set); // skip chunk we're removing 206 207 if(string[sz] == 0) { // if that was the last... 208 if(string != start) { 209 ret[string - start - 1] = 0; // then kill any trailing delimiter 210 } 211 return ret; // and bail 212 } 213 214 string += sz + 1; // skip the extra field delimiter 215 dStrcat(ret, string, 2048); 216 return ret; 217 } 218} 219