+One of the simplest and most common extensions is the use of a custom parser.
+As <a href="#builtinparsers">discussed previously</a>, parsers are the portion
+of the CommandLine library that turns string input from the user into a
+particular parsed data type, validating the input in the process.<p>
+
+There are two ways to use a new parser:<p>
+
+<ol>
+<li>Specialize the <a href="#genericparser"><tt>cl::parser</tt></a> template for
+ your custom data type.<p>
+
+ This approach has the advantage that users of your custom data type will
+ automatically use your custom parser whenever they define an option with a
+ value type of your data type. The disadvantage of this approach is that it
+ doesn't work if your fundemental data type is something that is already
+ supported.<p>
+
+<li>Write an independant class, using it explicitly from options that need
+ it.<p>
+
+ This approach works well in situations where you would line to parse an
+ option using special syntax for a not-very-special data-type. The drawback
+ of this approach is that users of your parser have to be aware that they are
+ using your parser, instead of the builtin ones.<p>
+
+</ol><p>
+
+To guide the discussion, we will discuss a custom parser that accepts file
+sizes, specified with an optional unit after the numeric size. For example, we
+would like to parse "102kb", "41M", "1G" into the appropriate integer value. In
+this case, the underlying data type we want to parse into is
+'<tt>unsigned</tt>'. We choose approach #2 above because we don't want to make
+this the default for all <tt>unsigned</tt> options.<p>
+
+To start out, we declare our new <tt>FileSizeParser</tt> class:<p>
+
+<pre>
+<b>struct</b> FileSizeParser : <b>public</b> cl::basic_parser<<b>unsigned</b>> {
+ <i>// parse - Return true on error.</i>
+ <b>bool</b> parse(cl::Option &O, <b>const char</b> *ArgName, <b>const</b> std::string &ArgValue,
+ <b>unsigned</b> &Val);
+};
+</pre><p>
+
+Our new class inherits from the <tt>cl::basic_parser</tt> template class to fill
+in the default, boiler plate, code for us. We give it the data type that we
+parse into (the last argument to the <tt>parse</tt> method so that clients of
+our custom parser know what object type to pass in to the parse method (here we
+declare that we parse into '<tt>unsigned</tt>' variables.<p>
+
+For most purposes, the only method that must be implemented in a custom parser
+is the <tt>parse</tt> method. The <tt>parse</tt> method is called whenever the
+option is invoked, passing in the option itself, the option name, the string to
+parse, and a reference to a return value. If the string to parse is not well formed, the parser should output an error message and return true. Otherwise it should return false and set '<tt>Val</tt>' to the parsed value. In our example, we implement <tt>parse</tt> as:<p>
+
+<pre>
+<b>bool</b> FileSizeParser::parse(cl::Option &O, <b>const char</b> *ArgName,
+ <b>const</b> std::string &Arg, <b>unsigned</b> &Val) {
+ <b>const char</b> *ArgStart = Arg.c_str();
+ <b>char</b> *End;
+
+ <i>// Parse integer part, leaving 'End' pointing to the first non-integer char</i>
+ Val = (unsigned)strtol(ArgStart, &End, 0);
+
+ <b>while</b> (1) {
+ <b>switch</b> (*End++) {
+ <b>case</b> 0: <b>return</b> false; <i>// No error</i>
+ <b>case</b> 'i': <i>// Ignore the 'i' in KiB if people use that</i>
+ <b>case</b> 'b': <b>case</b> 'B': <i>// Ignore B suffix</i>
+ <b>break</b>;
+
+ <b>case</b> 'g': <b>case</b> 'G': Val *= 1024*1024*1024; <b>break</b>;
+ <b>case</b> 'm': <b>case</b> 'M': Val *= 1024*1024; <b>break</b>;
+ <b>case</b> 'k': <b>case</b> 'K': Val *= 1024; <b>break</b>;
+
+ default:
+ <i>// Print an error message if unrecognized character!</i>
+ <b>return</b> O.error(": '" + Arg + "' value invalid for file size argument!");
+ }
+ }
+}
+</pre><p>
+
+This function implements a very simple parser for the kinds of strings we are
+interested in. Although it has some holes (it allows "<tt>123KKK</tt>" for
+example), it is good enough for this example. Note that we use the option
+itself to print out the error message (the <tt>error</tt> method always returns
+true) in order to get a nice error message (shown below). Now that we have our
+parser class, we can use it like this:<p>
+
+<pre>
+<b>static</b> <a href="#cl::opt">cl::opt</a><<b>unsigned</b>, <b>false</b>, FileSizeParser>
+MFS(<i>"max-file-size"</i>, <a href="#cl::desc">cl::desc</a>(<i>"Maximum file size to accept"</i>),
+ <a href="#cl::value_desc">cl::value_desc</a>("<i>size</i>"));
+</pre><p>
+
+Which adds this to the output of our program:<p>
+
+<pre>
+OPTIONS:
+ -help - display available options (--help-hidden for more)
+ ...
+ <b>-max-file-size=<size> - Maximum file size to accept</b>
+</pre><p>
+
+And we can test that our parse works correctly now (the test program just prints
+out the max-file-size argument value):<p>
+
+<pre>
+$ ./test
+MFS: 0
+$ ./test -max-file-size=123MB
+MFS: 128974848
+$ ./test -max-file-size=3G
+MFS: 3221225472
+$ ./test -max-file-size=dog
+-max-file-size option: 'dog' value invalid for file size argument!
+</pre><p>
+
+It looks like it works. The error message that we get is nice and helpful, and
+we seem to accept reasonable file sizes. This wraps up the "custom parser"
+tutorial.<p>