iv-phonic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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_