strutil.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <numeric>
  15. #include <string.h>
  16. #include <util/strutil.h>
  17. using namespace std;
  18. namespace isc {
  19. namespace util {
  20. namespace str {
  21. // Normalize slashes
  22. void
  23. normalizeSlash(std::string& name) {
  24. if (!name.empty()) {
  25. size_t pos = 0;
  26. while ((pos = name.find('\\', pos)) != std::string::npos) {
  27. name[pos] = '/';
  28. }
  29. }
  30. }
  31. // Trim String
  32. string
  33. trim(const string& instring) {
  34. string retstring = "";
  35. if (!instring.empty()) {
  36. static const char* blanks = " \t\n";
  37. // Search for first non-blank character in the string
  38. size_t first = instring.find_first_not_of(blanks);
  39. if (first != string::npos) {
  40. // String not all blanks, so look for last character
  41. size_t last = instring.find_last_not_of(blanks);
  42. // Extract the trimmed substring
  43. retstring = instring.substr(first, (last - first + 1));
  44. }
  45. }
  46. return (retstring);
  47. }
  48. // Tokenize string. As noted in the header, this is locally written to avoid
  49. // another dependency on a Boost library.
  50. vector<string>
  51. tokens(const std::string& text, const std::string& delim) {
  52. vector<string> result;
  53. // Search for the first non-delimiter character
  54. size_t start = text.find_first_not_of(delim);
  55. while (start != string::npos) {
  56. // Non-delimiter found, look for next delimiter
  57. size_t end = text.find_first_of(delim, start);
  58. if (end != string::npos) {
  59. // Delimiter found, so extract string & search for start of next
  60. // non-delimiter segment.
  61. result.push_back(text.substr(start, (end - start)));
  62. start = text.find_first_not_of(delim, end);
  63. } else {
  64. // End of string found, extract rest of string and flag to exit
  65. result.push_back(text.substr(start));
  66. start = string::npos;
  67. }
  68. }
  69. return (result);
  70. }
  71. // Local function to pass to accumulate() for summing up string lengths.
  72. namespace {
  73. size_t
  74. lengthSum(string::size_type curlen, const string& cur_string) {
  75. return (curlen + cur_string.size());
  76. }
  77. }
  78. // Provide printf-style formatting.
  79. std::string
  80. format(const std::string& format, const std::vector<std::string>& args) {
  81. static const string flag = "%s";
  82. // Initialize return string. To speed things up, we'll reserve an
  83. // appropriate amount of space - current string size, plus length of all
  84. // the argument strings, less two characters for each argument (the %s in
  85. // the format string is being replaced).
  86. string result;
  87. size_t length = accumulate(args.begin(), args.end(), format.size(),
  88. lengthSum) - (args.size() * flag.size());
  89. result.reserve(length);
  90. // Iterate through replacing all tokens
  91. result = format;
  92. size_t tokenpos = 0; // Position of last token replaced
  93. std::vector<std::string>::size_type i = 0; // Index into argument array
  94. while ((i < args.size()) && (tokenpos != string::npos)) {
  95. tokenpos = result.find(flag, tokenpos);
  96. if (tokenpos != string::npos) {
  97. result.replace(tokenpos, flag.size(), args[i++]);
  98. }
  99. }
  100. return (result);
  101. }
  102. std::string
  103. getToken(std::istringstream& iss) {
  104. string token;
  105. iss >> token;
  106. if (iss.bad() || iss.fail()) {
  107. isc_throw(StringTokenError, "could not read token from string");
  108. }
  109. return (token);
  110. }
  111. } // namespace str
  112. } // namespace util
  113. } // namespace isc