Angel 3.2
A 2D Game Prototyping Engine
StringUtil.cpp
1 
2 // Copyright (C) 2008-2013, Shane Liesegang
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of the copyright holder nor the names of any
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "stdafx.h"
31 #include "../Util/StringUtil.h"
32 
33 #include <sstream>
34 #include <algorithm>
35 #include <cctype>
36 
37 #ifdef WIN32
38  #define ci_strcmp _stricmp
39 #endif
40 #if defined(__APPLE__) || defined(__linux__)
41  #define ci_strcmp strcasecmp
42  #include <strings.h>
43 #endif
44 
45 const char StringUtil_WhiteSpaceChars[] = " \t\n\r";
46 
47 template <class T>
48 bool from_string(T& t,
49  const String& s,
50  std::ios_base& (*f)(std::ios_base&))
51 {
52  std::istringstream iss(s);
53  return !(iss >> f >> t).fail();
54 }
55 
56 template <class T>
57 String to_string(T& t,
58  std::ios_base& (*f)(std::ios_base&))
59 {
60  std::stringstream ss;
61  ss << f << t;
62  return ss.str();
63 }
64 
65 int StringToInt( const String& s )
66 {
67  int retVal = 0;
68  from_string<int>( retVal, s, std::dec );
69  return retVal;
70 }
71 
72 float StringToFloat( const String& s )
73 {
74  float retVal = 0.0f;
75  from_string<float>( retVal, s, std::dec );
76  return retVal;
77 }
78 
79 bool StringToBool( const String& s )
80 {
81  //compare to boolean vals first
82  if( !ci_strcmp( s.c_str(), "true") )
83  return true;
84  else if( !ci_strcmp(s.c_str(), "false") )
85  return false;
86  return StringToInt(s) != 0;
87 }
88 
89 Vector2 StringToVector2( const String& s )
90 {
91  StringList split = SplitString(s);
92  Vector2 retVal;
93 
94  if( split.size() > 0 )
95  retVal.X = StringToFloat(split[0]);
96 
97  if( split.size() > 1 )
98  retVal.Y = StringToFloat(split[1]);
99 
100  return retVal;
101 }
102 
103 
104 String IntToString( int val )
105 {
106  return to_string( val, std::dec );
107 }
108 
109 String FloatToString( float val )
110 {
111  return to_string( val, std::dec );
112 }
113 
114 String ULLIntToString( unsigned long long val )
115 {
116  return to_string( val, std::dec );
117 }
118 
119 String BoolToString( bool val )
120 {
121  return IntToString( val );
122 }
123 
124 String Vector2ToString( const Vector2& val )
125 {
126  return FloatToString( val.X ) + " " + FloatToString( val.Y );
127 }
128 
129 
130 String ToUpper( const String& s )
131 {
132  String retVal = s;
133  // explicit cast needed to resolve ambiguity
134  std::transform(retVal.begin(), retVal.end(), retVal.begin(),
135  (int(*)(int)) std::toupper);
136 
137  return retVal;
138 }
139 
140 String ToLower( const String& s )
141 {
142  String retVal = s;
143  // explicit cast needed to resolve ambiguity
144  std::transform(retVal.begin(), retVal.end(), retVal.begin(),
145  (int(*)(int)) std::tolower);
146 
147  return retVal;
148 }
149 
150 
151 StringList SplitString( const String& splitMe, const String& splitChars, bool bRemoveEmptyEntries /*=true*/)
152 {
153  StringList retVal;
154 
155  //iterate over string
156  String buildString;
157  for ( unsigned int i = 0; i < splitMe.length(); i++ )
158  {
159  char ch = splitMe[i];
160  if( splitChars.find( ch ) != String::npos)
161  {
162  //Add the build string to our return val
163  if( !bRemoveEmptyEntries || buildString.length() > 0 )
164  retVal.push_back( buildString );
165  buildString.clear();
166  }
167  else
168  {
169  buildString += ch;
170  }
171  }
172 
173  //handle any dangling strings
174  if( buildString.length() > 0 )
175  retVal.push_back( buildString );
176 
177  return retVal;
178 }
179 
180 StringList SplitString( const String& splitMe )
181 {
182  return SplitString( splitMe, StringUtil_WhiteSpaceChars );
183 }
184 
185 String JoinString (const StringList &list, const String& joinString)
186 {
187  String forReturn;
188 
189  for (int i=0; i < list.size(); i++)
190  {
191  forReturn += list[i];
192  if (i < list.size()-1)
193  {
194  forReturn += joinString;
195  }
196  }
197 
198  return forReturn;
199 }
200 
201 String TrimString( const String& trimMe, const String& trimChars )
202 {
203  String retVal;
204 
205  if( trimChars.length() == 0 )
206  return retVal;
207 
208  //trim from the front
209  int trimStart = -1;
210  for( unsigned int i = 0; i < trimMe.length(); i++ )
211  {
212  char ch = trimMe[i];
213  if( trimChars.find(ch) == String::npos)
214  {
215  trimStart = i;
216  break;
217  }
218  }
219 
220  if( trimStart >= 0 && trimStart < ((int)trimMe.length()) )
221  {
222  for( int i = (int)trimMe.length()-1; i >= 0; i-- )
223  {
224  char ch = trimMe[i];
225  if( trimChars.find(ch) == String::npos )
226  {
227  retVal = trimMe.substr( trimStart, i - trimStart + 1);
228  break;
229  }
230  }
231  }
232 
233  return retVal;
234 }
235 
236 String TrimString( const String& trimMe )
237 {
238  return TrimString( trimMe, StringUtil_WhiteSpaceChars );
239 }
240 
241 void GetCarCdr( StringList& inputStrings, String& car, String& cdr, int numInputStrings )
242 {
243  if( inputStrings.size() == 0 )
244  return;
245 
246  if( numInputStrings < 0 )
247  numInputStrings = (int)inputStrings.size();
248 
249  car = inputStrings[0];
250  for( int i = 1; i < numInputStrings; i++ )
251  {
252  cdr += inputStrings[i];
253  //Only add a space between args that aren't at the end of the input string
254  if( i < numInputStrings - 1 )
255  cdr += " ";
256 
257  }
258 }