summaryrefslogtreecommitdiff
path: root/libcult/cult/cli/scanner.hxx
blob: 13fa804577796ee63e232a2142572a04d12956d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// file      : cult/cli/scanner.hxx
// author    : Boris Kolpackov <boris@kolpackov.net>
// copyright : Copyright (c) 2005-2010 Boris Kolpackov
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef CULT_CLI_SCANNER_HXX
#define CULT_CLI_SCANNER_HXX

#include <cult/types.hxx>

#include <cult/cli/exceptions.hxx>
#include <cult/cli/arguments.hxx>

namespace Cult
{
  namespace CLI
  {
    class Scanner: public NonCopyable
    {
    public:
      class Action
      {
      public:
        static Action const keep, erase;

        friend Boolean
        operator== (Action const& a, Action const& b)
        {
          return a.v_ == b.v_;
        }

        friend Boolean
        operator!= (Action const& a, Action const& b)
        {
          return a.v_ != b.v_;
        }

      private:
        enum Value { keep_, erase_ } v_;

        Action (Value v)
            : v_ (v)
        {
        }
      };

    public:
      Scanner (Arguments& args, Action a = Action::keep, Index start = 1)
          : cargs_ (args),
            args_ (a == Action::erase ? &args : 0),
            next_ (start)
      {
      }

      Scanner (Arguments const& args, Index start = 1)
          : cargs_ (args), args_ (0), next_ (start)
      {
      }

    public:
      static Char const* const eos;

      class PastEOS: public virtual Exception {};

      Char const*
      next ()
      {
        if (next_ > cargs_.size ())
        {
          throw PastEOS ();
        }
        else if (next_ == cargs_.size ())
        {
          ++next_;
          return eos;
        }
        else
        {
          Char const* r (cargs_[next_]);

          if (args_ != 0)
          {
            hold_ = r;
            args_->erase (next_);
            return hold_.c_str ();
          }
          else
          {
            ++next_;
            return r;
          }
        }
      }

      Char const*
      peek ()
      {
        if (next_ > cargs_.size ())
        {
          throw PastEOS ();
        }
        else if (next_ == cargs_.size ())
        {
          return eos;
        }
        else
        {
          return cargs_[next_];
        }
      }

      Void
      skip ()
      {
        if (next_ > cargs_.size ())
          throw PastEOS ();
        else
          ++next_;
      }

    private:
      Arguments const& cargs_;
      Arguments* args_;
      Index next_;
      String hold_;
    };
  }
}

#include <cult/cli/scanner.ixx>

#endif  // CULT_CLI_SCANNER_HXX