xref: /freebsd/contrib/atf/atf-c++/detail/text.cpp (revision c243e4902be8df1e643c76b5f18b68bb77cc5268)
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