| @ -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 | |||