BasicSubString.h

// BasicSubString.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2005

#pragma once
#ifndef Ceda_cxUtils_BasicSubString_H
#define Ceda_cxUtils_BasicSubString_H

#include "xstring.h"
#include "CedaAssert.h"

namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// BasicSubString<T>

// A char range represents a substring of characters in the range [p1,p2).  No ownership semantics
// is implied.

template <typename T>
class BasicSubString
{
public:
    BasicSubString() : m_p1(nullptr), m_p2(nullptr) {}
    BasicSubString(const T* str) : m_p1(str), m_p2(str ? str + GetStringLength(str) : nullptr) {}
    BasicSubString(const T* p1, const T* p2) : m_p1(p1), m_p2(p2) {}
    BasicSubString(const basic_xstring<T>& s) : m_p1(s.data()), m_p2(s.data()+s.size()) {}
    ~BasicSubString() {}

    explicit operator bool() const { return m_p1 < m_p2; }

    ssize_t size() const { return m_p2 - m_p1; }
    bool empty() const { return m_p2 == m_p1; }
    basic_xstring<T> GetString() const { return basic_xstring<T>(m_p1,m_p2); }

    T operator[](ssize_t i) const { return m_p1[i]; }

    BasicSubString& operator+=(ssize_t i) { m_p1 += i; cxAssert(m_p1 <= m_p2); return *this; }
    BasicSubString& operator-=(ssize_t i) { m_p1 -= i; return *this; }

    BasicSubString& operator++() { cxAssert(m_p1 < m_p2); ++m_p1; return *this; }
    const BasicSubString operator++(int) { BasicSubString s = *this; ++(*this); return s; }
    BasicSubString& operator--() { --m_p1; return *this; }
    const BasicSubString operator--(int) { BasicSubString s = *this; --(*this); return s; }
    T operator*() const { cxAssert(m_p1 < m_p2); return *m_p1; }

    typedef const T* const_iterator;
    const_iterator begin() const { return m_p1; }
    const_iterator end() const { return m_p2; }

    void setbegin(const T* p1) { m_p1 = p1; }
    void setend(const T* p2) { m_p2 = p2; }
    
    const T* ptr() const { return m_p1; }

// TODO: The SubString8 typedef needs to be reflected so that cxPython can dispatch python's print 
// function to PythonCallback_WriteToStdOut(SubString8 s). However, the Ceda reflection system
// can't reflect private members (offsetof is used to get the address of the member in the object).
//private:
    const T* m_p1;
    const T* m_p2;
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// BasicReversedSubString<T>

// As for BasicSubString<T> except that it processes the characters in reverse order

template <typename T>
class BasicReversedSubString
{
public:
    BasicReversedSubString() : m_p1(nullptr), m_p2(nullptr) {}
    BasicReversedSubString(const T* str) : m_p1(str - 1), m_p2(str + GetStringLength(str) - 1) {}
    BasicReversedSubString(const T* p1, const T* p2) : m_p1(p1-1), m_p2(p2-1) {}
    BasicReversedSubString(const basic_xstring<T>& s) : m_p1(s.begin()-1), m_p2(s.end()-1) {}

    explicit operator bool() const { return m_p1 < m_p2; }

    ssize_t size() const { return m_p2 - m_p1; }
    bool empty() const { return m_p2 <= m_p1; }
    basic_xstring<T> GetString() const { return basic_xstring<T>(m_p1+1,m_p2+1); }

    T operator[](ssize_t i) const { return *(m_p2 - i); }

    BasicReversedSubString& operator+=(ssize_t i) { m_p2 -= i; cxAssert(m_p1 <= m_p2); return *this; }
    BasicReversedSubString& operator-=(ssize_t i) { m_p2 += i; return *this; }

    BasicReversedSubString& operator++() { cxAssert(m_p1 < m_p2); --m_p2; return *this; }
    const BasicReversedSubString operator++(int) { BasicReversedSubString s = *this; ++(*this); return s; }
    T operator*() const { cxAssert(m_p1 < m_p2); return *m_p2; }

    class const_iterator
    {
    public:
        const_iterator(const T* _p) : p(_p) {}
        
        operator const T*() const { return p; }
        
        const T& operator*() const { cxAssert(p); return *p; }
        const T* operator->() const { cxAssert(p); return p; }

        const_iterator& operator++() { cxAssert(p); --p; return *this; }
        const const_iterator operator++(int) { const_iterator it = *this; ++(*this); return it; }

        const_iterator& operator--() { cxAssert(p); ++p; return *this; }
        const const_iterator operator--(int) { const_iterator it = *this; --(*this); return it; }

        bool operator==(const const_iterator& rhs) const { return p == rhs.p; }
        bool operator!=(const const_iterator& rhs) const { return p != rhs.p; }
    
    private:
        const T* p;
    };
    
    const_iterator begin() const { return m_p2; }
    const_iterator end() const { return m_p1; }

    void setbegin(const T* p2) { m_p2 = p2; }
    void setend(const T* p1) { m_p1 = p1; }
    
    const T* ptr() const { return m_p2; }

private:
    // represent range of characters (m_p1, m_p2]
    const T* m_p1;
    const T* m_p2;
};

} // namespace ceda

#endif // include guard