| [672] | 1 | /* $Id$ $URL$ */ |
|---|
| [257] | 2 | #ifndef RXSTRING_DOT_AITCH |
|---|
| 3 | #define RXSTRING_DOT_AITCH |
|---|
| 4 | /**\file rxstring.h |
|---|
| [672] | 5 | * Declaration of the RxString class. |
|---|
| [257] | 6 | * \ingroup rxstring |
|---|
| 7 | * \author Trent Apted <tapted@it.usyd.edu.au> |
|---|
| 8 | * $Revision$ |
|---|
| 9 | * $Date$ |
|---|
| 10 | */ |
|---|
| 11 | |
|---|
| [398] | 12 | #include <vector> |
|---|
| [257] | 13 | #include <string> |
|---|
| 14 | #include <iostream> |
|---|
| 15 | #include <algorithm> |
|---|
| 16 | #include <sstream> |
|---|
| 17 | #include <cctype> |
|---|
| 18 | |
|---|
| 19 | /* for flags */ |
|---|
| 20 | #include <sys/types.h> |
|---|
| 21 | |
|---|
| 22 | #ifdef HAVE_CONFIG_H |
|---|
| 23 | #include "config.h" |
|---|
| 24 | #endif |
|---|
| 25 | |
|---|
| [398] | 26 | #ifdef const |
|---|
| 27 | #undef const |
|---|
| 28 | #endif |
|---|
| 29 | |
|---|
| [257] | 30 | extern "C" { |
|---|
| 31 | #ifdef HAVE_SYSREGEX_H |
|---|
| 32 | #include <regex.h> |
|---|
| 33 | #else |
|---|
| 34 | #include "myregex.h" |
|---|
| 35 | #endif |
|---|
| 36 | } |
|---|
| 37 | |
|---|
| 38 | /** |
|---|
| 39 | * A Regular Expression std::string. This class currently has no data members, |
|---|
| 40 | * so it is just a convenient subclass for extending the functionality of a |
|---|
| 41 | * std::string to include sugar functions from algoritm and regular expression |
|---|
| 42 | * matching within the string. |
|---|
| 43 | */ |
|---|
| [398] | 44 | class RxString { |
|---|
| [257] | 45 | public: |
|---|
| [672] | 46 | typedef std::string S; ///< STL string class to mimic |
|---|
| 47 | //@{ |
|---|
| 48 | /// Mimicry of std::string |
|---|
| [398] | 49 | typedef S::traits_type traits_type; |
|---|
| 50 | typedef S::allocator_type allocator_type; |
|---|
| 51 | typedef S::iterator iterator; |
|---|
| 52 | typedef S::const_iterator const_iterator; |
|---|
| 53 | typedef S::size_type size_type; |
|---|
| 54 | typedef S::difference_type difference_type; |
|---|
| 55 | typedef S::const_reverse_iterator const_reverse_iterator; |
|---|
| 56 | typedef S::reverse_iterator reverse_iterator; |
|---|
| 57 | typedef allocator_type::pointer pointer; |
|---|
| 58 | typedef allocator_type::const_pointer const_pointer; |
|---|
| 59 | typedef allocator_type::reference reference; |
|---|
| 60 | typedef allocator_type::const_reference const_reference; |
|---|
| 61 | typedef allocator_type::value_type value_type; |
|---|
| 62 | static const size_type npos = static_cast<size_type>(-1); |
|---|
| [672] | 63 | //@} |
|---|
| [398] | 64 | private: |
|---|
| [672] | 65 | S s; ///< The instance of std::string we wrap |
|---|
| [398] | 66 | public: |
|---|
| [672] | 67 | enum { |
|---|
| 68 | DEFAULT_RE_MAX_MATCH = 10 ///< Default maximum number of matches |
|---|
| 69 | }; |
|---|
| [257] | 70 | |
|---|
| [672] | 71 | //@{ |
|---|
| 72 | /// Mimicry of regex_t |
|---|
| [398] | 73 | struct my_regex_t { |
|---|
| [672] | 74 | regex_t rx; ///< The regular expression |
|---|
| 75 | unsigned nmatch; ///< The number of '(' characters in the expression |
|---|
| [398] | 76 | }; |
|---|
| [672] | 77 | //@} |
|---|
| 78 | class Regex : public my_regex_t { |
|---|
| 79 | public: |
|---|
| 80 | Regex(const RxString& regstr, RxString *err_string = 0, int cflags = REG_EXTENDED); |
|---|
| 81 | }; |
|---|
| [398] | 82 | |
|---|
| [672] | 83 | //always use std:: here |
|---|
| 84 | typedef std::vector<RxString> match_vec_type; ///< Type for substring matches |
|---|
| [257] | 85 | static const RxString NO_MATCH; ///< The RxString corresponding to NO_MATCH |
|---|
| 86 | |
|---|
| 87 | /** Create an empty RxString */ |
|---|
| [672] | 88 | RxString() : s() {} |
|---|
| [257] | 89 | /** Create an RxString from the std::string \a s */ |
|---|
| [398] | 90 | RxString(const S &ss) : s(ss) {} |
|---|
| [257] | 91 | /** Create an RxString from the c-style string \a s */ |
|---|
| [398] | 92 | RxString(const value_type *ss) : s(ss) {} |
|---|
| [257] | 93 | |
|---|
| [672] | 94 | /** Convert to a std::string */ |
|---|
| [398] | 95 | operator S() const {return s;} |
|---|
| 96 | //std::string str() const {return s;} |
|---|
| 97 | //operator std::string() {return s;} |
|---|
| 98 | |
|---|
| [257] | 99 | /** Remove spaces from \a this RxString and return \a *this */ |
|---|
| 100 | RxString &trim(); |
|---|
| 101 | |
|---|
| [672] | 102 | //@{ |
|---|
| [257] | 103 | /** |
|---|
| 104 | * Perform a regular expression matching of this RxString. |
|---|
| 105 | * |
|---|
| 106 | * \param regex The regular expression to match (conforming to Posix regex(7)) |
|---|
| 107 | * \param matches If non-null, append all substring matches to this using push_back() |
|---|
| 108 | * \param err_string If non-null and an error occurs, set to the regex error description |
|---|
| 109 | * \param cflags Regular expression compilation flags (see regcomp(3)) |
|---|
| 110 | * \param eflags Regular expression execution flags (see regexec(3)) |
|---|
| 111 | * \return the number of substring matches |
|---|
| 112 | */ |
|---|
| 113 | size_t match(const RxString ®ex, |
|---|
| [398] | 114 | match_vec_type *matches = 0, |
|---|
| 115 | RxString *err_string = 0, |
|---|
| 116 | int cflags = REG_EXTENDED, |
|---|
| 117 | int eflags = 0 |
|---|
| 118 | ) const; |
|---|
| [257] | 119 | |
|---|
| [398] | 120 | size_t match(const my_regex_t ®ex, |
|---|
| 121 | match_vec_type *matches = 0, |
|---|
| 122 | RxString *err_string = 0, |
|---|
| 123 | int eflags = 0 |
|---|
| 124 | ) const; |
|---|
| 125 | |
|---|
| 126 | RxString matchn(const RxString ®ex, unsigned n = 0, RxString *err_string = 0, int cflags = REG_EXTENDED, int eflags = 0) const; |
|---|
| 127 | RxString matchn(const my_regex_t ®ex, unsigned n = 0, RxString *err_string = 0, int eflags = 0) const; |
|---|
| [672] | 128 | //@} |
|---|
| [398] | 129 | |
|---|
| [672] | 130 | /** Compile a regular expression, that can be cached for matchn */ |
|---|
| [398] | 131 | static bool compile(my_regex_t ®ex, const RxString ®str, RxString *err_string = 0, int cflags = REG_EXTENDED); |
|---|
| [672] | 132 | /** Release resources used by a precompiled regular expression */ |
|---|
| [398] | 133 | static void release(my_regex_t ®ex); |
|---|
| 134 | |
|---|
| [257] | 135 | /** |
|---|
| 136 | * Match, ignoring case of the string. |
|---|
| 137 | *\copydoc RxString::match() |
|---|
| 138 | */ |
|---|
| 139 | size_t match_icase(const RxString ®ex, |
|---|
| 140 | RxString::match_vec_type *matches = 0, |
|---|
| 141 | RxString *err_string = 0, |
|---|
| 142 | int cflags = REG_EXTENDED|REG_ICASE, |
|---|
| 143 | int eflags = 0 |
|---|
| 144 | ) const { |
|---|
| 145 | return match(regex, matches, err_string, cflags | REG_ICASE, eflags); |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | /** |
|---|
| 149 | * Append to this string, characters read from \a in, until an \a eol |
|---|
| 150 | * character is encountered. The \a eol character is not appended. |
|---|
| 151 | * |
|---|
| 152 | * \param in The std::istream to read from |
|---|
| 153 | * \param eol The termination character to use |
|---|
| 154 | * \return \a *this |
|---|
| 155 | */ |
|---|
| 156 | RxString &append_line(std::istream& in = std::cin, const char eol = '\n'); |
|---|
| 157 | |
|---|
| 158 | /** Convert \a this RxString to upper case and return \a *this */ |
|---|
| 159 | RxString &toUpper(); |
|---|
| 160 | /** Convert \a this RxString to lower case and return \a *this */ |
|---|
| 161 | RxString &toLower(); |
|---|
| 162 | /** Convert characters in this string occuring after white space to uppercase */ |
|---|
| 163 | RxString &toTitleCase(); |
|---|
| 164 | |
|---|
| 165 | /** Return the number of occurences of \a val in \a this */ |
|---|
| [398] | 166 | size_type count_char(value_type val) const; |
|---|
| [672] | 167 | //@{ |
|---|
| [257] | 168 | /** Return the position of the last occurence of \a val in \a this */ |
|---|
| [398] | 169 | iterator find_last(value_type val); |
|---|
| [257] | 170 | std::string::const_iterator find_last(value_type val) const; |
|---|
| [672] | 171 | //@} |
|---|
| 172 | //@{ |
|---|
| [257] | 173 | /** Return the character after the last one for which \a p is true */ |
|---|
| 174 | template <class Pred> |
|---|
| 175 | std::string::iterator find_last_not_if(Pred p); |
|---|
| 176 | template <class Pred> |
|---|
| 177 | std::string::const_iterator find_last_not_if(Pred p) const; |
|---|
| [672] | 178 | //@} |
|---|
| 179 | //@{ |
|---|
| [257] | 180 | /** Return the first character for which \a p is true */ |
|---|
| 181 | template <class Pred> |
|---|
| 182 | std::string::iterator find_if(Pred p); |
|---|
| 183 | template <class Pred> |
|---|
| 184 | std::string::const_iterator find_if(Pred p) const; |
|---|
| [672] | 185 | //@} |
|---|
| 186 | |
|---|
| [257] | 187 | /** Removes all characters from \a this for which \a p is true */ |
|---|
| 188 | template <class Pred> |
|---|
| 189 | void remove_if(Pred p); |
|---|
| 190 | /** Replace all characters for whic \a p is true with \a val */ |
|---|
| 191 | template <class Pred> |
|---|
| 192 | void replace_if(Pred p, value_type val); |
|---|
| 193 | |
|---|
| 194 | /** |
|---|
| 195 | * Assign to \a t the value of \a this when converted to the type T. |
|---|
| 196 | * |
|---|
| 197 | * \param t the variable to assign to, and format determiner |
|---|
| 198 | * \return false if the conversion failed, otherwise true |
|---|
| 199 | */ |
|---|
| 200 | template <class T> |
|---|
| 201 | bool convertTo(T &t) const; |
|---|
| 202 | |
|---|
| 203 | /** |
|---|
| 204 | * Assign to \a this the value of \a val converted to a string. |
|---|
| 205 | * |
|---|
| 206 | * \param val the value to assign, and format determiner |
|---|
| 207 | * \return \a *this (the conversion should never fail |
|---|
| 208 | */ |
|---|
| 209 | template <class T> |
|---|
| 210 | RxString &convertFrom(const T &val); |
|---|
| 211 | |
|---|
| [398] | 212 | /*==STRING FUNCTIONS==*/ |
|---|
| [672] | 213 | //@{ |
|---|
| 214 | /// More mimicry of std::string |
|---|
| [398] | 215 | explicit RxString(const allocator_type& al) : s(al) {} |
|---|
| 216 | //RxString (const S& right); |
|---|
| 217 | RxString(const RxString& right, size_type roff, size_type count = npos) : s(right.s, roff, count) {} |
|---|
| 218 | RxString(const RxString& right, size_type roff, size_type count, const allocator_type& al) : s(right.s, roff, count, al) {} |
|---|
| 219 | RxString(const value_type *ptr, size_type count) : s(ptr, count) {} |
|---|
| 220 | RxString(const value_type *ptr, size_type count, const allocator_type& al) : s(ptr, count, al) {} |
|---|
| 221 | //RxString(const value_type *ptr) : s(ptr) {} |
|---|
| 222 | RxString(const value_type *ptr, const allocator_type& al) : s(ptr, al) {} |
|---|
| 223 | RxString(size_type count, value_type ch) : s(count, ch) {} |
|---|
| 224 | RxString(size_type count, value_type ch, const allocator_type& al) : s(count, ch, al) {} |
|---|
| 225 | template <class InIt> RxString(InIt first, InIt last) : s(first, last) {} |
|---|
| 226 | template <class InIt> RxString(InIt first, InIt last, const allocator_type& al) : s(first, last, al) {} |
|---|
| 227 | RxString& operator=(const RxString& right) {s = right.s; return *this;} |
|---|
| 228 | RxString& operator=(const value_type *ptr) {s = ptr; return *this;} |
|---|
| 229 | RxString& operator=(value_type ch) {s = ch; return *this;} |
|---|
| 230 | iterator begin() {return s.begin();} |
|---|
| 231 | const_iterator begin() const {return s.begin();} |
|---|
| 232 | iterator end() {return s.end();} |
|---|
| 233 | const_iterator end() const {return s.end();} |
|---|
| 234 | reverse_iterator rbegin() {return s.rbegin();} |
|---|
| 235 | const_reverse_iterator rbegin() const {return s.rbegin();} |
|---|
| 236 | reverse_iterator rend() {return s.rend();} |
|---|
| 237 | const_reverse_iterator rend() const {return s.rend();} |
|---|
| 238 | const_reference at(size_type off) const {return s.at(off);} |
|---|
| 239 | reference at(size_type off) {return s.at(off);} |
|---|
| 240 | const_reference operator[](size_type off) const {return s[off];} |
|---|
| 241 | reference operator[](size_type off) {return s[off];} |
|---|
| 242 | void push_back(value_type ch) {s.push_back(ch);} |
|---|
| 243 | const value_type *c_str() const {return s.c_str();} |
|---|
| 244 | const value_type *data() const {return s.data();} |
|---|
| 245 | size_type length() const {return s.length();} |
|---|
| 246 | size_type size() const {return s.size();} |
|---|
| 247 | size_type max_size() const {return s.max_size();} |
|---|
| 248 | void resize(size_type newsize, value_type ch = value_type()) {s.resize(newsize, ch);} |
|---|
| 249 | size_type capacity() const {return s.capacity();} |
|---|
| 250 | void reserve(size_type count = 0) {s.reserve(count);} |
|---|
| 251 | bool empty() const {return s.empty();} |
|---|
| 252 | RxString& operator+=(const RxString& right) {s += right.s; return *this;} |
|---|
| 253 | RxString& operator+=(const value_type *ptr) {s += ptr; return *this;} |
|---|
| 254 | RxString& operator+=(value_type ch) {s += ch; return *this;} |
|---|
| 255 | RxString& append(const RxString& right) {s.append(right.s); return *this;} |
|---|
| 256 | RxString& append(const RxString& right, size_type roff, size_type count) {s.append(right.s, roff, count); return *this;} |
|---|
| 257 | RxString& append(const value_type *ptr, size_type count) {s.append(ptr, count); return *this;} |
|---|
| 258 | RxString& append(const value_type *ptr) {s.append(ptr); return *this;} |
|---|
| 259 | RxString& append(size_type count, value_type ch) {s.append(count, ch); return *this;} |
|---|
| 260 | template<class InIt> RxString& append(InIt first, InIt last) {s.append(first, last); return *this;} |
|---|
| 261 | RxString& assign(const RxString& right) {s.assign(right.s); return *this;} |
|---|
| 262 | RxString& assign(const RxString& right, size_type roff, size_type count) {s.assign(right.s, roff, count); return *this;} |
|---|
| 263 | RxString& assign(const value_type *ptr, size_type count) {s.assign(ptr, count); return *this;} |
|---|
| 264 | RxString& assign(const value_type *ptr) {s.assign(ptr); return *this;} |
|---|
| 265 | RxString& assign(size_type count, value_type ch) {s.assign(count, ch); return *this;} |
|---|
| 266 | template<class InIt> RxString& assign(InIt first, InIt last) {s.assign(first, last); return *this;} |
|---|
| 267 | RxString& insert(size_type off, const RxString& right) {s.insert(off, right.s); return *this;} |
|---|
| 268 | RxString& insert(size_type off, const RxString& right, size_type roff, size_type count) {s.insert(off, right.s, roff, count); return *this;} |
|---|
| 269 | RxString& insert(size_type off, const value_type *ptr, size_type count) {s.insert(off, ptr, count); return *this;} |
|---|
| 270 | RxString& insert(size_type off, const value_type *ptr) {s.insert(off, ptr); return *this;} |
|---|
| 271 | RxString& insert(size_type off, size_type count, value_type ch) {s.insert(off, count, ch); return *this;} |
|---|
| 272 | iterator insert(iterator where, value_type ch = value_type()) {return s.insert(where, ch);} |
|---|
| 273 | void insert(iterator where, size_type count, value_type ch) {s.insert(where, count, ch);} |
|---|
| 274 | template<class InIt> void insert(iterator where, InIt first, InIt last) {s.insert(where, first, last);} |
|---|
| 275 | RxString& erase(size_type off = 0, size_type count = npos) {s.erase(off, count); return *this;} |
|---|
| 276 | iterator erase(iterator where) {return s.erase(where);} |
|---|
| 277 | iterator erase(iterator first, iterator last) {return s.erase(first, last);} |
|---|
| 278 | void clear() {s.clear();} |
|---|
| 279 | RxString& replace(size_type off, size_type n0, const RxString& right) {s.replace(off, n0, right.s); return *this;} |
|---|
| 280 | RxString& replace(size_type off, size_type n0, const RxString& right, size_type roff, size_type count) { |
|---|
| 281 | s.replace(off, n0, right.s, roff, count); return *this;} |
|---|
| 282 | RxString& replace(size_type off, size_type n0, const value_type *ptr, size_type count) {s.replace(off, n0, ptr, count); return *this;} |
|---|
| 283 | RxString& replace(size_type off, size_type n0, const value_type *ptr) {s.replace(off, n0, ptr); return *this;} |
|---|
| 284 | RxString& replace(size_type off, size_type n0, size_type count, value_type ch) {s.replace(off, n0, count, ch); return *this;} |
|---|
| 285 | RxString& replace(iterator first, iterator last, const RxString& right) {s.replace(first, last, right.s); return *this;} |
|---|
| 286 | RxString& replace(iterator first, iterator last, const value_type *ptr, size_type count) {s.replace(first, last, ptr, count); return *this;} |
|---|
| 287 | RxString& replace(iterator first, iterator last, const value_type *ptr) {s.replace(first, last, ptr); return *this;} |
|---|
| 288 | RxString& replace(iterator first, iterator last, size_type count, value_type ch) {s.replace(first, last, count, ch); return *this;} |
|---|
| 289 | template<class InIt> RxString& replace(iterator first, iterator last, InIt first2, InIt last2) { |
|---|
| 290 | s.replace(first, last, first2, last2); return *this;} |
|---|
| 291 | size_type copy(value_type *ptr, size_type count, size_type off = 0) const {return s.copy(ptr, count, off);} |
|---|
| 292 | void swap(RxString& right) {s.swap(right.s);} |
|---|
| 293 | size_type find(const RxString& right, size_type off = 0) const {return s.find(right.s, off);} |
|---|
| 294 | size_type find(const value_type *ptr, size_type off, size_type count) const {return s.find(ptr, off, count);} |
|---|
| 295 | size_type find(const value_type *ptr, size_type off = 0) const {return s.find(ptr, off);} |
|---|
| 296 | size_type find(value_type ch, size_type off = 0) const {return s.find(ch, off);} |
|---|
| 297 | size_type rfind(const RxString& right, size_type off = npos) const {return s.rfind(right.s, off);} |
|---|
| 298 | size_type rfind(const value_type *ptr, size_type off, size_type count = npos) const {return s.rfind(ptr, off, count);} |
|---|
| 299 | size_type rfind(const value_type *ptr, size_type off = npos) const {return s.rfind(ptr, off);} |
|---|
| 300 | size_type rfind(value_type ch, size_type off = npos) const {return s.rfind(ch, off);} |
|---|
| 301 | size_type find_first_of(const RxString& right, size_type off = 0) const {return s.find_first_of(right.s, off);} |
|---|
| 302 | size_type find_first_of(const value_type *ptr, size_type off, size_type count) const {return s.find_first_of(ptr, off, count);} |
|---|
| 303 | size_type find_first_of(const value_type *ptr, size_type off = 0) const {return s.find_first_of(ptr, off);} |
|---|
| 304 | size_type find_first_of(value_type ch, size_type off = 0) const {return s.find_first_of(ch, off);} |
|---|
| 305 | size_type find_last_of(const RxString& right, size_type off = npos) const {return s.find_last_of(right.s, off);} |
|---|
| 306 | size_type find_last_of(const value_type *ptr, size_type off, size_type count = npos) const {return s.find_last_of(ptr, off, count);} |
|---|
| 307 | size_type find_last_of(const value_type *ptr, size_type off = npos) const {return s.find_last_of(ptr, off);} |
|---|
| 308 | size_type find_last_of(value_type ch, size_type off = npos) const {return s.find_last_of(ch, off);} |
|---|
| 309 | size_type find_first_not_of(const RxString& right, size_type off = 0) const {return s.find_first_not_of(right.s, off);} |
|---|
| 310 | size_type find_first_not_of(const value_type *ptr, size_type off, size_type count) const {return s.find_first_not_of(ptr, off, count);} |
|---|
| 311 | size_type find_first_not_of(const value_type *ptr, size_type off = 0) const {return s.find_first_not_of(ptr, off);} |
|---|
| 312 | size_type find_first_not_of(value_type ch, size_type off = 0) const {return s.find_first_not_of(ch, off);} |
|---|
| 313 | size_type find_last_not_of(const RxString& right, size_type off = npos) const {return s.find_last_not_of(right.s, off);} |
|---|
| 314 | size_type find_last_not_of(const value_type *ptr, size_type off, size_type count) const {return s.find_last_not_of(ptr, off, count);} |
|---|
| 315 | size_type find_last_not_of(const value_type *ptr, size_type off = npos) const {return s.find_last_not_of(ptr, off);} |
|---|
| 316 | size_type find_last_not_of(value_type ch, size_type off = npos) const {return s.find_last_not_of(ch, off);} |
|---|
| 317 | RxString substr(size_type off = 0, size_type count = npos) const {return s.substr(off, count);} |
|---|
| 318 | int compare(const RxString& right) const {return s.compare(right.s);} |
|---|
| 319 | int compare(size_type off, size_type n0, const RxString& right) {return s.compare(off, n0, right.s);} |
|---|
| 320 | int compare(size_type off, size_type n0, const RxString& right, size_type roff, size_type count) {return s.compare(off, n0, right.s, roff, count);} |
|---|
| 321 | int compare(const value_type *ptr) const {return s.compare(ptr);} |
|---|
| 322 | int compare(size_type off, size_type n0, const value_type *ptr) const {return s.compare(off, n0, ptr);} |
|---|
| 323 | int compare(size_type off, size_type n0, const value_type *ptr, size_type roff) const {return s.compare(off, n0, ptr, roff);} |
|---|
| 324 | allocator_type get_allocator() const {return s.get_allocator();} |
|---|
| [672] | 325 | //@} |
|---|
| [257] | 326 | }; |
|---|
| 327 | |
|---|
| [398] | 328 | /** Formatted output operator for RxString */ |
|---|
| 329 | inline std::ostream& operator<<(std::ostream &o, const RxString &rs) { |
|---|
| 330 | return o << static_cast<std::string>(rs); |
|---|
| 331 | } |
|---|
| 332 | |
|---|
| 333 | /** Adds \a rhs and \a lhs, after converting \a rhs to a string, returns the result */ |
|---|
| 334 | template <class T> |
|---|
| 335 | RxString operator+ (const RxString& lhs, T rhs) { |
|---|
| 336 | RxString l(lhs); |
|---|
| 337 | RxString r; r.convertFrom(rhs); |
|---|
| 338 | return l += r; |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| 341 | /** compare two RxStrings for equality */ |
|---|
| 342 | inline bool operator==(const RxString &lhs, const RxString &rhs) { |
|---|
| 343 | return lhs.compare(rhs) == 0; |
|---|
| 344 | } |
|---|
| 345 | /** compare two RxStrings for equality */ |
|---|
| 346 | inline bool operator!=(const RxString &lhs, const RxString &rhs) { |
|---|
| 347 | return lhs.compare(rhs) != 0; |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| [257] | 350 | template <class Pred> |
|---|
| [398] | 351 | RxString::iterator RxString::find_if(Pred p) { |
|---|
| [257] | 352 | return std::find_if(begin(), end(), p); |
|---|
| 353 | } |
|---|
| 354 | |
|---|
| 355 | template <class Pred> |
|---|
| [398] | 356 | RxString::const_iterator RxString::find_if(Pred p) const { |
|---|
| [257] | 357 | return std::find_if(begin(), end(), p); |
|---|
| 358 | } |
|---|
| 359 | |
|---|
| 360 | template <class Pred> |
|---|
| 361 | void RxString::remove_if(Pred p) { |
|---|
| 362 | erase(std::remove_if(begin(), end(), p), end()); |
|---|
| 363 | } |
|---|
| 364 | |
|---|
| 365 | template <class Pred> |
|---|
| 366 | void RxString::replace_if(Pred p, value_type val) { |
|---|
| 367 | std::replace_if(begin(), end(), p, val); |
|---|
| 368 | } |
|---|
| 369 | |
|---|
| 370 | template <class Pred> |
|---|
| [398] | 371 | RxString::iterator RxString::find_last_not_if(Pred p) { |
|---|
| [257] | 372 | iterator b = begin(), e = end(); |
|---|
| 373 | iterator tail = b; |
|---|
| 374 | while (b != e) |
|---|
| 375 | if (p(*b++)) |
|---|
| 376 | tail = b; |
|---|
| 377 | return tail; |
|---|
| 378 | } |
|---|
| 379 | |
|---|
| 380 | template <class Pred> |
|---|
| [398] | 381 | RxString::const_iterator RxString::find_last_not_if(Pred p) const { |
|---|
| [257] | 382 | const_iterator b = begin(), e = end(); |
|---|
| 383 | const_iterator tail = b; |
|---|
| 384 | while (b != e) |
|---|
| 385 | if (p(*b++)) |
|---|
| 386 | tail = b; |
|---|
| 387 | return tail; |
|---|
| 388 | } |
|---|
| 389 | |
|---|
| 390 | template <class T> |
|---|
| 391 | bool RxString::convertTo(T &t) const { |
|---|
| 392 | std::istringstream iss(*this); |
|---|
| 393 | return (iss >> t); |
|---|
| 394 | } |
|---|
| 395 | |
|---|
| 396 | template <class T> |
|---|
| 397 | RxString &RxString::convertFrom(const T &val) { |
|---|
| 398 | std::ostringstream oss; |
|---|
| 399 | oss << val; |
|---|
| 400 | *this = oss.str(); |
|---|
| 401 | return *this; |
|---|
| 402 | } |
|---|
| 403 | |
|---|
| [689] | 404 | template<class IN> |
|---|
| 405 | IN& getline(IN& in, RxString& str, const char eol = '\n') { |
|---|
| 406 | str.append_line(in, eol); |
|---|
| 407 | return in; |
|---|
| 408 | } |
|---|
| [257] | 409 | |
|---|
| 410 | #endif |
|---|