iv-phonic 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/.autotest +24 -0
  2. data/Manifest.txt +49 -0
  3. data/README.rdoc +32 -0
  4. data/Rakefile +54 -0
  5. data/ext/include/iv/algorithm.h +23 -0
  6. data/ext/include/iv/alloc.h +200 -0
  7. data/ext/include/iv/any.h +71 -0
  8. data/ext/include/iv/ast-factory.h +277 -0
  9. data/ext/include/iv/ast-fwd.h +92 -0
  10. data/ext/include/iv/ast-serializer.h +579 -0
  11. data/ext/include/iv/ast-visitor.h +121 -0
  12. data/ext/include/iv/ast.h +1127 -0
  13. data/ext/include/iv/chars.h +83 -0
  14. data/ext/include/iv/cmdline.h +830 -0
  15. data/ext/include/iv/conversions.h +308 -0
  16. data/ext/include/iv/dtoa.h +20 -0
  17. data/ext/include/iv/enable_if.h +18 -0
  18. data/ext/include/iv/errors.h +15 -0
  19. data/ext/include/iv/fixedcontainer.h +42 -0
  20. data/ext/include/iv/functor.h +29 -0
  21. data/ext/include/iv/lexer.h +1281 -0
  22. data/ext/include/iv/location.h +23 -0
  23. data/ext/include/iv/mt19937.h +175 -0
  24. data/ext/include/iv/noncopyable.h +30 -0
  25. data/ext/include/iv/none.h +10 -0
  26. data/ext/include/iv/parser.h +2150 -0
  27. data/ext/include/iv/source.h +27 -0
  28. data/ext/include/iv/space.h +178 -0
  29. data/ext/include/iv/static_assert.h +30 -0
  30. data/ext/include/iv/stringpiece.h +385 -0
  31. data/ext/include/iv/token.h +311 -0
  32. data/ext/include/iv/ucdata.h +58 -0
  33. data/ext/include/iv/uchar.h +8 -0
  34. data/ext/include/iv/ustring.h +28 -0
  35. data/ext/include/iv/ustringpiece.h +9 -0
  36. data/ext/include/iv/utils.h +83 -0
  37. data/ext/include/iv/xorshift.h +74 -0
  38. data/ext/iv/phonic/ast-fwd.h +21 -0
  39. data/ext/iv/phonic/ast.h +10 -0
  40. data/ext/iv/phonic/creator.h +530 -0
  41. data/ext/iv/phonic/encoding.h +110 -0
  42. data/ext/iv/phonic/extconf.rb +5 -0
  43. data/ext/iv/phonic/factory.h +247 -0
  44. data/ext/iv/phonic/parser.h +12 -0
  45. data/ext/iv/phonic/phonic.cc +69 -0
  46. data/ext/iv/phonic/rnode.h +15 -0
  47. data/ext/iv/phonic/rparser.h +48 -0
  48. data/ext/iv/phonic/source.h +146 -0
  49. data/test/test_iv_phonic.rb +32 -0
  50. metadata +159 -0
@@ -0,0 +1,830 @@
1
+ // Copyright 2010 Constellation <utatane.tea@gmail.com> All rights reserved.
2
+ // New BSD Lisence.
3
+ // this is modified and created as CmdLine.
4
+ // original source is
5
+ // cmdline.h (http://github.com/tanakh/cmdline) (c) Hideyuki Tanaka
6
+ // and original lisence is folloing
7
+ //
8
+ // Copyright (c) 2009, Hideyuki Tanaka
9
+ // All rights reserved.
10
+ //
11
+ // Redistribution and use in source and binary forms, with or without
12
+ // modification, are permitted provided that the following conditions are met:
13
+ // * Redistributions of source code must retain the above copyright
14
+ // notice, this list of conditions and the following disclaimer.
15
+ // * Redistributions in binary form must reproduce the above copyright
16
+ // notice, this list of conditions and the following disclaimer in the
17
+ // documentation and/or other materials provided with the distribution.
18
+ // * Neither the name of the <organization> nor the
19
+ // names of its contributors may be used to endorse or promote products
20
+ // derived from this software without specific prior written permission.
21
+ //
22
+ // THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
23
+ // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24
+ // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ // DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
26
+ // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27
+ // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
+ // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29
+ // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #ifndef _IV_CMDLINE_H
33
+ #define _IV_CMDLINE_H_
34
+
35
+ #include <sstream>
36
+ #include <iterator>
37
+ #include <algorithm>
38
+ #include <vector>
39
+ #include <map>
40
+ #include <string>
41
+ #include <stdexcept>
42
+ #include <typeinfo>
43
+ #include <cstring>
44
+ #include <cxxabi.h>
45
+ #include <cstdlib>
46
+ #include <cassert>
47
+
48
+ namespace iv {
49
+ namespace cmdline {
50
+ namespace detail {
51
+
52
+ template <typename Target, typename Source, bool Same>
53
+ class lexical_cast_t {
54
+ public:
55
+ static Target cast(const Source &arg) {
56
+ Target ret;
57
+ std::stringstream ss;
58
+ if (!(ss << arg && ss >> ret && ss.eof())) {
59
+ throw std::bad_cast();
60
+ }
61
+ return ret;
62
+ }
63
+ };
64
+
65
+ template <typename Target, typename Source>
66
+ class lexical_cast_t<Target, Source, true> {
67
+ public:
68
+ static Target cast(const Source &arg) {
69
+ return arg;
70
+ }
71
+ };
72
+
73
+ template <typename Source>
74
+ class lexical_cast_t<std::string, Source, false> {
75
+ public:
76
+ static std::string cast(const Source &arg) {
77
+ std::ostringstream ss;
78
+ ss << arg;
79
+ return ss.str();
80
+ }
81
+ };
82
+
83
+ template <typename Target>
84
+ class lexical_cast_t<Target, std::string, false> {
85
+ public:
86
+ static Target cast(const std::string& arg) {
87
+ Target ret;
88
+ std::istringstream ss(arg);
89
+ if (!(ss >> ret && ss.eof())) {
90
+ throw std::bad_cast();
91
+ }
92
+ return ret;
93
+ }
94
+ };
95
+
96
+ template <typename T1, typename T2>
97
+ struct is_same {
98
+ static const bool value = false;
99
+ };
100
+
101
+ template <typename T>
102
+ struct is_same<T, T> {
103
+ static const bool value = true;
104
+ };
105
+
106
+ template<typename Target, typename Source>
107
+ Target lexical_cast(const Source &arg) {
108
+ return lexical_cast_t<Target,
109
+ Source,
110
+ detail::is_same<Target, Source>::value>::cast(arg);
111
+ }
112
+
113
+ static inline std::string demangle(const std::string& name) {
114
+ int status = 0;
115
+ char *p = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
116
+ std::string ret(p);
117
+ free(p);
118
+ return ret;
119
+ }
120
+
121
+ template <class T>
122
+ std::string readable_typename() {
123
+ return demangle(typeid(T).name());
124
+ }
125
+
126
+ template <>
127
+ std::string readable_typename<std::string>() {
128
+ return "string";
129
+ }
130
+
131
+ } // namespace iv::cmdline::detail
132
+
133
+ //-----
134
+
135
+ class cmdline_error : public std::exception {
136
+ public:
137
+ cmdline_error(const std::string& msg) : msg(msg) { } // NOLINT
138
+ ~cmdline_error() throw() { }
139
+ const char *what() const throw() { return msg.c_str(); }
140
+ private:
141
+ std::string msg;
142
+ };
143
+
144
+ template <class T>
145
+ struct default_reader {
146
+ T operator()(const std::string& str) {
147
+ return detail::lexical_cast<T>(str);
148
+ }
149
+ };
150
+
151
+ template <class T>
152
+ struct range_reader {
153
+ range_reader(const T& low, const T& high): low(low), high(high) {}
154
+ T operator()(const std::string& s) const {
155
+ T ret = default_reader<T>()(s);
156
+ if (!(ret >= low && ret <= high)) {
157
+ throw cmdline::cmdline_error("range_error");
158
+ }
159
+ return ret;
160
+ }
161
+ private:
162
+ T low, high;
163
+ };
164
+
165
+ template <class T>
166
+ range_reader<T> range(const T& low, const T& high) {
167
+ return range_reader<T>(low, high);
168
+ }
169
+
170
+ template <class T>
171
+ struct oneof_reader {
172
+ T operator()(const std::string& s) {
173
+ T ret = default_reader<T>()(s);
174
+ if (std::find(alt.begin(), alt.end(), s) == alt.end()) {
175
+ throw cmdline_error("");
176
+ }
177
+ return ret;
178
+ }
179
+ void add(const T& v) { alt.push_back(v); }
180
+ private:
181
+ std::vector<T> alt;
182
+ };
183
+
184
+ template <class T>
185
+ oneof_reader<T> oneof(T a1) {
186
+ oneof_reader<T> ret;
187
+ ret.add(a1);
188
+ return ret;
189
+ }
190
+
191
+ template <class T>
192
+ oneof_reader<T> oneof(T a1, T a2) {
193
+ oneof_reader<T> ret;
194
+ ret.add(a1);
195
+ ret.add(a2);
196
+ return ret;
197
+ }
198
+
199
+ template <class T>
200
+ oneof_reader<T> oneof(T a1, T a2, T a3) {
201
+ oneof_reader<T> ret;
202
+ ret.add(a1);
203
+ ret.add(a2);
204
+ ret.add(a3);
205
+ return ret;
206
+ }
207
+
208
+ template <class T>
209
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4) {
210
+ oneof_reader<T> ret;
211
+ ret.add(a1);
212
+ ret.add(a2);
213
+ ret.add(a3);
214
+ ret.add(a4);
215
+ return ret;
216
+ }
217
+
218
+ template <class T>
219
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5) {
220
+ oneof_reader<T> ret;
221
+ ret.add(a1);
222
+ ret.add(a2);
223
+ ret.add(a3);
224
+ ret.add(a4);
225
+ ret.add(a5);
226
+ return ret;
227
+ }
228
+
229
+ template <class T>
230
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6) {
231
+ oneof_reader<T> ret;
232
+ ret.add(a1);
233
+ ret.add(a2);
234
+ ret.add(a3);
235
+ ret.add(a4);
236
+ ret.add(a5);
237
+ ret.add(a6);
238
+ return ret;
239
+ }
240
+
241
+ template <class T>
242
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7) {
243
+ oneof_reader<T> ret;
244
+ ret.add(a1);
245
+ ret.add(a2);
246
+ ret.add(a3);
247
+ ret.add(a4);
248
+ ret.add(a5);
249
+ ret.add(a6);
250
+ ret.add(a7);
251
+ return ret;
252
+ }
253
+
254
+ template <class T>
255
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8) {
256
+ oneof_reader<T> ret;
257
+ ret.add(a1);
258
+ ret.add(a2);
259
+ ret.add(a3);
260
+ ret.add(a4);
261
+ ret.add(a5);
262
+ ret.add(a6);
263
+ ret.add(a7);
264
+ ret.add(a8);
265
+ return ret;
266
+ }
267
+
268
+ template <class T>
269
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9) {
270
+ oneof_reader<T> ret;
271
+ ret.add(a1);
272
+ ret.add(a2);
273
+ ret.add(a3);
274
+ ret.add(a4);
275
+ ret.add(a5);
276
+ ret.add(a6);
277
+ ret.add(a7);
278
+ ret.add(a8);
279
+ ret.add(a9);
280
+ return ret;
281
+ }
282
+
283
+ template <class T>
284
+ oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5,
285
+ T a6, T a7, T a8, T a9, T a10) {
286
+ oneof_reader<T> ret;
287
+ ret.add(a1);
288
+ ret.add(a2);
289
+ ret.add(a3);
290
+ ret.add(a4);
291
+ ret.add(a5);
292
+ ret.add(a6);
293
+ ret.add(a7);
294
+ ret.add(a8);
295
+ ret.add(a9);
296
+ ret.add(a10);
297
+ return ret;
298
+ }
299
+
300
+ //-----
301
+
302
+ class Parser {
303
+ private:
304
+ class option_base {
305
+ public:
306
+ virtual ~option_base() { }
307
+
308
+ virtual bool has_value() const = 0;
309
+ virtual bool set() = 0;
310
+ virtual bool set(const std::string& value) = 0;
311
+ virtual bool has_set() const = 0;
312
+ virtual bool valid() const = 0;
313
+ virtual bool must() const = 0;
314
+
315
+ virtual const std::string& name() const = 0;
316
+ virtual char short_name() const = 0;
317
+ virtual const std::string& description() const = 0;
318
+ virtual std::string short_description() const = 0;
319
+ };
320
+
321
+ class option_without_value : public option_base {
322
+ public:
323
+ option_without_value(const std::string& name,
324
+ char short_name,
325
+ const std::string& desc)
326
+ : name_(name),
327
+ short_name_(short_name),
328
+ has_(false),
329
+ description_(desc) {
330
+ }
331
+ ~option_without_value() { }
332
+
333
+ bool has_value() const { return false; }
334
+
335
+ bool set() {
336
+ return has_ = true;
337
+ }
338
+
339
+ bool set(const std::string&) {
340
+ return false;
341
+ }
342
+
343
+ bool has_set() const {
344
+ return has_;
345
+ }
346
+
347
+ bool valid() const {
348
+ return true;
349
+ }
350
+
351
+ bool must() const {
352
+ return false;
353
+ }
354
+
355
+ const std::string& name() const {
356
+ return name_;
357
+ }
358
+
359
+ char short_name() const {
360
+ return short_name_;
361
+ }
362
+
363
+ const std::string& description() const {
364
+ return description_;
365
+ }
366
+
367
+ std::string short_description() const {
368
+ return "--"+name_;
369
+ }
370
+
371
+ private:
372
+ std::string name_;
373
+ char short_name_;
374
+ bool has_;
375
+ std::string description_;
376
+ };
377
+
378
+ template <class T>
379
+ class option_with_value : public option_base {
380
+ public:
381
+ option_with_value(const std::string& name,
382
+ char short_name,
383
+ bool need,
384
+ const T& def,
385
+ const std::string& desc)
386
+ : name_(name),
387
+ short_name_(short_name),
388
+ need_(need),
389
+ has_(false),
390
+ def_(def) {
391
+ description_ = full_description(desc);
392
+ }
393
+ ~option_with_value() { }
394
+
395
+ const T& get() const {
396
+ return def_;
397
+ }
398
+
399
+ bool has_value() const { return true; }
400
+
401
+ bool set() {
402
+ return false;
403
+ }
404
+
405
+ bool set(const std::string& value) {
406
+ try {
407
+ def_ = read(value);
408
+ has_ = true;
409
+ } catch(const std::exception &e) {
410
+ return false;
411
+ }
412
+ return true;
413
+ }
414
+
415
+ bool has_set() const {
416
+ return has_;
417
+ }
418
+
419
+ bool valid() const {
420
+ return !need_ || has_;
421
+ }
422
+
423
+ bool must() const {
424
+ return need_;
425
+ }
426
+
427
+ const std::string& name() const {
428
+ return name_;
429
+ }
430
+
431
+ char short_name() const {
432
+ return short_name_;
433
+ }
434
+
435
+ const std::string& description() const {
436
+ return description_;
437
+ }
438
+
439
+ std::string short_description() const {
440
+ return "--"+name_+"="+detail::readable_typename<T>();
441
+ }
442
+
443
+ protected:
444
+ std::string full_description(const std::string& desc) {
445
+ return
446
+ desc + " (" + detail::readable_typename<T>() +
447
+ (need_ ? "" : " [="+detail::lexical_cast<std::string>(def_)+"]" )
448
+ +")";
449
+ }
450
+
451
+ virtual T read(const std::string& s) = 0;
452
+
453
+ std::string name_;
454
+ char short_name_;
455
+ bool need_;
456
+ bool has_;
457
+ T def_;
458
+ std::string description_;
459
+ };
460
+
461
+ template <class T, class F>
462
+ class option_with_value_with_reader : public option_with_value<T> {
463
+ public:
464
+ option_with_value_with_reader(const std::string& name,
465
+ char short_name,
466
+ bool need,
467
+ const T def,
468
+ const std::string& desc,
469
+ F reader)
470
+ : option_with_value<T>(name, short_name, need, def, desc),
471
+ reader(reader) {
472
+ }
473
+
474
+ private:
475
+ T read(const std::string& s) {
476
+ return reader(s);
477
+ }
478
+
479
+ F reader;
480
+ };
481
+
482
+ public:
483
+ typedef std::map<std::string, option_base*> OptionMap;
484
+ typedef std::vector<option_base*> OptionVector;
485
+
486
+ explicit Parser(const std::string& program_name = "")
487
+ : options_(),
488
+ ordered_(),
489
+ footer_(""),
490
+ program_name_(program_name),
491
+ others_(),
492
+ errors_() {
493
+ }
494
+ ~Parser() {
495
+ for (OptionMap::const_iterator it = options_.begin(),
496
+ end = options_.end();it != end; it++) {
497
+ delete it->second;
498
+ }
499
+ }
500
+
501
+ void Add(const std::string& key,
502
+ const std::string& name = "",
503
+ char short_name = 0,
504
+ const std::string& desc = "") {
505
+ assert(options_.count(key) == 0);
506
+ option_base* const ptr = new option_without_value(name, short_name, desc);
507
+ options_[key] = ptr;
508
+ ordered_.push_back(ptr);
509
+ }
510
+
511
+ template <class T>
512
+ void Add(const std::string& key,
513
+ const std::string& name = "",
514
+ char short_name = 0,
515
+ const std::string& desc = "",
516
+ bool need = true,
517
+ const T def = T()) {
518
+ Add(key, name, short_name, desc, need, def, default_reader<T>());
519
+ }
520
+
521
+ template <class T, class F>
522
+ void Add(const std::string& key,
523
+ const std::string& name = "",
524
+ char short_name = 0,
525
+ const std::string& desc = "",
526
+ bool need = true,
527
+ const T def = T(),
528
+ F reader = F()) {
529
+ assert(options_.count(key) == 0);
530
+ option_base* const ptr =
531
+ new option_with_value_with_reader<T, F>(name, short_name,
532
+ need, def, desc, reader);
533
+ options_[key] = ptr;
534
+ ordered_.push_back(ptr);
535
+ }
536
+
537
+ void set_footer(const std::string& f) {
538
+ footer_ = f;
539
+ }
540
+
541
+ void set_program_name(const std::string& name) {
542
+ program_name_ = name;
543
+ }
544
+
545
+ bool Exist(const std::string& key) const {
546
+ const OptionMap::const_iterator it = options_.find(key);
547
+ assert(it != options_.end());
548
+ return it->second->has_set();
549
+ }
550
+
551
+ template <class T>
552
+ const T& get(const std::string& key) const {
553
+ const OptionMap::const_iterator it = options_.find(key);
554
+ assert(it != options_.end());
555
+ const option_with_value<T> *p = dynamic_cast< //NOLINT
556
+ const option_with_value<T>*>(it->second);
557
+ assert(p != NULL);
558
+ return p->get();
559
+ }
560
+
561
+ const std::vector<std::string>& rest() const {
562
+ return others_;
563
+ }
564
+
565
+ bool Parse(const std::string& arg) {
566
+ std::vector<std::string> args;
567
+
568
+ std::string buf;
569
+ bool in_quote = false;
570
+ for (std::string::const_iterator it = arg.begin(),
571
+ end = arg.end();it != end; ++it) {
572
+ if (*it == '\"') {
573
+ in_quote = !in_quote;
574
+ continue;
575
+ }
576
+
577
+ if (*it == ' ' && !in_quote) {
578
+ args.push_back(buf);
579
+ buf.clear();
580
+ continue;
581
+ }
582
+
583
+ if (*it == '\\') {
584
+ ++it;
585
+ if (it == end) {
586
+ errors_.push_back("unexpected occurrence of '\\' at end of string");
587
+ return false;
588
+ }
589
+ }
590
+
591
+ buf.push_back(*it);
592
+ }
593
+
594
+ if (in_quote) {
595
+ errors_.push_back("quote is not closed");
596
+ return false;
597
+ }
598
+
599
+ if (!buf.empty()) {
600
+ args.push_back(buf);
601
+ }
602
+
603
+ return Parse(args);
604
+ }
605
+
606
+ bool Parse(const std::vector<std::string>& args) {
607
+ const std::size_t argc = args.size();
608
+ std::vector<const char*> argv(argc);
609
+ std::transform(args.begin(), args.end(),
610
+ argv.begin(), mem_fun_ref(&std::string::c_str));
611
+ return Parse(argc, argv.data());
612
+ }
613
+
614
+ bool Parse(int argc, const char * const argv[]) {
615
+ typedef std::map<char, option_base*> ShortLookup;
616
+ typedef std::map<std::string, option_base*> LongLookup;
617
+ errors_.clear();
618
+ others_.clear();
619
+
620
+ if (argc < 1) {
621
+ errors_.push_back("argument number must be longer than 0");
622
+ return false;
623
+ }
624
+
625
+ if (program_name_.empty()) {
626
+ program_name_ = argv[0];
627
+ }
628
+
629
+ ShortLookup short_lookup;
630
+ LongLookup long_lookup;
631
+ // set short options to lookup table
632
+ for (OptionMap::const_iterator p = options_.begin(),
633
+ end = options_.end();p != end; ++p) {
634
+ char initial = p->second->short_name();
635
+ if (initial) {
636
+ const ShortLookup::iterator it = short_lookup.find(initial);
637
+ if (it != short_lookup.end()) {
638
+ errors_.push_back(
639
+ std::string("short option '")+initial+"' is ambiguous");
640
+ return false;
641
+ } else {
642
+ short_lookup.insert(it,
643
+ ShortLookup::value_type(initial, p->second));
644
+ }
645
+ }
646
+ const std::string& name = p->second->name();
647
+ if (!name.empty()) {
648
+ const LongLookup::iterator it = long_lookup.find(name);
649
+ if (it != long_lookup.end()) {
650
+ errors_.push_back("option '"+name+"' is ambiguous");
651
+ return false;
652
+ } else {
653
+ long_lookup.insert(it, LongLookup::value_type(name, p->second));
654
+ }
655
+ }
656
+ }
657
+
658
+ for (int i = 1; i < argc; ++i) {
659
+ if (strncmp(argv[i], "--", 2) == 0) {
660
+ const char *p = strchr(argv[i]+2, '=');
661
+ if (p) {
662
+ std::string name(argv[i]+2, p);
663
+ std::string val(p+1);
664
+ const LongLookup::iterator it = long_lookup.find(name);
665
+ if (it == long_lookup.end()) {
666
+ errors_.push_back("undefined option: --"+name);
667
+ continue;
668
+ }
669
+ set_option(it->second, name, val);
670
+ } else {
671
+ std::string name(argv[i]+2);
672
+ const LongLookup::iterator it = long_lookup.find(name);
673
+ if (it == long_lookup.end()) {
674
+ errors_.push_back("undefined option: --"+name);
675
+ continue;
676
+ }
677
+ if (it->second->has_value()) {
678
+ if (i+1 >= argc) {
679
+ errors_.push_back("option needs value: --"+name);
680
+ continue;
681
+ } else {
682
+ ++i;
683
+ set_option(it->second, name, argv[i]);
684
+ }
685
+ } else {
686
+ set_option(it->second, name);
687
+ }
688
+ }
689
+ } else if (strncmp(argv[i], "-", 1) == 0) {
690
+ if (!argv[i][1]) {
691
+ continue;
692
+ }
693
+
694
+ char last = argv[i][1];
695
+ for (int j = 2; argv[i][j]; ++j) {
696
+ last = argv[i][j];
697
+ char initial = argv[i][j-1];
698
+ const ShortLookup::iterator it = short_lookup.find(initial);
699
+ if (it == short_lookup.end()) {
700
+ errors_.push_back(
701
+ std::string("undefined short option: -")+initial);
702
+ continue;
703
+ }
704
+ set_option(it->second, initial);
705
+ }
706
+
707
+ const ShortLookup::iterator it = short_lookup.find(last);
708
+ if (it == short_lookup.end()) {
709
+ errors_.push_back(std::string("undefined short option: -")+last);
710
+ continue;
711
+ }
712
+ if (i+1 < argc && it->second->has_value()) {
713
+ set_option(it->second, last, argv[i+1]);
714
+ ++i;
715
+ } else {
716
+ set_option(it->second, last);
717
+ }
718
+ } else {
719
+ others_.push_back(argv[i]);
720
+ }
721
+ }
722
+
723
+ for (OptionMap::const_iterator p = options_.begin(),
724
+ end = options_.end();p != end; ++p) {
725
+ if (!p->second->valid()) {
726
+ errors_.push_back("need option: --"+std::string(p->first));
727
+ }
728
+ }
729
+
730
+ return errors_.empty();
731
+ }
732
+
733
+ std::string error() const {
734
+ return errors_.empty() ? "" : errors_[0];
735
+ }
736
+
737
+ std::string error_full() const {
738
+ std::ostringstream oss;
739
+ std::copy(errors_.begin(), errors_.end(),
740
+ std::ostream_iterator<std::string>(oss, "\n"));
741
+ return oss.str();
742
+ }
743
+
744
+ std::string usage() const {
745
+ std::ostringstream oss;
746
+ oss << "usage: " << program_name_ << " ";
747
+
748
+ std::size_t max_width = 0;
749
+ for (OptionVector::const_iterator it = ordered_.begin(),
750
+ end = ordered_.end(); it != end; ++it) {
751
+ if ((*it)->must()) {
752
+ oss << (*it)->short_description() << " ";
753
+ }
754
+ max_width = std::max(max_width, (*it)->name().size());
755
+ }
756
+
757
+ oss << "[options] " << footer_ << std::endl
758
+ << "options:" << std::endl;
759
+
760
+ const std::size_t real_width = max_width + 4;
761
+ for (OptionVector::const_iterator it = ordered_.begin(),
762
+ end = ordered_.end(); it != end; ++it) {
763
+ const char short_name = (*it)->short_name();
764
+ if (short_name) {
765
+ oss << " -" << short_name;
766
+ } else {
767
+ oss << " ";
768
+ }
769
+ const std::string& name = (*it)->name();
770
+ if (name.empty()) {
771
+ oss << " ";
772
+ } else {
773
+ if (short_name) {
774
+ oss << ", --";
775
+ } else {
776
+ oss << " --";
777
+ }
778
+ oss << name;
779
+ }
780
+ oss << std::string(real_width - name.size(), ' ')
781
+ << (*it)->description() << std::endl;
782
+ }
783
+ return oss.str();
784
+ }
785
+
786
+ private:
787
+ void set_option(option_base* opt,
788
+ const std::string& name) {
789
+ if (!opt->set()) {
790
+ errors_.push_back("option needs value: --"+name);
791
+ return;
792
+ }
793
+ }
794
+
795
+ void set_option(option_base* opt,
796
+ const std::string& name, const std::string& value) {
797
+ if (!opt->set(value)) {
798
+ errors_.push_back("option value is invalid: --"+name+"="+value);
799
+ return;
800
+ }
801
+ }
802
+
803
+ void set_option(option_base* opt,
804
+ const char name) {
805
+ if (!opt->set()) {
806
+ errors_.push_back(
807
+ std::string("option needs value: -")+name);
808
+ return;
809
+ }
810
+ }
811
+
812
+ void set_option(option_base* opt,
813
+ const char name, const std::string& value) {
814
+ if (!opt->set(value)) {
815
+ errors_.push_back(
816
+ std::string("option value is invalid: -")+name+"="+value);
817
+ return;
818
+ }
819
+ }
820
+
821
+ OptionMap options_;
822
+ OptionVector ordered_;
823
+ std::string footer_;
824
+ std::string program_name_;
825
+ std::vector<std::string> others_;
826
+ std::vector<std::string> errors_;
827
+ };
828
+
829
+ } } // namespace iv::cmdline
830
+ #endif // _IV_CMDLINE_H_