yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.0.2
StringUtils.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of YODA -- Yet more Objects for Data Analysis
4// Copyright (C) 2008-2024 The YODA collaboration (see AUTHORS for details)
5//
6#ifndef YODA_STRINGUTILS_H
7#define YODA_STRINGUTILS_H
8
9#include <vector>
10#include <sstream>
11#include <algorithm>
12#include <limits>
13#include <stdexcept>
14
15namespace YODA {
16 namespace Utils {
17
18
20 struct bad_lexical_cast : public std::runtime_error {
21 bad_lexical_cast(const std::string& what) : std::runtime_error(what) {}
22 };
23
25 template<typename T, typename U>
26 T lexical_cast(const U& in) {
27 try {
28 std::stringstream ss;
29 ss << in;
30 T out;
31 ss >> out;
32 return out;
33 } catch (const std::exception& e) {
34 throw bad_lexical_cast(e.what());
35 }
36 }
37
38
40 template <typename T>
41 inline std::string toStr(const T& x) {
42 // std::ostringstream ss; ss << x;
43 // return ss.str();
44 return lexical_cast<std::string>(x);
45 }
46
47
49 inline double toDbl(const std::string& s) {
50 try {
51 return std::stod(s);
52 }
53 catch (...) {
54 return std::numeric_limits<double>::quiet_NaN();
55 }
56 }
57
58
60 inline std::string toLower(const std::string& s) {
61 std::string out = s;
62 std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) tolower);
63 return out;
64 }
65
66
68 inline std::string toUpper(const std::string& s) {
69 std::string out = s;
70 std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) toupper);
71 return out;
72 }
73
74
76 inline std::string encodeForXML(const std::string& in) {
77 std::string out = in;
78 typedef std::pair<std::string, std::string> CharsToEntities;
79 std::vector<CharsToEntities> cs2es;
80 cs2es.push_back(std::make_pair("&", "&amp;"));
81 cs2es.push_back(std::make_pair("<", "&lt;"));
82 cs2es.push_back(std::make_pair(">", "&gt;"));
83 for (std::vector<CharsToEntities>::const_iterator c2e = cs2es.begin(); c2e != cs2es.end(); ++c2e) {
84 std::string::size_type pos = -1;
85 while ( ( pos = out.find(c2e->first, pos + 1) ) != std::string::npos ) {
86 out.replace(pos, 1, c2e->second);
87 }
88 }
89 return out;
90 }
91
92
94 inline bool contains(const std::string& s, const std::string& sub) {
95 return s.find(sub) != std::string::npos;
96 }
97
99 inline bool startswith(const std::string& s, const std::string& sub) {
100 return s.find(sub) == 0;
101 }
102
104 inline bool endswith(const std::string& s, const std::string& sub) {
105 const size_t pos = s.find(sub);
106 return pos != std::string::npos && pos == (s.size()-sub.size());
107 }
108
109
111 inline std::string& iltrim(std::string& s) {
112 s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c){ return !std::isspace(c); }));
113
114 return s;
115 }
116
118 inline std::string& irtrim(std::string& s) {
119 s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c){ return !std::isspace(c); }).base(), s.end());
120 return s;
121 }
122
124 inline std::string& itrim(std::string& s) {
125 return iltrim(irtrim(s));
126 }
127
128
130 inline std::string ltrim(const std::string& s) { //< @note Could just pass by value, but const& sends a symbolic message
131 std::string s2 = s;
132 return iltrim(s2);
133 }
134
136 inline std::string rtrim(const std::string& s) { //< @note Could just pass by value, but const& sends a symbolic message
137 std::string s2 = s;
138 return irtrim(s2);
139 }
140
142 inline std::string trim(const std::string& s) { //< @note Could just pass by value, but const& sends a symbolic message
143 std::string s2 = s;
144 return itrim(s2);
145 }
146
148 inline std::vector<std::string> split(const std::string& s, const std::string& sep) {
149 std::vector<std::string> dirs;
150 std::string tmp = s;
151 while (true) {
152 const size_t delim_pos = tmp.find(sep);
153 if (delim_pos == std::string::npos) break;
154 const std::string dir = tmp.substr(0, delim_pos);
155 if (dir.length()) dirs.push_back(dir); // Don't insert "empties"
156 tmp.replace(0, delim_pos+1, "");
157 }
158 if (tmp.length()) dirs.push_back(tmp); // Don't forget the trailing component!
159 return dirs;
160 }
161
165 inline std::vector<std::string> pathsplit(const std::string& path) {
166 return split(path, ":");
167 }
168
169 }
170
171
172 // Annoyingly, this doesn't work without significant SFINAE etc., due to clashes with existing string & stream operators
173 // /// string + any appending operator for convenience in the YODA namespace
174 // template <typename T>
175 // std::string& operator + (std::string& s, const T& x) {
176 // s += Utils::toStr(x);
177 // return s;
178 // }
179 // template <typename T>
180 // std::string operator + (const T& x, std::string& s) {
181 // return Utils::toStr(x) + s;
182 // }
183 // template <typename T>
184 // std::string operator + (const char* s, const T& x) {
185 // return s + Utils::toStr(x);
186 // }
187 // template <typename T>
188 // std::string operator + (const T& x, const char* s) {
189 // return Utils::toStr(x) + x;
190 // }
191
192
193}
194
195#endif
Anonymous namespace to limit visibility.