private static void ShowCLIdetails(cliDataSet cli) { if (cliDebugLevel < 2) { return; } WriteDebugLevel2(new string('=', 100)); WriteDebugLevel2(String.Format("Switch Name: {0} [{1}])", cli.fullSwitchName, cli.fullAliasName)); WriteDebugLevel2(new string('-', 48) + "+" + new string('-', 51)); WriteDebugLevel2(String.Format(" default Value: {0,-31} | {1}{2}", cli.defaultValue, " argument Value: ", cli.argumentValue)); WriteDebugLevel2(String.Format(" has Argument: {0,-31} | {1}{2}", cli.hasArgument, " is Mandatory: ", cli.isMandatory)); WriteDebugLevel2(String.Format(" is Secret: {0,-31} | {1}{2}", cli.isSecret, "not NullOrEmpty: ", cli.notNullOrEmpty)); WriteDebugLevel2(String.Format(" is Negatable: {0,-31} | {1}{2}", cli.isNegatable, " is Negated: ", cli.isNegated)); WriteDebugLevel2(String.Format(" value Type: {0,-31} | {1}{2}", cli.type, " valid. Pattern: ", cli.validatePattern)); string pn = String.Format("{0}/{1}", cli.validateCount[0], cli.validateCount[1]); string an = String.Format("{0}/{1}", cli.validateLength[0], cli.validateLength[1]); WriteDebugLevel2(String.Format(" valid. Length: {0,-31} | {1}{2}/{3}", an, " valid. Range: ", cli.validateRange[0], cli.validateRange[1])); WriteDebugLevel2(String.Format(" valid. Count: {0,-31} | {1}{2}", pn, " valid. Set: ", cli.validateSet)); }
// ==================================================================================================================================================== // cli.LoadDefinitions will use the added definitions to process the command-line arguments. // ==================================================================================================================================================== public static void LoadDefinitions() { cliDataSet cliData = new cliDataSet(); cliDefinitionsLoaded = false; // ================================================================================================================================================ // Before doing anything else: check the debug state and whether a switch identifier has been set // ------------------------------------------------------------------------------------------------------------------------------------------------ CheckDebugState(); if (cliSwitchIdentifier == null) { SetSwitchIdentifier(); } // ------------------------------------------------------------------------------------------------------------------------------------------------ // Convert the commandline argument string to a list and remove the 1st elelement (image name) and the cliDebug arguments // Also make sure a switch identifier has been set // ------------------------------------------------------------------------------------------------------------------------------------------------ List<string> argumentList = new List<string>(); string argValueString = ""; string[] cmndLineArgs = Environment.GetCommandLineArgs(); WriteDebugLevel3("Original argumentlist: [" + string.Join("] [", cmndLineArgs) + "]"); for (int i = 1; i < cmndLineArgs.Length; i++) { if (cmndLineArgs[i].StartsWith("--cliDebugLevel")) { continue; } if (!cmndLineArgs[i].StartsWith(cliSwitchIdentifier)) { argValueString += cmndLineArgs[i] + ","; continue; } if (argValueString.Length > 0) { argumentList.Add(argValueString.TrimEnd(',')); argValueString = ""; } argumentList.Add(cmndLineArgs[i]); } // Do not forget to save the last set of argument values (if any!) if (argValueString.Length > 0) { argumentList.Add(argValueString.TrimEnd(',')); argValueString = ""; } string workingArgumentList = ""; foreach (string arg in argumentList) { workingArgumentList += "[" + arg + "] "; } WriteDebugLevel3("Working argumentlist: " + workingArgumentList); // ------------------------------------------------------------------------------------------------------------------------------------------------ // Now process the remaining arguments. When starting with the switch identifier, get the fullSwitchName and fetch its dataset // ------------------------------------------------------------------------------------------------------------------------------------------------ bool switchFound = false; string switchName = "", aliasName = ""; foreach (string thisArgument in argumentList) { if (!thisArgument.StartsWith(cliSwitchIdentifier)) { if (!switchFound) { WriteError("Unassigned argument " + thisArgument + " found."); } cliData.argumentValue = thisArgument; cliData.hasArgument = true; switchDictionary[switchName] = cliData; switchFound = false; } else { bool switchIsNegated = false, switchIsAlias = false; string argValue = ""; int stdAliasCnt = 0, negAliasCnt = 0, stdSwitchCnt = 0, negSwitchCnt = 0; // ---------------------------------------------------------------------------------------------------------------------------------------- // First check whether the argument is a alias or a negated alias. A switch starting with "no" is not perse negated (aka /nonsense). // So if stdSwitchCnt or stdAliasCnt is > 0 skip the negated check // ---------------------------------------------------------------------------------------------------------------------------------------- switchName = thisArgument.Substring(cliSwitchIdentifier.Length); if (switchName.Contains('=')) { argValue = switchName.Split('=')[1]; switchName = switchName.Split('=')[0]; } if (switchName.Contains(':')) { argValue = switchName.Split(':')[1]; switchName = switchName.Split(':')[0]; } stdSwitchCnt = switchDictionary.Count(d => d.Key.StartsWith(switchName, StringComparison.OrdinalIgnoreCase)); stdAliasCnt = aliasDictionary.Count(d => d.Key.StartsWith(switchName, StringComparison.OrdinalIgnoreCase)); if ((stdSwitchCnt == 0) & (stdAliasCnt == 0) & switchName.StartsWith("no")) { switchIsNegated = true; negAliasCnt = aliasDictionary.Count(d => d.Key.StartsWith(switchName.Substring(2))); negSwitchCnt = switchDictionary.Count(d => d.Key.StartsWith(switchName.Substring(2))); } // ---------------------------------------------------------------------------------------------------------------------------------------- // There can be only 1 !!! So if the total count is < 1 or > 1 we have a problem. Say so and quit // ---------------------------------------------------------------------------------------------------------------------------------------- int switchCount = stdAliasCnt + negAliasCnt + stdSwitchCnt + negSwitchCnt; if (switchCount > 1) { WriteError("Switch " + thisArgument + " is ambiguous."); } if (switchCount < 1) { WriteError("Switch " + thisArgument + " is unknown."); } // ---------------------------------------------------------------------------------------------------------------------------------------- // If negAliasCnt or negSwitchCnt = 1 the switch is negated! Set the flag and trim the switch. // If stdAliasCnt or negAliasCnt = 1 the switch is an alias! Set the flag and save switch as alias // ---------------------------------------------------------------------------------------------------------------------------------------- if (negAliasCnt + negSwitchCnt == 1) { switchIsNegated = true; switchName = switchName.Substring(2); } if (stdAliasCnt + negAliasCnt == 1) { switchIsAlias = true; aliasName = switchName; } // ---------------------------------------------------------------------------------------------------------------------------------------- // Time to get the full switch name and load its cliDataSet. // ---------------------------------------------------------------------------------------------------------------------------------------- if (switchIsAlias) { var keyPair = aliasDictionary.Where(d => d.Key.StartsWith(aliasName, StringComparison.OrdinalIgnoreCase)); foreach (var pair in keyPair) { switchName = pair.Value; } } else { var keyPair = switchDictionary.Where(d => d.Key.StartsWith(switchName, StringComparison.OrdinalIgnoreCase)); foreach (var pair in keyPair) { switchName = pair.Key; } } if (!switchIsAlias) { WriteDebugLevel1("Processing switch: " + switchName); } else { WriteDebugLevel1("Processing switch: " + switchName + " (from Alias: " + aliasName + ")"); } cliData = switchDictionary[switchName]; // ---------------------------------------------------------------------------------------------------------------------------------------- // Add the full switchname to a comma-separated list which can be used to match is with an aloow/disallow rule. // Update the dataset with what we found sofar. Also check whether a negated switch/alias is allowed to be negated! // ---------------------------------------------------------------------------------------------------------------------------------------- cliData.isPresent = true; cliData.isNegated = switchIsNegated; if (!cliData.isNegatable && cliData.isNegated) { WriteError("Switch " + thisArgument + " is not negatable"); } if (cliData.type == "[bool]") { cliData.hasArgument = true; if (switchIsNegated) { cliData.argumentValue = "False"; } else { cliData.argumentValue = "True"; } } if (argValue.Length > 0) { cliData.argumentValue = argValue; cliData.hasArgument = true; } switchDictionary[switchName] = cliData; switchFound = true; } } // ------------------------------------------------------------------------------------------------------------------------------------------------ // Now scan the switchDictionary for all switches with the isPresent flag set, and collect these in a separate switchList // ------------------------------------------------------------------------------------------------------------------------------------------------ foreach (var pair in switchDictionary) { if (pair.Value.isPresent) { switchList.Add(pair.Key); WriteDebugLevel1(String.Format("Switch List: {0,-20} - Is present: {1}", pair.Key, pair.Value.isPresent)); ShowCLIdetails(pair.Value); } } // ------------------------------------------------------------------------------------------------------------------------------------------------ // Match the found commandline switches with a possible allow/disallow rule // ------------------------------------------------------------------------------------------------------------------------------------------------ if ((checkRules.Count > 0) & (switchList.Count > 0)) { foreach (string chkRule in checkRules) { int disallowCnt = 0; int allowanyCnt = 0; // ---------------------------------------------------------------------------------------------------------------------------------------- // Is it a DisAllow check?? // ---------------------------------------------------------------------------------------------------------------------------------------- Match ruleCheck = rgxDisallow.Match(chkRule); if (ruleCheck.Success) { string disallowRule = ruleCheck.Groups[2].Value; foreach (string token in disallowRule.Split(',')) { if (switchList.Contains(token)) { disallowCnt += 1; } } } if (disallowCnt > 1) { WriteError("Switch conflict due to \"" + chkRule + "\""); } // ---------------------------------------------------------------------------------------------------------------------------------------- // Is it a AllowAny check?? (still need to figure out what it can be used for - aka when to warn) // ---------------------------------------------------------------------------------------------------------------------------------------- ruleCheck = rgxAllowAny.Match(chkRule); if (ruleCheck.Success) { string allowanyRule = ruleCheck.Groups[2].Value; foreach (string token in allowanyRule.Split(',')) { if (switchList.Contains(token)) { allowanyCnt += 1; } } } //if (disallowCnt > 1) { WriteError("Switch conflict due to \"" + chkRule + "\""); } } } // ================================================================================================================================================ // Peform the validation checks // ------------------------------------------------------------------------------------------------------------------------------------------------ foreach (string keyName in switchList) { cliData = switchDictionary[keyName]; // -------------------------------------------------------------------------------------------------------------------------------------------- // Switch is mandatory but does not have a value? Get it from the command line (interactive mode only!) // When prompted for input and nothing is entered: Quit! // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.isMandatory && !cliData.hasArgument) { string errMsg = "Value for mandatory switch " + keyName + " is missing, termination request."; if (!Environment.UserInteractive) { WriteError(errMsg); } Console.Write("Please enter mandatory " + keyName + ": "); cliData.argumentValue = Console.ReadLine(); if ((cliData.argumentValue == null) || (cliData.argumentValue.Length < 1)) { WriteError(errMsg); } } // -------------------------------------------------------------------------------------------------------------------------------------------- // Parameter is NotNullOrEmpty but does not have a value? Get it from the command line (only interactive mode!) // When prompted for input and nothing is entered: Quit! // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.notNullOrEmpty && !cliData.hasArgument) { string errMsg = "Value for switch " + keyName + " is missing, termination request."; if (!Environment.UserInteractive) { WriteError(errMsg); } string keyword = (cliData.isSecret) ? "Secret" : "NotNulOrEmpty"; Console.Write("Please enter " + keyword + " " + keyName + ": "); if (cliData.isSecret) { cliData.argumentValue = ReadPassword(); } else { cliData.argumentValue = Console.ReadLine(); } if ((cliData.argumentValue == null) || (cliData.argumentValue.Length < 1)) { WriteError(errMsg); } } // -------------------------------------------------------------------------------------------------------------------------------------------- // validate Count: cliData.argumentValue must have at least (x) elements and maximal (y) elements // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.doValidateCount) { int countLow = Convert.ToInt32(cliData.validateCount[0]); int countHigh = Convert.ToInt32(cliData.validateCount[1]); int elemCount = cliData.argumentValue.Split(',').Length; if (countHigh == 0) { countHigh = elemCount; } if (elemCount < countLow) { WriteError("Minimal " + countLow + " values required for switch " + keyName); } if (elemCount > countHigh) { WriteError("Maximal " + countHigh + " values allowed for switch " + keyName); } } // -------------------------------------------------------------------------------------------------------------------------------------------- // validate Length: minimum (x) and/or maximum (y) length of cliData.argumentValue // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.doValidateLength) { int lengthLow = Convert.ToInt32(cliData.validateLength[0]); int lengthHigh = Convert.ToInt32(cliData.validateLength[1]); foreach (string argValue in cliData.argumentValue.Split(',')) { int elemLength = argValue.Length; if (lengthHigh == 0) { lengthHigh = elemLength; } if (elemLength < lengthLow) { WriteError(keyName + " - Minimal required value length for switch value " + argValue + " is " + lengthLow); } if (elemLength > lengthHigh) { WriteError(keyName + " - Maximal allowed value length for switch value " + argValue + " is " + lengthHigh); } } } // -------------------------------------------------------------------------------------------------------------------------------------------- // validate Range: cliData.argumentValue value must be > (x) and/or < (y) Check is valueType dependend! // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.doValidateRange) { foreach (string argValue in cliData.argumentValue.Split(',')) { bool minFail = false; bool maxFail = false; switch (cliData.type.Replace("[]", "")) { case "[byte]": minFail = (Convert.ToByte(argValue) < Convert.ToByte(cliData.validateRange[0])); maxFail = (Convert.ToByte(argValue) > Convert.ToByte(cliData.validateRange[1])); break; case "[sbyte]": minFail = (Convert.ToSByte(argValue) < Convert.ToSByte(cliData.validateRange[0])); maxFail = (Convert.ToSByte(argValue) > Convert.ToSByte(cliData.validateRange[1])); break; case "[decimal]": minFail = (Convert.ToDecimal(argValue) < Convert.ToDecimal(cliData.validateRange[0])); maxFail = (Convert.ToDecimal(argValue) > Convert.ToDecimal(cliData.validateRange[1])); break; case "[float]": minFail = (Convert.ToSingle(argValue) < Convert.ToSingle(cliData.validateRange[0])); maxFail = (Convert.ToSingle(argValue) > Convert.ToSingle(cliData.validateRange[1])); break; case "[double]": minFail = (Convert.ToDouble(argValue) < Convert.ToDouble(cliData.validateRange[0])); maxFail = (Convert.ToDouble(argValue) > Convert.ToDouble(cliData.validateRange[1])); break; case "[short]": minFail = (Convert.ToInt16(argValue) < Convert.ToInt16(cliData.validateRange[0])); maxFail = (Convert.ToInt16(argValue) > Convert.ToInt16(cliData.validateRange[1])); break; case "[ushort]": minFail = (Convert.ToUInt16(argValue) < Convert.ToUInt16(cliData.validateRange[0])); maxFail = (Convert.ToUInt16(argValue) > Convert.ToUInt16(cliData.validateRange[1])); break; case "[int]": minFail = (Convert.ToInt32(argValue) < Convert.ToInt32(cliData.validateRange[0])); maxFail = (Convert.ToInt32(argValue) > Convert.ToInt32(cliData.validateRange[1])); break; case "[unint]": minFail = (Convert.ToUInt32(argValue) < Convert.ToUInt32(cliData.validateRange[0])); maxFail = (Convert.ToUInt32(argValue) > Convert.ToUInt32(cliData.validateRange[1])); break; case "[long]": minFail = (Convert.ToInt64(argValue) < Convert.ToInt64(cliData.validateRange[0])); maxFail = (Convert.ToInt64(argValue) > Convert.ToInt64(cliData.validateRange[1])); break; case "[ulong]": minFail = (Convert.ToUInt64(argValue) < Convert.ToUInt64(cliData.validateRange[0])); maxFail = (Convert.ToUInt64(argValue) > Convert.ToUInt64(cliData.validateRange[1])); break; default: break; } if (minFail) { WriteError(keyName + " argument value " + argValue + " is not in range, min value is " + cliData.validateRange[0]); } if (maxFail) { WriteError(keyName + " argument value " + argValue + " is not in range, max value is " + cliData.validateRange[1]); } } } // -------------------------------------------------------------------------------------------------------------------------------------------- // validate Set: cliData.validateSet contains "|" -> cliData.argumentValue can only be ONE of the set values // cliData.validateSet contains "&" -> cliData.argumentValue can only be one or more of the set values // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.doValidateSet) { bool orCheck = cliData.validateSet.Contains('|'); bool andCheck = cliData.validateSet.Contains('&'); string newArgumentValue = ""; if (orCheck & andCheck) { WriteError("Invalid combination of AND and OR directives in validationSet " + cliData.validateSet); } string[] checkSet = cliData.validateSet.Replace('&', '|').Split('|'); string[] checkValues = cliData.argumentValue.ToLower().Split(','); int valCount = checkValues.Length; int matchCount = 0; if ((orCheck) && (valCount > 1)) { WriteError("Too many values specified for switch " + keyName + ", validation set only allows for 1 value."); } foreach (string chkVal in checkValues) { matchCount = 0; foreach (string chkElm in checkSet) { if (chkElm.ToLower().StartsWith(chkVal.ToLower())) { newArgumentValue += chkElm + ","; matchCount += 1; } } } if ((matchCount == 0) || (orCheck & (matchCount > 1))) { WriteError("Invalid value " + cliData.argumentValue + " for switch " + keyName + " Select value from: " + cliData.validateSet); } cliData.argumentValue = newArgumentValue.TrimEnd(','); } // -------------------------------------------------------------------------------------------------------------------------------------------- // validate Pattern: Regex check cliData.argumentValue against the specified pattern // -------------------------------------------------------------------------------------------------------------------------------------------- if (cliData.doValidatePattern) { Regex valPattern = new Regex(cliData.validatePattern); Match patCheck = valPattern.Match(cliData.argumentValue); if (!patCheck.Success) { WriteError("Invalid value " + cliData.argumentValue + " for switch " + keyName + "\n\tPattern mismatch: " + cliData.validatePattern); } } // -------------------------------------------------------------------------------------------------------------------------------------------- // All checks passed? Then save all data in the dictionary. // -------------------------------------------------------------------------------------------------------------------------------------------- switchDictionary[keyName] = cliData; } // ================================================================================================================================================ // Finally - Raise the cliDefinitionsLoaded flag and return // ================================================================================================================================================ cliDefinitionsLoaded = true; }
// ==================================================================================================================================================== // cli.AddDefinition performs the following checks on the passed definition/rule; // 1 - Validate the used switch definitions (make sure no typo's have been made etc. This part creates a Dictionary using the full switch // name as key, all subsequent information is stored in a structure which is attached to this key. The function quits as soon as a invalid // definition is detected. // 2 - Determine of each switch and alias the shortest abbreviation, make sure there are no conflicts. // ==================================================================================================================================================== public static void AddDefinition(string Definition) { // ================================================================================================================================================ // Before doing anything else... Check for the TotalCLI specific argument cliDebugLevelX // ------------------------------------------------------------------------------------------------------------------------------------------------ CheckDebugState(); // ------------------------------------------------------------------------------------------------------------------------------------------------ // String.Split charater arrays; round, curly, square and angle brackets // ------------------------------------------------------------------------------------------------------------------------------------------------ char[] rBrackets = { '(', ')' }; char[] cBrackets = { '{', '}' }; char[] sBrackets = { '[', ']' }; char[] fBrackets = { '<', '>' }; // ------------------------------------------------------------------------------------------------------------------------------------------------ // Value type list. This is the lists of value types supported by TotalCLI // ------------------------------------------------------------------------------------------------------------------------------------------------ List<string> typeList = new List<string> { "[string]","[bool]","[byte]","[sbyte]","[char]","[decimal]","[float]", "[double]", "[int]", "[uint]", "[long]", "[ulong]", "[short]", "[ushort]", "[string[]]","[byte[]]","[sbyte[]]","[char[]]","[decimal[]]","[float[]]", "[double[]]", "[int[]]", "[uint[]]", "[long[]]", "[ulong[]]", "[short[]]", "[ushort[]]" }; // ------------------------------------------------------------------------------------------------------------------------------------------------ // Use a Regex expression to validate the passed definition and the validiation rules defined within. // - Definition record: "^(\{.*\})?(\[\w+(\[\])?\])?(\w+)(\=.*)?$" For example: {validation}[type]switch(=default) // - Validation ruiles: a lot! // ------------------------------------------------------------------------------------------------------------------------------------------------ Regex rgxDefinition = new Regex(@"^(\{.*\})?(\[\w+(\[\])?\])?(\w+)(\=.*)?$"); Regex rgxAlias = new Regex(@"(?i)^{(.*,)?(Alias\(([\x2a-\x7e]+)\))(,.*)?}$"); Regex rgxMandatory = new Regex(@"(?i)^{(.*,)?(Mandatory)(,.*)?}$"); Regex rgxNegatable = new Regex(@"(?i)^{(.*,)?(Negatable)(,.*)?}$"); Regex rgxNotNullOrEmpty = new Regex(@"(?i)^{(.*,)?(NotNullOrEmpty)(,.*)?}$"); Regex rgxSecret = new Regex(@"(?i)^{(.*,)?(Secret)(,.*)?}$"); Regex rgxValidateCount = new Regex(@"(?i)^{(.*,)?(ValidateCount\(((-?\d+)?(,-?\d+)?)\))(,.*)?}$"); Regex rgxValidateLength = new Regex(@"(?i)^{(.*,)?(ValidateLength\(((-?\d+)?(,-?\d+)?)\))(,.*)?}$"); Regex rgxValidatePattern = new Regex(@"(?i)^{(.*,)?(ValidatePattern\(\/(.*)\/\))(,.*)?}$"); Regex rgxValidateRange = new Regex(@"(?i)^{(.*,)?(ValidateRange\(((-?\d+)?(,-?\d+)?)\))(,.*)?}$"); Regex rgxValidateSetOr = new Regex(@"(?i)^{(.*,)?(ValidateSet\(((\w+)(\|\w+)+)\))(,.*)?}$"); Regex rgxValidateSetAnd = new Regex(@"(?i)^{(.*,)?(ValidateSet\(((\w+)(&\w+)+)\))(,.*)?}$"); // ================================================================================================================================================ // If requested show that we have started // ------------------------------------------------------------------------------------------------------------------------------------------------ WriteDebugLevel1("Preprocessing definition: " + Definition); // -------------------------------------------------------------------------------------------------------------------------------------------- // Primary validation (rgxDefinition). If this one fails we might as well quit..... // -------------------------------------------------------------------------------------------------------------------------------------------- Match cliMatch = rgxDefinition.Match(Definition); if (!cliMatch.Success) { WriteError("Definition rule \"" + Definition + "\" not recognized, please validate."); } // -------------------------------------------------------------------------------------------------------------------------------------------- // Start a new cliDataset and initialize its values // -------------------------------------------------------------------------------------------------------------------------------------------- cliDataSet cli = new cliDataSet(); cli.isPresent = cli.hasArgument = cli.isMandatory = cli.isSecret = cli.isNegated = cli.isNegatable = false; cli.notNullOrEmpty = cli.doValidateCount = cli.doValidateLength = cli.doValidatePattern = cli.doValidateRange = cli.doValidateSet = false; cli.fullSwitchName = cli.fullAliasName = cli.type = cli.argumentValue = cli.defaultValue = cli.validatePattern = cli.validateSet = ""; cli.validateCount = cli.validateLength = cli.validateRange = new string[2]; // -------------------------------------------------------------------------------------------------------------------------------------------- // Process the passed definition and store the info in the dataset // -------------------------------------------------------------------------------------------------------------------------------------------- string validationRules = (cliMatch.Groups[1].Value != "") ? cliMatch.Groups[1].Value : ""; cli.type = (cliMatch.Groups[2].Value != "") ? cliMatch.Groups[2].Value.ToLower() : "[string]"; if (!typeList.Contains(cli.type.ToLower())) { WriteError(cli.fullSwitchName + " - Invalid type definition"); } cli.fullSwitchName = cliMatch.Groups[4].Value; cli.argumentValue = cli.defaultValue = (cliMatch.Groups[5].Value != "") ? cliMatch.Groups[5].Value.TrimStart('=') : ""; if (cli.argumentValue.Length > 0) { cli.hasArgument = true; } // -------------------------------------------------------------------------------------------------------------------------------------------- // Get the switch validation string, pre-process it if it isn't empty. Cannot use a Regex: rules can contain any possible character! // -------------------------------------------------------------------------------------------------------------------------------------------- if (validationRules != null) { // ---------------------------------------------------------------------------------------------------------------------------------------- // If set get the switch alias, store it in its own dictionary and remove it from validaton string. // ---------------------------------------------------------------------------------------------------------------------------------------- Match valMatch = rgxAlias.Match(validationRules); if (valMatch.Success) { cli.fullAliasName = valMatch.Groups[3].Value; aliasDictionary.Add(cli.fullAliasName, cli.fullSwitchName); validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // If Mandatory is set, set the flag and remove it from validaton string and add it to to the localArgumentList // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxMandatory.Match(validationRules); if (valMatch.Success) { cli.isMandatory = true; cli.isPresent = true; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // If negatable is set, set the flag and remove it from validaton string. // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxNegatable.Match(validationRules); if (valMatch.Success) { cli.isNegatable = true; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // If mandatory is set, set the flag and remove it from validaton string. // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxNotNullOrEmpty.Match(validationRules); if (valMatch.Success) { cli.notNullOrEmpty = true; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // If secret is set, set the flag and remove it from validaton string. Also sets the notnullorempty flag! // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxSecret.Match(validationRules); if (valMatch.Success) { cli.isSecret = true; cli.notNullOrEmpty = true; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // ValidateCount(x) or ValidateCount(x,y) -> x-only then y=0, y-only than x=1 // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxValidateCount.Match(validationRules); if (valMatch.Success) { cli.doValidateCount = true; string rangeValues = valMatch.Groups[3].Value; string[] mmValues = rangeValues.Split(','); if (mmValues.Length > 2) { WriteError(cli.fullSwitchName + " - To many arguments for ValidateCount (" + rangeValues + ") - specification should be (min,max)"); } if (mmValues.Length == 1) { mmValues = new string[] { mmValues[0], "0" }; } if (mmValues[0].Length == 0) { mmValues[0] = "1"; } cli.validateCount = mmValues; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // ValidateLength(x) or ValidateLength(x,y) -> x-only then y=0, y-only than x=1 // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxValidateLength.Match(validationRules); if (valMatch.Success) { cli.doValidateLength = true; string lengthValues = valMatch.Groups[3].Value; string[] mmValues = lengthValues.Split(','); if (mmValues.Length > 2) { WriteError(cli.fullSwitchName + " - To many arguments for ValidateLength (" + lengthValues + ") - specification should be (min,max)"); } if (mmValues.Length == 1) { mmValues = new string[] { mmValues[0], "0" }; } if (mmValues[0].Length == 0) { mmValues[0] = "1"; } cli.validateLength = mmValues; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // ValidatePattern - Regex must be encapsulated by (/ and /) // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxValidatePattern.Match(validationRules); if (valMatch.Success) { cli.doValidatePattern = true; cli.validatePattern = valMatch.Groups[3].Value; try { new Regex(cli.validatePattern); } catch { WriteError(cli.fullSwitchName + " - ValidatePattern - regex pattern does not compile."); } validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // ValidateRange(x,y) -> value must be between x & y. Perform type based checking! // Value type can be one of byte, sbyte, decimal, float, double, int, uint, long, ulong, short, ushort (strip "[]" if present!) // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxValidateRange.Match(validationRules); if (valMatch.Success) { cli.doValidateRange = true; object minValue = null; bool minFail = false; object maxValue = null; bool maxFail = false; string rangeValues = valMatch.Groups[3].Value; object[] mmValues = rangeValues.Split(','); if (mmValues.Length > 2) { WriteError(cli.fullSwitchName + " - To many arguments for ValidateRange (" + rangeValues + ") - specification should be (min,max)"); } switch (cli.type.Replace("[]", "")) { case "[byte]": minValue = Byte.MinValue; maxValue = Byte.MaxValue; try { minFail = (Convert.ToByte(mmValues[0]) < Convert.ToByte(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToByte(mmValues[1]) > Convert.ToByte(maxValue)); } catch { maxFail = true; } break; case "[sbyte]": minValue = SByte.MinValue; maxValue = SByte.MaxValue; try { minFail = (Convert.ToSByte(mmValues[0]) < Convert.ToSByte(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToSByte(mmValues[1]) > Convert.ToSByte(maxValue)); } catch { maxFail = true; } break; case "[decimal]": minValue = Decimal.MinValue; maxValue = Decimal.MaxValue; try { minFail = (Convert.ToDecimal(mmValues[0]) < Convert.ToDecimal(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToDecimal(mmValues[1]) > Convert.ToDecimal(maxValue)); } catch { maxFail = true; } break; case "[float]": minValue = Single.MinValue; maxValue = Single.MaxValue; try { minFail = (Convert.ToSingle(mmValues[0]) < Convert.ToSingle(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToSingle(mmValues[1]) > Convert.ToSingle(maxValue)); } catch { maxFail = true; } break; case "[double]": minValue = Double.MinValue; maxValue = Double.MaxValue; try { minFail = (Convert.ToDouble(mmValues[0]) < Convert.ToDouble(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToDouble(mmValues[1]) > Convert.ToDouble(maxValue)); } catch { maxFail = true; } break; case "[short]": minValue = Int16.MinValue; maxValue = Int16.MaxValue; try { minFail = (Convert.ToInt16(mmValues[0]) < Convert.ToInt16(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToInt16(mmValues[1]) > Convert.ToInt16(maxValue)); } catch { maxFail = true; } break; case "[ushort]": minValue = UInt16.MinValue; maxValue = UInt16.MaxValue; try { minFail = (Convert.ToUInt16(mmValues[0]) < Convert.ToUInt16(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToUInt16(mmValues[1]) > Convert.ToUInt16(maxValue)); } catch { maxFail = true; } break; case "[int]": minValue = Int32.MinValue; maxValue = Int32.MaxValue; try { minFail = (Convert.ToInt32(mmValues[0]) < Convert.ToInt32(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToInt32(mmValues[1]) > Convert.ToInt32(maxValue)); } catch { maxFail = true; } break; case "[unint]": minValue = UInt32.MinValue; maxValue = UInt32.MaxValue; try { minFail = (Convert.ToUInt32(mmValues[0]) < Convert.ToUInt32(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToUInt32(mmValues[1]) > Convert.ToUInt32(maxValue)); } catch { maxFail = true; } break; case "[long]": minValue = Int64.MinValue; maxValue = Int64.MaxValue; try { minFail = (Convert.ToInt64(mmValues[0]) < Convert.ToInt64(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToInt64(mmValues[1]) > Convert.ToInt64(maxValue)); } catch { maxFail = true; } break; case "[ulong]": minValue = UInt64.MinValue; maxValue = UInt64.MaxValue; try { minFail = (Convert.ToUInt64(mmValues[0]) < Convert.ToUInt64(minValue)); } catch { minFail = true; } try { maxFail = (Convert.ToUInt64(mmValues[1]) > Convert.ToUInt64(maxValue)); } catch { maxFail = true; } break; default: break; } if (mmValues.Length == 1) { mmValues = new object[] { mmValues[0], maxValue.ToString() }; } if (Convert.ToString(mmValues[0]).Length == 0) { mmValues[0] = minValue.ToString(); } if (minFail) { WriteError(cli.fullSwitchName + " - ValidateRange min " + cli.type + " value (" + mmValues[0] + ",y) is out of type range. Min: " + minValue); } if (maxFail) { WriteError(cli.fullSwitchName + " - ValidateRange max " + cli.type + " value (x," + mmValues[1] + ") is out of type range. Max: " + maxValue); } cli.validateRange = new string[] { (string)mmValues[0], (string)mmValues[1] }; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } // ---------------------------------------------------------------------------------------------------------------------------------------- // ValidateSet(x&y&...) or ValidateSet(x|y|...) - Keep this the 1st in the execution order, the set might contain rule directives! // ---------------------------------------------------------------------------------------------------------------------------------------- valMatch = rgxValidateSetOr.Match(validationRules); if (valMatch.Success) { cli.doValidateSet = true; cli.validateSet = valMatch.Groups[3].Value; validationRules = validationRules.Remove(valMatch.Groups[2].Index, valMatch.Groups[2].Length); } else { valMatch = rgxValidateSetAnd.Match(validationRules); } // ---------------------------------------------------------------------------------------------------------------------------------------- // All possibilities of the validation entries have been verified, and the original validationRules should be empty (well almost) // Remove 'balast' and verify, if not an invalid rule has been entered (could be a typo). Inform the developer and quit // ---------------------------------------------------------------------------------------------------------------------------------------- while (validationRules.Contains(",,")) { validationRules = validationRules.Replace(",,", ","); } validationRules = validationRules.Trim(cBrackets).TrimEnd(','); if (validationRules.Length > 1) { WriteError(cli.fullSwitchName + " - Invalid validation rule {..." + validationRules + "...}"); } // ---------------------------------------------------------------------------------------------------------------------------------------- } // -------------------------------------------------------------------------------------------------------------------------------------------- // Save the cli data results in the switch dictionary. // If wanted show the cli data details and return to caller // -------------------------------------------------------------------------------------------------------------------------------------------- switchDictionary.Add(cli.fullSwitchName, cli); //ShowCLIdetails(cli); return; }
// ==================================================================================================================================================== // cli.IsPresent takes the passed switch name and will return true or false depending on whether the switch is present on the command line. // Mandatory switchs witll of cause always return true ;) // ==================================================================================================================================================== public static bool IsPresent(string Switch) { // ================================================================================================================================================ // Before doing anything else... Check for the TotalCLI specific argument cliDebugLevelX // ------------------------------------------------------------------------------------------------------------------------------------------------ CheckDebugState(); // ------------------------------------------------------------------------------------------------------------------------------------------------ // Try to load the dataset of the given switch. If not available return false, else return the value of isPresent // ------------------------------------------------------------------------------------------------------------------------------------------------ cliDataSet cliData = new cliDataSet(); try { cliData = switchDictionary[Switch]; } catch { WriteError(Switch + " is not a valid switchname, cli.IsPreset is terminating."); } return cliData.isPresent; }