1895f502bSjmmv //
2895f502bSjmmv // Automated Testing Framework (atf)
3895f502bSjmmv //
4*e0531b9cSjmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
5895f502bSjmmv // All rights reserved.
6895f502bSjmmv //
7895f502bSjmmv // Redistribution and use in source and binary forms, with or without
8895f502bSjmmv // modification, are permitted provided that the following conditions
9895f502bSjmmv // are met:
10895f502bSjmmv // 1. Redistributions of source code must retain the above copyright
11895f502bSjmmv //    notice, this list of conditions and the following disclaimer.
12895f502bSjmmv // 2. Redistributions in binary form must reproduce the above copyright
13895f502bSjmmv //    notice, this list of conditions and the following disclaimer in the
14895f502bSjmmv //    documentation and/or other materials provided with the distribution.
15895f502bSjmmv //
16895f502bSjmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17895f502bSjmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18895f502bSjmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19895f502bSjmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20895f502bSjmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21895f502bSjmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22895f502bSjmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23895f502bSjmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24895f502bSjmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25895f502bSjmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26895f502bSjmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27895f502bSjmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28895f502bSjmmv //
29895f502bSjmmv 
30895f502bSjmmv extern "C" {
31895f502bSjmmv #include <regex.h>
32895f502bSjmmv }
33895f502bSjmmv 
34895f502bSjmmv #include <cctype>
35895f502bSjmmv #include <cstring>
36895f502bSjmmv 
37895f502bSjmmv extern "C" {
38895f502bSjmmv #include "../../atf-c/error.h"
39895f502bSjmmv 
40895f502bSjmmv #include "../../atf-c/detail/text.h"
41895f502bSjmmv }
42895f502bSjmmv 
43895f502bSjmmv #include "exceptions.hpp"
44895f502bSjmmv #include "text.hpp"
45895f502bSjmmv 
46895f502bSjmmv namespace impl = atf::text;
47895f502bSjmmv #define IMPL_NAME "atf::text"
48895f502bSjmmv 
49895f502bSjmmv char*
duplicate(const char * str)50895f502bSjmmv impl::duplicate(const char* str)
51895f502bSjmmv {
52895f502bSjmmv     char* copy = new char[std::strlen(str) + 1];
53895f502bSjmmv     std::strcpy(copy, str);
54895f502bSjmmv     return copy;
55895f502bSjmmv }
56895f502bSjmmv 
57895f502bSjmmv bool
match(const std::string & str,const std::string & regex)58895f502bSjmmv impl::match(const std::string& str, const std::string& regex)
59895f502bSjmmv {
60895f502bSjmmv     bool found;
61895f502bSjmmv 
62895f502bSjmmv     // Special case: regcomp does not like empty regular expressions.
63895f502bSjmmv     if (regex.empty()) {
64895f502bSjmmv         found = str.empty();
65895f502bSjmmv     } else {
66895f502bSjmmv         ::regex_t preg;
67895f502bSjmmv 
68895f502bSjmmv         if (::regcomp(&preg, regex.c_str(), REG_EXTENDED) != 0)
69895f502bSjmmv             throw std::runtime_error("Invalid regular expression '" + regex +
70895f502bSjmmv                                      "'");
71895f502bSjmmv 
72895f502bSjmmv         const int res = ::regexec(&preg, str.c_str(), 0, NULL, 0);
73895f502bSjmmv         regfree(&preg);
74895f502bSjmmv         if (res != 0 && res != REG_NOMATCH)
75895f502bSjmmv             throw std::runtime_error("Invalid regular expression " + regex);
76895f502bSjmmv 
77895f502bSjmmv         found = res == 0;
78895f502bSjmmv     }
79895f502bSjmmv 
80895f502bSjmmv     return found;
81895f502bSjmmv }
82895f502bSjmmv 
83895f502bSjmmv std::string
to_lower(const std::string & str)84895f502bSjmmv impl::to_lower(const std::string& str)
85895f502bSjmmv {
86895f502bSjmmv     std::string lc;
87895f502bSjmmv     for (std::string::const_iterator iter = str.begin(); iter != str.end();
88895f502bSjmmv          iter++)
89895f502bSjmmv         lc += std::tolower(*iter);
90895f502bSjmmv     return lc;
91895f502bSjmmv }
92895f502bSjmmv 
93895f502bSjmmv std::vector< std::string >
split(const std::string & str,const std::string & delim)94895f502bSjmmv impl::split(const std::string& str, const std::string& delim)
95895f502bSjmmv {
96895f502bSjmmv     std::vector< std::string > words;
97895f502bSjmmv 
98895f502bSjmmv     std::string::size_type pos = 0, newpos = 0;
99895f502bSjmmv     while (pos < str.length() && newpos != std::string::npos) {
100895f502bSjmmv         newpos = str.find(delim, pos);
101895f502bSjmmv         if (newpos != pos)
102895f502bSjmmv             words.push_back(str.substr(pos, newpos - pos));
103895f502bSjmmv         pos = newpos + delim.length();
104895f502bSjmmv     }
105895f502bSjmmv 
106895f502bSjmmv     return words;
107895f502bSjmmv }
108895f502bSjmmv 
109895f502bSjmmv std::string
trim(const std::string & str)110895f502bSjmmv impl::trim(const std::string& str)
111895f502bSjmmv {
112895f502bSjmmv     std::string::size_type pos1 = str.find_first_not_of(" \t");
113895f502bSjmmv     std::string::size_type pos2 = str.find_last_not_of(" \t");
114895f502bSjmmv 
115895f502bSjmmv     if (pos1 == std::string::npos && pos2 == std::string::npos)
116895f502bSjmmv         return "";
117895f502bSjmmv     else if (pos1 == std::string::npos)
118895f502bSjmmv         return str.substr(0, str.length() - pos2);
119895f502bSjmmv     else if (pos2 == std::string::npos)
120895f502bSjmmv         return str.substr(pos1);
121895f502bSjmmv     else
122895f502bSjmmv         return str.substr(pos1, pos2 - pos1 + 1);
123895f502bSjmmv }
124895f502bSjmmv 
125895f502bSjmmv bool
to_bool(const std::string & str)126895f502bSjmmv impl::to_bool(const std::string& str)
127895f502bSjmmv {
128895f502bSjmmv     bool b;
129895f502bSjmmv 
130895f502bSjmmv     atf_error_t err = atf_text_to_bool(str.c_str(), &b);
131895f502bSjmmv     if (atf_is_error(err))
132895f502bSjmmv         throw_atf_error(err);
133895f502bSjmmv 
134895f502bSjmmv     return b;
135895f502bSjmmv }
1361f62702fSchristos 
1371f62702fSchristos int64_t
to_bytes(std::string str)138*e0531b9cSjmmv impl::to_bytes(std::string str)
1391f62702fSchristos {
140*e0531b9cSjmmv     if (str.empty())
141*e0531b9cSjmmv         throw std::runtime_error("Empty value");
1421f62702fSchristos 
143*e0531b9cSjmmv     const char unit = str[str.length() - 1];
144*e0531b9cSjmmv     int64_t multiplier;
145*e0531b9cSjmmv     switch (unit) {
146*e0531b9cSjmmv     case 'k': case 'K': multiplier = 1 << 10; break;
147*e0531b9cSjmmv     case 'm': case 'M': multiplier = 1 << 20; break;
148*e0531b9cSjmmv     case 'g': case 'G': multiplier = 1 << 30; break;
149*e0531b9cSjmmv     case 't': case 'T': multiplier = int64_t(1) << 40; break;
150*e0531b9cSjmmv     default:
151*e0531b9cSjmmv         if (!std::isdigit(unit))
152*e0531b9cSjmmv             throw std::runtime_error(std::string("Unknown size unit '") + unit
153*e0531b9cSjmmv                                      + "'");
154*e0531b9cSjmmv         multiplier = 1;
155*e0531b9cSjmmv     }
156*e0531b9cSjmmv     if (multiplier != 1)
157*e0531b9cSjmmv         str.erase(str.length() - 1);
158*e0531b9cSjmmv 
159*e0531b9cSjmmv     return to_type< int64_t >(str) * multiplier;
160*e0531b9cSjmmv }
161