• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2011 The Libphonenumber Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // A formatter which formats phone numbers as they are entered.
16 //
17 // An AsYouTypeFormatter can be created by invoking the GetAsYouTypeFormatter
18 // method of the PhoneNumberUtil. After that digits can be added by invoking the
19 // InputDigit method on the formatter instance, and the partially formatted
20 // phone number will be returned each time a digit is added. The Clear method
21 // can be invoked before a new number needs to be formatted.
22 //
23 // See AYTF_US, AYTF_GBFixedLine and AYTF_DE test functions in
24 // asyoutypeformatter_test.cc for more details on how the formatter is to be
25 // used.
26 //
27 // This is a direct port from AsYouTypeFormatter.java.
28 // Changes to this class should also happen to the Java version, whenever it
29 // makes sense.
30 //
31 // This class is NOT THREAD SAFE.
32 
33 #ifndef I18N_PHONENUMBERS_ASYOUTYPEFORMATTER_H_
34 #define I18N_PHONENUMBERS_ASYOUTYPEFORMATTER_H_
35 
36 #include <list>
37 #include <string>
38 
39 #include "phonenumbers/base/basictypes.h"
40 #include "phonenumbers/base/memory/scoped_ptr.h"
41 #include "phonenumbers/regexp_adapter.h"
42 #include "phonenumbers/regexp_cache.h"
43 #include "phonenumbers/phonemetadata.pb.h"
44 #include "phonenumbers/unicodestring.h"
45 
46 namespace i18n {
47 namespace phonenumbers {
48 
49 using std::list;
50 using std::string;
51 
52 class PhoneNumberUtil;
53 
54 class AsYouTypeFormatter {
55  public:
~AsYouTypeFormatter()56   ~AsYouTypeFormatter() {}
57 
58   // Formats a phone number on-the-fly as each digit is entered.
59   // next_char is the most recently entered digit of a phone number. Formatting
60   // characters are allowed, but as soon as they are encountered this method
61   // formats the number as entered and not "as you type" anymore. Full width
62   // digits and Arabic-indic digits are allowed, and will be shown as they are.
63   // Returns the partially formatted phone number (which is a reference to the
64   // given string parameter for convenience).
65   const string& InputDigit(char32 next_char, string* result);
66 
67   // Same as InputDigit, but remembers the position where next_char is inserted,
68   // so that it could be retrieved later by using GetRememberedPosition(). The
69   // remembered position will be automatically adjusted if additional formatting
70   // characters are later inserted/removed in front of next_char.
71   // Returns the partially formatted phone number (which is a reference to the
72   // given string parameter for convenience).
73   const string& InputDigitAndRememberPosition(char32 next_char, string* result);
74 
75   // Returns the current position in the partially formatted phone number of the
76   // character which was previously passed in as the parameter of
77   // InputDigitAndRememberPosition().
78   int GetRememberedPosition() const;
79 
80   // Clears the internal state of the formatter, so it could be reused.
81   void Clear();
82 
83  private:
84   // Constructs an as-you-type formatter. Should be obtained from
85   // PhoneNumberUtil::GetAsYouTypeFormatter().
86   explicit AsYouTypeFormatter(const string& region_code);
87 
88   // Returns the metadata corresponding to the given region code or empty
89   // metadata if it is unsupported.
90   const PhoneMetadata* GetMetadataForRegion(const string& region_code) const;
91 
92   // Returns true if a new template is created as opposed to reusing the
93   // existing template.
94   bool MaybeCreateNewTemplate();
95 
96   void GetAvailableFormats(const string& leading_three_digits);
97 
98   void NarrowDownPossibleFormats(const string& leading_digits);
99 
100   // Calculates whether we should be adding a space after the national prefix
101   // for this formatting rule or not.
102   void SetShouldAddSpaceAfterNationalPrefix(const NumberFormat& format);
103 
104   bool CreateFormattingTemplate(const NumberFormat& format);
105 
106   // Gets a formatting template which could be used to efficiently format a
107   // partial number where digits are added one by one.
108   void GetFormattingTemplate(const string& number_pattern,
109                              const string& number_format,
110                              UnicodeString* formatting_template);
111 
112   void InputDigitWithOptionToRememberPosition(char32 next_char,
113                                               bool remember_position,
114                                               string* phone_number);
115 
116   void AttemptToChoosePatternWithPrefixExtracted(string* formatted_number);
117 
118   // Some national prefixes are a substring of others. If extracting the
119   // shorter NDD doesn't result in a number we can format, we try to see if we
120   // can extract a longer version here.
121   bool AbleToExtractLongerNdd();
122 
123   // Check to see if there is an exact pattern match for these digits. If so, we
124   // should use this instead of any other formatting template whose
125   // leadingDigitsPattern also matches the input.
126   void AttemptToFormatAccruedDigits(string* formatted_number);
127 
128   // Combines the national number with any prefix (IDD/+ and country code or
129   // national prefix) that was collected. A space will be inserted between them
130   // if the current formatting template indicates this to be suitable.
131   // The result will be stored in phone_number.
132   void AppendNationalNumber(const string& national_number,
133                             string* phone_number) const;
134 
135   // Attempts to set the formatting template and assigns the passed-in string
136   // parameter to the formatted version of the digits entered so far.
137   void AttemptToChooseFormattingPattern(string* formatted_number);
138 
139   // Invokes InputDigitHelper on each digit of the national number accrued, and
140   // assigns the passed-in string parameter to a formatted string in the end.
141   void InputAccruedNationalNumber(string* number);
142 
143   // Returns true if the current country is a NANPA country and the national
144   // number begins with the national prefix.
145   bool IsNanpaNumberWithNationalPrefix() const;
146 
147   // Extracts the national prefix into national_prefix, or sets it to empty
148   // string if a national prefix is not present.
149   void RemoveNationalPrefixFromNationalNumber(string* national_prefix);
150 
151   // Extracts IDD and plus sign to prefix_before_national_number_ when they are
152   // available, and places the remaining input into national_number_.
153   bool AttemptToExtractIdd();
154 
155   // Extracts country code from the begining of national_number_ to
156   // prefix_before_national_number_ when they are available, and places the
157   // remaining input into national_number_.
158   // Returns true when a valid country code can be found.
159   bool AttemptToExtractCountryCode();
160 
161   // Accrues digits and the plus sign to accrued_input_without_formatting for
162   // later use. If next_char contains a digit in non-ASCII format (e.g the
163   // full-width version of digits), it is first normalized to the ASCII
164   // version. The return value is next_char itself, or its normalized version,
165   // if next_char is a digit in non-ASCII format.
166   char NormalizeAndAccrueDigitsAndPlusSign(char32 next_char,
167                                            bool remember_position);
168 
169   void InputDigitHelper(char next_char, string* number);
170 
171   // Converts UnicodeString position to std::string position.
172   static int ConvertUnicodeStringPosition(const UnicodeString& s, int pos);
173 
174   // Class attributes.
175   const scoped_ptr<const AbstractRegExpFactory> regexp_factory_;
176   RegExpCache regexp_cache_;
177 
178   string current_output_;
179 
180   UnicodeString formatting_template_;
181   string current_formatting_pattern_;
182 
183   UnicodeString accrued_input_;
184   UnicodeString accrued_input_without_formatting_;
185 
186   // This indicates whether AsYouTypeFormatter is currently doing the
187   // formatting.
188   bool able_to_format_;
189   // Set to true when users enter their own formatting. AsYouTypeFormatter will
190   // do no formatting at all when this is set to true.
191   bool input_has_formatting_;
192   // This is set to true when we know the user is entering a full national
193   // significant number, since we have either detected a national prefix or an
194   // international dialing prefix. When this is true, we will no longer use
195   // local number formatting patterns.
196   bool is_complete_number_;
197   bool is_expecting_country_code_;
198 
199   const PhoneNumberUtil& phone_util_;
200 
201   const string default_country_;
202 
203   const PhoneMetadata empty_metadata_;
204   const PhoneMetadata* const default_metadata_;
205   const PhoneMetadata* current_metadata_;
206 
207   int last_match_position_;
208 
209   // The position of a digit upon which InputDigitAndRememberPosition is most
210   // recently invoked, as found in the original sequence of characters the user
211   // entered.
212   int original_position_;
213 
214   // The position of a digit upon which InputDigitAndRememberPosition is most
215   // recently invoked, as found in AccruedInputWithoutFormatting.
216   int position_to_remember_;
217 
218   // This contains anything that has been entered so far preceding the national
219   // significant number, and it is formatted (e.g. with space inserted). For
220   // example, this can contain IDD, country code, and/or NDD, etc.
221   string prefix_before_national_number_;
222   bool should_add_space_after_national_prefix_;
223   // This contains the national prefix that has been extracted. It contains only
224   // digits without formatting.
225   string national_prefix_extracted_;
226   string national_number_;
227 
228   list<const NumberFormat*> possible_formats_;
229 
230   friend class PhoneNumberUtil;
231   friend class AsYouTypeFormatterTest;
232 
233   // Disallow copy and assign since this class uses RegExpCache which can't be
234   // copied.
235   DISALLOW_COPY_AND_ASSIGN(AsYouTypeFormatter);
236 };
237 
238 }  // namespace phonenumbers
239 }  // namespace i18n
240 
241 #endif  // I18N_PHONENUMBERS_ASYOUTYPEFORMATTER_H_
242