rm boost/{format,foreach}; reduce #includes; small fixes
[Tsunagari.git] / src / string.cpp
blob14b2846185a2893cb1e638b5d5b13ee324f5f66e
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 <ctype.h>
28 #include <sstream>
29 #include <stdlib.h>
31 #include <boost/algorithm/string.hpp> // for iequals
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 parseBool(const std::string& s)
149 // boost::equals is case-insensative
150 return boost::iequals(s, "true") ||
151 boost::iequals(s, "yes") ||
152 boost::iequals(s, "on") ||
153 s == "1";
156 int parseUInt(const std::string& s)
158 int i = atoi(s.c_str());
159 return Gosu::clamp(i, 0, INT_MAX);
162 int parseInt100(const std::string& s)
164 int i = atoi(s.c_str());
165 return Gosu::clamp(i, 0, 100);
168 std::vector<std::string> splitStr(const std::string& input,
169 const std::string& delimiter)
171 std::vector<std::string> strlist;
172 size_t i = 0;
174 for (size_t pos = input.find(delimiter); pos != std::string::npos; pos = input.find(delimiter, i)) {
175 if (input.size() != i) // Don't save empty strings
176 strlist.push_back(input.substr(i, pos - i)); // Save
177 i = pos + delimiter.size();
180 if (input.size() != i)
181 strlist.push_back(input.substr(i));
182 return strlist;
185 std::vector<int> parseRanges(const std::string& format)
187 std::vector<int> ints;
188 typedef std::vector<std::string> StringVector;
189 StringVector ranges = splitStr(format, ",");
190 for (StringVector::const_iterator it = ranges.begin(); it != ranges.end(); it++) {
191 const std::string& range = *it;
192 size_t dash = range.find("-");
193 if (dash == std::string::npos) {
194 if (!isInteger(range)) {
195 Log::err("parseRanges", "not an integer");
196 continue;
198 int i = atoi(range.c_str());
199 ints.push_back(i);
201 else {
202 std::string rngbeg = range.substr(0, dash);
203 std::string rngend = range.substr(dash + 1);
204 if (!isInteger(rngbeg) || !isInteger(rngend)) {
205 Log::err("parseRanges", "not an integer");
206 continue;
208 int beg = atoi(rngbeg.c_str());
209 int end = atoi(rngend.c_str());
210 if (beg > end) {
211 Log::err("parseRanges", "beg > end");
212 continue;
214 for (int i = beg; i <= end; i++)
215 ints.push_back(i);
218 return ints;
221 std::string itostr(int in)
223 std::stringstream out;
224 out << in;
225 return out.str();