#ifndef STRBLOB_H #define STRBLOB_H #include #include #include #include #include class StrBlobPtr; class StrBlob { friend class StrBlobPtr; public: typedef std::vector::size_type size_type; StrBlob(); StrBlob(std::initializer_list il); void push_back(const std::string &s) { data->push_back(s); } void pop_back(); std::string &front(); const std::string &front() const; std::string &back(); const std::string &back() const; StrBlobPtr begin(); StrBlobPtr begin() const; StrBlobPtr end(); StrBlobPtr end() const; size_type size() const { return data->size(); } bool empty() const { return data->empty(); } private: std::shared_ptr> data; void check(size_type i, const std::string &msg) const; }; // !StrBlob // functions of StrBlob inline StrBlob::StrBlob() : data(std::make_shared>()) {} inline StrBlob::StrBlob(std::initializer_list il) : data(std::make_shared>(il)) {} inline void StrBlob::check(size_type i, const std::string &msg) const { if (i >= data->size()) throw std::out_of_range(msg); } inline const std::string &StrBlob::front() const { check(0, "front on empty StrBlob"); return data->front(); } inline std::string &StrBlob::front() { check(0, "front on empty StrBlob"); return data->front(); } inline const std::string &StrBlob::back() const { check(0, "back on empty StrBlob"); return data->back(); } inline std::string &StrBlob::back() { check(0, "back on empty StrBlob"); return data->back(); } class StrBlobPtr { public: StrBlobPtr() : curr(0) {} StrBlobPtr(StrBlob &a, std::size_t sz = 0) : wptr(a.data), curr(sz) {} StrBlobPtr(const StrBlob &a, std::size_t sz = 0) : wptr(a.data), curr(sz) {} std::string &deref() const; StrBlobPtr &incr(); bool equal(const StrBlobPtr &); private: std::shared_ptr> check(std::size_t, const std::string &msg) const; std::weak_ptr> wptr; std::size_t curr; }; // !StrBlobPtr // functions of StrBlobPtr inline std::string &StrBlobPtr::deref() const { auto p = check(curr, "deref pass end"); return (*p)[curr]; } inline StrBlobPtr &StrBlobPtr::incr() { ++curr; return *this; } inline bool StrBlobPtr::equal(const StrBlobPtr &sbp) { return (*this).curr == sbp.curr; } inline std::shared_ptr> StrBlobPtr::check(std::size_t i, const std::string &msg) const { auto ret = wptr.lock(); if (!ret) throw std::runtime_error("unbound StrBlob"); if (i >= ret->size()) throw std::out_of_range(msg); return ret; } // functions of StrBlob StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); } StrBlobPtr StrBlob::begin() const { return StrBlobPtr(*this); } StrBlobPtr StrBlob::end() { return StrBlobPtr(*this, data->size()); } StrBlobPtr StrBlob::end() const { return StrBlobPtr(*this, data->size()); } #endif // !STRBLOB_H