stringUnit.cpp

Engine/source/core/strings/stringUnit.cpp

More...

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