Print corner coodinates in decimal form for more precision.
[gocam.git] / str.cc
blob49460eaead2b1d81389188ffb20b524572d3ad41
1 #include <math.h>
2 #include <string.h>
3 #include <cassert>
4 #include <cstdlib>
5 #include <climits>
6 #include "str.hh"
8 namespace str {
10 bool
11 read_line(std::string *str, FILE *file, bool do_chomp)
13 char *ptr;
14 char buf[4096];
16 str->erase();
17 while (1) {
18 ptr = fgets(buf, 4096, file);
19 if (!ptr)
20 break;
22 str->append(buf);
23 if ((*str)[str->length() - 1] == '\n') {
24 break;
28 if (ferror(file) || str->length() == 0)
29 return false;
31 if (do_chomp)
32 chomp(str);
34 return true;
37 bool
38 read_string(std::string *str, size_t length, FILE *file)
40 assert(length >= 0);
42 str->erase();
43 if (length == 0)
44 return true;
45 str->reserve(length);
47 // Read the string
48 char buf[4096];
49 size_t buf_size = 4096;
50 while (length > 0) {
51 if (length < buf_size)
52 buf_size = length;
53 size_t ret = fread(buf, buf_size, 1, file);
54 if (ret != 1)
55 return false;
57 str->append(buf, buf_size);
58 length -= buf_size;
61 return true;
64 bool read_file(std::string *str, FILE *file, size_t length)
66 const int chunk_size = 4096;
67 char buf[chunk_size];
68 str->clear();
70 // Read file buffer by buffer and process
71 while (1) {
73 // Grow the string for the next chunk
74 size_t pos = str->length();
75 size_t new_size = pos + chunk_size;
76 if (length > 0 && new_size > length)
77 new_size = length;
78 str->resize(new_size);
80 // Read the next chunk
81 int bytes_read = fread(buf, 1, str->length() - pos, file);
82 for (int i = 0; i < bytes_read; i++)
83 (*str)[pos + i] = buf[i];
84 if (bytes_read < chunk_size) {
85 str->resize(pos + bytes_read);
86 if (ferror(file))
87 return false;
88 return true;
91 if (str->length() == length)
92 return true;
96 void
97 chomp(std::string *str)
99 if (str->empty())
100 return;
102 if ((*str)[str->length() - 1] == '\n')
103 str->resize(str->length() - 1);
106 void
107 clean(std::string *str, const char *chars)
109 int i;
111 // Clean trailing chars
112 for (i = str->length(); i > 0; i--)
113 if (!strchr(chars, (*str)[i - 1]))
114 break;
115 str->erase(i);
117 // Clean leading chars
118 for (i = 0; i < (int)str->length(); i++)
119 if (!strchr(chars, (*str)[i]))
120 break;
121 str->erase(0, i);
124 void
125 split(const std::string *str, const char *delims, bool group,
126 std::vector<std::string> *fields, int num_fields)
128 int begin = 0;
129 int end = 0;
131 fields->clear();
132 while (begin < (int)str->length()) {
134 // If 'fields' fields was requested and, this is the last field,
135 // include the rest.
136 if (num_fields > 0 && (int)fields->size() == num_fields - 1) {
137 fields->push_back(str->substr(begin));
138 break;
141 // Find the string before the next delim
142 while (end < (int)str->length() && !strchr(delims, (*str)[end]))
143 end++;
144 fields->push_back(str->substr(begin, end - begin));
146 // Eat the delim or group of delims
147 end++;
148 if (group)
149 while (end < (int)str->length() && strchr(delims, (*str)[end]))
150 end++;
152 begin = end;
156 void
157 split_with_quotes(std::string *str, const char *delims, bool group,
158 std::vector<std::string> *fields)
160 enum { NONE, BACKSLASH, SINGLE, DOUBLE } mode = NONE;
161 size_t begin = 0;
162 size_t src = 0;
163 size_t tgt = 0;
165 fields->clear();
166 while (src < str->length()) {
168 // Find the string before the next delim while processing
169 // quotes.
170 while (src < str->length()) {
172 switch ((*str)[src]) {
174 case '\\':
175 if (mode == NONE)
176 mode = BACKSLASH;
177 else
178 (*str)[tgt++] = '\\';
179 break;
181 case '\'':
182 if (mode == NONE)
183 mode = SINGLE;
184 else if (mode == SINGLE)
185 mode = NONE;
186 else
187 (*str)[tgt++] = '\'';
188 break;
190 case '"':
191 if (mode == NONE)
192 mode = DOUBLE;
193 else if (mode == DOUBLE)
194 mode = NONE;
195 else
196 (*str)[tgt++] = '"';
197 break;
199 default:
200 (*str)[tgt++] = (*str)[src];
201 if (mode == NONE && strchr(delims, (*str)[src])) {
202 src++;
203 tgt--;
204 goto end_of_field;
206 break;
208 if (mode == BACKSLASH && (*str)[src] != '\\')
209 mode = NONE;
210 src++;
213 end_of_field:
214 fields->push_back(str->substr(begin, tgt - begin));
215 tgt++;
217 // Eat the delim or group of delims
218 if (group)
219 while (src < str->length() && strchr(delims, (*str)[src]))
220 src++;
221 begin = tgt;
225 long
226 str2long(const char *str, bool *ok)
228 char *endptr;
230 long value = strtol(str, &endptr, 10);
231 if (value == LONG_MIN || value == LONG_MAX) {
232 fprintf(stderr, "str2long(): value out of range\n");
233 exit(1);
236 if (*str == '\0' || *endptr != '\0')
237 *ok = false;
239 return value;
242 double
243 str2float(const char *str, bool *ok)
245 char *endptr;
247 float value = strtod(str, &endptr);
248 #ifdef HUGE_VALF
249 if (value == HUGE_VALF || value == -HUGE_VALF) {
250 fprintf(stderr, "str2float(): value out of range\n");
251 exit(1);
253 #else
254 if (value == HUGE_VAL || value == -HUGE_VAL) {
255 fprintf(stderr, "str2float(): value out of range\n");
256 exit(1);
258 #endif
260 if (*str == '\0' || *endptr != '\0')
261 *ok = false;
263 return value;
266 long
267 str2long(std::string *str, bool *ok)
269 return str2long(str->c_str(), ok);
272 double
273 str2float(std::string *str, bool *ok)
275 return str2float(str->c_str(), ok);