src/CLIParser.h
branchv_0
changeset 8 513ea30d2fa3
parent 0 644fd2ce2580
child 9 b064f1b3676e
equal deleted inserted replaced
7:46db0e6e548b 8:513ea30d2fa3
    27 
    27 
    28 namespace relpipe {
    28 namespace relpipe {
    29 namespace tr {
    29 namespace tr {
    30 namespace awk {
    30 namespace awk {
    31 
    31 
       
    32 /**
       
    33  * This tr-awk CLI options are inspired by tr-guile options.
       
    34  * These configurations are independent and might diverge, but when possible, the should share same option names and same logic for common parts.
       
    35  */
    32 class CLIParser {
    36 class CLIParser {
    33 private:
    37 private:
    34 
    38 
    35 	// FIXME: move common methods/classes to relpipe-lib-cli or relpipe-lib-helper
    39 	// FIXME: move common methods/classes to relpipe-lib-cli or relpipe-lib-helper
    36 
    40 
    37 	string_t readNext(std::vector<string_t> arguments, int& i) {
    41 	string_t readNext(std::vector<string_t> arguments, int& i) {
    38 		if (i < arguments.size()) return arguments[i++];
    42 		if (i < arguments.size()) return arguments[i++];
    39 		else throw relpipe::cli::RelpipeCLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
    43 		else throw relpipe::cli::RelpipeCLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
    40 	}
    44 	}
    41 
    45 
       
    46 	void addRelation(Configuration& c, RelationConfiguration& currentRelation) {
       
    47 		if (currentRelation.relation.size()) {
       
    48 			c.relationConfigurations.push_back(currentRelation);
       
    49 			currentRelation = RelationConfiguration();
       
    50 		}
       
    51 	}
       
    52 
       
    53 	relpipe::writer::TypeId parseTypeId(const string_t& value) {
       
    54 		using t = relpipe::writer::TypeId;
       
    55 		if (value == L"string") return t::STRING;
       
    56 		else if (value == L"integer") return t::INTEGER;
       
    57 		else if (value == L"boolean") return t::BOOLEAN;
       
    58 		else throw relpipe::cli::RelpipeCLIException(L"Unable to parse TypeId: " + value, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
       
    59 	}
       
    60 
    42 public:
    61 public:
    43 
    62 
    44 	static const string_t OPTION_EXPRESSION;
    63 	static const string_t OPTION_RELATION;
       
    64 	static const string_t OPTION_OUTPUT_ATTRIBUTE;
       
    65 	static const string_t OPTION_INPUT_ATTRIBUTES_APPEND;
       
    66 	static const string_t OPTION_INPUT_ATTRIBUTES_PREPEND;
       
    67 	static const string_t OPTION_BEFORE_RECORDS;
       
    68 	static const string_t OPTION_AFTER_RECORDS;
       
    69 	static const string_t OPTION_FOR_EACH;
       
    70 	static const string_t OPTION_DEFINE;
    45 
    71 
    46 	Configuration parse(const std::vector<string_t>& arguments) {
    72 	Configuration parse(const std::vector<string_t>& arguments) {
    47 		Configuration c;
    73 		Configuration c;
       
    74 		RelationConfiguration currentRelation;
    48 
    75 
    49 		for (int i = 0; i < arguments.size();) {
    76 		{
    50 			string_t option = readNext(arguments, i);
    77 			for (int i = 0; i < arguments.size();) {
    51 			if (option == OPTION_EXPRESSION) c.awkExpression = readNext(arguments, i);
    78 				string_t option = readNext(arguments, i);
    52 			else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
    79 
       
    80 				if (option == OPTION_BEFORE_RECORDS) currentRelation.awkBeforeRecords = readNext(arguments, i);
       
    81 				else if (option == OPTION_AFTER_RECORDS) currentRelation.awkAfterRecords = readNext(arguments, i);
       
    82 				else if (option == OPTION_FOR_EACH) currentRelation.awkForEach = readNext(arguments, i);
       
    83 				else if (option == OPTION_INPUT_ATTRIBUTES_APPEND) currentRelation.inputAttributesAppend = true;
       
    84 				else if (option == OPTION_INPUT_ATTRIBUTES_PREPEND) currentRelation.inputAttributesPrepend = true;
       
    85 				else if (option == OPTION_RELATION) {
       
    86 					addRelation(c, currentRelation); // previous relation
       
    87 					currentRelation.relation = readNext(arguments, i);
       
    88 				} else if (option == OPTION_OUTPUT_ATTRIBUTE) {
       
    89 					relpipe::writer::AttributeMetadata attribute;
       
    90 					attribute.attributeName = readNext(arguments, i);
       
    91 					attribute.typeId = parseTypeId(readNext(arguments, i));
       
    92 					currentRelation.writerMetadata.push_back(attribute);
       
    93 				} else if (option == OPTION_DEFINE) {
       
    94 					DefinitionRecipe definition;
       
    95 					definition.name = readNext(arguments, i);
       
    96 					definition.type = readNext(arguments, i);
       
    97 					definition.value = readNext(arguments, i);
       
    98 					if (currentRelation.relation.size()) currentRelation.definitions.push_back(definition);
       
    99 					else c.definitions.push_back(definition);
       
   100 				} else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
       
   101 
       
   102 			}
       
   103 
       
   104 			addRelation(c, currentRelation); // last relation
    53 		}
   105 		}
    54 
   106 
    55 		return c;
   107 		return c;
    56 	}
   108 	}
    57 
   109 
    58 	virtual ~CLIParser() {
   110 	virtual ~CLIParser() {
    59 	}
   111 	}
    60 };
   112 };
    61 
   113 
    62 const string_t CLIParser::OPTION_EXPRESSION = L"--expression";
   114 const string_t CLIParser::OPTION_RELATION = L"--relation";
       
   115 const string_t CLIParser::OPTION_OUTPUT_ATTRIBUTE = L"--output-attribute";
       
   116 const string_t CLIParser::OPTION_INPUT_ATTRIBUTES_APPEND = L"--input-attributes-append";
       
   117 const string_t CLIParser::OPTION_INPUT_ATTRIBUTES_PREPEND = L"--input-attributes-prepend";
       
   118 const string_t CLIParser::OPTION_BEFORE_RECORDS = L"--before-records";
       
   119 const string_t CLIParser::OPTION_AFTER_RECORDS = L"--after-records";
       
   120 const string_t CLIParser::OPTION_FOR_EACH = L"--for-each";
       
   121 const string_t CLIParser::OPTION_DEFINE = L"--define";
    63 
   122 
    64 }
   123 }
    65 }
   124 }
    66 }
   125 }