str.hh revision 13530
1/*
2 * Copyright (c) 2018 ARM Limited
3 * All rights reserved
4 *
5 * Copyright (c) 2001-2005 The Regents of The University of Michigan
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution;
15 * neither the name of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Authors: Nathan Binkert
32 *          Steve Reinhardt
33 */
34
35#ifndef __BASE_STR_HH__
36#define __BASE_STR_HH__
37
38#include <cstring>
39#include <limits>
40#include <locale>
41#include <stdexcept>
42#include <string>
43#include <vector>
44
45#include "base/logging.hh"
46
47inline void
48eat_lead_white(std::string &s)
49{
50    std::string::size_type off = s.find_first_not_of(' ');
51    if (off != std::string::npos) {
52        std::string::iterator begin = s.begin();
53        s.erase(begin, begin + off);
54    }
55}
56
57inline void
58eat_end_white(std::string &s)
59{
60    std::string::size_type off = s.find_last_not_of(' ');
61    if (off != std::string::npos)
62        s.erase(s.begin() + off + 1, s.end());
63}
64
65inline void
66eat_white(std::string &s)
67{
68    eat_lead_white(s);
69    eat_end_white(s);
70}
71
72inline std::string
73to_lower(const std::string &s)
74{
75    std::string lower;
76    int len = s.size();
77
78    lower.reserve(len);
79
80    for (const auto &c : s)
81        lower.push_back(std::tolower(c));
82
83    return lower;
84}
85
86// Split the string s into lhs and rhs on the first occurence of the
87// character c.
88bool
89split_first(const std::string &s, std::string &lhs, std::string &rhs, char c);
90
91// Split the string s into lhs and rhs on the last occurence of the
92// character c.
93bool
94split_last(const std::string &s, std::string &lhs, std::string &rhs, char c);
95
96// Tokenize the string <s> splitting on the character <token>, and
97// place the result in the string vector <vector>.  If <ign> is true,
98// then empty result strings (due to trailing tokens, or consecutive
99// tokens) are skipped.
100void
101tokenize(std::vector<std::string> &vector, const std::string &s,
102         char token, bool ign = true);
103
104/**
105 * @{
106 *
107 * @name String to number helper functions for signed and unsigned
108 *       integeral type, as well as enums and floating-point types.
109 */
110template <class T>
111typename std::enable_if<(std::is_integral<T>::value ||
112                        std::is_enum<T>::value) &&
113                        std::is_signed<T>::value, T>::type
114__to_number(const std::string &value)
115{
116    // start big and narrow it down if needed, determine the base dynamically
117    long long r = std::stoll(value, nullptr, 0);
118    if (r < std::numeric_limits<T>::min() || r > std::numeric_limits<T>::max())
119        throw std::out_of_range("Out of range");
120    return static_cast<T>(r);
121}
122
123template <class T>
124typename std::enable_if<(std::is_integral<T>::value ||
125                        std::is_enum<T>::value) &&
126                        !std::is_signed<T>::value, T>::type
127__to_number(const std::string &value)
128{
129    // start big and narrow it down if needed, determine the base dynamically
130    unsigned long long r = std::stoull(value, nullptr, 0);
131    if (r > std::numeric_limits<T>::max())
132        throw std::out_of_range("Out of range");
133    return static_cast<T>(r);
134}
135
136template <class T>
137typename std::enable_if<std::is_floating_point<T>::value, T>::type
138__to_number(const std::string &value)
139{
140    // start big and narrow it down if needed
141    long double r = std::stold(value);
142    if (r < std::numeric_limits<T>::min() || r > std::numeric_limits<T>::max())
143        throw std::out_of_range("Out of range");
144    return static_cast<T>(r);
145}
146/** @} */
147
148/**
149 * Turn a string representation of a number, either integral or
150 * floating point, into an actual number.
151 *
152 * @param value The string representing the number
153 * @param retval The resulting value
154 * @return True if the parsing was successful
155 */
156template <class T>
157inline bool
158to_number(const std::string &value, T &retval)
159{
160    try {
161        retval = __to_number<T>(value);
162        return true;
163    } catch (const std::out_of_range&) {
164        return false;
165    } catch (const std::invalid_argument&) {
166        return false;
167    } catch (...) {
168        panic("Unrecognized exception.\n");
169    }
170}
171
172/**
173 * Turn a string representation of a boolean into a boolean value.
174 */
175inline bool
176to_bool(const std::string &value, bool &retval)
177{
178    std::string s = to_lower(value);
179
180    if (s == "true") {
181        retval = true;
182        return true;
183    } else if (s == "false") {
184        retval = false;
185        return true;
186    }
187
188    return false;
189}
190
191// Put quotes around string arg if it contains spaces.
192inline std::string
193quote(const std::string &s)
194{
195    std::string ret;
196    bool quote = s.find(' ') != std::string::npos;
197
198    if (quote)
199        ret = '"';
200
201    ret += s;
202
203    if (quote)
204        ret += '"';
205
206    return ret;
207}
208
209
210/**
211 * Return true if 's' starts with the prefix string 'prefix'.
212 */
213inline bool
214startswith(const char *s, const char *prefix)
215{
216    return (strncmp(s, prefix, strlen(prefix)) == 0);
217}
218
219
220/**
221 * Return true if 's' starts with the prefix string 'prefix'.
222 */
223inline bool
224startswith(const std::string &s, const char *prefix)
225{
226    return (s.compare(0, strlen(prefix), prefix) == 0);
227}
228
229
230/**
231 * Return true if 's' starts with the prefix string 'prefix'.
232 */
233inline bool
234startswith(const std::string &s, const std::string &prefix)
235{
236    return (s.compare(0, prefix.size(), prefix) == 0);
237}
238
239
240#endif //__BASE_STR_HH__
241