1 // Copyright (c) 2007 The NetBSD Foundation, Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 13 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 #include "atf-c++/detail/text.hpp" 27 28 extern "C" { 29 #include <regex.h> 30 } 31 32 #include <cctype> 33 #include <cstring> 34 35 extern "C" { 36 #include "atf-c/detail/text.h" 37 #include "atf-c/error.h" 38 } 39 40 #include "atf-c++/detail/exceptions.hpp" 41 42 namespace impl = atf::text; 43 #define IMPL_NAME "atf::text" 44 45 bool 46 impl::match(const std::string& str, const std::string& regex) 47 { 48 bool found; 49 50 // Special case: regcomp does not like empty regular expressions. 51 if (regex.empty()) { 52 found = str.empty(); 53 } else { 54 ::regex_t preg; 55 56 if (::regcomp(&preg, regex.c_str(), REG_EXTENDED) != 0) 57 throw std::runtime_error("Invalid regular expression '" + regex + 58 "'"); 59 60 const int res = ::regexec(&preg, str.c_str(), 0, NULL, 0); 61 regfree(&preg); 62 if (res != 0 && res != REG_NOMATCH) 63 throw std::runtime_error("Invalid regular expression " + regex); 64 65 found = res == 0; 66 } 67 68 return found; 69 } 70 71 std::string 72 impl::to_lower(const std::string& str) 73 { 74 std::string lc; 75 for (std::string::const_iterator iter = str.begin(); iter != str.end(); 76 iter++) 77 lc += std::tolower(*iter); 78 return lc; 79 } 80 81 std::vector< std::string > 82 impl::split(const std::string& str, const std::string& delim) 83 { 84 std::vector< std::string > words; 85 86 std::string::size_type pos = 0, newpos = 0; 87 while (pos < str.length() && newpos != std::string::npos) { 88 newpos = str.find(delim, pos); 89 if (newpos != pos) 90 words.push_back(str.substr(pos, newpos - pos)); 91 pos = newpos + delim.length(); 92 } 93 94 return words; 95 } 96 97 std::string 98 impl::trim(const std::string& str) 99 { 100 std::string::size_type pos1 = str.find_first_not_of(" \t"); 101 std::string::size_type pos2 = str.find_last_not_of(" \t"); 102 103 if (pos1 == std::string::npos && pos2 == std::string::npos) 104 return ""; 105 else if (pos1 == std::string::npos) 106 return str.substr(0, str.length() - pos2); 107 else if (pos2 == std::string::npos) 108 return str.substr(pos1); 109 else 110 return str.substr(pos1, pos2 - pos1 + 1); 111 } 112 113 bool 114 impl::to_bool(const std::string& str) 115 { 116 bool b; 117 118 atf_error_t err = atf_text_to_bool(str.c_str(), &b); 119 if (atf_is_error(err)) 120 throw_atf_error(err); 121 122 return b; 123 } 124 125 int64_t 126 impl::to_bytes(std::string str) 127 { 128 if (str.empty()) 129 throw std::runtime_error("Empty value"); 130 131 const char unit = str[str.length() - 1]; 132 int64_t multiplier; 133 switch (unit) { 134 case 'k': case 'K': multiplier = 1 << 10; break; 135 case 'm': case 'M': multiplier = 1 << 20; break; 136 case 'g': case 'G': multiplier = 1 << 30; break; 137 case 't': case 'T': multiplier = int64_t(1) << 40; break; 138 default: 139 if (!std::isdigit(unit)) 140 throw std::runtime_error(std::string("Unknown size unit '") + unit 141 + "'"); 142 multiplier = 1; 143 } 144 if (multiplier != 1) 145 str.erase(str.length() - 1); 146 147 return to_type< int64_t >(str) * multiplier; 148 } 149