internal static bool TryParseLetterString(string s, PasswordStyles style, string name, int length, out Letter[] letters, out int value) { letters = null; value = 0; if (s == null) { return(false); } // Check and remove flags bool allowSpecifier = style.HasFlag(PasswordStyles.AllowSpecifier); style &= ~PasswordStyles.FlagsMask; PasswordStyles specifier = PasswordStyles.AllowSpecifier; // Identify the specifier if (s.StartsWith("0B") || s.StartsWith("0b")) { specifier = PasswordStyles.Binary; } else if (s.StartsWith("0X") || s.StartsWith("0x")) { specifier = PasswordStyles.Hex; } // Don't mix up hex/binary numbers with decimal else if (style != PasswordStyles.Hex && style != PasswordStyles.Binary && IsOnlyDigits(s)) { specifier = PasswordStyles.Value; } // Handle specifier or pure digits if (specifier == PasswordStyles.Value) { // Validate the decimal style if (style != PasswordStyles.Value && style != PasswordStyles.PasswordOrValue && style != PasswordStyles.None) { return(false); } style = specifier; } else if (specifier != PasswordStyles.AllowSpecifier) { // Validate the specifier if (!allowSpecifier || (style != PasswordStyles.None && specifier != style)) { return(false); } style = specifier; s = s.Substring(2); } else if (style == PasswordStyles.PasswordOrValue) { // We're not a value, set us to password style style = PasswordStyles.Password; } // No trailing whitespace if (s.Trim() != s) { return(false); } // Internal whitespace can be removed from binary if (style == PasswordStyles.Binary) { s = Regex.Replace(s, @"\s+", ""); } if (style != PasswordStyles.Value) { // Make sure the length is correct if (s.Length != length * (style == PasswordStyles.Binary ? 4 : 1)) { return(false); } // Easymode shortcut if (length == 0) { letters = Array.Empty <Letter>(); return(true); } } // Parse the string Letter[] newLetters = new Letter[length]; switch (style) { case PasswordStyles.None: case PasswordStyles.Password: case PasswordStyles.Hex: for (int i = 0; i < length; i++) { if (!TryParseLetter(s.Substring(i, 1), style, out newLetters[i])) { return(false); } } break; case PasswordStyles.Binary: for (int i = 0; i < length; i++) { if (!TryParseLetter(s.Substring(i * 4, 4), style, out newLetters[i])) { return(false); } } break; case PasswordStyles.Value: if (!int.TryParse(s, out value)) { return(false); } letters = null; // Null signifies a value return break; default: return(false); } letters = newLetters; return(true); }
internal static bool TryParseLetter(string s, PasswordStyles style, out Letter letter) { letter = new Letter(); if (s == null || s.Length == 0) { return(false); } // Check and remove flags bool allowSpecifier = style.HasFlag(PasswordStyles.AllowSpecifier); style &= ~PasswordStyles.FlagsMask; PasswordStyles specifier = PasswordStyles.AllowSpecifier; // Identify the specifier if (s.StartsWith("0B") || s.StartsWith("0b")) { specifier = PasswordStyles.Binary; } else if (s.StartsWith("0X") || s.StartsWith("0x")) { specifier = PasswordStyles.Hex; } // Don't mix up hex/binary numbers with decimal else if (style != PasswordStyles.Hex && style != PasswordStyles.Binary && IsOnlyDigits(s)) { specifier = PasswordStyles.Value; } // Handle specifier or pure digits if (specifier == PasswordStyles.Value) { // Validate the decimal style if (style != PasswordStyles.Value && style != PasswordStyles.PasswordOrValue && style != PasswordStyles.None) { return(false); } style = specifier; } else if (specifier != PasswordStyles.AllowSpecifier) { // Validate the specifier if (!allowSpecifier || (style != PasswordStyles.None && specifier != style)) { return(false); } style = specifier; s = s.Substring(2); } else if (style == PasswordStyles.PasswordOrValue) { // We're not a value, set us to password style style = PasswordStyles.Password; } char c; switch (style) { case PasswordStyles.None: case PasswordStyles.Password: c = s[0]; if (s.Length != 1 || !Letter.IsValidChar(c)) { return(false); } letter = new Letter(c); return(true); case PasswordStyles.Hex: c = char.ToUpper(s[0]); if (s.Length != 1 || (!char.IsDigit(c) && c < 'A' && c > 'F')) { return(false); } letter = new Letter(Convert.ToInt32(s, 16)); return(true); case PasswordStyles.Binary: if (s.Length != 4) { return(false); } for (int i = 0; i < 4; i++) { if (s[i] != '0' && s[i] != '1') { return(false); } } letter = new Letter(Convert.ToInt32(s, 2)); return(true); case PasswordStyles.Value: if (!int.TryParse(s, out int value)) { return(false); } letter = new Letter(value); return(true); default: return(false); } }
internal static Letter[] ParseLetterString(string s, PasswordStyles style, string name, int length, out int value) { value = 0; if (s == null) { throw new ArgumentNullException(nameof(s)); } // Check and remove flags bool allowSpecifier = style.HasFlag(PasswordStyles.AllowSpecifier); style &= ~PasswordStyles.FlagsMask; PasswordStyles specifier = PasswordStyles.AllowSpecifier; // Identify the specifier if (s.StartsWith("0B") || s.StartsWith("0b")) { specifier = PasswordStyles.Binary; } else if (s.StartsWith("0X") || s.StartsWith("0x")) { specifier = PasswordStyles.Hex; } // Don't mix up hex/binary numbers with decimal else if (style != PasswordStyles.Hex && style != PasswordStyles.Binary && IsOnlyDigits(s)) { specifier = PasswordStyles.Value; } // Handle specifier or pure digits if (specifier == PasswordStyles.Value) { // Validate the decimal style if (style != PasswordStyles.Value && style != PasswordStyles.PasswordOrValue && style != PasswordStyles.None) { throw new ArgumentException($"{name} format as value does not match style!"); } style = specifier; } else if (specifier != PasswordStyles.AllowSpecifier) { // Validate the specifier if (!allowSpecifier) { throw new ArgumentException($"{name} format specifier is not allowed!"); } if (style != PasswordStyles.None && specifier != style) { throw new ArgumentException($"{name} format specifier does not match style!"); } style = specifier; s = s.Substring(2); } else if (style == PasswordStyles.PasswordOrValue) { // We're not a value, set us to password style style = PasswordStyles.Password; } // No trailing whitespace if (s.Trim() != s) { throw new Exception($"{name} string cannot have trailing whitespace, got \"{s}\"!"); } // Internal whitespace can be removed from binary if (style == PasswordStyles.Binary) { s = Regex.Replace(s, @"\s+", ""); } if (style != PasswordStyles.Value) { // Make sure the length is correct if (s.Length != length * (style == PasswordStyles.Binary ? 4 : 1)) { throw new ArgumentException($"{name} string must be {length} letters long, got {s.Length} letters!", nameof(s)); } // Easymode shortcut if (length == 0) { return(Array.Empty <Letter>()); } } // Parse the string Letter[] letters = new Letter[length]; switch (style) { case PasswordStyles.None: case PasswordStyles.Password: for (int i = 0; i < length; i++) { letters[i] = new Letter(s[i]); } return(letters); case PasswordStyles.Hex: for (int i = 0; i < length; i++) { letters[i] = new Letter(Convert.ToInt32(s.Substring(i, 1), 16)); } return(letters); case PasswordStyles.Binary: for (int i = 0; i < length; i++) { letters[i] = new Letter(Convert.ToInt32(s.Substring(i * 4, 4), 2)); } return(letters); case PasswordStyles.Value: value = int.Parse(s); return(null); // Null signifies a value return. default: throw new ArgumentException($"Invalid {name} Password Style {style}!"); } }
internal static Letter ParseLetter(string s, PasswordStyles style) { if (s == null) { throw new ArgumentNullException(nameof(s)); } // Check and remove flags bool allowSpecifier = style.HasFlag(PasswordStyles.AllowSpecifier); style &= ~PasswordStyles.FlagsMask; PasswordStyles specifier = PasswordStyles.AllowSpecifier; // Identify the specifier if (s.StartsWith("0B") || s.StartsWith("0b")) { specifier = PasswordStyles.Binary; } else if (s.StartsWith("0X") || s.StartsWith("0x")) { specifier = PasswordStyles.Hex; } // Don't mix up hex/binary numbers with decimal else if (style != PasswordStyles.Hex && style != PasswordStyles.Binary && IsOnlyDigits(s)) { specifier = PasswordStyles.Value; } // Handle specifier or pure digits if (specifier == PasswordStyles.Value) { // Validate the decimal style if (style != PasswordStyles.Value && style != PasswordStyles.PasswordOrValue && style != PasswordStyles.None) { throw new ArgumentException($"Letter format as value does not match style!"); } style = specifier; } else if (specifier != PasswordStyles.AllowSpecifier) { // Validate the specifier if (!allowSpecifier) { throw new ArgumentException($"Letter format specifier is not allowed!"); } if (style != PasswordStyles.None && specifier != style) { throw new ArgumentException($"Letter format specifier does not match style!"); } style = specifier; s = s.Substring(2); } else if (style == PasswordStyles.PasswordOrValue) { // We're not a value, set us to password style style = PasswordStyles.Password; } switch (style) { case PasswordStyles.None: case PasswordStyles.Password: if (s.Length != 1) { throw new ArgumentException($"Letter Password string must be one character long, got {s.Length}!"); } return(new Letter(s[0])); case PasswordStyles.Hex: if (s.Length != 1) { throw new ArgumentException($"Letter Hex string must be one character long, got {s.Length}!"); } return(new Letter(Convert.ToInt32(s, 16))); case PasswordStyles.Binary: if (s.Length != 4) { throw new ArgumentException($"Letter Binary string must be four characters long, got {s.Length}!"); } return(new Letter(Convert.ToInt32(s, 2))); case PasswordStyles.Value: return(new Letter(int.Parse(s))); default: throw new ArgumentException($"Invalid Password Style {style}!"); } }