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