1 #ifndef HERBSTLUFT_ARGLIST_H
2 #define HERBSTLUFT_ARGLIST_H
3 
4 #include <algorithm>
5 #include <initializer_list>
6 #include <iterator>
7 #include <memory>
8 #include <string>
9 #include <vector>
10 
11 class ArgList {
12 
13 public:
14     using Container = std::vector<std::string>;
15 
16     //! a simple split(), as C++ doesn't have it
17     static Container split(const std::string &s, char delim = '.');
18 
19     ArgList(const std::initializer_list<std::string> &l);
20     ArgList(Container::const_iterator from, Container::const_iterator to);
21     ArgList(const ArgList &al);
22     ArgList(const Container &c);
23     // constructor that splits the given string
24     ArgList(const std::string &s, char delim = '.');
~ArgList()25     virtual ~ArgList() {}
26 
begin()27     Container::const_iterator begin() const { return begin_; }
end()28     Container::const_iterator end() const { return container_->cend(); }
front()29     const std::string& front() { return *begin_; }
back()30     const std::string& back() { return container_->back(); }
empty()31     bool empty() const { return begin_ == container_->end(); }
size()32     Container::size_type size() const {
33         return std::distance(begin_, container_->cend());
34     }
35 
36     std::string join(char delim = '.');
37 
38     //! reset internal pointer to begin of arguments
reset()39     void reset() {
40         begin_ = container_->cbegin();
41         shiftedTooFar_ = false;
42     }
43     //! shift the internal pointer by amount
44     void shift(Container::difference_type amount = 1) {
45         begin_ += std::min(amount, std::distance(begin_, container_->cend()));
46     }
toVector()47     Container toVector() const {
48         return Container(begin_, container_->cend());
49     }
50     //! try read a value if possible
51     virtual ArgList& operator>>(std::string& val);
52 
53     //! tell whether all previous operator>>() succeeded
54     operator bool() const {
55         return !shiftedTooFar_;
56     }
57 
58 protected:
59     //! shift state pointing into container_
60     Container::const_iterator begin_;
61     //! indicator that we attempted to shift too far (shift is at end())
62     bool shiftedTooFar_ = false;
63     /*! Argument vector
64      * @note This is a shared pointer to make object copy-able:
65      * 1. payload is shared (no redundant copies)
66      * 2. begin_ stays valid
67      * 3. The C-style compatibility layer DEPENDS on the shared_ptr!
68      */
69     std::shared_ptr<Container> container_;
70 };
71 
72 #endif
73