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