File: option_stream.h

package info (click to toggle)
swish%2B%2B 6.1.5-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 2,256 kB
  • ctags: 1,759
  • sloc: ansic: 11,931; lisp: 804; sh: 629; perl: 366; makefile: 80
file content (172 lines) | stat: -rw-r--r-- 5,748 bytes parent folder | download | duplicates (7)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
**      PJL C++ Library
**      option_stream.h
**
**      Copyright (C) 1999  Paul J. Lucas
**
**      This program is free software; you can redistribute it and/or modify
**      it under the terms of the GNU General Public License as published by
**      the Free Software Foundation; either version 2 of the License, or
**      (at your option) any later version.
**
**      This program is distributed in the hope that it will be useful,
**      but WITHOUT ANY WARRANTY; without even the implied warranty of
**      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**      GNU General Public License for more details.
**
**      You should have received a copy of the GNU General Public License
**      along with this program; if not, write to the Free Software
**      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef option_stream_H
#define option_stream_H

// standard
#include <iostream>

#if 0
extern char const* dtoa( double );

// local
#include "itoa.h"
#include "util.h"
#endif

namespace PJL {

//*****************************************************************************
//
// SYNOPSIS
//
        class option_stream
//
// DESCRIPTION
//
//      Given the traditional argc and argv for command-line arguments, extract
//      options from them following the stream model.
//
// RATIONALE
//
//      Why not use the standard getopt() or GNU's getopt_long()?  Because
//      neither are thread-safe and I needed a thread-safe version.
//
//*****************************************************************************
{
public:
    enum {
        os_arg_none = 0,
        os_arg_req  = 1,
        os_arg_opt  = 2
    };
    struct spec {
        //
        // A spec gives a specfication for an option: its long name, its
        // argument type, and it's short option equivalent.  A null-terminated
        // array of specs is given to the option_stream constructor.
        //
        // The arg_type takes on one of the above enum values, but is not
        // declared as an enum to allow the integer values to be used as a
        // shorthand.
        //
        // Regardless of whether the user enters a long or a short option, it
        // is the short option character that is returned to the caller in
        // order to be able to use a simple switch statement to do different
        // things depending on the option.
        //
        // If, for a given long option there is to be no short option
        // equivalent, then the caller has to make up bogus ones that the user
        // will never type.  Either the ASCII control or high characters can be
        // user for this.  The null character may not be used.
        //
#if 0
        //
        // Ignore the class in this section.  I'm not sure I want to implement
        // default values for options that can have optional arguments.  I left
        // the code here in case I ever decide I want to implement it.
        //
        class default_value {
        public:
            default_value( char v ) : val_( new char[2] ) {
                val_[0] = v;
                val_[1] = '\0';
            }

            default_value( char const *v = "" ) :
                val_( new_strdup( v ) ) { }

            default_value( long v ) :
                val_( new_strdup( ltoa( v ) ) ) { }

            default_value( double v ) :
                val_( new_strdup( dtoa( v ) ) ) { }

            default_value( default_value const &v ) :
                val_( new_strdup( v.val_ ) ) { }

            ~default_value() { delete[] val_; }

            operator char*() const { return val_; }
        private:
            char *const val_;

            default_value& operator=( default_value const& );
        };
#endif

        char const*     long_name;
        short           arg_type;
        unsigned char   short_name;
#if 0
        default_value   def_arg;
#endif
    };

    option_stream(
        int argc, char *argv[], spec const[], std::ostream& = std::cerr
    );

    int shift() const                           { return argi_; }
    operator bool() const                       { return !end_; }

    class option {
        //
        // An option is what is extracted from an option_stream.  Its operator
        // char() gives which option it is and arg() gives its argument, if
        // any.  For options that do not have an argument, arg() returns the
        // null pointer.
        //
        // An option may be copied in which case it has a private copy of its
        // argument.
        //
    public:
        option( char c = '\0', char *a = 0 ) : short_name_( c ), arg_( a ) { }

        char*    arg() const                    { return arg_; }
        operator char() const                   { return short_name_; }

        friend option_stream& operator>>( option_stream&, option& );
    private:
        char    short_name_;
        char*   arg_;

        option( option const& );                // forbid copy
        option& operator=( option const& );     // forbid assignment
    };

    friend option_stream& operator>>( option_stream&, option& );
private:
    int             argc_;                      // argument count from main()
    char**          argv_;                      // argument vector from main()
    spec const*     specs_;                     // the option specifications
    std::ostream&   err_;                       // ostream to write wrrors to

    int             argi_;              // current index into argv_[]
    char*           next_c_;            // next char in group of short options
    bool            end_;               // reached end of options?
};

} // namespace PJL

#endif  /* option_stream_H */
/* vim:set et sw=4 ts=4: */