1414#include < functional> // std::hash
1515#include < iosfwd>
1616#include < stdexcept>
17+ #include < cstdlib> // std::strtol
18+ #include < cerrno> // errno, ERANGE
1719
1820namespace docopt {
1921
@@ -58,9 +60,13 @@ namespace docopt {
5860
5961 // Throws std::invalid_argument if the type does not match
6062 bool asBool () const ;
63+ bool asBoolOr (const bool value) const noexcept ;
6164 long asLong () const ;
65+ long asLongOr (const long value) const noexcept ;
6266 std::string const & asString () const ;
67+ std::string const & asStringOr (std::string const & value) const noexcept ;
6368 std::vector<std::string> const & asStringList () const ;
69+ std::vector<std::string> const & asStringListOr (std::vector<std::string> const & value) const noexcept ;
6470
6571 size_t hash () const noexcept ;
6672
@@ -274,6 +280,16 @@ namespace docopt {
274280 return variant_.boolValue ;
275281 }
276282
283+ inline
284+ bool value::asBoolOr (const bool value) const noexcept
285+ {
286+ if (!isBool ())
287+ {
288+ return value;
289+ }
290+ return variant_.boolValue ;
291+ }
292+
277293 inline
278294 long value::asLong () const
279295 {
@@ -292,20 +308,68 @@ namespace docopt {
292308 return variant_.longValue ;
293309 }
294310
311+ inline
312+ long value::asLongOr (const long value) const noexcept
313+ {
314+ // Attempt to convert a string to a long
315+ if (isString ()) {
316+ const std::string& str = variant_.strValue ;
317+ char * str_end;
318+ const long ret = std::strtol (str.c_str (), &str_end, 10 );
319+ // Case 1: No Conversion was possible, return given default value
320+ if (str_end == str.c_str () && ret == 0 )
321+ {
322+ return value;
323+ }
324+ // Case 2: Parsed value is out of range, return given default value
325+ if (errno == ERANGE) {
326+ return value;
327+ }
328+ // Case 3: Everything is fine, return parsed value
329+ return ret;
330+ }
331+ if (!isLong ())
332+ {
333+ return value;
334+ }
335+ return variant_.longValue ;
336+ }
337+
295338 inline
296339 std::string const & value::asString () const
297340 {
298341 throwIfNotKind (Kind::String);
299342 return variant_.strValue ;
300343 }
301344
345+ inline
346+ std::string const & value::asStringOr (std::string const & value) const noexcept
347+ {
348+ if (!isString ())
349+ {
350+ return value;
351+ }
352+ return variant_.strValue ;
353+ }
354+
355+
302356 inline
303357 std::vector<std::string> const & value::asStringList () const
304358 {
305359 throwIfNotKind (Kind::StringList);
306360 return variant_.strList ;
307361 }
308362
363+ inline
364+ std::vector<std::string> const & value::asStringListOr (std::vector<std::string> const & value) const noexcept
365+ {
366+ if (!isStringList ())
367+ {
368+ return value;
369+ }
370+ return variant_.strList ;
371+ }
372+
309373 inline
310374 bool operator ==(value const & v1, value const & v2)
311375 {
0 commit comments