Added random_real
[ail.git] / source / string.cpp
blobf495660ec33689a52f1193bd2a877343fdbe3903
1 #include <ail/string.hpp>
2 #include <ail/array.hpp>
4 namespace ail
6 bool is_alpha(char input)
8 return (input >= 'A' && input <= 'Z') || (input >= 'a' && input <= 'z');
11 bool is_digit(char input)
13 return input >= '0' && input <= '9';
16 bool is_oct_digit(char input)
18 return input >= '0' && input <= '7';
21 bool is_hex_digit(char input)
23 return is_digit(input) || (input >= 'a' && input <= 'f') || (input >= 'A' && input <= 'F');
26 bool is_whitespace(char input)
28 return input == '\t' || input == '\n' || input == '\r' || input == ' ';
31 char to_upper(char input)
33 char output = input;
34 if(output >= 'a' && output <= 'z')
35 output -= 32;
36 return output;
39 char to_lower(char input)
41 char output = input;
42 if(output >= 'A' && output <= 'Z')
43 output += 32;
44 return output;
47 std::string to_upper(std::string const & input)
49 std::string output = input;
50 for(std::string::iterator i = output.begin(), end = output.end(); i != end; ++i)
52 char & current_char = *i;
53 current_char = to_upper(current_char);
55 return output;
58 std::string to_lower(std::string const & input)
60 std::string output = input;
61 for(std::string::iterator i = output.begin(), end = output.end(); i != end; ++i)
63 char & current_char = *i;
64 current_char = to_lower(current_char);
66 return output;
69 std::string left_trim(std::string const & input)
71 std::string output = input;
72 std::string::iterator
73 begin = output.begin(),
74 end = output.end();
76 for(;; ++begin)
78 if(begin >= end)
79 return "";
81 if(is_whitespace(*begin) == false)
82 break;
85 output.erase(output.begin(), begin);
87 return output;
90 std::string right_trim(std::string const & input)
92 std::string output = input;
93 std::string::iterator
94 end = output.end();
96 for(end -= 1; is_whitespace(*end); --end);
98 output.erase(end + 1, output.end());
100 return output;
103 std::string trim(std::string const & input)
105 std::string output = input;
106 std::string::iterator
107 begin = output.begin(),
108 end = output.end();
110 for(;; ++begin)
112 if(begin >= end)
113 return "";
115 if(is_whitespace(*begin) == false)
116 break;
119 for(end -= 1; is_whitespace(*end); --end);
121 std::size_t offset_begin = begin - output.begin();
122 std::size_t offset_end = end - output.begin();
123 output = output.substr(offset_begin, offset_end - offset_begin + 1);
125 return output;
128 unsigned long count_strings(std::string const & input, std::string const & target)
130 if(input.empty() == true)
131 return 0;
133 if(target.empty() == true)
134 throw exception("Empty target");
136 unsigned long output = 0;
138 std::size_t target_length = target.length();
139 std::size_t result = input.find(target);
141 while(result != std::string::npos)
143 ++output;
144 result = input.find(target, result + target_length);
147 return output;
150 std::string erase_string(std::string const & input, std::string const & target)
152 std::stringstream output;
154 if(target.empty())
155 return input;
157 std::size_t
158 target_length = target.length(),
159 offset = input.find(target),
160 last_offset = 0;
162 while(offset != std::string::npos)
164 output << input.substr(last_offset, offset - last_offset);
165 offset += target_length;
166 last_offset = offset;
167 offset = input.find(target, offset);
170 output << input.substr(last_offset);
172 return output.str();
175 std::string replace_string(std::string const & input, std::string const & target, std::string const & replacement)
177 std::string output = input;
179 if(target.empty() == true)
180 throw exception("Empty target");
182 if(target == replacement)
183 return input;
185 std::size_t target_length = target.length();
186 std::size_t replacement_length = replacement.length();
188 std::size_t result = output.find(target);
190 while(result != std::string::npos)
192 output.replace(result, target_length, replacement);
193 result = output.find(target, result);
196 return output;
200 void tokenise(std::string const & input, string_vector & output, char delimiter)
202 std::string token;
203 std::istringstream stream(input);
204 while(std::getline(stream, token, delimiter))
205 output.push_back(token);
209 void tokenise(std::string const & input, std::string const & delimiter, string_vector & output)
211 std::size_t
212 delimiter_length = delimiter.length(),
213 left = 0,
214 right = input.find(delimiter),
215 count = 1;
217 while(right != std::string::npos)
219 std::string new_token(input.substr(left, right - left));
220 left = right + delimiter_length;
221 right = input.find(delimiter, left);
222 count++;
225 left = 0;
226 right = input.find(delimiter);
228 output.reserve(count);
230 while(right != std::string::npos)
232 std::string new_token(input.substr(left, right - left));
233 output.push_back(new_token);
234 left = right + delimiter_length;
235 right = input.find(delimiter, left);
238 output.push_back(input.substr(left));
241 string_vector tokenise(std::string const & input, std::string const & delimiter)
243 string_vector output;
244 tokenise(input, delimiter, output);
245 return output;
248 std::string join_strings(std::vector<std::string> const & input, std::string const & delimiter)
250 std::string output;
251 std::vector<std::string>::const_iterator
252 i = input.begin(),
253 end = input.end();
254 if(i != end)
256 output = *i;
257 for(++i; i != end; ++i)
259 output += delimiter + *i;
262 return output;
265 bool string_to_bool(std::string const & input, bool & output)
267 if(input == "true" || input == "1")
269 output = true;
270 return true;
272 else if(input == "false" || input == "0")
274 output = false;
275 return true;
278 return false;
281 std::string bool_to_string(bool input)
283 return input ? "true" : "false";
286 bool wildcard_match(std::string const & target, std::string const & wildcard_string)
288 std::string::const_iterator target_iterator = target.begin(), target_end = target.end();
289 for(std::string::const_iterator i = wildcard_string.begin(), end = wildcard_string.end(); i != end; ++i, ++target_iterator)
291 char current_char = *i;
292 switch(current_char)
294 case '*':
296 ++i;
297 if(i == end)
298 return true;
299 char next_char = *i;
300 while(true)
302 if(target_iterator == target_end)
303 return false;
304 if(*target_iterator == next_char)
305 break;
306 ++target_iterator;
308 break;
311 case '?':
313 if(target_iterator == target_end)
314 return false;
315 break;
318 default:
320 if(target_iterator == target_end)
321 return false;
322 if(current_char != *target_iterator)
323 return false;
324 break;
328 return (target_iterator == target_end);
331 std::string consolify(std::string const & input)
333 std::string output = input;
334 output = replace_string(output, "\b", "\\b");
335 output = replace_string(output, "\t", "\\t");
336 output = replace_string(output, "\n", "\\n");
337 output = replace_string(output, "\v", "\\v");
338 output = replace_string(output, "\f", "\\f");
339 output = replace_string(output, "\r", "\\r");
340 output = replace_string(output, "\x07", "\\x07");
341 return output;
344 std::size_t locate_string(std::string const & input, std::string const & target, long occurence, std::size_t offset)
346 for(; occurence > 0; occurence--)
348 offset = input.find(target, offset + 1);
349 if(offset == std::string::npos)
350 break;
352 return offset;
355 bool extract_string(std::string const & input, std::string const & left_target, std::string const & right_target, std::string & output, long occurence)
357 std::size_t left_offset = locate_string(input, left_target, occurence, 0);
358 if(left_offset == std::string::npos)
359 return false;
360 left_offset += left_target.length();
361 std::size_t right_offset = input.find(right_target, left_offset);
362 if(right_offset == std::string::npos)
363 return false;
364 output = input.substr(left_offset, right_offset - left_offset);
365 return true;
368 string_vector extract_strings(std::string const & input, std::string const & left_target, std::string const & right_target)
370 string_vector output;
371 std::size_t last_offset = 0;
372 while(true)
374 std::size_t left_offset = input.find(left_target, last_offset);
375 if(left_offset == std::string::npos)
376 break;
377 left_offset += left_target.length();
378 std::size_t right_offset = input.find(right_target, left_offset);
379 if(right_offset == std::string::npos)
380 break;
381 std::string element = input.substr(left_offset, right_offset - left_offset);
382 output.push_back(element);
383 last_offset = right_offset + right_target.length();
385 return output;
388 bool split_string(std::string const & input, std::string const & delimiter, std::string & left_string, std::string & right_string)
390 std::size_t offset = input.find(delimiter);
391 if(offset == std::string::npos)
393 left_string = input;
394 right_string.clear();
395 return false;
397 left_string = input.substr(0, offset);
398 std::size_t right_offset = offset + delimiter.length();
399 right_string = input.substr(right_offset);
400 return true;
403 std::string get_size_string(ullong size)
405 std::string const size_strings[] =
407 "byte",
408 "KiB",
409 "MiB",
410 "GiB",
411 "TiB"
414 double adjusted_size = static_cast<double>(size);
415 ullong const base = 1024;
416 double const divisor = static_cast<double>(base);
417 std::size_t size_index = 0;
418 for(std::size_t maximum = ail::countof(size_strings) - 1; adjusted_size > divisor && size_index < maximum; adjusted_size /= base, size_index++);
420 std::stringstream stream;
421 stream << std::fixed;
423 if(size_index > 0)
425 stream.precision(2);
426 stream << adjusted_size << " " << size_strings[size_index];
427 return stream.str();
429 else
431 stream << size << " " << size_strings[size_index];
432 std::string output = stream.str();
433 if(size != 1)
434 output += "s";
435 return output;
439 ulong binary_string_to_number(std::string const & input, bool big_endian)
441 ulong output = 0;
443 std::size_t
444 initial_value,
445 limit,
446 direction;
448 if(big_endian)
450 initial_value = 0;
451 limit = input.size();
452 direction = 1;
454 else
456 initial_value = input.size() - 1;
457 limit = -1;
458 direction = -1;
461 for(std::size_t i = initial_value; i != limit; i += direction)
463 output <<= 1;
464 output |= input[i] & 1;
467 return output;
470 std::string hex_string(ullong input, std::size_t bytes, bool prefix = true)
472 std::stringstream output;
473 if(prefix)
474 output << "0x";
475 output.width(2 * bytes);
476 output.fill('0');
477 output << std::hex << input;
478 return output.str();
481 std::string hex_string_8(ulong input)
483 return hex_string(input, 1);
486 std::string hex_string_16(ulong input)
488 return hex_string(input, 2);
491 std::string hex_string_32(ulong input)
493 return hex_string(input, 4);
496 std::string hex_string_64(ullong input)
498 return hex_string(input, 8);
501 std::string hex_string(std::string const & input)
503 uchar const * data = reinterpret_cast<uchar const *>(input.c_str());
504 std::string output;
505 bool first = true;
506 for(std::size_t i = 0, end = input.size(); i < end; i++)
508 if(first)
509 first = false;
510 else
511 output += " ";
512 output += hex_string(data[i], 1, false);
514 return output;
518 std::string operator+(char left, std::string const & right)
520 std::string string;
521 string += left;
522 return string + right;
525 std::string operator+(char const * left, std::string const & right)
527 return std::string(left) + right;