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