Fix INT_MAX definition on some newer systems.
[Tsunagari.git] / src / string.cpp
blobb40a3def52a79d3d538b897481ee84c3ae09ea50
1 /***************************************
2 ** Tsunagari Tile Engine **
3 ** string.cpp **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
7 // **********
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // **********
27 #include <climits>
28 #include <ctype.h>
29 #include <sstream>
30 #include <stdlib.h>
32 #include <Gosu/Math.hpp>
34 #include "log.h"
35 #include "string.h"
37 /**
38 * Matches regex /\s*-?\d+/
40 bool isInteger(const std::string& s)
42 const int space = 0;
43 const int sign = 1;
44 const int digit = 2;
46 int state = space;
48 for (size_t i = 0; i < s.size(); i++) {
49 char c = s[i];
50 if (state == space) {
51 if (isspace(c)) continue;
52 else state++;
54 if (state == sign) {
55 state++;
56 if (c == '-') continue;
58 if (state == digit) {
59 if (isdigit(c)) continue;
60 else return false;
63 return true;
66 /**
67 * Matches regex /\s*-?\d+\.?\d* / [sic: star-slash ends comment]
69 bool isDecimal(const std::string& s)
71 const int space = 0;
72 const int sign = 1;
73 const int digit = 2;
74 const int dot = 3;
75 const int digit2 = 4;
77 int state = space;
79 for (size_t i = 0; i < s.size(); i++) {
80 char c = s[i];
81 switch (state) {
82 case space:
83 if (isspace(c)) continue;
84 else state++;
85 case sign:
86 state++;
87 if (c == '-') continue;
88 case digit:
89 if (isdigit(c)) continue;
90 else state++;
91 case dot:
92 state++;
93 if (c == '.') continue;
94 else return false;
95 case digit2:
96 if (isdigit(c)) continue;
97 else return false;
100 return true;
104 * Matches "5-7,2,12-14" no whitespace.
106 bool isRanges(const std::string& s)
108 const int sign = 0;
109 const int digit = 1;
110 const int dash = 3;
111 const int comma = 4;
113 bool dashed = false;
115 int state = sign;
117 for (size_t i = 0; i < s.size(); i++) {
118 char c = s[i];
119 switch (state) {
120 case sign:
121 state++;
122 if (c == '-' || c == '+') break;
123 case digit:
124 if (isdigit(c)) break;
125 state++;
126 case dash:
127 state++;
128 if (c == '-') {
129 if (dashed) return false;
130 dashed = true;
131 state = sign;
132 break;
134 case comma:
135 state++;
136 if (c == ',') {
137 dashed = false;
138 state = sign;
139 break;
141 return false;
144 return true;
147 bool iequals(const std::string& a, const std::string& b)
149 if (a.length() != b.length())
150 return false;
151 size_t len = a.length();
152 for (int i = 0; i < len; i++) {
153 if (tolower(a[i]) != tolower(b[i]))
154 return false;
156 return true;
159 bool parseBool(const std::string& s)
161 static std::string true_ = "true";
162 static std::string yes = "yes";
163 static std::string on = "on";
165 return iequals(s, true_) ||
166 iequals(s, yes) ||
167 iequals(s, on) ||
168 s == "1";
171 int parseUInt(const std::string& s)
173 int i = atoi(s.c_str());
174 return Gosu::clamp(i, 0, INT_MAX);
177 int parseInt100(const std::string& s)
179 int i = atoi(s.c_str());
180 return Gosu::clamp(i, 0, 100);
183 std::vector<std::string> splitStr(const std::string& input,
184 const std::string& delimiter)
186 std::vector<std::string> strlist;
187 size_t i = 0;
189 for (size_t pos = input.find(delimiter); pos != std::string::npos; pos = input.find(delimiter, i)) {
190 if (input.size() != i) // Don't save empty strings
191 strlist.push_back(input.substr(i, pos - i)); // Save
192 i = pos + delimiter.size();
195 if (input.size() != i)
196 strlist.push_back(input.substr(i));
197 return strlist;
200 std::vector<int> parseRanges(const std::string& format)
202 std::vector<int> ints;
203 typedef std::vector<std::string> StringVector;
204 StringVector ranges = splitStr(format, ",");
205 for (StringVector::const_iterator it = ranges.begin(); it != ranges.end(); it++) {
206 const std::string& range = *it;
207 size_t dash = range.find("-");
208 if (dash == std::string::npos) {
209 if (!isInteger(range)) {
210 Log::err("parseRanges", "not an integer");
211 continue;
213 int i = atoi(range.c_str());
214 ints.push_back(i);
216 else {
217 std::string rngbeg = range.substr(0, dash);
218 std::string rngend = range.substr(dash + 1);
219 if (!isInteger(rngbeg) || !isInteger(rngend)) {
220 Log::err("parseRanges", "not an integer");
221 continue;
223 int beg = atoi(rngbeg.c_str());
224 int end = atoi(rngend.c_str());
225 if (beg > end) {
226 Log::err("parseRanges", "beg > end");
227 continue;
229 for (int i = beg; i <= end; i++)
230 ints.push_back(i);
233 return ints;
236 std::string itostr(int in)
238 std::stringstream out;
239 out << in;
240 return out.str();