root/rxstring/trunk/rxstring.h @ 689

Revision 689, 18.8 kB (checked in by tapted, 2 years ago)

Add getline

  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision url Rev Revision
RevLine 
[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]30extern "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]44class RxString {
[257]45public:
[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]64private:
[672]65    S s; ///< The instance of std::string we wrap
[398]66public:
[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 &regex,
[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 &regex,
121                 match_vec_type *matches = 0,
122                 RxString *err_string = 0,
123                 int eflags = 0
124                ) const;
125
126    RxString matchn(const RxString &regex, unsigned n = 0, RxString *err_string = 0, int cflags = REG_EXTENDED, int eflags = 0) const;
127    RxString matchn(const my_regex_t  &regex, 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 &regex, const RxString &regstr, 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 &regex);
134
[257]135    /**
136     * Match, ignoring case of the string.
137     *\copydoc RxString::match()
138     */     
139    size_t match_icase(const RxString &regex,
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 */
329inline 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 */
334template <class T>
335RxString 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 */
342inline bool operator==(const RxString &lhs, const RxString &rhs) {
343    return lhs.compare(rhs) == 0;
344}
345/** compare two RxStrings for equality */
346inline bool operator!=(const RxString &lhs, const RxString &rhs) {
347    return lhs.compare(rhs) != 0;
348}
349
[257]350template <class Pred>
[398]351RxString::iterator RxString::find_if(Pred p) {
[257]352    return std::find_if(begin(), end(), p);
353}
354
355template <class Pred>
[398]356RxString::const_iterator RxString::find_if(Pred p) const {
[257]357    return std::find_if(begin(), end(), p);
358}
359
360template <class Pred>
361void RxString::remove_if(Pred p) {
362    erase(std::remove_if(begin(), end(), p), end());
363}
364
365template <class Pred>
366void RxString::replace_if(Pred p, value_type val) {
367    std::replace_if(begin(), end(), p, val);
368}
369
370template <class Pred>
[398]371RxString::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
380template <class Pred>
[398]381RxString::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
390template <class T>
391bool RxString::convertTo(T &t) const {
392    std::istringstream iss(*this);
393    return (iss >> t);
394}
395
396template <class T>
397RxString &RxString::convertFrom(const T &val) {
398    std::ostringstream oss;
399    oss << val;
400    *this = oss.str();
401    return *this;
402}
403
[689]404template<class IN>
405IN& getline(IN& in, RxString& str, const char eol = '\n') {
406    str.append_line(in, eol);
407    return in;
408}
[257]409
410#endif
Note: See TracBrowser for help on using the browser.