/// <devdoc> /// Initializes the test string according to the mask and populates the character descirptor table /// (stringDescriptor). /// </devdoc> private void Initialize() { this.testString = new StringBuilder(); this.stringDescriptor = new List<CharDescriptor>(); CaseConversion caseConversion = CaseConversion.None; // The conversion specified in the mask. bool escapedChar = false; // indicates the current char is to be escaped. int testPosition = 0; // the position of the char in the test string. CharType charType = CharType.Literal; // the mask language char type. char ch; // the char under test. string locSymbol = string.Empty; // the locale symbol corresponding to a separator in the mask. // in some cultures a symbol is represented with more than one // char, for instance '$' for en-JA is '$J'. // // Traverse the mask to generate the test string and the string descriptor table so we don't have // to traverse those strings anymore. // for (int maskPos = 0; maskPos < this.mask.Length; maskPos++) { ch = this.mask[maskPos]; if (!escapedChar) // if false treat the char as literal. { switch (ch) { // // Mask language placeholders. // set the corresponding localized char to be added to the test string. // case '.': // decimal separator. locSymbol = this.culture.NumberFormat.NumberDecimalSeparator; charType = CharType.Separator; break; case ',': // thousands separator. locSymbol = this.culture.NumberFormat.NumberGroupSeparator; charType = CharType.Separator; break; case ':': // time separator. locSymbol = this.culture.DateTimeFormat.TimeSeparator; charType = CharType.Separator; break; case '/': // date separator. locSymbol = this.culture.DateTimeFormat.DateSeparator; charType = CharType.Separator; break; case '$': // currency symbol. locSymbol = this.culture.NumberFormat.CurrencySymbol; charType = CharType.Separator; break; // // Mask language modifiers. // StringDescriptor won't have an entry for modifiers, the modified character // descriptor contains an entry for case conversion that is set accordingly. // Just set the appropriate flag for the characters that follow and continue. // case '<': // convert all chars that follow to lowercase. caseConversion = CaseConversion.ToLower; continue; case '>': // convert all chars that follow to uppercase. caseConversion = CaseConversion.ToUpper; continue; case '|': // no convertion performed on the chars that follow. caseConversion = CaseConversion.None; continue; case '\\': // escape char - next will be a literal. escapedChar = true; charType = CharType.Literal; continue; // // Mask language edit identifiers (#, 9, &, C, A, a, ?). // Populate a CharDescriptor structure desrcribing the editable char corresponding to this // identifier. // case '0': // digit required. case 'L': // letter required. case '&': // any character required. case 'A': // alphanumeric (letter or digit) required. this.requiredEditChars++; ch = this.promptChar; // replace edit identifier with prompt. charType = CharType.EditRequired; // set char as editable. break; case '?': // letter optional (space OK). case '9': // digit optional (space OK). case '#': // digit or plus/minus sign optional (space OK). case 'C': // any character optional (space OK). case 'a': // alphanumeric (letter or digit) optional. this.optionalEditChars++; ch = this.promptChar; // replace edit identifier with prompt. charType = CharType.EditOptional; // set char as editable. break; // // Literals just break so they're added to the test string. // default: charType = CharType.Literal; break; } } else { escapedChar = false; // reset flag since the escaped char is now going to be added to the test string. } // Populate a character descriptor for the current character (or loc symbol). CharDescriptor chDex = new CharDescriptor(maskPos, charType); if (IsEditPosition(chDex)) { chDex.CaseConversion = caseConversion; } // Now let's add the character to the string description table. // For code clarity we treat all characters as localizable symbols (can have multi-char representation). if (charType != CharType.Separator) { locSymbol = ch.ToString(); } foreach (char chVal in locSymbol) { this.testString.Append(chVal); this.stringDescriptor.Add(chDex); testPosition++; } } // // Trim test string to needed size. // this.testString.Capacity = this.testString.Length; }
private bool TestEscapeChar( char input, int position, CharDescriptor charDex ) { // Test literals first. See VSW#454461. // If the position holds a literal, it is escaped only if the input is the same as the literal independently on // the input value (space, prompt,...). if (IsLiteralPosition(charDex)) { return this.SkipLiterals && input == this.testString[position]; } if ((this.ResetOnPrompt && (input == this.promptChar)) || (this.ResetOnSpace && (input == spaceChar))) { return true; } return false; }
/// <devdoc> /// Sets the character at the specified position in the test string to the specified value. /// SetChar increments the number of assigned characters in the test string. /// </devdoc> private void SetChar(char input, int position, CharDescriptor charDescriptor) { Debug.Assert(position >= 0 && position < this.testString.Length, "Position out of range."); Debug.Assert(charDescriptor != null, "Null character descriptor."); // Get the character info from the char descriptor table. CharDescriptor charDex = this.stringDescriptor[position]; // If input is space or prompt and is to be escaped, we are actually resetting the position if assigned, // this doesn't affect literal positions. if (TestEscapeChar(input, position, charDescriptor)) { ResetChar(position); return; } Debug.Assert( !IsLiteralPosition( charDex ), "Setting char in literal position." ); if (Char.IsLetter(input)) { if (Char.IsUpper(input)) { if (charDescriptor.CaseConversion == CaseConversion.ToLower) { input = this.culture.TextInfo.ToLower(input); } } else // Char.IsLower( input ) { if (charDescriptor.CaseConversion == CaseConversion.ToUpper) { input = this.culture.TextInfo.ToUpper(input); } } } this.testString[position] = input; if (!charDescriptor.IsAssigned) // if position not counted for already (replace case) we do it (add case). { charDescriptor.IsAssigned = true; this.assignedCharCount++; if (charDescriptor.CharType == CharType.EditRequired) { this.requiredCharCount++; } } Debug.Assert(this.assignedCharCount <= this.EditPositionCount, "Invalid count of assigned chars."); }
/// <devdoc> /// Checks wheteher the character in the specified position is a literal and the same as the specified character. /// </devdoc> private static bool IsLiteralPosition( CharDescriptor charDescriptor ) { return (charDescriptor.CharType == CharType.Literal) || (charDescriptor.CharType == CharType.Separator); }
private static bool IsEditPosition( CharDescriptor charDescriptor ) { return (charDescriptor.CharType == CharType.EditRequired || charDescriptor.CharType == CharType.EditOptional); }
private bool TestEscapeChar( char input, int position, CharDescriptor charDex ) { if (IsLiteralPosition(charDex)) { return this.SkipLiterals && input == this.testString[position]; } if ((this.ResetOnPrompt && (input == this.promptChar)) || (this.ResetOnSpace && (input == spaceChar))) { return true; } return false; }