| @ -0,0 +1,629 @@ | |||||
| // Copyright (C) 2011 The Libphonenumber Authors | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| #include "phonenumbers/asyoutypeformatter.h" | |||||
| #include <cctype> | |||||
| #include <list> | |||||
| #include <string> | |||||
| #include <google/protobuf/message_lite.h> | |||||
| #include "base/logging.h" | |||||
| #include "base/memory/scoped_ptr.h" | |||||
| #include "phonenumbers/phonemetadata.pb.h" | |||||
| #include "phonenumbers/phonenumberutil.h" | |||||
| #include "phonenumbers/regexp_cache.h" | |||||
| #include "phonenumbers/regexp_factory.h" | |||||
| #include "phonenumbers/stringutil.h" | |||||
| #include "phonenumbers/unicodestring.h" | |||||
| namespace i18n { | |||||
| namespace phonenumbers { | |||||
| using google::protobuf::RepeatedPtrField; | |||||
| namespace { | |||||
| const char kPlusSign = '+'; | |||||
| // A pattern that is used to match character classes in regular expressions. | |||||
| // An example of a character class is [1-4]. | |||||
| const char kCharacterClassPattern[] = "\\[([^\\[\\]])*\\]"; | |||||
| // This is the minimum length of national number accrued that is required to | |||||
| // trigger the formatter. The first element of the leading_digits_pattern of | |||||
| // each number_format contains a regular expression that matches up to this | |||||
| // number of digits. | |||||
| const size_t kMinLeadingDigitsLength = 3; | |||||
| // The digits that have not been entered yet will be represented by a \u2008, | |||||
| // the punctuation space. | |||||
| const char kDigitPlaceholder[] = "\xE2\x80\x88"; /* " " */ | |||||
| // Replaces any standalone digit in the pattern (not any inside a {} grouping) | |||||
| // with \d. This function replaces the standalone digit regex used in the Java | |||||
| // version which is currently not supported by RE2 because it uses a special | |||||
| // construct (?=). | |||||
| void ReplacePatternDigits(string* pattern) { | |||||
| DCHECK(pattern); | |||||
| string new_pattern; | |||||
| for (string::const_iterator it = pattern->begin(); it != pattern->end(); | |||||
| ++it) { | |||||
| const char current_char = *it; | |||||
| if (isdigit(current_char)) { | |||||
| if (it + 1 != pattern->end()) { | |||||
| const char next_char = it[1]; | |||||
| if (next_char != ',' && next_char != '}') { | |||||
| new_pattern += "\\d"; | |||||
| } else { | |||||
| new_pattern += current_char; | |||||
| } | |||||
| } else { | |||||
| new_pattern += "\\d"; | |||||
| } | |||||
| } else { | |||||
| new_pattern += current_char; | |||||
| } | |||||
| } | |||||
| pattern->assign(new_pattern); | |||||
| } | |||||
| // Matches all the groups contained in 'input' against 'pattern'. | |||||
| void MatchAllGroups(const string& pattern, | |||||
| const string& input, | |||||
| const AbstractRegExpFactory& regexp_factory, | |||||
| RegExpCache* cache, | |||||
| string* group) { | |||||
| DCHECK(cache); | |||||
| DCHECK(group); | |||||
| string new_pattern(pattern); | |||||
| // Transforms pattern "(...)(...)(...)" to "(.........)". | |||||
| strrmm(&new_pattern, "()"); | |||||
| new_pattern = StrCat("(", new_pattern, ")"); | |||||
| const scoped_ptr<RegExpInput> consume_input( | |||||
| regexp_factory.CreateInput(input)); | |||||
| bool status = | |||||
| cache->GetRegExp(new_pattern).Consume(consume_input.get(), group); | |||||
| DCHECK(status); | |||||
| } | |||||
| PhoneMetadata CreateEmptyMetadata() { | |||||
| PhoneMetadata metadata; | |||||
| metadata.set_international_prefix("NA"); | |||||
| return metadata; | |||||
| } | |||||
| } // namespace | |||||
| AsYouTypeFormatter::AsYouTypeFormatter(const string& region_code) | |||||
| : regexp_factory_(new RegExpFactory()), | |||||
| regexp_cache_(*regexp_factory_.get(), 64), | |||||
| current_output_(), | |||||
| formatting_template_(), | |||||
| current_formatting_pattern_(), | |||||
| accrued_input_(), | |||||
| accrued_input_without_formatting_(), | |||||
| able_to_format_(true), | |||||
| is_international_formatting_(false), | |||||
| is_expecting_country_code_(false), | |||||
| phone_util_(*PhoneNumberUtil::GetInstance()), | |||||
| default_country_(region_code), | |||||
| empty_metadata_(CreateEmptyMetadata()), | |||||
| default_metadata_(GetMetadataForRegion(region_code)), | |||||
| current_metadata_(default_metadata_), | |||||
| last_match_position_(0), | |||||
| original_position_(0), | |||||
| position_to_remember_(0), | |||||
| prefix_before_national_number_(), | |||||
| national_number_(), | |||||
| possible_formats_() { | |||||
| } | |||||
| // The metadata needed by this class is the same for all regions sharing the | |||||
| // same country calling code. Therefore, we return the metadata for "main" | |||||
| // region for this country calling code. | |||||
| const PhoneMetadata* AsYouTypeFormatter::GetMetadataForRegion( | |||||
| const string& region_code) const { | |||||
| int country_calling_code = phone_util_.GetCountryCodeForRegion(region_code); | |||||
| string main_country; | |||||
| phone_util_.GetRegionCodeForCountryCode(country_calling_code, &main_country); | |||||
| const PhoneMetadata* const metadata = | |||||
| phone_util_.GetMetadataForRegion(main_country); | |||||
| if (metadata) { | |||||
| return metadata; | |||||
| } | |||||
| // Set to a default instance of the metadata. This allows us to function with | |||||
| // an incorrect region code, even if formatting only works for numbers | |||||
| // specified with "+". | |||||
| return &empty_metadata_; | |||||
| } | |||||
| bool AsYouTypeFormatter::MaybeCreateNewTemplate() { | |||||
| // When there are multiple available formats, the formatter uses the first | |||||
| // format where a formatting template could be created. | |||||
| for (list<const NumberFormat*>::const_iterator it = possible_formats_.begin(); | |||||
| it != possible_formats_.end(); ++it) { | |||||
| DCHECK(*it); | |||||
| const NumberFormat& number_format = **it; | |||||
| const string& pattern = number_format.pattern(); | |||||
| if (current_formatting_pattern_ == pattern) { | |||||
| return false; | |||||
| } | |||||
| if (CreateFormattingTemplate(number_format)) { | |||||
| current_formatting_pattern_ = pattern; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| able_to_format_ = false; | |||||
| return false; | |||||
| } | |||||
| void AsYouTypeFormatter::GetAvailableFormats( | |||||
| const string& leading_three_digits) { | |||||
| const RepeatedPtrField<NumberFormat>& format_list = | |||||
| (is_international_formatting_ && | |||||
| current_metadata_->intl_number_format().size() > 0) | |||||
| ? current_metadata_->intl_number_format() | |||||
| : current_metadata_->number_format(); | |||||
| for (RepeatedPtrField<NumberFormat>::const_iterator it = format_list.begin(); | |||||
| it != format_list.end(); ++it) { | |||||
| if (phone_util_.IsFormatEligibleForAsYouTypeFormatter(it->format())) { | |||||
| possible_formats_.push_back(&*it); | |||||
| } | |||||
| } | |||||
| NarrowDownPossibleFormats(leading_three_digits); | |||||
| } | |||||
| void AsYouTypeFormatter::NarrowDownPossibleFormats( | |||||
| const string& leading_digits) { | |||||
| const int index_of_leading_digits_pattern = | |||||
| leading_digits.length() - kMinLeadingDigitsLength; | |||||
| for (list<const NumberFormat*>::iterator it = possible_formats_.begin(); | |||||
| it != possible_formats_.end(); ) { | |||||
| DCHECK(*it); | |||||
| const NumberFormat& format = **it; | |||||
| if (format.leading_digits_pattern_size() > | |||||
| index_of_leading_digits_pattern) { | |||||
| const scoped_ptr<RegExpInput> input( | |||||
| regexp_factory_->CreateInput(leading_digits)); | |||||
| if (!regexp_cache_.GetRegExp(format.leading_digits_pattern().Get( | |||||
| index_of_leading_digits_pattern)).Consume(input.get())) { | |||||
| it = possible_formats_.erase(it); | |||||
| continue; | |||||
| } | |||||
| } // else the particular format has no more specific leadingDigitsPattern, | |||||
| // and it should be retained. | |||||
| ++it; | |||||
| } | |||||
| } | |||||
| bool AsYouTypeFormatter::CreateFormattingTemplate(const NumberFormat& format) { | |||||
| string number_pattern = format.pattern(); | |||||
| // The formatter doesn't format numbers when numberPattern contains "|", e.g. | |||||
| // (20|3)\d{4}. In those cases we quickly return. | |||||
| if (number_pattern.find('|') != string::npos) { | |||||
| return false; | |||||
| } | |||||
| // Replace anything in the form of [..] with \d. | |||||
| static const scoped_ptr<const RegExp> character_class_pattern( | |||||
| regexp_factory_->CreateRegExp(kCharacterClassPattern)); | |||||
| character_class_pattern->GlobalReplace(&number_pattern, "\\\\d"); | |||||
| // Replace any standalone digit (not the one in d{}) with \d. | |||||
| ReplacePatternDigits(&number_pattern); | |||||
| string number_format = format.format(); | |||||
| formatting_template_.remove(); | |||||
| UnicodeString temp_template; | |||||
| GetFormattingTemplate(number_pattern, number_format, &temp_template); | |||||
| if (temp_template.length() > 0) { | |||||
| formatting_template_.append(temp_template); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| void AsYouTypeFormatter::GetFormattingTemplate( | |||||
| const string& number_pattern, | |||||
| const string& number_format, | |||||
| UnicodeString* formatting_template) { | |||||
| DCHECK(formatting_template); | |||||
| // Creates a phone number consisting only of the digit 9 that matches the | |||||
| // number_pattern by applying the pattern to the longest_phone_number string. | |||||
| static const char longest_phone_number[] = "999999999999999"; | |||||
| string a_phone_number; | |||||
| MatchAllGroups(number_pattern, longest_phone_number, *regexp_factory_, | |||||
| ®exp_cache_, &a_phone_number); | |||||
| // No formatting template can be created if the number of digits entered so | |||||
| // far is longer than the maximum the current formatting rule can accommodate. | |||||
| if (a_phone_number.length() < national_number_.length()) { | |||||
| formatting_template->remove(); | |||||
| return; | |||||
| } | |||||
| // Formats the number according to number_format. | |||||
| regexp_cache_.GetRegExp(number_pattern).GlobalReplace( | |||||
| &a_phone_number, number_format); | |||||
| // Replaces each digit with character kDigitPlaceholder. | |||||
| GlobalReplaceSubstring("9", kDigitPlaceholder, &a_phone_number); | |||||
| formatting_template->setTo(a_phone_number.c_str(), a_phone_number.size()); | |||||
| } | |||||
| void AsYouTypeFormatter::Clear() { | |||||
| current_output_.clear(); | |||||
| accrued_input_.remove(); | |||||
| accrued_input_without_formatting_.remove(); | |||||
| formatting_template_.remove(); | |||||
| last_match_position_ = 0; | |||||
| current_formatting_pattern_.clear(); | |||||
| prefix_before_national_number_.clear(); | |||||
| national_number_.clear(); | |||||
| able_to_format_ = true; | |||||
| position_to_remember_ = 0; | |||||
| original_position_ = 0; | |||||
| is_international_formatting_ = false; | |||||
| is_expecting_country_code_ = false; | |||||
| possible_formats_.clear(); | |||||
| if (current_metadata_ != default_metadata_) { | |||||
| current_metadata_ = GetMetadataForRegion(default_country_); | |||||
| } | |||||
| } | |||||
| const string& AsYouTypeFormatter::InputDigit(char32 next_char, string* result) { | |||||
| DCHECK(result); | |||||
| InputDigitWithOptionToRememberPosition(next_char, false, ¤t_output_); | |||||
| result->assign(current_output_); | |||||
| return *result; | |||||
| } | |||||
| const string& AsYouTypeFormatter::InputDigitAndRememberPosition( | |||||
| char32 next_char, | |||||
| string* result) { | |||||
| DCHECK(result); | |||||
| InputDigitWithOptionToRememberPosition(next_char, true, ¤t_output_); | |||||
| result->assign(current_output_); | |||||
| return *result; | |||||
| } | |||||
| void AsYouTypeFormatter::InputDigitWithOptionToRememberPosition( | |||||
| char32 next_char, | |||||
| bool remember_position, | |||||
| string* phone_number) { | |||||
| DCHECK(phone_number); | |||||
| accrued_input_.append(next_char); | |||||
| if (remember_position) { | |||||
| original_position_ = accrued_input_.length(); | |||||
| } | |||||
| // We do formatting on-the-fly only when each character entered is either a | |||||
| // plus sign or a digit. | |||||
| string next_char_string; | |||||
| UnicodeString(next_char).toUTF8String(next_char_string); | |||||
| if (next_char != kPlusSign && | |||||
| !phone_util_.ContainsOnlyValidDigits(next_char_string)) { | |||||
| able_to_format_ = false; | |||||
| } | |||||
| if (!able_to_format_) { | |||||
| phone_number->clear(); | |||||
| accrued_input_.toUTF8String(*phone_number); | |||||
| return; | |||||
| } | |||||
| char normalized_next_char = | |||||
| NormalizeAndAccrueDigitsAndPlusSign(next_char, remember_position); | |||||
| // We start to attempt to format only when at least kMinLeadingDigitsLength | |||||
| // digits (the plus sign is counted as a digit as well for this purpose) have | |||||
| // been entered. | |||||
| switch (accrued_input_without_formatting_.length()) { | |||||
| case 0: | |||||
| case 1: | |||||
| case 2: | |||||
| phone_number->clear(); | |||||
| accrued_input_.toUTF8String(*phone_number); | |||||
| return; | |||||
| case 3: | |||||
| if (AttemptToExtractIdd()) { | |||||
| is_expecting_country_code_ = true; | |||||
| } else { | |||||
| // No IDD or plus sign is found, must be entering in national format. | |||||
| RemoveNationalPrefixFromNationalNumber(); | |||||
| AttemptToChooseFormattingPattern(phone_number); | |||||
| return; | |||||
| } | |||||
| case 4: | |||||
| case 5: | |||||
| if (is_expecting_country_code_) { | |||||
| if (AttemptToExtractCountryCode()) { | |||||
| is_expecting_country_code_ = false; | |||||
| } | |||||
| phone_number->assign(prefix_before_national_number_); | |||||
| phone_number->append(national_number_); | |||||
| return; | |||||
| } | |||||
| // We make a last attempt to extract a country code at the 6th digit because | |||||
| // the maximum length of IDD and country code are both 3. | |||||
| case 6: | |||||
| if (is_expecting_country_code_ && !AttemptToExtractCountryCode()) { | |||||
| able_to_format_ = false; | |||||
| phone_number->clear(); | |||||
| accrued_input_.toUTF8String(*phone_number); | |||||
| return; | |||||
| } | |||||
| default: | |||||
| if (possible_formats_.size() > 0) { | |||||
| // The formatting pattern is already chosen. | |||||
| string temp_national_number; | |||||
| InputDigitHelper(normalized_next_char, &temp_national_number); | |||||
| // See if accrued digits can be formatted properly already. If not, use | |||||
| // the results from InputDigitHelper, which does formatting based on the | |||||
| // formatting pattern chosen. | |||||
| string formatted_number; | |||||
| AttemptToFormatAccruedDigits(&formatted_number); | |||||
| if (formatted_number.length() > 0) { | |||||
| phone_number->assign(formatted_number); | |||||
| return; | |||||
| } | |||||
| NarrowDownPossibleFormats(national_number_); | |||||
| if (MaybeCreateNewTemplate()) { | |||||
| InputAccruedNationalNumber(phone_number); | |||||
| return; | |||||
| } | |||||
| phone_number->assign(able_to_format_ | |||||
| ? prefix_before_national_number_ + temp_national_number | |||||
| : temp_national_number); | |||||
| } else { | |||||
| AttemptToChooseFormattingPattern(phone_number); | |||||
| } | |||||
| } | |||||
| } | |||||
| void AsYouTypeFormatter::AttemptToFormatAccruedDigits( | |||||
| string* formatted_number) { | |||||
| DCHECK(formatted_number); | |||||
| for (list<const NumberFormat*>::const_iterator it = possible_formats_.begin(); | |||||
| it != possible_formats_.end(); ++it) { | |||||
| DCHECK(*it); | |||||
| const NumberFormat& num_format = **it; | |||||
| string pattern = num_format.pattern(); | |||||
| if (regexp_cache_.GetRegExp(pattern).FullMatch(national_number_)) { | |||||
| formatted_number->assign(national_number_); | |||||
| string new_formatted_number(*formatted_number); | |||||
| string format = num_format.format(); | |||||
| bool status = regexp_cache_.GetRegExp(pattern).GlobalReplace( | |||||
| &new_formatted_number, format); | |||||
| DCHECK(status); | |||||
| formatted_number->assign(prefix_before_national_number_); | |||||
| formatted_number->append(new_formatted_number); | |||||
| return; | |||||
| } | |||||
| } | |||||
| formatted_number->clear(); | |||||
| } | |||||
| int AsYouTypeFormatter::GetRememberedPosition() const { | |||||
| UnicodeString current_output(current_output_.c_str()); | |||||
| if (!able_to_format_) { | |||||
| return ConvertUnicodeStringPosition(current_output, original_position_); | |||||
| } | |||||
| int accrued_input_index = 0; | |||||
| int current_output_index = 0; | |||||
| while (accrued_input_index < position_to_remember_ && | |||||
| current_output_index < current_output.length()) { | |||||
| if (accrued_input_without_formatting_[accrued_input_index] == | |||||
| current_output[current_output_index]) { | |||||
| ++accrued_input_index; | |||||
| } | |||||
| ++current_output_index; | |||||
| } | |||||
| return ConvertUnicodeStringPosition(current_output, current_output_index); | |||||
| } | |||||
| void AsYouTypeFormatter::AttemptToChooseFormattingPattern( | |||||
| string* formatted_number) { | |||||
| DCHECK(formatted_number); | |||||
| if (national_number_.length() >= kMinLeadingDigitsLength) { | |||||
| const string leading_digits = | |||||
| national_number_.substr(0, kMinLeadingDigitsLength); | |||||
| GetAvailableFormats(leading_digits); | |||||
| MaybeCreateNewTemplate(); | |||||
| InputAccruedNationalNumber(formatted_number); | |||||
| } else { | |||||
| formatted_number->assign(prefix_before_national_number_ + national_number_); | |||||
| } | |||||
| } | |||||
| void AsYouTypeFormatter::InputAccruedNationalNumber(string* number) { | |||||
| DCHECK(number); | |||||
| int length_of_national_number = national_number_.length(); | |||||
| if (length_of_national_number > 0) { | |||||
| string temp_national_number; | |||||
| for (int i = 0; i < length_of_national_number; ++i) { | |||||
| temp_national_number.clear(); | |||||
| InputDigitHelper(national_number_[i], &temp_national_number); | |||||
| } | |||||
| number->assign(able_to_format_ | |||||
| ? prefix_before_national_number_ + temp_national_number | |||||
| : temp_national_number); | |||||
| } else { | |||||
| number->assign(prefix_before_national_number_); | |||||
| } | |||||
| } | |||||
| void AsYouTypeFormatter::RemoveNationalPrefixFromNationalNumber() { | |||||
| int start_of_national_number = 0; | |||||
| if (current_metadata_->country_code() == 1 && national_number_[0] == '1') { | |||||
| start_of_national_number = 1; | |||||
| prefix_before_national_number_.append("1 "); | |||||
| is_international_formatting_ = true; | |||||
| } else if (current_metadata_->has_national_prefix()) { | |||||
| const scoped_ptr<RegExpInput> consumed_input( | |||||
| regexp_factory_->CreateInput(national_number_)); | |||||
| const RegExp& pattern = regexp_cache_.GetRegExp( | |||||
| current_metadata_->national_prefix_for_parsing()); | |||||
| if (pattern.Consume(consumed_input.get())) { | |||||
| // When the national prefix is detected, we use international formatting | |||||
| // rules instead of national ones, because national formatting rules could | |||||
| // countain local formatting rules for numbers entered without area code. | |||||
| is_international_formatting_ = true; | |||||
| start_of_national_number = | |||||
| national_number_.length() - consumed_input->ToString().length(); | |||||
| prefix_before_national_number_.append( | |||||
| national_number_.substr(0, start_of_national_number)); | |||||
| } | |||||
| } | |||||
| national_number_.erase(0, start_of_national_number); | |||||
| } | |||||
| bool AsYouTypeFormatter::AttemptToExtractIdd() { | |||||
| string accrued_input_without_formatting_stdstring; | |||||
| accrued_input_without_formatting_ | |||||
| .toUTF8String(accrued_input_without_formatting_stdstring); | |||||
| const scoped_ptr<RegExpInput> consumed_input( | |||||
| regexp_factory_->CreateInput(accrued_input_without_formatting_stdstring)); | |||||
| const RegExp& international_prefix = regexp_cache_.GetRegExp( | |||||
| StrCat("\\", string(&kPlusSign, 1), "|", | |||||
| current_metadata_->international_prefix())); | |||||
| if (international_prefix.Consume(consumed_input.get())) { | |||||
| is_international_formatting_ = true; | |||||
| const int start_of_country_code = | |||||
| accrued_input_without_formatting_.length() - | |||||
| consumed_input->ToString().length(); | |||||
| national_number_.clear(); | |||||
| accrued_input_without_formatting_.tempSubString(start_of_country_code) | |||||
| .toUTF8String(national_number_); | |||||
| string before_country_code; | |||||
| accrued_input_without_formatting_.tempSubString(0, start_of_country_code) | |||||
| .toUTF8String(before_country_code); | |||||
| prefix_before_national_number_.append(before_country_code); | |||||
| if (accrued_input_without_formatting_[0] != kPlusSign) { | |||||
| prefix_before_national_number_.append(" "); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool AsYouTypeFormatter::AttemptToExtractCountryCode() { | |||||
| if (national_number_.length() == 0) { | |||||
| return false; | |||||
| } | |||||
| string number_without_country_code(national_number_); | |||||
| int country_code = | |||||
| phone_util_.ExtractCountryCode(&number_without_country_code); | |||||
| if (country_code == 0) { | |||||
| return false; | |||||
| } | |||||
| national_number_.assign(number_without_country_code); | |||||
| string new_region_code; | |||||
| phone_util_.GetRegionCodeForCountryCode(country_code, &new_region_code); | |||||
| if (new_region_code != default_country_) { | |||||
| current_metadata_ = GetMetadataForRegion(new_region_code); | |||||
| } | |||||
| StrAppend(&prefix_before_national_number_, country_code, " "); | |||||
| return true; | |||||
| } | |||||
| char AsYouTypeFormatter::NormalizeAndAccrueDigitsAndPlusSign( | |||||
| char32 next_char, | |||||
| bool remember_position) { | |||||
| char normalized_char = next_char; | |||||
| if (next_char == kPlusSign) { | |||||
| accrued_input_without_formatting_.append(next_char); | |||||
| } else { | |||||
| string number; | |||||
| UnicodeString(next_char).toUTF8String(number); | |||||
| phone_util_.NormalizeDigitsOnly(&number); | |||||
| accrued_input_without_formatting_.append(next_char); | |||||
| national_number_.append(number); | |||||
| normalized_char = number[0]; | |||||
| } | |||||
| if (remember_position) { | |||||
| position_to_remember_ = accrued_input_without_formatting_.length(); | |||||
| } | |||||
| return normalized_char; | |||||
| } | |||||
| void AsYouTypeFormatter::InputDigitHelper(char next_char, string* number) { | |||||
| DCHECK(number); | |||||
| number->clear(); | |||||
| const char32 placeholder_codepoint = UnicodeString(kDigitPlaceholder)[0]; | |||||
| int placeholder_pos = formatting_template_ | |||||
| .tempSubString(last_match_position_).indexOf(placeholder_codepoint); | |||||
| if (placeholder_pos != -1) { | |||||
| UnicodeString temp_template = formatting_template_; | |||||
| placeholder_pos = temp_template.indexOf(placeholder_codepoint); | |||||
| temp_template.setCharAt(placeholder_pos, UnicodeString(next_char)[0]); | |||||
| last_match_position_ = placeholder_pos; | |||||
| formatting_template_.replace(0, temp_template.length(), temp_template); | |||||
| formatting_template_.tempSubString(0, last_match_position_ + 1) | |||||
| .toUTF8String(*number); | |||||
| } else { | |||||
| if (possible_formats_.size() == 1) { | |||||
| // More digits are entered than we could handle, and there are no other | |||||
| // valid patterns to try. | |||||
| able_to_format_ = false; | |||||
| } // else, we just reset the formatting pattern. | |||||
| current_formatting_pattern_.clear(); | |||||
| accrued_input_.toUTF8String(*number); | |||||
| } | |||||
| } | |||||
| // Returns the number of bytes contained in the given UnicodeString up to the | |||||
| // specified position. | |||||
| // static | |||||
| int AsYouTypeFormatter::ConvertUnicodeStringPosition(const UnicodeString& s, | |||||
| int pos) { | |||||
| if (pos > s.length()) { | |||||
| return -1; | |||||
| } | |||||
| string substring; | |||||
| s.tempSubString(0, pos).toUTF8String(substring); | |||||
| return substring.length(); | |||||
| } | |||||
| } // namespace phonenumbers | |||||
| } // namespace i18n | |||||
| @ -0,0 +1,197 @@ | |||||
| // Copyright (C) 2011 The Libphonenumber Authors | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| // A formatter which formats phone numbers as they are entered. | |||||
| // | |||||
| // An AsYouTypeFormatter can be created by invoking the GetAsYouTypeFormatter | |||||
| // method of the PhoneNumberUtil. After that digits can be added by invoking the | |||||
| // InputDigit method on the formatter instance, and the partially formatted | |||||
| // phone number will be returned each time a digit is added. The Clear method | |||||
| // can be invoked before a new number needs to be formatted. | |||||
| // | |||||
| // See AYTF_US, AYTF_GBFixedLine and AYTF_DE test functions in | |||||
| // asyoutypeformatter_test.cc for more details on how the formatter is to be | |||||
| // used. | |||||
| // | |||||
| // This is a direct port from AsYouTypeFormatter.java. Changes to this class | |||||
| // should also happen to the Java version, whenever it makes sense. | |||||
| // | |||||
| // This class is NOT THREAD SAFE. | |||||
| #ifndef I18N_PHONENUMBERS_ASYOUTYPEFORMATTER_H_ | |||||
| #define I18N_PHONENUMBERS_ASYOUTYPEFORMATTER_H_ | |||||
| #include <list> | |||||
| #include <string> | |||||
| #include "base/basictypes.h" | |||||
| #include "base/memory/scoped_ptr.h" | |||||
| #include "phonenumbers/regexp_adapter.h" | |||||
| #include "phonenumbers/regexp_cache.h" | |||||
| #include "phonenumbers/phonemetadata.pb.h" | |||||
| #include "phonenumbers/unicodestring.h" | |||||
| namespace i18n { | |||||
| namespace phonenumbers { | |||||
| using std::list; | |||||
| using std::string; | |||||
| class PhoneNumberUtil; | |||||
| class AsYouTypeFormatter { | |||||
| public: | |||||
| ~AsYouTypeFormatter() {} | |||||
| // Formats a phone number on-the-fly as each digit is entered. | |||||
| // next_char is the most recently entered digit of a phone number. Formatting | |||||
| // characters are allowed, but as soon as they are encountered this method | |||||
| // formats the number as entered and not "as you type" anymore. Full width | |||||
| // digits and Arabic-indic digits are allowed, and will be shown as they are. | |||||
| // Returns the partially formatted phone number (which is a reference to the | |||||
| // given string parameter for convenience). | |||||
| const string& InputDigit(char32 next_char, string* result); | |||||
| // Same as InputDigit, but remembers the position where next_char is inserted, | |||||
| // so that it could be retrieved later by using GetRememberedPosition(). The | |||||
| // remembered position will be automatically adjusted if additional formatting | |||||
| // characters are later inserted/removed in front of next_char. | |||||
| // Returns the partially formatted phone number (which is a reference to the | |||||
| // given string parameter for convenience). | |||||
| const string& InputDigitAndRememberPosition(char32 next_char, string* result); | |||||
| // Returns the current position in the partially formatted phone number of the | |||||
| // character which was previously passed in as the parameter of | |||||
| // InputDigitAndRememberPosition(). | |||||
| int GetRememberedPosition() const; | |||||
| // Clears the internal state of the formatter, so it could be reused. | |||||
| void Clear(); | |||||
| private: | |||||
| // Constructs an as-you-type formatter. Should be obtained from | |||||
| // PhoneNumberUtil::GetAsYouTypeFormatter(). | |||||
| explicit AsYouTypeFormatter(const string& region_code); | |||||
| // Returns the metadata corresponding to the given region code or empty | |||||
| // metadata if it is unsupported. | |||||
| const PhoneMetadata* GetMetadataForRegion(const string& region_code) const; | |||||
| // Returns true if a new template is created as opposed to reusing the | |||||
| // existing template. | |||||
| bool MaybeCreateNewTemplate(); | |||||
| void GetAvailableFormats(const string& leading_three_digits); | |||||
| void NarrowDownPossibleFormats(const string& leading_digits); | |||||
| bool CreateFormattingTemplate(const NumberFormat& format); | |||||
| // Gets a formatting template which could be used to efficiently format a | |||||
| // partial number where digits are added one by one. | |||||
| void GetFormattingTemplate(const string& number_pattern, | |||||
| const string& number_format, | |||||
| UnicodeString* formatting_template); | |||||
| void InputDigitWithOptionToRememberPosition(char32 next_char, | |||||
| bool remember_position, | |||||
| string* phone_number); | |||||
| void AttemptToFormatAccruedDigits(string* formatted_number); | |||||
| // Attempts to set the formatting template and assigns the passed-in string | |||||
| // parameter to the formatted version of the digits entered so far. | |||||
| void AttemptToChooseFormattingPattern(string* formatted_number); | |||||
| // Invokes InputDigitHelper on each digit of the national number accrued, and | |||||
| // assigns the passed-in string parameter to a formatted string in the end. | |||||
| void InputAccruedNationalNumber(string* number); | |||||
| void RemoveNationalPrefixFromNationalNumber(); | |||||
| // Extracts IDD and plus sign to prefix_before_national_number_ when they are | |||||
| // available, and places the remaining input into national_number_. | |||||
| bool AttemptToExtractIdd(); | |||||
| // Extracts country code from the begining of national_number_ to | |||||
| // prefix_before_national_number_ when they are available, and places the | |||||
| // remaining input into national_number_. | |||||
| // Returns true when a valid country code can be found. | |||||
| bool AttemptToExtractCountryCode(); | |||||
| // Accrues digits and the plus sign to accrued_input_without_formatting for | |||||
| // later use. If next_char contains a digit in non-ASCII format (e.g the | |||||
| // full-width version of digits), it is first normalized to the ASCII | |||||
| // version. The return value is next_char itself, or its normalized version, | |||||
| // if next_char is a digit in non-ASCII format. | |||||
| char NormalizeAndAccrueDigitsAndPlusSign(char32 next_char, | |||||
| bool remember_position); | |||||
| void InputDigitHelper(char next_char, string* number); | |||||
| // Converts UnicodeString position to std::string position. | |||||
| static int ConvertUnicodeStringPosition(const UnicodeString& s, int pos); | |||||
| // Class attributes. | |||||
| const scoped_ptr<const AbstractRegExpFactory> regexp_factory_; | |||||
| RegExpCache regexp_cache_; | |||||
| string current_output_; | |||||
| UnicodeString formatting_template_; | |||||
| string current_formatting_pattern_; | |||||
| UnicodeString accrued_input_; | |||||
| UnicodeString accrued_input_without_formatting_; | |||||
| bool able_to_format_; | |||||
| bool is_international_formatting_; | |||||
| bool is_expecting_country_code_; | |||||
| const PhoneNumberUtil& phone_util_; | |||||
| const string default_country_; | |||||
| const PhoneMetadata empty_metadata_; | |||||
| const PhoneMetadata* const default_metadata_; | |||||
| const PhoneMetadata* current_metadata_; | |||||
| int last_match_position_; | |||||
| // The position of a digit upon which InputDigitAndRememberPosition is most | |||||
| // recently invoked, as found in the original sequence of characters the user | |||||
| // entered. | |||||
| int original_position_; | |||||
| // The position of a digit upon which InputDigitAndRememberPosition is most | |||||
| // recently invoked, as found in AccruedInputWithoutFormatting. | |||||
| int position_to_remember_; | |||||
| string prefix_before_national_number_; | |||||
| string national_number_; | |||||
| list<const NumberFormat*> possible_formats_; | |||||
| friend class PhoneNumberUtil; | |||||
| friend class AsYouTypeFormatterTest; | |||||
| // Disallow copy and assign since this class uses RegExpCache which can't be | |||||
| // copied. | |||||
| DISALLOW_COPY_AND_ASSIGN(AsYouTypeFormatter); | |||||
| }; | |||||
| } // namespace phonenumbers | |||||
| } // namespace i18n | |||||
| #endif // I18N_PHONENUMBERS_ASYOUTYPEFORMATTER_H_ | |||||
| @ -0,0 +1,114 @@ | |||||
| // Copyright (C) 2011 The Libphonenumber Authors | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| // Author: Philippe Liard | |||||
| #include "phonenumbers/unicodestring.h" | |||||
| #include <algorithm> | |||||
| #include <cassert> | |||||
| #include <iterator> | |||||
| using std::advance; | |||||
| using std::equal; | |||||
| namespace i18n { | |||||
| namespace phonenumbers { | |||||
| UnicodeString& UnicodeString::operator=(const UnicodeString& src) { | |||||
| if (&src != this) { | |||||
| invalidateCachedIndex(); | |||||
| text_ = src.text_; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| bool UnicodeString::operator==(const UnicodeString& rhs) const { | |||||
| return equal(text_.begin(), text_.end(), rhs.text_.begin()); | |||||
| } | |||||
| void UnicodeString::append(const UnicodeString& unicode_string) { | |||||
| invalidateCachedIndex(); | |||||
| for (UnicodeString::const_iterator it = unicode_string.begin(); | |||||
| it != unicode_string.end(); ++it) { | |||||
| append(*it); | |||||
| } | |||||
| } | |||||
| int UnicodeString::indexOf(char32 codepoint) const { | |||||
| int pos = 0; | |||||
| for (UnicodeText::const_iterator it = text_.begin(); it != text_.end(); | |||||
| ++it, ++pos) { | |||||
| if (*it == codepoint) { | |||||
| return pos; | |||||
| } | |||||
| } | |||||
| return -1; | |||||
| } | |||||
| void UnicodeString::replace(int start, int length, const UnicodeString& src) { | |||||
| assert(length >= 0 && length <= this->length()); | |||||
| invalidateCachedIndex(); | |||||
| UnicodeText::const_iterator start_it = text_.begin(); | |||||
| advance(start_it, start); | |||||
| UnicodeText unicode_text; | |||||
| unicode_text.append(text_.begin(), start_it); | |||||
| unicode_text.append(src.text_); | |||||
| advance(start_it, length); | |||||
| unicode_text.append(start_it, text_.end()); | |||||
| text_ = unicode_text; | |||||
| } | |||||
| void UnicodeString::setCharAt(int pos, char32 c) { | |||||
| assert(pos < length()); | |||||
| invalidateCachedIndex(); | |||||
| UnicodeText::const_iterator pos_it = text_.begin(); | |||||
| advance(pos_it, pos); | |||||
| UnicodeText unicode_text; | |||||
| unicode_text.append(text_.begin(), pos_it); | |||||
| unicode_text.push_back(c); | |||||
| ++pos_it; | |||||
| unicode_text.append(pos_it, text_.end()); | |||||
| text_ = unicode_text; | |||||
| } | |||||
| UnicodeString UnicodeString::tempSubString(int start, int length) const { | |||||
| const int unicodestring_length = this->length(); | |||||
| if (length == std::numeric_limits<int>::max()) { | |||||
| length = unicodestring_length - start; | |||||
| } | |||||
| if (start > unicodestring_length || length > unicodestring_length) { | |||||
| return UnicodeString(""); | |||||
| } | |||||
| UnicodeText::const_iterator start_it = text_.begin(); | |||||
| advance(start_it, start); | |||||
| UnicodeText::const_iterator end_it = start_it; | |||||
| advance(end_it, length); | |||||
| UnicodeString substring; | |||||
| substring.text_.PointTo(start_it, end_it); | |||||
| return substring; | |||||
| } | |||||
| char32 UnicodeString::operator[](int index) const { | |||||
| assert(index < length()); | |||||
| if (cached_index_ == -1 || cached_index_ > index) { | |||||
| cached_it_ = text_.begin(); | |||||
| cached_index_ = 0; | |||||
| } | |||||
| for (; cached_index_ < index; ++cached_index_, ++cached_it_) {} | |||||
| return *cached_it_; | |||||
| } | |||||
| } // namespace phonenumbers | |||||
| } // namespace i18n | |||||
| @ -0,0 +1,133 @@ | |||||
| // Copyright (C) 2011 The Libphonenumber Authors | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| // Author: Philippe Liard | |||||
| #ifndef I18N_PHONENUMBERS_UNICODESTRING_H_ | |||||
| #define I18N_PHONENUMBERS_UNICODESTRING_H_ | |||||
| #include "phonenumbers/utf/unicodetext.h" | |||||
| #include <cstring> | |||||
| #include <limits> | |||||
| namespace i18n { | |||||
| namespace phonenumbers { | |||||
| // This class supports the minimal subset of icu::UnicodeString needed by | |||||
| // AsYouTypeFormatter in order to let the libphonenumber not depend on ICU | |||||
| // which is not available by default on some systems, such as iOS. | |||||
| class UnicodeString { | |||||
| public: | |||||
| UnicodeString() : cached_index_(-1) {} | |||||
| // Constructs a new unicode string copying the provided C string. | |||||
| explicit UnicodeString(const char* utf8) | |||||
| : text_(UTF8ToUnicodeText(utf8, std::strlen(utf8))), | |||||
| cached_index_(-1) {} | |||||
| // Constructs a new unicode string containing the provided codepoint. | |||||
| explicit UnicodeString(char32 codepoint) : cached_index_(-1) { | |||||
| append(codepoint); | |||||
| } | |||||
| UnicodeString(const UnicodeString& src) | |||||
| : text_(src.text_), cached_index_(-1) {} | |||||
| UnicodeString& operator=(const UnicodeString& src); | |||||
| bool operator==(const UnicodeString& rhs) const; | |||||
| void append(const UnicodeString& unicode_string); | |||||
| inline void append(char32 codepoint) { | |||||
| invalidateCachedIndex(); | |||||
| text_.push_back(codepoint); | |||||
| } | |||||
| typedef UnicodeText::const_iterator const_iterator; | |||||
| inline const_iterator begin() const { | |||||
| return text_.begin(); | |||||
| } | |||||
| inline const_iterator end() const { | |||||
| return text_.end(); | |||||
| } | |||||
| // Returns the index of the provided codepoint or -1 if not found. | |||||
| int indexOf(char32 codepoint) const; | |||||
| // Returns the number of codepoints contained in the unicode string. | |||||
| inline int length() const { | |||||
| return text_.size(); | |||||
| } | |||||
| // Clears the unicode string. | |||||
| inline void remove() { | |||||
| invalidateCachedIndex(); | |||||
| text_.clear(); | |||||
| } | |||||
| // Replaces the substring located at [ start, start + length - 1 ] with the | |||||
| // provided unicode string. | |||||
| void replace(int start, int length, const UnicodeString& src); | |||||
| void setCharAt(int pos, char32 c); | |||||
| // Copies the provided C string. | |||||
| inline void setTo(const char* s, size_t len) { | |||||
| invalidateCachedIndex(); | |||||
| text_.CopyUTF8(s, len); | |||||
| } | |||||
| // Returns the substring located at [ start, start + length - 1 ] without | |||||
| // copying the underlying C string. If one of the provided parameters is out | |||||
| // of range, the function returns an empty unicode string. | |||||
| UnicodeString tempSubString( | |||||
| int start, | |||||
| int length = std::numeric_limits<int>::max()) const; | |||||
| inline void toUTF8String(string& out) const { | |||||
| out = UnicodeTextToUTF8(text_); | |||||
| } | |||||
| char32 operator[](int index) const; | |||||
| private: | |||||
| UnicodeText text_; | |||||
| // As UnicodeText doesn't provide random access, an operator[] implementation | |||||
| // would naively iterate from the beginning of the string to the supplied | |||||
| // index which would be inefficient. | |||||
| // As operator[] is very likely to be called in a loop with consecutive | |||||
| // indexes, we save the corresponding iterator so we can reuse it the next | |||||
| // time it is called. | |||||
| // The following function which invalidates the cached index corresponding to | |||||
| // the iterator position must be called every time the unicode string is | |||||
| // modified (i.e. in all the non-const methods). | |||||
| inline void invalidateCachedIndex() { | |||||
| cached_index_ = -1; | |||||
| } | |||||
| // Iterator corresponding to the cached index below, used by operator[]. | |||||
| mutable UnicodeText::const_iterator cached_it_; | |||||
| mutable int cached_index_; | |||||
| }; | |||||
| } // namespace phonenumbers | |||||
| } // namespace i18n | |||||
| #endif // I18N_PHONENUMBERS_UNICODESTRING_H_ | |||||
| @ -0,0 +1,759 @@ | |||||
| // Copyright (C) 2011 The Libphonenumber Authors | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| // Unit tests for asyoutypeformatter.cc, ported from AsYouTypeFormatterTest.java | |||||
| #include "phonenumbers/asyoutypeformatter.h" | |||||
| #include <gtest/gtest.h> | |||||
| #include "base/logging.h" | |||||
| #include "base/memory/scoped_ptr.h" | |||||
| #include "phonenumbers/phonenumberutil.h" | |||||
| #include "phonenumbers/region_code.h" | |||||
| namespace i18n { | |||||
| namespace phonenumbers { | |||||
| class PhoneMetadata; | |||||
| class AsYouTypeFormatterTest : public testing::Test { | |||||
| protected: | |||||
| AsYouTypeFormatterTest() : phone_util_(*PhoneNumberUtil::GetInstance()) { | |||||
| } | |||||
| const PhoneMetadata* GetCurrentMetadata() const { | |||||
| return CHECK_NOTNULL(formatter_.get())->current_metadata_; | |||||
| } | |||||
| int ConvertUnicodeStringPosition(const UnicodeString& s, int pos) const { | |||||
| return AsYouTypeFormatter::ConvertUnicodeStringPosition(s, pos); | |||||
| } | |||||
| const PhoneNumberUtil& phone_util_; | |||||
| scoped_ptr<AsYouTypeFormatter> formatter_; | |||||
| string result_; | |||||
| private: | |||||
| DISALLOW_COPY_AND_ASSIGN(AsYouTypeFormatterTest); | |||||
| }; | |||||
| TEST_F(AsYouTypeFormatterTest, ConvertUnicodeStringPosition) { | |||||
| EXPECT_EQ(-1, ConvertUnicodeStringPosition(UnicodeString("12345"), 10)); | |||||
| EXPECT_EQ(3, ConvertUnicodeStringPosition(UnicodeString("12345"), 3)); | |||||
| EXPECT_EQ(0, ConvertUnicodeStringPosition( | |||||
| UnicodeString("\xEF\xBC\x95" /* "5" */), 0)); | |||||
| EXPECT_EQ(4, ConvertUnicodeStringPosition( | |||||
| UnicodeString("0\xEF\xBC\x95""3" /* "053" */), 2)); | |||||
| EXPECT_EQ(5, ConvertUnicodeStringPosition( | |||||
| UnicodeString("0\xEF\xBC\x95""3" /* "053" */), 3)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, Constructor) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("US")); | |||||
| EXPECT_TRUE(GetCurrentMetadata() != NULL); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, TooLongNumberMatchingMultipleLeadingDigits) { | |||||
| // See http://code.google.com/p/libphonenumber/issues/detail?id=36 | |||||
| // The bug occurred last time for countries which have two formatting rules | |||||
| // with exactly the same leading digits pattern but differ in length. | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter(RegionCode::GetUnknown())); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+81 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+81 9", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("+81 90", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("+81 90 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+81 90 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 90 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+81 90 1234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+81 90 1234 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+81 90 1234 56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+81 90 1234 567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+81 90 1234 5678", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+81 90 12 345 6789", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("+81901234567890", formatter_->InputDigit('0', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_US) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("US")); | |||||
| EXPECT_EQ("6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("650 253", formatter_->InputDigit('3', &result_)); | |||||
| // Note this is how a US local number (without area code) should be formatted. | |||||
| EXPECT_EQ("650 2532", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650 253 2222", formatter_->InputDigit('2', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("16", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("1 65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("1 650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("1 650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("1 650 253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("1 650 253 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 253 2222", formatter_->InputDigit('2', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 4", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("011 44 ", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("011 44 6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("011 44 61", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 44 6 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 44 6 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 44 6 123 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 44 6 123 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 44 6 123 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 44 6 123 123 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 44 6 123 123 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 44 6 123 123 123", formatter_->InputDigit('3', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("011 54 ", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("011 54 9", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("011 54 91", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 54 9 11", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 231", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 2312", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 2312 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 2312 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 2312 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 54 9 11 2312 1234", formatter_->InputDigit('4', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 24", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("011 244 ", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("011 244 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 244 28", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("011 244 280", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 244 280 0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 244 280 00", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 244 280 000", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 244 280 000 0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 244 280 000 00", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 244 280 000 000", formatter_->InputDigit('0', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+4", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+48 ", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+48 8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+48 88", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+48 88 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+48 88 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+48 88 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+48 88 123 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+48 88 123 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+48 88 123 12 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+48 88 123 12 12", formatter_->InputDigit('2', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_USFullWidthCharacters) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("US")); | |||||
| EXPECT_EQ("\xEF\xBC\x96" /* "6" */, | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x96" /* "6" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("\xEF\xBC\x96\xEF\xBC\x95" /* "65" */, | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x95" /* "5" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x90" /* "0" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 2", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x92" /* "2" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 25", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x95" /* "5" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 253", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x93" /* "3" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 2532", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x92" /* "2" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 253 22", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x92" /* "2" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 253 222", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x92" /* "2" */)[0], | |||||
| &result_)); | |||||
| EXPECT_EQ("650 253 2222", | |||||
| formatter_->InputDigit(UnicodeString("\xEF\xBC\x92" /* "2" */)[0], | |||||
| &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_USMobileShortCode) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("US")); | |||||
| EXPECT_EQ("*", formatter_->InputDigit('*', &result_)); | |||||
| EXPECT_EQ("*1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("*12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("*121", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("*121#", formatter_->InputDigit('#', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_USVanityNumber) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("US")); | |||||
| EXPECT_EQ("8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("80", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("800", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("800 ", formatter_->InputDigit(' ', &result_)); | |||||
| EXPECT_EQ("800 M", formatter_->InputDigit('M', &result_)); | |||||
| EXPECT_EQ("800 MY", formatter_->InputDigit('Y', &result_)); | |||||
| EXPECT_EQ("800 MY ", formatter_->InputDigit(' ', &result_)); | |||||
| EXPECT_EQ("800 MY A", formatter_->InputDigit('A', &result_)); | |||||
| EXPECT_EQ("800 MY AP", formatter_->InputDigit('P', &result_)); | |||||
| EXPECT_EQ("800 MY APP", formatter_->InputDigit('P', &result_)); | |||||
| EXPECT_EQ("800 MY APPL", formatter_->InputDigit('L', &result_)); | |||||
| EXPECT_EQ("800 MY APPLE", formatter_->InputDigit('E', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTFAndRememberPositionUS) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("US")); | |||||
| EXPECT_EQ("1", formatter_->InputDigitAndRememberPosition('1', &result_)); | |||||
| EXPECT_EQ(1, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("16", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("1 65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ(1, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650", formatter_->InputDigitAndRememberPosition('0', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 25", formatter_->InputDigit('5', &result_)); | |||||
| // Note the remembered position for digit "0" changes from 4 to 5, because a | |||||
| // space is now inserted in the front. | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("1 650 253 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 253 222", formatter_->InputDigitAndRememberPosition('2', | |||||
| &result_)); | |||||
| EXPECT_EQ(13, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 253 2222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(13, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("165025322222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(10, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1650253222222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(10, formatter_->GetRememberedPosition()); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("16", formatter_->InputDigitAndRememberPosition('6', &result_)); | |||||
| EXPECT_EQ(2, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("1 650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ(3, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ(3, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("1 650 253 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(3, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1 650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("1 650 253 2222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("165025322222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(2, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("1650253222222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(2, formatter_->GetRememberedPosition()); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("650 253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("650 2532", | |||||
| formatter_->InputDigitAndRememberPosition('2', &result_)); | |||||
| EXPECT_EQ(8, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(9, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| // No more formatting when semicolon is entered. | |||||
| EXPECT_EQ("650253222;", formatter_->InputDigit(';', &result_)); | |||||
| EXPECT_EQ(7, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("650253222;2", formatter_->InputDigit('2', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("650", formatter_->InputDigit('0', &result_)); | |||||
| // No more formatting when users choose to do their own formatting. | |||||
| EXPECT_EQ("650-", formatter_->InputDigit('-', &result_)); | |||||
| EXPECT_EQ("650-2", formatter_->InputDigitAndRememberPosition('2', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("650-25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("650-253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("650-253-", formatter_->InputDigit('-', &result_)); | |||||
| EXPECT_EQ("650-253-2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650-253-22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650-253-222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("650-253-2222", formatter_->InputDigit('2', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 4", formatter_->InputDigitAndRememberPosition('4', &result_)); | |||||
| EXPECT_EQ("011 48 ", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("011 48 8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("011 48 88", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("011 48 88 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 48 88 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("011 48 88 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 48 88 123 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 48 88 123 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("011 48 88 123 12 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 48 88 123 12 12", formatter_->InputDigit('2', &result_)); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+1 6", formatter_->InputDigitAndRememberPosition('6', &result_)); | |||||
| EXPECT_EQ("+1 65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+1 650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ(4, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("+1 650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(4, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("+1 650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+1 650 253", | |||||
| formatter_->InputDigitAndRememberPosition('3', &result_)); | |||||
| EXPECT_EQ("+1 650 253 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+1 650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+1 650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(10, formatter_->GetRememberedPosition()); | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+1 6", formatter_->InputDigitAndRememberPosition('6', &result_)); | |||||
| EXPECT_EQ("+1 65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+1 650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ(4, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("+1 650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ(4, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("+1 650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+1 650 253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+1 650 253 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+1 650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+1 650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+1650253222;", formatter_->InputDigit(';', &result_)); | |||||
| EXPECT_EQ(3, formatter_->GetRememberedPosition()); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_GBFixedLine) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("GB")); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("02", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("020", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("020 7", formatter_->InputDigitAndRememberPosition('7', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("020 70", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("020 703", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ(5, formatter_->GetRememberedPosition()); | |||||
| EXPECT_EQ("020 7031", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("020 7031 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("020 7031 30", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("020 7031 300", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("020 7031 3000", formatter_->InputDigit('0', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_GBTollFree) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("GB")); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("08", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("080", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("080 7", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("080 70", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("080 703", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("080 7031", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("080 7031 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("080 7031 30", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("080 7031 300", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("080 7031 3000", formatter_->InputDigit('0', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_GBPremiumRate) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("GB")); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("09", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("090", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("090 7", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("090 70", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("090 703", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("090 7031", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("090 7031 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("090 7031 30", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("090 7031 300", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("090 7031 3000", formatter_->InputDigit('0', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_NZMobile) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("NZ")); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("02", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("021", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("02-11", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("02-112", formatter_->InputDigit('2', &result_)); | |||||
| // Note the unittest is using fake metadata which might produce non-ideal | |||||
| // results. | |||||
| EXPECT_EQ("02-112 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("02-112 34", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("02-112 345", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("02-112 3456", formatter_->InputDigit('6', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_DE) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("DE")); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("03", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("030", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("030/1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("030/12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("030/123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("030/1234", formatter_->InputDigit('4', &result_)); | |||||
| // 08021 2345 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("08", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("080", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("080 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("080 21", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("08021 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("08021 23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("08021 234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("08021 2345", formatter_->InputDigit('5', &result_)); | |||||
| // 00 1 650 253 2250 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("00", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("00 1 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("00 1 6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("00 1 65", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("00 1 650", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("00 1 650 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("00 1 650 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("00 1 650 253", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("00 1 650 253 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("00 1 650 253 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("00 1 650 253 222", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("00 1 650 253 2222", formatter_->InputDigit('2', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_AR) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("AR")); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 7", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("011 70", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 703", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 7031", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011 7031-3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("011 7031-30", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 7031-300", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("011 7031-3000", formatter_->InputDigit('0', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_ARMobile) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("AR")); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+54 ", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+54 9", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("+54 91", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+54 9 11", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+54 9 11 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+54 9 11 23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+54 9 11 231", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+54 9 11 2312", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+54 9 11 2312 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+54 9 11 2312 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+54 9 11 2312 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+54 9 11 2312 1234", formatter_->InputDigit('4', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_KR) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("KR")); | |||||
| // +82 51 234 5678 | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+82 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+82 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+82 51", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+82 51-2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+82 51-23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+82 51-234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+82 51-234-5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+82 51-234-56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+82 51-234-567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+82 51-234-5678", formatter_->InputDigit('8', &result_)); | |||||
| // +82 2 531 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+82 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+82 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+82 25", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+82 2-53", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+82 2-531", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+82 2-531-5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+82 2-531-56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+82 2-531-567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+82 2-531-5678", formatter_->InputDigit('8', &result_)); | |||||
| // +82 2 3665 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+82 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+82 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+82 23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+82 2-36", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+82 2-366", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+82 2-3665", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+82 2-3665-5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+82 2-3665-56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+82 2-3665-567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+82 2-3665-5678", formatter_->InputDigit('8', &result_)); | |||||
| // 02-114 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("02", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("021", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("02-11", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("02-114", formatter_->InputDigit('4', &result_)); | |||||
| // 02-1300 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("02", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("021", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("02-13", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("02-130", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("02-1300", formatter_->InputDigit('0', &result_)); | |||||
| // 011-456-7890 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011-4", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("011-45", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("011-456", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("011-456-7", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("011-456-78", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("011-456-789", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("011-456-7890", formatter_->InputDigit('0', &result_)); | |||||
| // 011-9876-7890 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("0", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("01", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("011-9", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("011-98", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("011-987", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("011-9876", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("011-9876-7", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("011-9876-78", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("011-9876-789", formatter_->InputDigit('9', &result_)); | |||||
| EXPECT_EQ("011-9876-7890", formatter_->InputDigit('0', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_MX) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("MX")); | |||||
| // +52 800 123 4567 | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+52 80", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("+52 800", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("+52 800 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 800 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 800 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+52 800 123 4", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+52 800 123 45", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 800 123 456", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+52 800 123 4567", formatter_->InputDigit('7', &result_)); | |||||
| // +52 55 1234 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 55", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 55 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 55 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 55 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+52 55 1234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+52 55 1234 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 55 1234 56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+52 55 1234 567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+52 55 1234 5678", formatter_->InputDigit('8', &result_)); | |||||
| // +52 212 345 6789 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 21", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 212", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 212 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+52 212 34", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+52 212 345", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 212 345 6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+52 212 345 67", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+52 212 345 678", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+52 212 345 6789", formatter_->InputDigit('9', &result_)); | |||||
| // +52 1 55 1234 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 15", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 1 55", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 1 55 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 1 55 12", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 1 55 123", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+52 1 55 1234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+52 1 55 1234 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 1 55 1234 56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+52 1 55 1234 567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+52 1 55 1234 5678", formatter_->InputDigit('8', &result_)); | |||||
| // +52 1 541 234 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 ", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 1", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 15", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 1 54", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+52 1 541", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+52 1 541 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+52 1 541 23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+52 1 541 234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+52 1 541 234 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+52 1 541 234 56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+52 1 541 234 567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+52 1 541 234 5678", formatter_->InputDigit('8', &result_)); | |||||
| } | |||||
| TEST_F(AsYouTypeFormatterTest, AYTF_MultipleLeadingDigitPatterns) { | |||||
| formatter_.reset(phone_util_.GetAsYouTypeFormatter("JP")); | |||||
| // +81 50 2345 6789 | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+81 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+81 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+81 50", formatter_->InputDigit('0', &result_)); | |||||
| EXPECT_EQ("+81 50 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 50 23", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+81 50 234", formatter_->InputDigit('4', &result_)); | |||||
| EXPECT_EQ("+81 50 2345", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+81 50 2345 6", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+81 50 2345 67", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+81 50 2345 678", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+81 50 2345 6789", formatter_->InputDigit('9', &result_)); | |||||
| // +81 222 12 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+81 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+81 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 22", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 22 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 22 21", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+81 2221 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 222 12 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+81 222 12 56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+81 222 12 567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+81 222 12 5678", formatter_->InputDigit('8', &result_)); | |||||
| // +81 3332 2 5678 | |||||
| formatter_->Clear(); | |||||
| EXPECT_EQ("+", formatter_->InputDigit('+', &result_)); | |||||
| EXPECT_EQ("+8", formatter_->InputDigit('8', &result_)); | |||||
| EXPECT_EQ("+81 ", formatter_->InputDigit('1', &result_)); | |||||
| EXPECT_EQ("+81 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+81 33", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+81 33 3", formatter_->InputDigit('3', &result_)); | |||||
| EXPECT_EQ("+81 3332", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 3332 2", formatter_->InputDigit('2', &result_)); | |||||
| EXPECT_EQ("+81 3332 2 5", formatter_->InputDigit('5', &result_)); | |||||
| EXPECT_EQ("+81 3332 2 56", formatter_->InputDigit('6', &result_)); | |||||
| EXPECT_EQ("+81 3332 2 567", formatter_->InputDigit('7', &result_)); | |||||
| EXPECT_EQ("+81 3332 2 5678", formatter_->InputDigit('8', &result_)); | |||||
| } | |||||
| } // namespace phonenumbers | |||||
| } // namespace i18n | |||||
| @ -0,0 +1,236 @@ | |||||
| // Copyright (C) 2011 The Libphonenumber Authors | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| // Author: Philippe Liard | |||||
| #include <iostream> | |||||
| #include <gtest/gtest.h> | |||||
| #include "phonenumbers/unicodestring.h" | |||||
| using std::ostream; | |||||
| // Used by GTest to print the expected and actual results in case of failure. | |||||
| ostream& operator<<(ostream& out, const i18n::phonenumbers::UnicodeString& s) { | |||||
| string utf8; | |||||
| s.toUTF8String(utf8); | |||||
| out << utf8; | |||||
| return out; | |||||
| } | |||||
| namespace i18n { | |||||
| namespace phonenumbers { | |||||
| TEST(UnicodeString, ToUTF8StringWithEmptyString) { | |||||
| UnicodeString s; | |||||
| string utf8; | |||||
| s.toUTF8String(utf8); | |||||
| EXPECT_EQ("", utf8); | |||||
| } | |||||
| TEST(UnicodeString, ToUTF8String) { | |||||
| UnicodeString s("hello"); | |||||
| string utf8; | |||||
| s.toUTF8String(utf8); | |||||
| EXPECT_EQ("hello", utf8); | |||||
| } | |||||
| TEST(UnicodeString, ToUTF8StringWithNonAscii) { | |||||
| UnicodeString s("\xEF\xBC\x95\xEF\xBC\x93" /* "53" */); | |||||
| string utf8; | |||||
| s.toUTF8String(utf8); | |||||
| EXPECT_EQ("\xEF\xBC\x95\xEF\xBC\x93", utf8); | |||||
| } | |||||
| TEST(UnicodeString, AppendCodepoint) { | |||||
| UnicodeString s; | |||||
| s.append('h'); | |||||
| ASSERT_EQ(UnicodeString("h"), s); | |||||
| s.append('e'); | |||||
| EXPECT_EQ(UnicodeString("he"), s); | |||||
| } | |||||
| TEST(UnicodeString, AppendCodepointWithNonAscii) { | |||||
| UnicodeString s; | |||||
| s.append(0xFF15 /* 5 */); | |||||
| ASSERT_EQ(UnicodeString("\xEF\xBC\x95" /* 5 */), s); | |||||
| s.append(0xFF13 /* 3 */); | |||||
| EXPECT_EQ(UnicodeString("\xEF\xBC\x95\xEF\xBC\x93" /* 53 */), s); | |||||
| } | |||||
| TEST(UnicodeString, AppendUnicodeString) { | |||||
| UnicodeString s; | |||||
| s.append(UnicodeString("he")); | |||||
| ASSERT_EQ(UnicodeString("he"), s); | |||||
| s.append(UnicodeString("llo")); | |||||
| EXPECT_EQ(UnicodeString("hello"), s); | |||||
| } | |||||
| TEST(UnicodeString, AppendUnicodeStringWithNonAscii) { | |||||
| UnicodeString s; | |||||
| s.append(UnicodeString("\xEF\xBC\x95" /* 5 */)); | |||||
| ASSERT_EQ(UnicodeString("\xEF\xBC\x95"), s); | |||||
| s.append(UnicodeString("\xEF\xBC\x93" /* 3 */)); | |||||
| EXPECT_EQ(UnicodeString("\xEF\xBC\x95\xEF\xBC\x93" /* 53 */), s); | |||||
| } | |||||
| TEST(UnicodeString, IndexOf) { | |||||
| UnicodeString s("hello"); | |||||
| EXPECT_EQ(0, s.indexOf('h')); | |||||
| EXPECT_EQ(2, s.indexOf('l')); | |||||
| EXPECT_EQ(4, s.indexOf('o')); | |||||
| } | |||||
| TEST(UnicodeString, IndexOfWithNonAscii) { | |||||
| UnicodeString s("\xEF\xBC\x95\xEF\xBC\x93" /* 53 */); | |||||
| EXPECT_EQ(1, s.indexOf(0xFF13 /* 3 */)); | |||||
| } | |||||
| TEST(UnicodeString, ReplaceWithEmptyInputs) { | |||||
| UnicodeString s; | |||||
| s.replace(0, 0, UnicodeString("")); | |||||
| EXPECT_EQ(UnicodeString(""), s); | |||||
| } | |||||
| TEST(UnicodeString, ReplaceWithEmptyReplacement) { | |||||
| UnicodeString s("hello"); | |||||
| s.replace(0, 5, UnicodeString("")); | |||||
| EXPECT_EQ(UnicodeString(""), s); | |||||
| } | |||||
| TEST(UnicodeString, ReplaceBegining) { | |||||
| UnicodeString s("hello world"); | |||||
| s.replace(0, 5, UnicodeString("HELLO")); | |||||
| EXPECT_EQ(UnicodeString("HELLO world"), s); | |||||
| } | |||||
| TEST(UnicodeString, ReplaceMiddle) { | |||||
| UnicodeString s("hello world"); | |||||
| s.replace(5, 1, UnicodeString("AB")); | |||||
| EXPECT_EQ(UnicodeString("helloABworld"), s); | |||||
| } | |||||
| TEST(UnicodeString, ReplaceEnd) { | |||||
| UnicodeString s("hello world"); | |||||
| s.replace(10, 1, UnicodeString("AB")); | |||||
| EXPECT_EQ(UnicodeString("hello worlAB"), s); | |||||
| } | |||||
| TEST(UnicodeString, ReplaceWithNonAscii) { | |||||
| UnicodeString s("hello world"); | |||||
| s.replace(3, 2, UnicodeString("\xEF\xBC\x91\xEF\xBC\x90" /* 10 */)); | |||||
| EXPECT_EQ(UnicodeString("hel\xEF\xBC\x91\xEF\xBC\x90 world"), s); | |||||
| } | |||||
| TEST(UnicodeString, SetCharBegining) { | |||||
| UnicodeString s("hello"); | |||||
| s.setCharAt(0, 'H'); | |||||
| EXPECT_EQ(UnicodeString("Hello"), s); | |||||
| } | |||||
| TEST(UnicodeString, SetCharMiddle) { | |||||
| UnicodeString s("hello"); | |||||
| s.setCharAt(2, 'L'); | |||||
| EXPECT_EQ(UnicodeString("heLlo"), s); | |||||
| } | |||||
| TEST(UnicodeString, SetCharEnd) { | |||||
| UnicodeString s("hello"); | |||||
| s.setCharAt(4, 'O'); | |||||
| EXPECT_EQ(UnicodeString("hellO"), s); | |||||
| } | |||||
| TEST(UnicodeString, SetCharWithNonAscii) { | |||||
| UnicodeString s("hello"); | |||||
| s.setCharAt(4, 0xFF10 /* 0 */); | |||||
| EXPECT_EQ(UnicodeString("hell\xEF\xBC\x90" /* 0 */), s); | |||||
| } | |||||
| TEST(UnicodeString, TempSubStringWithEmptyString) { | |||||
| EXPECT_EQ(UnicodeString(""), UnicodeString().tempSubString(0, 0)); | |||||
| } | |||||
| TEST(UnicodeString, TempSubStringWithInvalidInputs) { | |||||
| UnicodeString s("hello"); | |||||
| // tempSubString() returns an empty unicode string if one of the provided | |||||
| // paramaters is out of range. | |||||
| EXPECT_EQ(UnicodeString(""), s.tempSubString(6)); | |||||
| EXPECT_EQ(UnicodeString(""), s.tempSubString(2, 6)); | |||||
| } | |||||
| TEST(UnicodeString, TempSubString) { | |||||
| UnicodeString s("hello"); | |||||
| EXPECT_EQ(UnicodeString(""), s.tempSubString(0, 0)); | |||||
| EXPECT_EQ(UnicodeString("h"), s.tempSubString(0, 1)); | |||||
| EXPECT_EQ(UnicodeString("hello"), s.tempSubString(0, 5)); | |||||
| EXPECT_EQ(UnicodeString("llo"), s.tempSubString(2, 3)); | |||||
| } | |||||
| TEST(UnicodeString, TempSubStringWithNoLength) { | |||||
| UnicodeString s("hello"); | |||||
| EXPECT_EQ(UnicodeString("hello"), s.tempSubString(0)); | |||||
| EXPECT_EQ(UnicodeString("llo"), s.tempSubString(2)); | |||||
| } | |||||
| TEST(UnicodeString, TempSubStringWithNonAscii) { | |||||
| UnicodeString s("hel\xEF\xBC\x91\xEF\xBC\x90" /* 10 */); | |||||
| EXPECT_EQ(UnicodeString("\xEF\xBC\x91" /* 1 */), s.tempSubString(3, 1)); | |||||
| } | |||||
| TEST(UnicodeString, OperatorEqual) { | |||||
| UnicodeString s("hello"); | |||||
| s = UnicodeString("Hello"); | |||||
| EXPECT_EQ(UnicodeString("Hello"), s); | |||||
| } | |||||
| TEST(UnicodeString, OperatorEqualWithNonAscii) { | |||||
| UnicodeString s("hello"); | |||||
| s = UnicodeString("hel\xEF\xBC\x91\xEF\xBC\x90" /* 10 */); | |||||
| EXPECT_EQ(UnicodeString("hel\xEF\xBC\x91\xEF\xBC\x90"), s); | |||||
| } | |||||
| TEST(UnicodeString, OperatorBracket) { | |||||
| UnicodeString s("hello"); | |||||
| EXPECT_EQ('h', s[0]); | |||||
| EXPECT_EQ('e', s[1]); | |||||
| EXPECT_EQ('l', s[2]); | |||||
| EXPECT_EQ('l', s[3]); | |||||
| EXPECT_EQ('o', s[4]); | |||||
| } | |||||
| TEST(UnicodeString, OperatorBracketWithNonAscii) { | |||||
| UnicodeString s("hel\xEF\xBC\x91\xEF\xBC\x90" /* 10 */); | |||||
| EXPECT_EQ('h', s[0]); | |||||
| EXPECT_EQ('e', s[1]); | |||||
| EXPECT_EQ('l', s[2]); | |||||
| EXPECT_EQ(0xFF11 /* 1 */, s[3]); | |||||
| EXPECT_EQ(0xFF10 /* 0 */, s[4]); | |||||
| } | |||||
| TEST(UnicodeString, OperatorBracketWithIteratorCacheInvalidation) { | |||||
| UnicodeString s("hello"); | |||||
| EXPECT_EQ('h', s[0]); | |||||
| EXPECT_EQ('e', s[1]); | |||||
| // Modify the string which should invalidate the iterator cache. | |||||
| s.setCharAt(1, 'E'); | |||||
| EXPECT_EQ(UnicodeString("hEllo"), s); | |||||
| EXPECT_EQ('E', s[1]); | |||||
| // Get the previous character which should invalidate the iterator cache. | |||||
| EXPECT_EQ('h', s[0]); | |||||
| EXPECT_EQ('o', s[4]); | |||||
| } | |||||
| } // namespace phonenumbers | |||||
| } // namespace i18n | |||||