[System.Security.SecurityCritical] // auto-generated internal TokenHashValue[] CreateTokenHashTable() { TokenHashValue[] temp = m_dtfiTokenHash; if (temp == null) { temp = new TokenHashValue[TOKEN_HASH_SIZE]; bool koreanLanguage = LanguageName.Equals(KoreanLangName); string sep = this.TimeSeparator.Trim(); if (IgnorableComma != sep) InsertHash(temp, IgnorableComma, TokenType.IgnorableSymbol, 0); if (IgnorablePeriod != sep) InsertHash(temp, IgnorablePeriod, TokenType.IgnorableSymbol, 0); if (KoreanHourSuff != sep && CJKHourSuff != sep && ChineseHourSuff != sep) { // // On the Macintosh, the default TimeSeparator is identical to the KoreanHourSuff, CJKHourSuff, or ChineseHourSuff for some cultures like // ja-JP and ko-KR. In these cases having the same symbol inserted into the hash table with multiple TokenTypes causes undesirable // DateTime.Parse behavior. For instance, the DateTimeFormatInfo.Tokenize() method might return SEP_DateOrOffset for KoreanHourSuff // instead of SEP_HourSuff. // InsertHash(temp, this.TimeSeparator, TokenType.SEP_Time, 0); } InsertHash(temp, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); // if (LanguageName.Equals("sq")) { // Albanian allows time formats like "12:00.PD" InsertHash(temp, IgnorablePeriod + this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, IgnorablePeriod + this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); } // CJK suffix InsertHash(temp, CJKYearSuff, TokenType.SEP_YearSuff, 0); InsertHash(temp, KoreanYearSuff, TokenType.SEP_YearSuff, 0); InsertHash(temp, CJKMonthSuff, TokenType.SEP_MonthSuff, 0); InsertHash(temp, KoreanMonthSuff, TokenType.SEP_MonthSuff, 0); InsertHash(temp, CJKDaySuff, TokenType.SEP_DaySuff, 0); InsertHash(temp, KoreanDaySuff, TokenType.SEP_DaySuff, 0); InsertHash(temp, CJKHourSuff, TokenType.SEP_HourSuff, 0); InsertHash(temp, ChineseHourSuff, TokenType.SEP_HourSuff, 0); InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0); InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0); // if (koreanLanguage) { // Korean suffix InsertHash(temp, KoreanHourSuff, TokenType.SEP_HourSuff, 0); InsertHash(temp, KoreanMinuteSuff, TokenType.SEP_MinuteSuff, 0); InsertHash(temp, KoreanSecondSuff, TokenType.SEP_SecondSuff, 0); } if ( LanguageName.Equals("ky")) { // For some cultures, the date separator works more like a comma, being allowed before or after any date part InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.IgnorableSymbol, 0); } else { InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0); } String[] dateWords = null; DateTimeFormatInfoScanner scanner = null; // We need to rescan the date words since we're always synthetic scanner = new DateTimeFormatInfoScanner(); // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix. // The only reason they're being assigned to m_dateWords is for Whidbey Deserialization m_dateWords = dateWords = scanner.GetDateWordsOfDTFI(this); // Ensure the formatflags is initialized. DateTimeFormatFlags flag = FormatFlags; // For some cultures, the date separator works more like a comma, being allowed before or after any date part. // In these cultures, we do not use normal date separator since we disallow date separator after a date terminal state. // This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol. bool useDateSepAsIgnorableSymbol = false; String monthPostfix = null; if (dateWords != null) { // There are DateWords. It could be a real date word (such as "de"), or a monthPostfix. // The monthPostfix starts with '\xfffe' (MonthPostfixChar), followed by the real monthPostfix. for (int i = 0; i < dateWords.Length; i++) { switch (dateWords[i][0]) { // This is a month postfix case DateTimeFormatInfoScanner.MonthPostfixChar: // Get the real month postfix. monthPostfix = dateWords[i].Substring(1); // Add the month name + postfix into the token. AddMonthNames(temp, monthPostfix); break; case DateTimeFormatInfoScanner.IgnorableSymbolChar: String symbol = dateWords[i].Substring(1); InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0); if (this.DateSeparator.Trim(null).Equals(symbol)) { // The date separator is the same as the ingorable symbol. useDateSepAsIgnorableSymbol = true; } break; default: InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0); // if (LanguageName.Equals("eu")) { // Basque has date words with leading dots InsertHash(temp, IgnorablePeriod + dateWords[i], TokenType.DateWordToken, 0); } break; } } } if (!useDateSepAsIgnorableSymbol) { // Use the normal date separator. InsertHash(temp, this.DateSeparator, TokenType.SEP_Date, 0); } // Add the regular month names. AddMonthNames(temp, null); // Add the abbreviated month names. for (int i = 1; i <= 13; i++) { InsertHash(temp, GetAbbreviatedMonthName(i), TokenType.MonthToken, i); } if ((FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0) { for (int i = 1; i <= 13; i++) { String str; str = internalGetMonthName(i, MonthNameStyles.Genitive, false); InsertHash(temp, str, TokenType.MonthToken, i); } } if ((FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0) { for (int i = 1; i <= 13; i++) { String str; str = internalGetMonthName(i, MonthNameStyles.LeapYear, false); InsertHash(temp, str, TokenType.MonthToken, i); } } for (int i = 0; i < 7; i++) { //String str = GetDayOfWeekNames()[i]; // We have to call public methods here to work with inherited DTFI. String str = GetDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); str = GetAbbreviatedDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); } int[] eras = calendar.Eras; for (int i = 1; i <= eras.Length; i++) { InsertHash(temp, GetEraName(i), TokenType.EraToken, i); InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i); } // if (LanguageName.Equals(JapaneseLangName)) { // Japanese allows day of week forms like: "(Tue)" for (int i = 0; i < 7; i++) { String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")"; InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i); } if (this.Calendar.GetType() != typeof(JapaneseCalendar)) { // Special case for Japanese. If this is a Japanese DTFI, and the calendar is not Japanese calendar, // we will check Japanese Era name as well when the calendar is Gregorian. DateTimeFormatInfo jaDtfi = GetJapaneseCalendarDTFI(); for (int i = 1; i <= jaDtfi.Calendar.Eras.Length; i++) { InsertHash(temp, jaDtfi.GetEraName(i), TokenType.JapaneseEraToken, i); InsertHash(temp, jaDtfi.GetAbbreviatedEraName(i), TokenType.JapaneseEraToken, i); // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1. InsertHash(temp, jaDtfi.AbbreviatedEnglishEraNames[i-1], TokenType.JapaneseEraToken, i); } } } // else if (CultureName.Equals("zh-TW")) { DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI(); for (int i = 1; i <= twDtfi.Calendar.Eras.Length; i++) { if (twDtfi.GetEraName(i).Length > 0) { InsertHash(temp, twDtfi.GetEraName(i), TokenType.TEraToken, i); } } } InsertHash(temp, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); // Add invariant month names and day names. for (int i = 1; i <= 12; i++) { String str; // We have to call public methods here to work with inherited DTFI. // Insert the month name first, so that they are at the front of abbrevaited // month names. str = InvariantInfo.GetMonthName(i); InsertHash(temp, str, TokenType.MonthToken, i); str = InvariantInfo.GetAbbreviatedMonthName(i); InsertHash(temp, str, TokenType.MonthToken, i); } for (int i = 0; i < 7; i++) { // We have to call public methods here to work with inherited DTFI. String str = InvariantInfo.GetDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); } for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++) { // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1. InsertHash(temp, AbbreviatedEnglishEraNames[i], TokenType.EraToken, i + 1); } InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0); InsertHash(temp, DateTimeParse.GMTName, TokenType.TimeZoneToken, 0); InsertHash(temp, DateTimeParse.ZuluName, TokenType.TimeZoneToken, 0); InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0); InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0); m_dtfiTokenHash = temp; } return (temp); }
private void AddMonthNames(TokenHashValue[] temp, String monthPostfix) { for (int i = 1; i <= 13; i++) { String str; //str = internalGetMonthName(i, MonthNameStyles.Regular, false); // We have to call public methods here to work with inherited DTFI. // Insert the month name first, so that they are at the front of abbrevaited // month names. str = GetMonthName(i); if (str.Length > 0) { if (monthPostfix != null) { // Insert the month name with the postfix first, so it can be matched first. InsertHash(temp, str + monthPostfix, TokenType.MonthToken, i); } else { InsertHash(temp, str, TokenType.MonthToken, i); } } str = GetAbbreviatedMonthName(i); InsertHash(temp, str, TokenType.MonthToken, i); } }
private void InsertHash(TokenHashValue[] hashTable, string str, TokenType tokenType, int tokenValue) { if (str == null || str.Length == 0) return; int pos = 0; if (char.IsWhiteSpace(str[0]) || char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim((char[]) null); if (str.Length == 0) return; } char ch = char.ToLower(str[0], this.Culture); int hashcode = (int) ch % 199; int hashProbe = 1 + (int) ch % 197; do { TokenHashValue tokenHashValue = hashTable[hashcode]; if (tokenHashValue == null) { hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); break; } else { if (str.Length >= tokenHashValue.tokenString.Length && string.Compare(str, 0, tokenHashValue.tokenString, 0, tokenHashValue.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0) { if (str.Length > tokenHashValue.tokenString.Length) { this.InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, pos, hashcode, hashProbe); break; } else { int num1 = (int) tokenType; int num2 = (int) tokenHashValue.tokenType; if (((num1 | num2) & (int) byte.MaxValue) == num1 || ((num1 | num2) & 65280) == num1) { tokenHashValue.tokenType |= tokenType; if (tokenValue != 0) tokenHashValue.tokenValue = tokenValue; } } } ++pos; hashcode += hashProbe; if (hashcode >= 199) hashcode -= 199; } } while (pos < 199); }
private void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) { // The month of the 13th month is allowed to be null, so make sure that we ignore null value here. if (str == null || str.Length == 0) { return; } TokenHashValue value; int i = 0; // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by // DateTime.Parse(). if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim(null); // Trim white space characters. // Could have space for separators if (str.Length == 0) return; } char ch = this.Culture.TextInfo.ToLower(str[0]); int hashcode = ch % TOKEN_HASH_SIZE; int hashProbe = 1 + ch % SECOND_PRIME; do { value = hashTable[hashcode]; if (value == null) { //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode); hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); return; } else { // Collision happens. Find another slot. if (str.Length >= value.tokenString.Length) { // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of // the shorter ones. if (this.Culture.CompareInfo.Compare(str, 0, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length, CompareOptions.IgnoreCase) == 0) { if (str.Length > value.tokenString.Length) { // The str to be inserted has the same prefix as the current token, and str is longer. // Insert str into this node, and shift every node behind it. InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe); return; } else { // Same token. If they have different types (regular token vs separator token). Add them. // If we have the same regular token or separator token in the hash already, do NOT update the hash. // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash. // // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet. // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet. // int nTokenType = (int)tokenType; int nCurrentTokenTypeInHash = (int)value.tokenType; // // The folowing is the fix for the issue of throwing FormatException when "mar" is passed in string of the short date format dd/MMM/yyyy for es-MX // if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) || ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) { value.tokenType |= tokenType; if (tokenValue != 0) { value.tokenValue = tokenValue; } } // The token to be inserted is already in the table. Skip it. } } } } //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str); i++; hashcode += hashProbe; if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; } while (i < TOKEN_HASH_SIZE); Contract.Assert(true, "The hashtable is full. This should not happen."); }
private void AddMonthNames(TokenHashValue[] temp, string monthPostfix) { for (int index = 1; index <= 13; ++index) { string monthName = this.GetMonthName(index); if (monthName.Length > 0) { if (monthPostfix != null) this.InsertHash(temp, monthName + monthPostfix, TokenType.MonthToken, index); else this.InsertHash(temp, monthName, TokenType.MonthToken, index); } string abbreviatedMonthName = this.GetAbbreviatedMonthName(index); this.InsertHash(temp, abbreviatedMonthName, TokenType.MonthToken, index); } }
private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, string str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe) { TokenHashValue tokenHashValue1 = hashTable[hashcode]; hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); while (++pos < 199) { hashcode += hashProbe; if (hashcode >= 199) hashcode -= 199; TokenHashValue tokenHashValue2 = hashTable[hashcode]; if (tokenHashValue2 == null || (int) char.ToLower(tokenHashValue2.tokenString[0], this.Culture) == (int) ch) { hashTable[hashcode] = tokenHashValue1; if (tokenHashValue2 == null) break; tokenHashValue1 = tokenHashValue2; } } }
private void InsertHash(TokenHashValue[] hashTable, string str, TokenType tokenType, int tokenValue) { TokenHashValue value2; if ((str == null) || (str.Length == 0)) { return; } int pos = 0; if (char.IsWhiteSpace(str[0]) || char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim(null); if (str.Length == 0) { return; } } char ch = char.ToLower(str[0], this.Culture); int index = ch % '\x00c7'; int hashProbe = 1 + (ch % '\x00c5'); Label_0069: value2 = hashTable[index]; if (value2 == null) { hashTable[index] = new TokenHashValue(str, tokenType, tokenValue); } else { if ((str.Length >= value2.tokenString.Length) && (string.Compare(str, 0, value2.tokenString, 0, value2.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0)) { if (str.Length > value2.tokenString.Length) { this.InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, pos, index, hashProbe); return; } int num4 = (int) tokenType; int num5 = (int) value2.tokenType; if ((((num4 | num5) & 0xff) == num4) || (((num4 | num5) & 0xff00) == num4)) { value2.tokenType |= tokenType; if (tokenValue != 0) { value2.tokenValue = tokenValue; } } } pos++; index += hashProbe; if (index >= 0xc7) { index -= 0xc7; } if (pos < 0xc7) { goto Label_0069; } } }
void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) { // The month of the 13th month is allowed to be null, so make sure that we ignore null value here. if (str == null || str.Length == 0) { return; } TokenHashValue value; int i = 0; // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by // DateTime.Parse(). if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim(null); // Trim white space characters. } char ch = Char.ToLower(str[0], CultureInfo.CurrentCulture); int hashcode = ch % TOKEN_HASH_SIZE; int hashProbe = 1 + ch % SECOND_PRIME; do { value = hashTable[hashcode]; if (value == null) { //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode); hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); return; } else { // Collision happens. Find another slot. if (str.Length >= value.tokenString.Length) { // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of // the shorter ones. if (String.Compare(str, 0, value.tokenString, 0, value.tokenString.Length, true, CultureInfo.CurrentCulture) == 0) { if (str.Length > value.tokenString.Length) { // The str to be inserted has the same prefix as the current token, and str is longer. // Insert str into this node, and shift every node behind it. InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe); return; } else { // Same token. If they have different types (regular token vs separator token. Add them. if (((int)tokenType & 0xff00) != ((int)value.tokenType & 0xff00)) { value.tokenType |= tokenType; if (tokenValue != 0) { value.tokenValue = tokenValue; } } // The token to be inserted is already in the table. Skip it. } } } } //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str); i++; hashcode += hashProbe; if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; } while (i < TOKEN_HASH_SIZE); BCLDebug.Assert(true, "The hashtable is full. This should not happen."); }
internal TokenHashValue[] CreateTokenHashTable() { TokenHashValue[] dtfiTokenHash = this.m_dtfiTokenHash; if (dtfiTokenHash == null) { dtfiTokenHash = new TokenHashValue[0xc7]; bool flag = this.LanguageName.Equals("ko"); string str = this.TimeSeparator.Trim(); if ("," != str) { this.InsertHash(dtfiTokenHash, ",", TokenType.IgnorableSymbol, 0); } if ("." != str) { this.InsertHash(dtfiTokenHash, ".", TokenType.IgnorableSymbol, 0); } if ((("시" != str) && ("時" != str)) && ("时" != str)) { this.InsertHash(dtfiTokenHash, this.TimeSeparator, TokenType.SEP_Time, 0); } this.InsertHash(dtfiTokenHash, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); this.InsertHash(dtfiTokenHash, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); if (this.LanguageName.Equals("sq")) { this.InsertHash(dtfiTokenHash, "." + this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); this.InsertHash(dtfiTokenHash, "." + this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); } this.InsertHash(dtfiTokenHash, "年", TokenType.SEP_YearSuff, 0); this.InsertHash(dtfiTokenHash, "년", TokenType.SEP_YearSuff, 0); this.InsertHash(dtfiTokenHash, "月", TokenType.SEP_MonthSuff, 0); this.InsertHash(dtfiTokenHash, "월", TokenType.SEP_MonthSuff, 0); this.InsertHash(dtfiTokenHash, "日", TokenType.SEP_DaySuff, 0); this.InsertHash(dtfiTokenHash, "일", TokenType.SEP_DaySuff, 0); this.InsertHash(dtfiTokenHash, "時", TokenType.SEP_HourSuff, 0); this.InsertHash(dtfiTokenHash, "时", TokenType.SEP_HourSuff, 0); this.InsertHash(dtfiTokenHash, "分", TokenType.SEP_MinuteSuff, 0); this.InsertHash(dtfiTokenHash, "秒", TokenType.SEP_SecondSuff, 0); if (flag) { this.InsertHash(dtfiTokenHash, "시", TokenType.SEP_HourSuff, 0); this.InsertHash(dtfiTokenHash, "분", TokenType.SEP_MinuteSuff, 0); this.InsertHash(dtfiTokenHash, "초", TokenType.SEP_SecondSuff, 0); } if (this.LanguageName.Equals("ky")) { this.InsertHash(dtfiTokenHash, "-", TokenType.IgnorableSymbol, 0); } else { this.InsertHash(dtfiTokenHash, "-", TokenType.SEP_DateOrOffset, 0); } string[] strArray = null; DateTimeFormatInfoScanner scanner = null; scanner = new DateTimeFormatInfoScanner(); this.m_dateWords = strArray = scanner.GetDateWordsOfDTFI(this); DateTimeFormatFlags formatFlags = this.FormatFlags; bool flag2 = false; string monthPostfix = null; if (strArray != null) { for (int num = 0; num < strArray.Length; num++) { switch (strArray[num][0]) { case 0xe000: monthPostfix = strArray[num].Substring(1); this.AddMonthNames(dtfiTokenHash, monthPostfix); break; case 0xe001: { string str3 = strArray[num].Substring(1); this.InsertHash(dtfiTokenHash, str3, TokenType.IgnorableSymbol, 0); if (this.DateSeparator.Trim(null).Equals(str3)) { flag2 = true; } break; } default: this.InsertHash(dtfiTokenHash, strArray[num], TokenType.DateWordToken, 0); if (this.LanguageName.Equals("eu")) { this.InsertHash(dtfiTokenHash, "." + strArray[num], TokenType.DateWordToken, 0); } break; } } } if (!flag2) { this.InsertHash(dtfiTokenHash, this.DateSeparator, TokenType.SEP_Date, 0); } this.AddMonthNames(dtfiTokenHash, null); for (int i = 1; i <= 13; i++) { this.InsertHash(dtfiTokenHash, this.GetAbbreviatedMonthName(i), TokenType.MonthToken, i); } if ((this.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != DateTimeFormatFlags.None) { for (int num3 = 1; num3 <= 13; num3++) { string str4 = this.internalGetMonthName(num3, MonthNameStyles.Genitive, false); this.InsertHash(dtfiTokenHash, str4, TokenType.MonthToken, num3); } } if ((this.FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != DateTimeFormatFlags.None) { for (int num4 = 1; num4 <= 13; num4++) { string str5 = this.internalGetMonthName(num4, MonthNameStyles.LeapYear, false); this.InsertHash(dtfiTokenHash, str5, TokenType.MonthToken, num4); } } for (int j = 0; j < 7; j++) { string dayName = this.GetDayName((DayOfWeek) j); this.InsertHash(dtfiTokenHash, dayName, TokenType.DayOfWeekToken, j); dayName = this.GetAbbreviatedDayName((DayOfWeek) j); this.InsertHash(dtfiTokenHash, dayName, TokenType.DayOfWeekToken, j); } int[] eras = this.calendar.Eras; for (int k = 1; k <= eras.Length; k++) { this.InsertHash(dtfiTokenHash, this.GetEraName(k), TokenType.EraToken, k); this.InsertHash(dtfiTokenHash, this.GetAbbreviatedEraName(k), TokenType.EraToken, k); } if (this.LanguageName.Equals("ja")) { for (int num7 = 0; num7 < 7; num7++) { string str7 = "(" + this.GetAbbreviatedDayName((DayOfWeek) num7) + ")"; this.InsertHash(dtfiTokenHash, str7, TokenType.DayOfWeekToken, num7); } if (this.Calendar.GetType() != typeof(JapaneseCalendar)) { DateTimeFormatInfo japaneseCalendarDTFI = GetJapaneseCalendarDTFI(); for (int num8 = 1; num8 <= japaneseCalendarDTFI.Calendar.Eras.Length; num8++) { this.InsertHash(dtfiTokenHash, japaneseCalendarDTFI.GetEraName(num8), TokenType.JapaneseEraToken, num8); this.InsertHash(dtfiTokenHash, japaneseCalendarDTFI.GetAbbreviatedEraName(num8), TokenType.JapaneseEraToken, num8); this.InsertHash(dtfiTokenHash, japaneseCalendarDTFI.AbbreviatedEnglishEraNames[num8 - 1], TokenType.JapaneseEraToken, num8); } } } else if (this.CultureName.Equals("zh-TW")) { DateTimeFormatInfo taiwanCalendarDTFI = GetTaiwanCalendarDTFI(); for (int num9 = 1; num9 <= taiwanCalendarDTFI.Calendar.Eras.Length; num9++) { if (taiwanCalendarDTFI.GetEraName(num9).Length > 0) { this.InsertHash(dtfiTokenHash, taiwanCalendarDTFI.GetEraName(num9), TokenType.TEraToken, num9); } } } this.InsertHash(dtfiTokenHash, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); this.InsertHash(dtfiTokenHash, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); for (int m = 1; m <= 12; m++) { string monthName = InvariantInfo.GetMonthName(m); this.InsertHash(dtfiTokenHash, monthName, TokenType.MonthToken, m); monthName = InvariantInfo.GetAbbreviatedMonthName(m); this.InsertHash(dtfiTokenHash, monthName, TokenType.MonthToken, m); } for (int n = 0; n < 7; n++) { string abbreviatedDayName = InvariantInfo.GetDayName((DayOfWeek) n); this.InsertHash(dtfiTokenHash, abbreviatedDayName, TokenType.DayOfWeekToken, n); abbreviatedDayName = InvariantInfo.GetAbbreviatedDayName((DayOfWeek) n); this.InsertHash(dtfiTokenHash, abbreviatedDayName, TokenType.DayOfWeekToken, n); } for (int num12 = 0; num12 < this.AbbreviatedEnglishEraNames.Length; num12++) { this.InsertHash(dtfiTokenHash, this.AbbreviatedEnglishEraNames[num12], TokenType.EraToken, num12 + 1); } this.InsertHash(dtfiTokenHash, "T", TokenType.SEP_LocalTimeMark, 0); this.InsertHash(dtfiTokenHash, "GMT", TokenType.TimeZoneToken, 0); this.InsertHash(dtfiTokenHash, "Z", TokenType.TimeZoneToken, 0); this.InsertHash(dtfiTokenHash, "/", TokenType.SEP_Date, 0); this.InsertHash(dtfiTokenHash, ":", TokenType.SEP_Time, 0); this.m_dtfiTokenHash = dtfiTokenHash; } return dtfiTokenHash; }
private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, string str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe) { TokenHashValue value2 = hashTable[hashcode]; hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); while (++pos < 0xc7) { hashcode += hashProbe; if (hashcode >= 0xc7) { hashcode -= 0xc7; } TokenHashValue value3 = hashTable[hashcode]; if ((value3 == null) || (char.ToLower(value3.tokenString[0], this.Culture) == ch)) { hashTable[hashcode] = value2; if (value3 == null) { return; } value2 = value3; } } }
private void AddMonthNames(TokenHashValue[] temp, string monthPostfix) { for (int i = 1; i <= 13; i++) { string monthName = this.GetMonthName(i); if (monthName.Length > 0) { if (monthPostfix != null) { this.InsertHash(temp, monthName + monthPostfix, TokenType.MonthToken, i); } else { this.InsertHash(temp, monthName, TokenType.MonthToken, i); } } monthName = this.GetAbbreviatedMonthName(i); this.InsertHash(temp, monthName, TokenType.MonthToken, i); } }
private void InsertHash(TokenHashValue[] hashTable, string str, TokenType tokenType, int tokenValue) { TokenHashValue value2; if ((str == null) || (str.Length == 0)) { return; } int pos = 0; if (char.IsWhiteSpace(str[0]) || char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim(null); if (str.Length == 0) { return; } } char ch = char.ToLower(str[0], CultureInfo.CurrentCulture); int index = ch % '\x00c7'; int hashProbe = 1 + (ch % '\x00c5'); Label_0068: value2 = hashTable[index]; if (value2 == null) { hashTable[index] = new TokenHashValue(str, tokenType, tokenValue); } else { if ((str.Length >= value2.tokenString.Length) && (string.Compare(str, 0, value2.tokenString, 0, value2.tokenString.Length, true, CultureInfo.CurrentCulture) == 0)) { if (str.Length > value2.tokenString.Length) { this.InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, pos, index, hashProbe); return; } if ((tokenType & TokenType.SeparatorTokenMask) != (value2.tokenType & TokenType.SeparatorTokenMask)) { value2.tokenType |= tokenType; if (tokenValue != 0) { value2.tokenValue = tokenValue; } } } pos++; index += hashProbe; if (index >= 0xc7) { index -= 0xc7; } if (pos < 0xc7) { goto Label_0068; } } }
void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) { // The month of the 13th month is allowed to be null, so make sure that we ignore null value here. if (str == null || str.Length == 0) { return; } TokenHashValue value; int i = 0; // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by // DateTime.Parse(). if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim(null); // Trim white space characters. // Could have space for separators if (str.Length == 0) return; } char ch = Char.ToLower(str[0], this.Culture); int hashcode = ch % TOKEN_HASH_SIZE; int hashProbe = 1 + ch % SECOND_PRIME; do { value = hashTable[hashcode]; if (value == null) { //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode); hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); return; } else { // Collision happens. Find another slot. if (str.Length >= value.tokenString.Length) { // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of // the shorter ones. if (String.Compare(str, 0, value.tokenString, 0, value.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0) { if (str.Length > value.tokenString.Length) { // The str to be inserted has the same prefix as the current token, and str is longer. // Insert str into this node, and shift every node behind it. InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe); return; } else { // Same token. If they have different types (regular token vs separator token). Add them. // If we have the same regular token or separator token in the hash already, do NOT update the hash. // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash. // // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet. // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet. // int nTokenType = (int)tokenType; int nCurrentTokenTypeInHash = (int)value.tokenType; // // Since RegularToken are stored in the lower 8-bit, we use RegularTokenMask to mask the upper 8-bit. // And SeparaToken are stroed in the upper 8-bit, we use SeparatorTokenMask to mask the lower 8-bit. // We only pass either a RegularToken or a SeparatorToken to be inserted to this function, so only one of the statement below could be true after the masking. // We do LOGICAL OR of the tokenType that we want to insert with the current tokenType in the hash (could be 0 or an existing non-zero value). // And we check the result after the OR with the tokenType that we want to insert. When the result is equal, it means that: // * Either the current tokenType is 0. // * Or the tokenType to insert is the same as the one that is already in the hash. // If the alues are not the same, we will NOT update the table. This means that we will just keep the tokenType that we had before. // if ((((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.RegularTokenMask) == nTokenType) || (((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.SeparatorTokenMask) == nTokenType)) { value.tokenType |= tokenType; if (tokenValue != 0) { value.tokenValue = tokenValue; } } // The token to be inserted is already in the table. Skip it. } } } } //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str); i++; hashcode += hashProbe; if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; } while (i < TOKEN_HASH_SIZE); Contract.Assert(true, "The hashtable is full. This should not happen."); }
void InsertAtCurrentHashNode(TokenHashValue[] hashTable, String str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe) { // Remember the current slot. TokenHashValue previousNode = hashTable[hashcode]; //// Console.WriteLine(" Insert Key: {0} in {1}", str, slotToInsert); // Insert the new node into the current slot. hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue);; while (++pos < TOKEN_HASH_SIZE) { hashcode += hashProbe; if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; // Remember this slot TokenHashValue temp = hashTable[hashcode]; if (temp != null && Char.ToLower(temp.tokenString[0], this.Culture) != ch) { continue; } // Put the previous slot into this slot. hashTable[hashcode] = previousNode; //// Console.WriteLine(" Move {0} to slot {1}", previousNode.tokenString, hashcode); if (temp == null) { // Done return; } previousNode = temp; } ; Contract.Assert(true, "The hashtable is full. This should not happen."); }
internal TokenHashValue[] CreateTokenHashTable() { TokenHashValue[] tokenHashValueArray = this.m_dtfiTokenHash; if (tokenHashValueArray == null) { tokenHashValueArray = new TokenHashValue[199]; bool flag1 = this.LanguageName.Equals("ko"); string str1 = this.TimeSeparator.Trim(); if ("," != str1) this.InsertHash(tokenHashValueArray, ",", TokenType.IgnorableSymbol, 0); if ("." != str1) this.InsertHash(tokenHashValueArray, ".", TokenType.IgnorableSymbol, 0); if ("시" != str1 && "時" != str1 && "时" != str1) this.InsertHash(tokenHashValueArray, this.TimeSeparator, TokenType.SEP_Time, 0); this.InsertHash(tokenHashValueArray, this.AMDesignator, (TokenType) 1027, 0); this.InsertHash(tokenHashValueArray, this.PMDesignator, (TokenType) 1284, 1); if (this.LanguageName.Equals("sq")) { this.InsertHash(tokenHashValueArray, "." + this.AMDesignator, (TokenType) 1027, 0); this.InsertHash(tokenHashValueArray, "." + this.PMDesignator, (TokenType) 1284, 1); } this.InsertHash(tokenHashValueArray, "年", TokenType.SEP_YearSuff, 0); this.InsertHash(tokenHashValueArray, "년", TokenType.SEP_YearSuff, 0); this.InsertHash(tokenHashValueArray, "月", TokenType.SEP_MonthSuff, 0); this.InsertHash(tokenHashValueArray, "월", TokenType.SEP_MonthSuff, 0); this.InsertHash(tokenHashValueArray, "日", TokenType.SEP_DaySuff, 0); this.InsertHash(tokenHashValueArray, "일", TokenType.SEP_DaySuff, 0); this.InsertHash(tokenHashValueArray, "時", TokenType.SEP_HourSuff, 0); this.InsertHash(tokenHashValueArray, "时", TokenType.SEP_HourSuff, 0); this.InsertHash(tokenHashValueArray, "分", TokenType.SEP_MinuteSuff, 0); this.InsertHash(tokenHashValueArray, "秒", TokenType.SEP_SecondSuff, 0); if (flag1) { this.InsertHash(tokenHashValueArray, "시", TokenType.SEP_HourSuff, 0); this.InsertHash(tokenHashValueArray, "분", TokenType.SEP_MinuteSuff, 0); this.InsertHash(tokenHashValueArray, "초", TokenType.SEP_SecondSuff, 0); } if (this.LanguageName.Equals("ky")) this.InsertHash(tokenHashValueArray, "-", TokenType.IgnorableSymbol, 0); else this.InsertHash(tokenHashValueArray, "-", TokenType.SEP_DateOrOffset, 0); DateTimeFormatInfoScanner formatInfoScanner = new DateTimeFormatInfoScanner(); string[] dateWordsOfDtfi; this.m_dateWords = dateWordsOfDtfi = formatInfoScanner.GetDateWordsOfDTFI(this); int num = (int) this.FormatFlags; bool flag2 = false; if (dateWordsOfDtfi != null) { for (int index = 0; index < dateWordsOfDtfi.Length; ++index) { switch (dateWordsOfDtfi[index][0]) { case '\xE000': string monthPostfix = dateWordsOfDtfi[index].Substring(1); this.AddMonthNames(tokenHashValueArray, monthPostfix); break; case '\xE001': string str2 = dateWordsOfDtfi[index].Substring(1); this.InsertHash(tokenHashValueArray, str2, TokenType.IgnorableSymbol, 0); if (this.DateSeparator.Trim((char[]) null).Equals(str2)) { flag2 = true; break; } else break; default: this.InsertHash(tokenHashValueArray, dateWordsOfDtfi[index], TokenType.DateWordToken, 0); if (this.LanguageName.Equals("eu")) { this.InsertHash(tokenHashValueArray, "." + dateWordsOfDtfi[index], TokenType.DateWordToken, 0); break; } else break; } } } if (!flag2) this.InsertHash(tokenHashValueArray, this.DateSeparator, TokenType.SEP_Date, 0); this.AddMonthNames(tokenHashValueArray, (string) null); for (int index = 1; index <= 13; ++index) this.InsertHash(tokenHashValueArray, this.GetAbbreviatedMonthName(index), TokenType.MonthToken, index); if ((this.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != DateTimeFormatFlags.None) { for (int index = 1; index <= 13; ++index) { string monthName = this.internalGetMonthName(index, MonthNameStyles.Genitive, false); this.InsertHash(tokenHashValueArray, monthName, TokenType.MonthToken, index); } } if ((this.FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != DateTimeFormatFlags.None) { for (int index = 1; index <= 13; ++index) { string monthName = this.internalGetMonthName(index, MonthNameStyles.LeapYear, false); this.InsertHash(tokenHashValueArray, monthName, TokenType.MonthToken, index); } } for (int tokenValue = 0; tokenValue < 7; ++tokenValue) { string dayName = this.GetDayName((DayOfWeek) tokenValue); this.InsertHash(tokenHashValueArray, dayName, TokenType.DayOfWeekToken, tokenValue); string abbreviatedDayName = this.GetAbbreviatedDayName((DayOfWeek) tokenValue); this.InsertHash(tokenHashValueArray, abbreviatedDayName, TokenType.DayOfWeekToken, tokenValue); } int[] eras = this.calendar.Eras; for (int index = 1; index <= eras.Length; ++index) { this.InsertHash(tokenHashValueArray, this.GetEraName(index), TokenType.EraToken, index); this.InsertHash(tokenHashValueArray, this.GetAbbreviatedEraName(index), TokenType.EraToken, index); } if (this.LanguageName.Equals("ja")) { for (int tokenValue = 0; tokenValue < 7; ++tokenValue) { string str2 = "(" + this.GetAbbreviatedDayName((DayOfWeek) tokenValue) + ")"; this.InsertHash(tokenHashValueArray, str2, TokenType.DayOfWeekToken, tokenValue); } if (this.Calendar.GetType() != typeof (JapaneseCalendar)) { DateTimeFormatInfo japaneseCalendarDtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI(); for (int index = 1; index <= japaneseCalendarDtfi.Calendar.Eras.Length; ++index) { this.InsertHash(tokenHashValueArray, japaneseCalendarDtfi.GetEraName(index), TokenType.JapaneseEraToken, index); this.InsertHash(tokenHashValueArray, japaneseCalendarDtfi.GetAbbreviatedEraName(index), TokenType.JapaneseEraToken, index); this.InsertHash(tokenHashValueArray, japaneseCalendarDtfi.AbbreviatedEnglishEraNames[index - 1], TokenType.JapaneseEraToken, index); } } } else if (this.CultureName.Equals("zh-TW")) { DateTimeFormatInfo taiwanCalendarDtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI(); for (int index = 1; index <= taiwanCalendarDtfi.Calendar.Eras.Length; ++index) { if (taiwanCalendarDtfi.GetEraName(index).Length > 0) this.InsertHash(tokenHashValueArray, taiwanCalendarDtfi.GetEraName(index), TokenType.TEraToken, index); } } this.InsertHash(tokenHashValueArray, DateTimeFormatInfo.InvariantInfo.AMDesignator, (TokenType) 1027, 0); this.InsertHash(tokenHashValueArray, DateTimeFormatInfo.InvariantInfo.PMDesignator, (TokenType) 1284, 1); for (int index = 1; index <= 12; ++index) { string monthName = DateTimeFormatInfo.InvariantInfo.GetMonthName(index); this.InsertHash(tokenHashValueArray, monthName, TokenType.MonthToken, index); string abbreviatedMonthName = DateTimeFormatInfo.InvariantInfo.GetAbbreviatedMonthName(index); this.InsertHash(tokenHashValueArray, abbreviatedMonthName, TokenType.MonthToken, index); } for (int tokenValue = 0; tokenValue < 7; ++tokenValue) { string dayName = DateTimeFormatInfo.InvariantInfo.GetDayName((DayOfWeek) tokenValue); this.InsertHash(tokenHashValueArray, dayName, TokenType.DayOfWeekToken, tokenValue); string abbreviatedDayName = DateTimeFormatInfo.InvariantInfo.GetAbbreviatedDayName((DayOfWeek) tokenValue); this.InsertHash(tokenHashValueArray, abbreviatedDayName, TokenType.DayOfWeekToken, tokenValue); } for (int index = 0; index < this.AbbreviatedEnglishEraNames.Length; ++index) this.InsertHash(tokenHashValueArray, this.AbbreviatedEnglishEraNames[index], TokenType.EraToken, index + 1); this.InsertHash(tokenHashValueArray, "T", TokenType.SEP_LocalTimeMark, 0); this.InsertHash(tokenHashValueArray, "GMT", TokenType.TimeZoneToken, 0); this.InsertHash(tokenHashValueArray, "Z", TokenType.TimeZoneToken, 0); this.InsertHash(tokenHashValueArray, "/", TokenType.SEP_Date, 0); this.InsertHash(tokenHashValueArray, ":", TokenType.SEP_Time, 0); this.m_dtfiTokenHash = tokenHashValueArray; } return tokenHashValueArray; }
void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) { // The month of the 13th month is allowed to be null, so make sure that we ignore null value here. if (str == null || str.Length == 0) { return; } TokenHashValue value; int i = 0; // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by // DateTime.Parse(). if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) { str = str.Trim(null); // Trim white space characters. // Could have space for separators if (str.Length == 0) return; } char ch = Char.ToLower(str[0], this.Culture); int hashcode = ch % TOKEN_HASH_SIZE; int hashProbe = 1 + ch % SECOND_PRIME; do { value = hashTable[hashcode]; if (value == null) { //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode); hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); return; } else { // Collision happens. Find another slot. if (str.Length >= value.tokenString.Length) { // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of // the shorter ones. if (String.Compare(str, 0, value.tokenString, 0, value.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0) { if (str.Length > value.tokenString.Length) { // The str to be inserted has the same prefix as the current token, and str is longer. // Insert str into this node, and shift every node behind it. InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe); return; } else { // Same token. If they have different types (regular token vs separator token). Add them. // If we have the same regular token or separator token in the hash already, do NOT update the hash. // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash. // // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet. // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet. // int nTokenType = (int)tokenType; int nCurrentTokenTypeInHash = (int)value.tokenType; // The idea behind this check is: // - if the app is targetting 4.5.1 or above OR the compat flag is set, use the correct behavior by default. // - if the app is targetting 4.5 or below AND the compat switch is set, use the correct behavior // - if the app is targetting 4.5 or below AND the compat switch is NOT set, use the incorrect behavior if (preferExistingTokens || BinaryCompatibility.TargetsAtLeast_Desktop_V4_5_1) { if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) || ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) { value.tokenType |= tokenType; if (tokenValue != 0) { value.tokenValue = tokenValue; } } } else { // The following logic is incorrect and causes updates to happen depending on the bitwise relationship between the existing token type and the // the stored token type. It was this way in .NET 4 RTM. The behavior above is correct and will be adopted going forward. if ((((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.RegularTokenMask) == nTokenType) || (((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.SeparatorTokenMask) == nTokenType)) { value.tokenType |= tokenType; if (tokenValue != 0) { value.tokenValue = tokenValue; } } } // The token to be inserted is already in the table. Skip it. } } } } //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str); i++; hashcode += hashProbe; if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; } while (i < TOKEN_HASH_SIZE); Contract.Assert(true, "The hashtable is full. This should not happen."); }
internal TokenHashValue[] CreateTokenHashTable() { TokenHashValue[] temp = m_dtfiTokenHash; if (temp == null) { temp = new TokenHashValue[TOKEN_HASH_SIZE]; InsertHash(temp, ",", TokenType.IgnorableSymbol, 0); InsertHash(temp, ".", TokenType.IgnorableSymbol, 0); InsertHash(temp, this.TimeSeparator, TokenType.SEP_Time, 0); InsertHash(temp, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); if (CultureName.Equals("sq-AL")) { // Algerian allows time formats like "12:00.PD" InsertHash(temp, "." + this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, "." + this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); } // CJK suffix InsertHash(temp, CJKYearSuff, TokenType.SEP_YearSuff, 0); InsertHash(temp, KoreanYearSuff, TokenType.SEP_YearSuff, 0); InsertHash(temp, CJKMonthSuff, TokenType.SEP_MonthSuff, 0); InsertHash(temp, KoreanMonthSuff, TokenType.SEP_MonthSuff, 0); InsertHash(temp, CJKDaySuff, TokenType.SEP_DaySuff, 0); InsertHash(temp, KoreanDaySuff, TokenType.SEP_DaySuff, 0); InsertHash(temp, CJKHourSuff, TokenType.SEP_HourSuff, 0); InsertHash(temp, ChineseHourSuff, TokenType.SEP_HourSuff, 0); InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0); InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0); if (LanguageName.Equals(KoreanLangName)) { // Korean suffix InsertHash(temp, KoreanHourSuff, TokenType.SEP_HourSuff, 0); InsertHash(temp, KoreanMinuteSuff, TokenType.SEP_MinuteSuff, 0); InsertHash(temp, KoreanSecondSuff, TokenType.SEP_SecondSuff, 0); } String[] dateWords = null; DateTimeFormatInfoScanner scanner = null; // Get the all of the long date pattern. The getter will check if the default LongDatePattern // is in the standard list or not. If not, m_scanDateWords will be true, and we will // need to scan the date words. // Note that dateWords is used as a temp buffer here. It will be reset as the real date words later. if (!m_scanDateWords) { dateWords = ClonedAllLongDatePatterns; } if (m_scanDateWords || m_cultureTableRecord.IsSynthetic) { scanner = new DateTimeFormatInfoScanner(); // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix. m_dateWords = dateWords = scanner.GetDateWordsOfDTFI(this); // Ensure the formatflags is initialized. DateTimeFormatFlags flag = FormatFlags; m_scanDateWords = false; } else { // Use the table value. dateWords = this.DateWords;; } // For some cultures, the date separator works more like a comma, being allowed before or after any date part. // In this cultures, we do not use normal date separator since we disallow date separator after a date terminal state. // This is determinted in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol. bool useDateSepAsIgnorableSymbol = false; String monthPostfix = null; if (dateWords != null) { // There are DateWords. It could be a real date word (such as "de"), or a monthPostfix. // The monthPostfix starts with '\xfffe' (MonthPostfixChar), followed by the real monthPostfix. for (int i = 0; i < dateWords.Length; i++) { switch (dateWords[i][0]) { // This is a month postfix case DateTimeFormatInfoScanner.MonthPostfixChar: // Get the real month postfix. monthPostfix = dateWords[i].Substring(1); // Add the month name + postfix into the token. AddMonthNames(temp, monthPostfix); break; case DateTimeFormatInfoScanner.IgnorableSymbolChar: String symbol = dateWords[i].Substring(1); InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0); if (this.DateSeparator.Trim(null).Equals(symbol)) { // The date separator is the same as the ingorable symbol. useDateSepAsIgnorableSymbol = true; } break; default: InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0); if (CultureName.Equals("eu-ES")) { // Basque has date words with leading dots InsertHash(temp, "." + dateWords[i], TokenType.DateWordToken, 0); } break; } } } if (!useDateSepAsIgnorableSymbol) { // Use the normal date separator. InsertHash(temp, this.DateSeparator, TokenType.SEP_Date, 0); } // Add the regular month names. AddMonthNames(temp, null); // Add the abbreviated month names. for (int i = 1; i <= 13; i++) { InsertHash(temp, GetAbbreviatedMonthName(i), TokenType.MonthToken, i); } if (CultureName.Equals("gl-ES")) { // // Special case for gl-ES. It has a potential incorrect format in year/month: MMMM'de 'yyyy. // It probably has to be MMMM' de 'yyyy. // // We keep this so that we can still parse dates formatted in the older version. for (int i = 1; i <= 13; i++) { String str; //str = internalGetMonthName(i, MonthNameStyles.Regular, false); // We have to call public methods here to work with inherited DTFI. // Insert the month name first, so that they are at the front of abbrevaited // month names. str = GetMonthName(i); if (str.Length > 0) { // Insert the month name with the postfix first, so it can be matched first. InsertHash(temp, str + "de", TokenType.MonthToken, i); } } } if ((FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0) { for (int i = 1; i <= 13; i++) { String str; str = internalGetMonthName(i, MonthNameStyles.Genitive, false); InsertHash(temp, str, TokenType.MonthToken, i); } } if ((FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0) { for (int i = 1; i <= 13; i++) { String str; str = internalGetMonthName(i, MonthNameStyles.LeapYear, false); InsertHash(temp, str, TokenType.MonthToken, i); } } for (int i = 0; i < 7; i++) { //String str = GetDayOfWeekNames()[i]; // We have to call public methods here to work with inherited DTFI. String str = GetDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); str = GetAbbreviatedDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); } int[] eras = calendar.Eras; for (int i = 1; i <= eras.Length; i++) { InsertHash(temp, GetEraName(i), TokenType.EraToken, i); InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i); } if (LanguageName.Equals(JapaneseLangName)) { // Japanese allows day of week forms like: "(Tue)" for (int i = 0; i < 7; i++) { String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")"; InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i); } if (this.Calendar.GetType() != typeof(JapaneseCalendar)) { // Special case for Japanese. If this is a Japanese DTFI, and the calendar is not Japanese calendar, // we will check Japanese Era name as well when the calendar is Gregorian. DateTimeFormatInfo jaDtfi = GetJapaneseCalendarDTFI(); for (int i = 1; i <= jaDtfi.Calendar.Eras.Length; i++) { InsertHash(temp, jaDtfi.GetEraName(i), TokenType.JapaneseEraToken, i); InsertHash(temp, jaDtfi.GetAbbreviatedEraName(i), TokenType.JapaneseEraToken, i); // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1. InsertHash(temp, jaDtfi.AbbreviatedEnglishEraNames[i-1], TokenType.JapaneseEraToken, i); } } } else if (CultureName.Equals("zh-TW")) { DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI(); for (int i = 1; i <= twDtfi.Calendar.Eras.Length; i++) { if (twDtfi.GetEraName(i).Length > 0) { InsertHash(temp, twDtfi.GetEraName(i), TokenType.TEraToken, i); } } } InsertHash(temp, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0); InsertHash(temp, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1); // Add invariant month names and day names. for (int i = 1; i <= 12; i++) { String str; // We have to call public methods here to work with inherited DTFI. // Insert the month name first, so that they are at the front of abbrevaited // month names. str = InvariantInfo.GetMonthName(i); InsertHash(temp, str, TokenType.MonthToken, i); str = InvariantInfo.GetAbbreviatedMonthName(i); InsertHash(temp, str, TokenType.MonthToken, i); } for (int i = 0; i < 7; i++) { // We have to call public methods here to work with inherited DTFI. String str = InvariantInfo.GetDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i); InsertHash(temp, str, TokenType.DayOfWeekToken, i); } for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++) { // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1. InsertHash(temp, AbbreviatedEnglishEraNames[i], TokenType.EraToken, i + 1); } InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0); InsertHash(temp, DateTimeParse.GMTName, TokenType.TimeZoneToken, 0); InsertHash(temp, DateTimeParse.ZuluName, TokenType.TimeZoneToken, 0); InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0); InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0); if (CultureName.Equals("ky-KG")) { // For some cultures, the date separator works more like a comma, being allowed before or after any date part InsertHash(temp, alternativeDateSeparator, TokenType.IgnorableSymbol, 0); } else { InsertHash(temp, alternativeDateSeparator, TokenType.SEP_Date, 0); } m_dtfiTokenHash = temp; } return (temp); }