str.hh revision 13530:765c1692adfb
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