Add license text to the top of every source file.
[Tsunagari.git] / src / string.cpp
blob3a7e7341ee73dee63458b27f52dc0d7b3fe4aa17
1 /*********************************
2 ** Tsunagari Tile Engine **
3 ** string.cpp **
4 ** Copyright 2011-2012 OmegaSDG **
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/foreach.hpp>
32 #include <boost/algorithm/string.hpp> // for iequals
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 std::vector<std::string> splitStr(const std::string& input,
157 const std::string& delimiter)
159 std::vector<std::string> strlist;
160 size_t i = 0;
162 for (size_t pos = input.find(delimiter); pos != std::string::npos; pos = input.find(delimiter, i)) {
163 if (input.size() != i) // Don't save empty strings
164 strlist.push_back(input.substr(i, pos - i)); // Save
165 i = pos + delimiter.size();
168 if (input.size() != i)
169 strlist.push_back(input.substr(i));
170 return strlist;
173 std::vector<int> parseRanges(const std::string& format)
175 std::vector<int> ints;
176 std::vector<std::string> ranges = splitStr(format, ",");
177 BOOST_FOREACH(const std::string& range, ranges) {
178 size_t dash = range.find("-");
179 if (dash == std::string::npos) {
180 if (!isInteger(range)) {
181 Log::err("parseRanges", "not an integer");
182 continue;
184 int i = atoi(range.c_str());
185 ints.push_back(i);
187 else {
188 std::string rngbeg = range.substr(0, dash);
189 std::string rngend = range.substr(dash + 1);
190 if (!isInteger(rngbeg) || !isInteger(rngend)) {
191 Log::err("parseRanges", "not an integer");
192 continue;
194 int beg = atoi(rngbeg.c_str());
195 int end = atoi(rngend.c_str());
196 if (beg > end) {
197 Log::err("parseRanges", "beg > end");
198 continue;
200 for (int i = beg; i <= end; i++)
201 ints.push_back(i);
204 return ints;
207 std::string itostr(int in)
209 std::stringstream out;
210 out << in;
211 return out.str();