| #include "Flag.h" | 
 | #include "StringPiece.h" | 
 |  | 
 | #include <functional> | 
 | #include <iomanip> | 
 | #include <iostream> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | namespace aapt { | 
 | namespace flag { | 
 |  | 
 | struct Flag { | 
 |     std::string name; | 
 |     std::string description; | 
 |     std::function<bool(const StringPiece&, std::string*)> action; | 
 |     bool required; | 
 |     bool* flagResult; | 
 |     bool flagValueWhenSet; | 
 |     bool parsed; | 
 | }; | 
 |  | 
 | static std::vector<Flag> sFlags; | 
 | static std::vector<std::string> sArgs; | 
 |  | 
 | static std::function<bool(const StringPiece&, std::string*)> wrap( | 
 |         const std::function<void(const StringPiece&)>& action) { | 
 |     return [action](const StringPiece& arg, std::string*) -> bool { | 
 |         action(arg); | 
 |         return true; | 
 |     }; | 
 | } | 
 |  | 
 | void optionalFlag(const StringPiece& name, const StringPiece& description, | 
 |                   std::function<void(const StringPiece&)> action) { | 
 |     sFlags.push_back(Flag{ | 
 |             name.toString(), description.toString(), wrap(action), | 
 |             false, nullptr, false, false }); | 
 | } | 
 |  | 
 | void requiredFlag(const StringPiece& name, const StringPiece& description, | 
 |                   std::function<void(const StringPiece&)> action) { | 
 |     sFlags.push_back(Flag{ name.toString(), description.toString(), wrap(action), | 
 |             true, nullptr, false, false }); | 
 | } | 
 |  | 
 | void requiredFlag(const StringPiece& name, const StringPiece& description, | 
 |                   std::function<bool(const StringPiece&, std::string*)> action) { | 
 |     sFlags.push_back(Flag{ name.toString(), description.toString(), action, | 
 |             true, nullptr, false, false }); | 
 | } | 
 |  | 
 | void optionalSwitch(const StringPiece& name, const StringPiece& description, bool resultWhenSet, | 
 |                     bool* result) { | 
 |     sFlags.push_back(Flag{ | 
 |             name.toString(), description.toString(), {}, | 
 |             false, result, resultWhenSet, false }); | 
 | } | 
 |  | 
 | void usageAndDie(const StringPiece& command) { | 
 |     std::cerr << command << " [options]"; | 
 |     for (const Flag& flag : sFlags) { | 
 |         if (flag.required) { | 
 |             std::cerr << " " << flag.name << " arg"; | 
 |         } | 
 |     } | 
 |     std::cerr << " files..." << std::endl << std::endl << "Options:" << std::endl; | 
 |  | 
 |     for (const Flag& flag : sFlags) { | 
 |         std::string command = flag.name; | 
 |         if (!flag.flagResult) { | 
 |             command += " arg "; | 
 |         } | 
 |         std::cerr << "  " << std::setw(30) << std::left << command | 
 |                   << flag.description << std::endl; | 
 |     } | 
 |     exit(1); | 
 | } | 
 |  | 
 | void parse(int argc, char** argv, const StringPiece& command) { | 
 |     std::string errorStr; | 
 |     for (int i = 0; i < argc; i++) { | 
 |         const StringPiece arg(argv[i]); | 
 |         if (*arg.data() != '-') { | 
 |             sArgs.push_back(arg.toString()); | 
 |             continue; | 
 |         } | 
 |  | 
 |         bool match = false; | 
 |         for (Flag& flag : sFlags) { | 
 |             if (arg == flag.name) { | 
 |                 match = true; | 
 |                 flag.parsed = true; | 
 |                 if (flag.flagResult) { | 
 |                     *flag.flagResult = flag.flagValueWhenSet; | 
 |                 } else { | 
 |                     i++; | 
 |                     if (i >= argc) { | 
 |                         std::cerr << flag.name << " missing argument." << std::endl | 
 |                                   << std::endl; | 
 |                         usageAndDie(command); | 
 |                     } | 
 |  | 
 |                     if (!flag.action(argv[i], &errorStr)) { | 
 |                         std::cerr << errorStr << "." << std::endl << std::endl; | 
 |                         usageAndDie(command); | 
 |                     } | 
 |                 } | 
 |                 break; | 
 |             } | 
 |         } | 
 |  | 
 |         if (!match) { | 
 |             std::cerr << "unknown option '" << arg << "'." << std::endl << std::endl; | 
 |             usageAndDie(command); | 
 |         } | 
 |     } | 
 |  | 
 |     for (const Flag& flag : sFlags) { | 
 |         if (flag.required && !flag.parsed) { | 
 |             std::cerr << "missing required flag " << flag.name << std::endl << std::endl; | 
 |             usageAndDie(command); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | const std::vector<std::string>& getArgs() { | 
 |     return sArgs; | 
 | } | 
 |  | 
 | } // namespace flag | 
 | } // namespace aapt |