Commit f0736ffc authored by georgey@chromium.org's avatar georgey@chromium.org

Re-committing http://codereview.chromium.org/8736001/ originally committed revision=112305

The difference is the phone library pulled is version 407 instead of 403, it includes fixes, including missing licenses.
Original description: Pull the phone library directly. Delete old version.
TEST=unit-tests
BUG=105577

Review URL: http://codereview.chromium.org/8790002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112865 0039d316-1c4b-4281-b951-d872f2087c98
parent 62283d20
...@@ -31,6 +31,7 @@ vars = { ...@@ -31,6 +31,7 @@ vars = {
"nacl_toolchain_revision": "7258", "nacl_toolchain_revision": "7258",
"libjingle_revision": "95", "libjingle_revision": "95",
"libphonenumber_revision": "407",
"libvpx_revision": "109236", "libvpx_revision": "109236",
"ffmpeg_revision": "112050", "ffmpeg_revision": "112050",
"sfntly_revision": "111", "sfntly_revision": "111",
...@@ -298,6 +299,16 @@ deps = { ...@@ -298,6 +299,16 @@ deps = {
"src/third_party/smhasher/src": "src/third_party/smhasher/src":
(Var("googlecode_url") % "smhasher") + "/trunk@136", (Var("googlecode_url") % "smhasher") + "/trunk@136",
"src/third_party/libphonenumber/src/phonenumbers":
(Var("googlecode_url") % "libphonenumber") +
"/trunk/cpp/src/phonenumbers@" + Var("libphonenumber_revision"),
"src/third_party/libphonenumber/src/test":
(Var("googlecode_url") % "libphonenumber") + "/trunk/cpp/test@" +
Var("libphonenumber_revision"),
"src/third_party/libphonenumber/src/resources":
(Var("googlecode_url") % "libphonenumber") + "/trunk/resources@" +
Var("libphonenumber_revision"),
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_country.h" #include "chrome/browser/autofill/autofill_country.h"
#include "third_party/libphonenumber/cpp/src/phonenumberutil.h" #include "third_party/libphonenumber/src/phonenumber_api.h"
using i18n::phonenumbers::PhoneNumber; using i18n::phonenumbers::PhoneNumber;
using i18n::phonenumbers::PhoneNumberUtil; using i18n::phonenumbers::PhoneNumberUtil;
...@@ -108,7 +108,7 @@ bool ParsePhoneNumberInternal(const string16& value, ...@@ -108,7 +108,7 @@ bool ParsePhoneNumberInternal(const string16& value,
*city_code = UTF8ToUTF16(area_code); *city_code = UTF8ToUTF16(area_code);
*country_code = string16(); *country_code = string16();
PhoneNumberUtil::NormalizeDigitsOnly(&number_text); phone_util->NormalizeDigitsOnly(&number_text);
string16 normalized_number(UTF8ToUTF16(number_text)); string16 normalized_number(UTF8ToUTF16(number_text));
// Check if parsed number has country code and it was not inferred from the // Check if parsed number has country code and it was not inferred from the
// locale. // locale.
...@@ -148,7 +148,7 @@ string16 NormalizePhoneNumber(const string16& value, ...@@ -148,7 +148,7 @@ string16 NormalizePhoneNumber(const string16& value,
return string16(); return string16();
} }
std::string result_utf8(UTF16ToUTF8(result)); std::string result_utf8(UTF16ToUTF8(result));
PhoneNumberUtil::NormalizeDigitsOnly(&result_utf8); PhoneNumberUtil::GetInstance()->NormalizeDigitsOnly(&result_utf8);
return UTF8ToUTF16(result_utf8); return UTF8ToUTF16(result_utf8);
} }
...@@ -176,7 +176,9 @@ bool ConstructPhoneNumber(const string16& country_code, ...@@ -176,7 +176,9 @@ bool ConstructPhoneNumber(const string16& country_code,
std::string normalized_number(UTF16ToUTF8(city_code)); std::string normalized_number(UTF16ToUTF8(city_code));
normalized_number.append(UTF16ToUTF8(number)); normalized_number.append(UTF16ToUTF8(number));
PhoneNumberUtil::NormalizeDigitsOnly(&normalized_number); PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
phone_util->NormalizeDigitsOnly(&normalized_number);
int64 number_int = 0; int64 number_int = 0;
if (!base::StringToInt64(normalized_number, &number_int) || !number_int) if (!base::StringToInt64(normalized_number, &number_int) || !number_int)
...@@ -185,8 +187,6 @@ bool ConstructPhoneNumber(const string16& country_code, ...@@ -185,8 +187,6 @@ bool ConstructPhoneNumber(const string16& country_code,
PhoneNumber i18n_number; PhoneNumber i18n_number;
i18n_number.set_national_number(static_cast<uint64>(number_int)); i18n_number.set_national_number(static_cast<uint64>(number_int));
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
int country_int = phone_util->GetCountryCodeForRegion( int country_int = phone_util->GetCountryCodeForRegion(
SanitizeLocaleCode(locale)); SanitizeLocaleCode(locale));
if (!country_code.empty() && !base::StringToInt(country_code, &country_int)) if (!country_code.empty() && !base::StringToInt(country_code, &country_int))
......
...@@ -2,7 +2,7 @@ Name: International Phone Number Library ...@@ -2,7 +2,7 @@ Name: International Phone Number Library
Short Name: libphonenumber Short Name: libphonenumber
URL: http://libphonenumber.googlecode.com/svn/trunk/ URL: http://libphonenumber.googlecode.com/svn/trunk/
Version: unknown Version: unknown
Revision: 277 Revision: 407
Security Critical: yes Security Critical: yes
This directory contains the source code of International Phone Number Library This directory contains the source code of International Phone Number Library
...@@ -17,15 +17,13 @@ This library depends on ...@@ -17,15 +17,13 @@ This library depends on
Additional files, not in the original library: Additional files, not in the original library:
libphonenumber.gyp libphonenumber.gyp
README.chromium README.chromium
src/LICENSE # Taken from http://code.google.com/p/libphonenumber.
src/phonenumber_api.h
Until the changes are upstreamed library is included directly, with patches The library is mapped through the DEPS file into src/ folder. To update:
in patches/version277.patch and patches/version277a.patch applied. 1. Get the latest version number from
http://code.google.com/p/libphonenumber/source/list
The folders included in our repository for now are 2. Locally update this file and DEPS.
cpp/ 3. run 'gclient sync'
resource/ 4. Adjust libphonenumber.gyp if necessary.
5. Verify that all compiles and all of the tests are successfull.
TODO(georgey) : remove following lines when updated to version after 186
cpp/src/phonelibutil.cc made icu::Transliteration member of PhoneUtil
to improve performance, Not needed in recent versions.
Copyright (C) 2011 Google Inc.
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.
C++ version of the libphonenumber project.
Work in progress.
This is a port of the Java version.
This project uses some third-party code:
- src/base/ sources come from Chromium browser.
- src/utf/ sources come from lib9 which is also used in Go.
Requirements:
- CMake build system
http://www.cmake.org
You can install it very easily on a Debian-based GNU/Linux distribution:
$ sudo apt-get install cmake
- Protocol Buffers
http://code.google.com/p/protobuf/
Version 2.4 or more recent is required.
You can install it very easily on a Debian-based GNU/Linux distribution:
$ sudo apt-get install libprotobuf-dev
Note: if your GNU/Linux distribution doesn't provide the needed package,
please download and install it manually:
$ tar xjf protobuf-2.4.tar.bz2
$ cd protobuf-2.4
$ ./configure && make && sudo make install
- Google Test
http://code.google.com/p/googletest/
You can install it very easily on a Debian-based GNU/Linux distribution:
$ sudo apt-get install libgtest-dev
- RE2
http://code.google.com/p/re2/
You can install it very easily on Ubuntu Maverick and later:
$ sudo apt-get install libre2-dev
Otherwise if you use a Debian-based distribution you can fetch the Ubuntu
package which should work:
http://packages.ubuntu.com/maverick/libre2-dev
If you want to install it manually:
You need Mercurial to checkout its source code:
$ sudo apt-get install mercurial
Then checkout, build and install it:
$ hg clone https://re2.googlecode.com/hg re2
$ cd re2
$ make test
$ make install
$ make testinstall
- ICU
Version 4.4 or more recent is required.
It can be built from sources. You need to download the source tarball at
this location:
http://site.icu-project.org/download
Then you can extract, build and install it this way:
$ tar xzf icu4c-4_4_2-src.tgz
$ cd icu/source
$ ./configure && make && sudo make install
If you have a Debian-based distribution providing an up-to-date version of
ICU, you can install it using apt-get:
$ sudo apt-get install libicu-dev
- Boost
Version 1.40 or more recent is required.
You can install it very easily on a Debian-based GNU/Linux distribution:
$ sudo apt-get install libboost1.40-dev libboost-thread1.40-dev
Note: Boost Thread is the only library needed at link time.
How to build libphonenumber C++:
$ cd libphonenumber
$ mkdir build
$ cd build
$ cmake ../cpp/
$ make
Supported build parameters:
Build parameters can be specified invoking CMake with '-DKEY=VALUE' or using a
CMake user interface (ccmake or cmake-gui).
USE_LITE_METADATA = ON | OFF [OFF] -- Generates smaller metadata that doesn't
include example numbers.
// Copyright (C) 2011 Google Inc.
//
// 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 "default_logger.h"
namespace i18n {
namespace phonenumbers {
using std::cout;
using std::string;
void StdoutLogger::WriteMessage(const string& msg) {
cout << " " << msg;
}
void StdoutLogger::WriteLevel() {
LogLevel log_level = level();
cout << "[";
switch (log_level) {
case LOG_FATAL: cout << "FATAL"; break;
#ifdef ERROR // In case ERROR is defined by MSVC (i.e not set to LOG_ERROR).
case ERROR:
#endif
case LOG_ERROR: cout << "ERROR"; break;
case LOG_WARNING: cout << "WARNING"; break;
case LOG_INFO: cout << "INFO"; break;
case LOG_DEBUG: cout << "DEBUG"; break;
}
cout << "]";
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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_DEFAULT_LOGGER_H_
#define I18N_PHONENUMBERS_DEFAULT_LOGGER_H_
#include <stdio.h>
#include <string>
#include "logger.h"
using std::string;
// Make the logging functions private (not declared in logger.h) as the client
// should not have any reason to use them.
namespace {
using i18n::phonenumbers::Logger;
// Class template used to inline the right implementation for the T -> string
// conversion.
template <typename T>
struct ConvertToString;
template <typename T>
struct ConvertToString {
static inline string DoWork(const T& s) {
return string(s);
}
};
template <>
struct ConvertToString<int> {
static inline string DoWork(const int& n) {
char buffer[16];
#if defined(OS_WIN)
_itoa_s(n, buffer, sizeof(buffer), 10);
#else
snprintf(buffer, sizeof(buffer), "%d", n);
#endif
return string(buffer);
}
};
class LoggerHandler {
public:
LoggerHandler(Logger* impl) : impl_(impl) {}
~LoggerHandler() {
if (impl_) {
impl_->WriteMessage("\n");
}
}
template <typename T>
LoggerHandler& operator<<(const T& value) {
if (impl_) {
impl_->WriteMessage(ConvertToString<T>::DoWork(value));
}
return *this;
}
private:
Logger* const impl_;
};
} // namespace
namespace i18n {
namespace phonenumbers {
// Default logger implementation used by PhoneNumberUtil class. It outputs the
// messages to the standard output.
class StdoutLogger : public Logger {
public:
virtual ~StdoutLogger() {}
virtual void WriteLevel();
virtual void WriteMessage(const string& msg);
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_DEFAULT_LOGGER_H_
// Copyright (C) 2011 Google Inc.
//
// 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.
#ifndef I18N_PHONENUMBERS_ENCODING_UTILS_H_
#define I18N_PHONENUMBERS_ENCODING_UTILS_H_
#include "base/basictypes.h"
#include "utf/utf.h"
namespace i18n {
namespace phonenumbers {
class EncodingUtils {
public:
// Decodes one Unicode code-point value from a UTF-8 array. Returns the number
// of bytes read from the array. If the array does not contain valid UTF-8,
// the function stores 0xFFFD in the output variable and returns 1.
static inline int DecodeUTF8Char(const char* in, char32* out) {
Rune r;
int len = chartorune(&r, in);
*out = r;
return len;
}
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_ENCODING_UTILS_H_
// Copyright (C) 2011 Google Inc.
//
// 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 "logger.h"
#include <cstddef>
namespace i18n {
namespace phonenumbers {
Logger* Logger::impl_ = NULL;
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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_LOGGER_H_
#define I18N_PHONENUMBERS_LOGGER_H_
#include <cstdio>
#include <string>
#include "base/memory/scoped_ptr.h"
namespace i18n {
namespace phonenumbers {
using std::string;
enum LogLevel {
LOG_FATAL = 1,
LOG_ERROR,
LOG_WARNING,
LOG_INFO,
LOG_DEBUG,
};
enum {
DFATAL = LOG_FATAL,
// ERROR seems to be defined on MSVC, therefore don't overwrite it.
#ifndef ERROR
ERROR = LOG_ERROR,
#endif
WARNING = LOG_WARNING,
};
// Subclass this abstract class to override the way logging is handled in the
// library. You can then call the PhoneNumberUtil::SetLogger() method.
class Logger {
public:
Logger() : level_(LOG_ERROR) {}
virtual ~Logger() {}
// Writes the message level to the underlying output stream.
virtual void WriteLevel() {}
// Writes the provided message to the underlying output stream.
virtual void WriteMessage(const string& msg) = 0;
inline LogLevel level() const {
return level_;
}
inline void set_level(LogLevel level) {
level_ = level;
}
static inline void set_logger_impl(Logger* logger) {
impl_ = logger;
}
static inline Logger* mutable_logger_impl() {
return impl_;
}
private:
static Logger* impl_;
LogLevel level_;
};
// Logger that does not log anything. It could be useful to "mute" the
// phonenumber library.
class NullLogger : public Logger {
public:
virtual ~NullLogger() {}
virtual void WriteMessage(const string& /* msg */) {}
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_LOGGER_ADAPTER_H_
// Copyright (C) 2011 Google Inc.
//
// 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 <string>
#include <gtest/gtest.h>
#include "default_logger.h"
namespace i18n {
namespace phonenumbers {
using std::string;
// String logger implementation used for testing. Messages are output to a
// string for convenience.
class StringLogger : public Logger {
public:
virtual ~StringLogger() {}
const string& message() const {
return msg_;
}
virtual void WriteMessage(const string& msg) {
msg_ += msg;
}
private:
string msg_;
};
class LoggerTest : public ::testing::Test {
protected:
virtual void SetUp() {
test_logger_.reset(new StringLogger());
test_logger_->set_level(LOG_INFO);
// Save the current logger implementation and restore it when the test is
// done to avoid side-effects in other tests (including phonenumberutil
// tests) as the logger implementation is global.
old_logger_ = Logger::mutable_logger_impl();
Logger::set_logger_impl(test_logger_.get());
}
virtual void TearDown() {
// Restore the previous logger implementation to avoid side-effects in other
// tests as mentioned above.
Logger::set_logger_impl(old_logger_);
}
scoped_ptr<StringLogger> test_logger_;
Logger* old_logger_;
};
TEST_F(LoggerTest, LoggerIgnoresHigherVerbosity) {
// The logger verbosity is set to LOG_INFO, therefore LOG_DEBUG messages
// should be ignored.
VLOG(LOG_DEBUG) << "Hello";
EXPECT_EQ("", test_logger_->message());
}
TEST_F(LoggerTest, LoggerOutputsNewline) {
VLOG(LOG_INFO) << "Hello";
EXPECT_EQ("Hello\n", test_logger_->message());
}
TEST_F(LoggerTest, LoggerLogsEqualVerbosity) {
VLOG(LOG_INFO) << "Hello";
EXPECT_EQ("Hello\n", test_logger_->message());
}
TEST_F(LoggerTest, LoggerLogsLowerVerbosity) {
VLOG(LOG_WARNING) << "Hello";
EXPECT_EQ("Hello\n", test_logger_->message());
}
TEST_F(LoggerTest, LoggerConcatenatesMessages) {
VLOG(LOG_INFO) << "Hello";
ASSERT_EQ("Hello\n", test_logger_->message());
VLOG(LOG_INFO) << " World";
EXPECT_EQ("Hello\n World\n", test_logger_->message());
}
TEST_F(LoggerTest, LoggerHandlesDifferentTypes) {
VLOG(LOG_INFO) << "Hello " << 42;
EXPECT_EQ("Hello 42\n", test_logger_->message());
}
} // namespace phonenumbers
} // namespace i18n
/*
* Copyright (C) 2011 Google Inc.
*
* 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.
*/
#ifndef I18N_PHONENUMBERS_METADATA_H_
#define I18N_PHONENUMBERS_METADATA_H_
namespace i18n {
namespace phonenumbers {
int metadata_size();
const void* metadata_get();
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_METADATA_H_
// Copyright (C) 2011 Google Inc.
//
// 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 <string>
#include "utf/unicodetext.h"
namespace i18n {
namespace phonenumbers {
using std::string;
struct NormalizeUTF8 {
// Put a UTF-8 string in ASCII digits: All decimal digits (Nd) replaced by
// their ASCII counterparts; all other characters are copied from input to
// output.
static string NormalizeDecimalDigits(const string& number) {
string normalized;
UnicodeText number_as_unicode;
number_as_unicode.PointToUTF8(number.data(), number.size());
for (UnicodeText::const_iterator it = number_as_unicode.begin();
it != number_as_unicode.end();
++it) {
int32_t digitValue = u_charDigitValue(*it);
if (digitValue == -1) {
// Not a decimal digit.
char utf8[4];
int len = it.get_utf8(utf8);
normalized.append(utf8, len);
} else {
normalized.push_back('0' + digitValue);
}
}
return normalized;
}
};
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2009 Google Inc.
//
// 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 "phonemetadata.pb.h"
#include "phonenumber.pb.h"
namespace i18n {
namespace phonenumbers {
bool ExactlySameAs(const PhoneNumber& first_number,
const PhoneNumber& second_number) {
if (first_number.has_country_code() != second_number.has_country_code() ||
first_number.country_code() != second_number.country_code()) {
return false;
}
if (first_number.has_national_number() !=
second_number.has_national_number() ||
first_number.national_number() != second_number.national_number()) {
return false;
}
if (first_number.has_extension() != second_number.has_extension() ||
first_number.extension() != second_number.extension()) {
return false;
}
if (first_number.has_italian_leading_zero() !=
second_number.has_italian_leading_zero() ||
first_number.italian_leading_zero() !=
second_number.italian_leading_zero()) {
return false;
}
if (first_number.has_raw_input() != second_number.has_raw_input() ||
first_number.raw_input() != second_number.raw_input()) {
return false;
}
if (first_number.has_country_code_source() !=
second_number.has_country_code_source() ||
first_number.country_code_source() !=
second_number.country_code_source()) {
return false;
}
if (first_number.has_preferred_domestic_carrier_code() !=
second_number.has_preferred_domestic_carrier_code() ||
first_number.preferred_domestic_carrier_code() !=
second_number.preferred_domestic_carrier_code()) {
return false;
}
return true;
}
bool ExactlySameAs(const PhoneNumberDesc& first_number_desc,
const PhoneNumberDesc& second_number_desc) {
if (first_number_desc.has_national_number_pattern() !=
second_number_desc.has_national_number_pattern() ||
first_number_desc.national_number_pattern() !=
second_number_desc.national_number_pattern()) {
return false;
}
if (first_number_desc.has_possible_number_pattern() !=
second_number_desc.has_possible_number_pattern() ||
first_number_desc.possible_number_pattern() !=
second_number_desc.possible_number_pattern()) {
return false;
}
if (first_number_desc.has_example_number() !=
second_number_desc.has_example_number() ||
first_number_desc.example_number() !=
second_number_desc.example_number()) {
return false;
}
return true;
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2009 Google Inc.
//
// 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_PHONENUMBER_H_
#define I18N_PHONENUMBERS_PHONENUMBER_H_
// Helper functions dealing with PhoneNumber and PhoneNumberDesc comparisons.
namespace i18n {
namespace phonenumbers {
class PhoneNumber;
class PhoneNumberDesc;
// Compares two phone numbers.
bool ExactlySameAs(const PhoneNumber& first_number,
const PhoneNumber& second_number);
// Compares two phone number descriptions.
bool ExactlySameAs(const PhoneNumberDesc& first_number_desc,
const PhoneNumberDesc& second_number_desc);
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_PHONENUMBER_H_
// Copyright (C) 2011 Google Inc.
//
// 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: George Yakovlev
// Philippe Liard
//
// Regexp adapter to allow a pluggable regexp engine. It has been introduced
// during the integration of the open-source version of this library into
// Chromium to be able to use the ICU Regex engine instead of RE2, which is not
// officially supported on Windows.
// Since RE2 was initially used in this library, the interface of this adapter
// is very close to the subset of the RE2 API used in phonenumberutil.cc.
#ifndef I18N_PHONENUMBERS_REGEXP_ADAPTER_H_
#define I18N_PHONENUMBERS_REGEXP_ADAPTER_H_
#include <cstddef>
#include <string>
namespace i18n {
namespace phonenumbers {
using std::string;
// RegExpInput is the interface that abstracts the input that feeds the
// Consume() method of RegExp which may differ depending on its various
// implementations (StringPiece for RE2, UnicodeString for ICU Regex).
class RegExpInput {
public:
virtual ~RegExpInput() {}
// Creates a new instance of the default RegExpInput implementation. The
// deletion of the returned instance is under the responsibility of the
// caller.
static RegExpInput* Create(const string& utf8_input);
// Converts to a C++ string.
virtual string ToString() const = 0;
};
// The regular expression abstract class. It supports only functions used in
// phonenumberutil.cc. Consume(), Match() and Replace() methods must be
// implemented.
class RegExp {
public:
virtual ~RegExp() {}
// Creates a new instance of the default RegExp implementation. The deletion
// of the returned instance is under the responsibility of the caller.
static RegExp* Create(const string& utf8_regexp);
// Matches string to regular expression, returns true if expression was
// matched, false otherwise, advances position in the match.
// input_string - string to be searched.
// anchor_at_start - if true, match would be successful only if it appears at
// the beginning of the tested region of the string.
// matched_string1 - the first string extracted from the match. Can be NULL.
// matched_string2 - the second string extracted from the match. Can be NULL.
// matched_string3 - the third string extracted from the match. Can be NULL.
virtual bool Consume(RegExpInput* input_string,
bool anchor_at_start,
string* matched_string1,
string* matched_string2,
string* matched_string3) const = 0;
// Helper methods calling the Consume method that assume the match must start
// at the beginning.
inline bool Consume(RegExpInput* input_string,
string* matched_string1,
string* matched_string2,
string* matched_string3) const {
return Consume(input_string, true, matched_string1, matched_string2,
matched_string3);
}
inline bool Consume(RegExpInput* input_string,
string* matched_string1,
string* matched_string2) const {
return Consume(input_string, true, matched_string1, matched_string2, NULL);
}
inline bool Consume(RegExpInput* input_string, string* matched_string) const {
return Consume(input_string, true, matched_string, NULL, NULL);
}
inline bool Consume(RegExpInput* input_string) const {
return Consume(input_string, true, NULL, NULL, NULL);
}
// Helper method calling the Consume method that assumes the match can start
// at any place in the string.
inline bool FindAndConsume(RegExpInput* input_string,
string* matched_string) const {
return Consume(input_string, false, matched_string, NULL, NULL);
}
// Matches string to regular expression, returns true if the expression was
// matched, false otherwise.
// input_string - string to be searched.
// full_match - if true, match would be successful only if it matches the
// complete string.
// matched_string - the string extracted from the match. Can be NULL.
virtual bool Match(const string& input_string,
bool full_match,
string* matched_string) const = 0;
// Helper methods calling the Match method with the right arguments.
inline bool PartialMatch(const string& input_string,
string* matched_string) const {
return Match(input_string, false, matched_string);
}
inline bool PartialMatch(const string& input_string) const {
return Match(input_string, false, NULL);
}
inline bool FullMatch(const string& input_string,
string* matched_string) const {
return Match(input_string, true, matched_string);
}
inline bool FullMatch(const string& input_string) const {
return Match(input_string, true, NULL);
}
// Replaces match(es) in 'string_to_process'. If 'global' is true,
// replaces all the matches, otherwise only the first match.
// replacement_string - text the matches are replaced with. The groups in the
// replacement string are referenced with the $[0-9] notation.
// Returns true if the pattern matches and a replacement occurs, false
// otherwise.
virtual bool Replace(string* string_to_process,
bool global,
const string& replacement_string) const = 0;
// Helper methods calling the Replace method with the right arguments.
inline bool Replace(string* string_to_process,
const string& replacement_string) const {
return Replace(string_to_process, false, replacement_string);
}
inline bool GlobalReplace(string* string_to_process,
const string& replacement_string) const {
return Replace(string_to_process, true, replacement_string);
}
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_REGEXP_ADAPTER_H_
// Copyright (C) 2011 Google Inc.
//
// 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: George Yakovlev
// Philippe Liard
#include "regexp_adapter.h"
#include <string>
#include <unicode/regex.h>
#include <unicode/unistr.h>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "default_logger.h"
namespace i18n {
namespace phonenumbers {
using icu::RegexMatcher;
using icu::RegexPattern;
using icu::UnicodeString;
namespace {
// Converts UnicodeString 'source' to a UTF8-formatted std::string.
string UnicodeStringToUtf8String(const UnicodeString& source) {
string data;
source.toUTF8String<string>(data);
return data;
}
} // namespace
// Implementation of the abstract classes RegExpInput and RegExp using ICU
// regular expression capabilities.
// ICU implementation of the RegExpInput abstract class.
class IcuRegExpInput : public RegExpInput {
public:
explicit IcuRegExpInput(const string& utf8_input)
: utf8_input_(UnicodeString::fromUTF8(utf8_input)),
position_(0) {}
virtual ~IcuRegExpInput() {}
virtual string ToString() const {
return UnicodeStringToUtf8String(utf8_input_.tempSubString(position_));
}
UnicodeString* Data() {
return &utf8_input_;
}
// The current start position. For a newly created input, position is 0. Each
// call to ConsumeRegExp() or RegExp::Consume() advances the position in the
// case of the successful match to be after the match.
int position() const {
return position_;
}
void set_position(int position) {
DCHECK(position >= 0 && position <= utf8_input_.length());
position_ = position;
}
private:
UnicodeString utf8_input_;
int position_;
DISALLOW_COPY_AND_ASSIGN(IcuRegExpInput);
};
// ICU implementation of the RegExp abstract class.
class IcuRegExp : public RegExp {
public:
explicit IcuRegExp(const string& utf8_regexp) {
UParseError parse_error;
UErrorCode status = U_ZERO_ERROR;
utf8_regexp_.reset(RegexPattern::compile(
UnicodeString::fromUTF8(utf8_regexp), 0, parse_error, status));
if (U_FAILURE(status)) {
// The provided regular expressions should compile correctly.
LOG(ERROR) << "Error compiling regular expression: " << utf8_regexp;
utf8_regexp_.reset(NULL);
}
}
virtual ~IcuRegExp() {}
virtual bool Consume(RegExpInput* input_string,
bool anchor_at_start,
string* matched_string1,
string* matched_string2,
string* matched_string3) const {
DCHECK(input_string);
if (!utf8_regexp_.get()) {
return false;
}
IcuRegExpInput* const input = static_cast<IcuRegExpInput*>(input_string);
UErrorCode status = U_ZERO_ERROR;
const scoped_ptr<RegexMatcher> matcher(
utf8_regexp_->matcher(*input->Data(), status));
bool match_succeeded = anchor_at_start
? matcher->lookingAt(input->position(), status)
: matcher->find(input->position(), status);
if (!match_succeeded || U_FAILURE(status)) {
return false;
}
string* const matched_strings[] = {
matched_string1, matched_string2, matched_string3
};
// If less matches than expected - fail.
for (size_t i = 0; i < arraysize(matched_strings); ++i) {
if (matched_strings[i]) {
// Groups are counted from 1 rather than 0.
const int group_index = i + 1;
if (group_index > matcher->groupCount()) {
return false;
}
*matched_strings[i] =
UnicodeStringToUtf8String(matcher->group(group_index, status));
}
}
input->set_position(matcher->end(status));
return !U_FAILURE(status);
}
bool Match(const string& input_string,
bool full_match,
string* matched_string) const {
if (!utf8_regexp_.get()) {
return false;
}
IcuRegExpInput input(input_string);
UErrorCode status = U_ZERO_ERROR;
const scoped_ptr<RegexMatcher> matcher(
utf8_regexp_->matcher(*input.Data(), status));
bool match_succeeded = full_match
? matcher->matches(input.position(), status)
: matcher->find(input.position(), status);
if (!match_succeeded || U_FAILURE(status)) {
return false;
}
if (matcher->groupCount() > 0 && matched_string) {
*matched_string = UnicodeStringToUtf8String(matcher->group(1, status));
}
return !U_FAILURE(status);
}
bool Replace(string* string_to_process,
bool global,
const string& replacement_string) const {
DCHECK(string_to_process);
if (!utf8_regexp_.get()) {
return false;
}
IcuRegExpInput input(*string_to_process);
UErrorCode status = U_ZERO_ERROR;
const scoped_ptr<RegexMatcher> matcher(
utf8_regexp_->matcher(*input.Data(), status));
if (U_FAILURE(status)) {
return false;
}
UnicodeString result = global
? matcher->replaceAll(
UnicodeString::fromUTF8(replacement_string), status)
: matcher->replaceFirst(
UnicodeString::fromUTF8(replacement_string), status);
if (U_FAILURE(status)) {
return false;
}
const string replaced_string = UnicodeStringToUtf8String(result);
if (replaced_string == *string_to_process) {
return false;
}
*string_to_process = replaced_string;
return true;
}
private:
scoped_ptr<RegexPattern> utf8_regexp_;
DISALLOW_COPY_AND_ASSIGN(IcuRegExp);
};
RegExpInput* RegExpInput::Create(const string& utf8_input) {
return new IcuRegExpInput(utf8_input);
}
RegExp* RegExp::Create(const string& utf8_regexp) {
return new IcuRegExp(utf8_regexp);
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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: George Yakovlev
// Philippe Liard
#include "regexp_adapter.h"
#include <cstddef>
#include <string>
#include <re2/re2.h>
#include <re2/stringpiece.h>
#include "base/basictypes.h"
#include "base/logging.h"
#include "stringutil.h"
namespace i18n {
namespace phonenumbers {
using re2::StringPiece;
// Implementation of RegExpInput abstract class.
class RE2RegExpInput : public RegExpInput {
public:
explicit RE2RegExpInput(const string& utf8_input)
: string_(utf8_input),
utf8_input_(string_) {}
virtual string ToString() const {
return utf8_input_.ToString();
}
StringPiece* Data() {
return &utf8_input_;
}
private:
// string_ holds the string referenced by utf8_input_ as StringPiece doesn't
// copy the string passed in.
const string string_;
StringPiece utf8_input_;
};
namespace {
template <typename Function, typename Input>
bool DispatchRE2Call(Function regex_function,
Input input,
const RE2& regexp,
string* out1,
string* out2,
string* out3) {
if (out3) {
return regex_function(input, regexp, out1, out2, out3);
}
if (out2) {
return regex_function(input, regexp, out1, out2);
}
if (out1) {
return regex_function(input, regexp, out1);
}
return regex_function(input, regexp);
}
// Replaces unescaped dollar-signs with backslashes. Backslashes are deleted
// when they escape dollar-signs.
string TransformRegularExpressionToRE2Syntax(const string& regex) {
string re2_regex(regex);
if (GlobalReplaceSubstring("$", "\\", &re2_regex) == 0) {
return regex;
}
// If we replaced a dollar sign with a backslash and there are now two
// backslashes in the string, we assume that the dollar-sign was previously
// escaped and that we need to retain it. To do this, we replace pairs of
// backslashes with a dollar sign.
GlobalReplaceSubstring("\\\\", "$", &re2_regex);
return re2_regex;
}
} // namespace
// Implementation of RegExp abstract class.
class RE2RegExp : public RegExp {
public:
explicit RE2RegExp(const string& utf8_regexp)
: utf8_regexp_(utf8_regexp) {}
virtual bool Consume(RegExpInput* input_string,
bool anchor_at_start,
string* matched_string1,
string* matched_string2,
string* matched_string3) const {
DCHECK(input_string);
StringPiece* utf8_input =
static_cast<RE2RegExpInput*>(input_string)->Data();
if (anchor_at_start) {
return DispatchRE2Call(RE2::Consume, utf8_input, utf8_regexp_,
matched_string1, matched_string2,
matched_string3);
} else {
return DispatchRE2Call(RE2::FindAndConsume, utf8_input, utf8_regexp_,
matched_string1, matched_string2,
matched_string3);
}
}
virtual bool Match(const string& input_string,
bool full_match,
string* matched_string) const {
if (full_match) {
return DispatchRE2Call(RE2::FullMatch, input_string, utf8_regexp_,
matched_string, NULL, NULL);
} else {
return DispatchRE2Call(RE2::PartialMatch, input_string, utf8_regexp_,
matched_string, NULL, NULL);
}
}
virtual bool Replace(string* string_to_process,
bool global,
const string& replacement_string) const {
DCHECK(string_to_process);
const string re2_replacement_string =
TransformRegularExpressionToRE2Syntax(replacement_string);
if (global) {
return RE2::GlobalReplace(string_to_process, utf8_regexp_,
re2_replacement_string);
} else {
return RE2::Replace(string_to_process, utf8_regexp_,
re2_replacement_string);
}
}
private:
RE2 utf8_regexp_;
};
// Implementation of the adapter static factory methods.
// RE2 RegExp engine is the default implementation.
RegExpInput* RegExpInput::Create(const string& utf8_input) {
return new RE2RegExpInput(utf8_input);
}
RegExp* RegExp::Create(const string& utf8_regexp) {
return new RE2RegExp(utf8_regexp);
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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: George Yakovlev
// Philippe Liard
#include "regexp_adapter.h"
#include <string>
#include <gtest/gtest.h>
#include "base/memory/scoped_ptr.h"
namespace i18n {
namespace phonenumbers {
using std::string;
class RegExpAdapterTest : public testing::Test {
protected:
RegExpAdapterTest()
: digits_(RegExp::Create("\\d+")),
parentheses_digits_(RegExp::Create("\\((\\d+)\\)")),
single_digit_(RegExp::Create("\\d")),
two_digit_groups_(RegExp::Create("(\\d+)-(\\d+)")) {}
const scoped_ptr<const RegExp> digits_;
const scoped_ptr<const RegExp> parentheses_digits_;
const scoped_ptr<const RegExp> single_digit_;
const scoped_ptr<const RegExp> two_digit_groups_;
};
TEST_F(RegExpAdapterTest, TestConsumeNoMatch) {
const scoped_ptr<RegExpInput> input(RegExpInput::Create("+1-123-456-789"));
// When 'true' is passed to Consume(), the match occurs from the beginning of
// the input.
ASSERT_FALSE(digits_->Consume(input.get(), true, NULL, NULL, NULL));
ASSERT_EQ("+1-123-456-789", input->ToString());
string res1;
ASSERT_FALSE(parentheses_digits_->Consume(
input.get(), true, &res1, NULL, NULL));
ASSERT_EQ("+1-123-456-789", input->ToString());
ASSERT_EQ("", res1);
}
TEST_F(RegExpAdapterTest, TestConsumeWithNull) {
const scoped_ptr<RegExpInput> input(RegExpInput::Create("+123"));
const scoped_ptr<const RegExp> plus_sign(RegExp::Create("(\\+)"));
ASSERT_TRUE(plus_sign->Consume(input.get(), true, NULL, NULL, NULL));
ASSERT_EQ("123", input->ToString());
}
TEST_F(RegExpAdapterTest, TestConsumeRetainsMatches) {
const scoped_ptr<RegExpInput> input(RegExpInput::Create("1-123-456-789"));
string res1, res2;
ASSERT_TRUE(two_digit_groups_->Consume(
input.get(), true, &res1, &res2, NULL));
ASSERT_EQ("-456-789", input->ToString());
ASSERT_EQ("1", res1);
ASSERT_EQ("123", res2);
}
TEST_F(RegExpAdapterTest, TestFindAndConsume) {
const scoped_ptr<RegExpInput> input(RegExpInput::Create("+1-123-456-789"));
// When 'false' is passed to Consume(), the match can occur from any place in
// the input.
ASSERT_TRUE(digits_->Consume(input.get(), false, NULL, NULL, NULL));
ASSERT_EQ("-123-456-789", input->ToString());
ASSERT_TRUE(digits_->Consume(input.get(), false, NULL, NULL, NULL));
ASSERT_EQ("-456-789", input->ToString());
ASSERT_FALSE(parentheses_digits_->Consume(
input.get(), false, NULL, NULL, NULL));
ASSERT_EQ("-456-789", input->ToString());
string res1, res2;
ASSERT_TRUE(two_digit_groups_->Consume(
input.get(), false, &res1, &res2, NULL));
ASSERT_EQ("", input->ToString());
ASSERT_EQ("456", res1);
ASSERT_EQ("789", res2);
}
TEST(RegExpAdapter, TestPartialMatch) {
const scoped_ptr<const RegExp> reg_exp(RegExp::Create("([\\da-z]+)"));
string matched;
EXPECT_TRUE(reg_exp->PartialMatch("12345af", &matched));
EXPECT_EQ("12345af", matched);
EXPECT_TRUE(reg_exp->PartialMatch("12345af", NULL));
EXPECT_TRUE(reg_exp->PartialMatch("[12]", &matched));
EXPECT_EQ("12", matched);
matched.clear();
EXPECT_FALSE(reg_exp->PartialMatch("[]", &matched));
EXPECT_EQ("", matched);
}
TEST(RegExpAdapter, TestFullMatch) {
const scoped_ptr<const RegExp> reg_exp(RegExp::Create("([\\da-z]+)"));
string matched;
EXPECT_TRUE(reg_exp->FullMatch("12345af", &matched));
EXPECT_EQ("12345af", matched);
EXPECT_TRUE(reg_exp->FullMatch("12345af", NULL));
matched.clear();
EXPECT_FALSE(reg_exp->FullMatch("[12]", &matched));
EXPECT_EQ("", matched);
matched.clear();
EXPECT_FALSE(reg_exp->FullMatch("[]", &matched));
EXPECT_EQ("", matched);
}
TEST_F(RegExpAdapterTest, TestReplace) {
string input("123-4567 ");
ASSERT_TRUE(single_digit_->Replace(&input, "+"));
ASSERT_EQ("+23-4567 ", input);
ASSERT_TRUE(single_digit_->Replace(&input, "+"));
ASSERT_EQ("++3-4567 ", input);
const scoped_ptr<const RegExp> single_letter(RegExp::Create("[a-z]"));
ASSERT_FALSE(single_letter->Replace(&input, "+"));
ASSERT_EQ("++3-4567 ", input);
}
TEST_F(RegExpAdapterTest, TestReplaceWithGroup) {
// Make sure referencing groups in the regexp in the replacement string works.
// $[0-9] notation is used.
string input = "123-4567 abc";
ASSERT_TRUE(two_digit_groups_->Replace(&input, "$2"));
ASSERT_EQ("4567 abc", input);
input = "123-4567";
ASSERT_TRUE(two_digit_groups_->Replace(&input, "$1"));
ASSERT_EQ("123", input);
input = "123-4567";
ASSERT_TRUE(two_digit_groups_->Replace(&input, "$2"));
ASSERT_EQ("4567", input);
input = "123-4567";
ASSERT_TRUE(two_digit_groups_->Replace(&input, "$1 $2"));
ASSERT_EQ("123 4567", input);
}
TEST_F(RegExpAdapterTest, TestReplaceWithDollarSign) {
// Make sure '$' can be used in the replacement string when escaped.
string input = "123-4567";
ASSERT_TRUE(two_digit_groups_->Replace(&input, "\\$1 \\$2"));
ASSERT_EQ("$1 $2", input);
}
TEST_F(RegExpAdapterTest, TestGlobalReplace) {
string input("123-4567 ");
ASSERT_TRUE(single_digit_->GlobalReplace(&input, "*"));
ASSERT_EQ("***-**** ", input);
ASSERT_FALSE(single_digit_->GlobalReplace(&input, "*"));
ASSERT_EQ("***-**** ", input);
}
TEST(RegExpAdapter, TestUtf8) {
const scoped_ptr<const RegExp> reg_exp(RegExp::Create("\xE2\x84\xA1\xE2\x8A\x8F([\xCE\xB1-\xCF\x89]*)\xE2\x8A\x90"));
string matched;
EXPECT_FALSE(reg_exp->Match("\xE2\x84\xA1\xE2\x8A\x8F" "123\xE2\x8A\x90", true, &matched));
EXPECT_TRUE(reg_exp->Match("\xE2\x84\xA1\xE2\x8A\x8F\xCE\xB1\xCE\xB2\xE2\x8A\x90", true, &matched));
EXPECT_EQ("\xCE\xB1\xCE\xB2", matched);
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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: Fredrik Roubert
#include "regexp_cache.h"
#include <cstddef>
#include <string>
#include <utility>
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "regexp_adapter.h"
using std::string;
namespace i18n {
namespace phonenumbers {
using base::AutoLock;
RegExpCache::RegExpCache(size_t min_items)
#ifdef USE_TR1_UNORDERED_MAP
: cache_impl_(new CacheImpl(min_items)) {}
#else // USE_TR1_UNORDERED_MAP
: cache_impl_(new CacheImpl()) {}
#endif // USE_TR1_UNORDERED_MAP
RegExpCache::~RegExpCache() {
AutoLock l(lock_);
for (CacheImpl::const_iterator
it = cache_impl_->begin(); it != cache_impl_->end(); ++it) {
delete it->second;
}
}
const RegExp& RegExpCache::GetRegExp(const string& pattern) {
AutoLock l(lock_);
CacheImpl::const_iterator it = cache_impl_->find(pattern);
if (it != cache_impl_->end()) return *it->second;
const RegExp* regexp = RegExp::Create(pattern);
cache_impl_->insert(make_pair(pattern, regexp));
return *regexp;
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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: Fredrik Roubert
// RegExpCache is a simple wrapper around hash_map<> to store RegExp objects.
//
// To get a cached RegExp object for a regexp pattern string, call the
// GetRegExp() method of the class RegExpCache providing the pattern string. If
// a RegExp object corresponding to the pattern string doesn't already exist, it
// will be created by the GetRegExp() method.
//
// RegExpCache cache;
// const RegExp& regexp = cache.GetRegExp("\d");
#ifndef I18N_PHONENUMBERS_REGEXP_CACHE_H_
#define I18N_PHONENUMBERS_REGEXP_CACHE_H_
#include <cstddef>
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#ifdef USE_TR1_UNORDERED_MAP
# include <tr1/unordered_map>
#elif defined(USE_HASH_MAP)
# include "base/hash_tables.h"
#else
# error STL map type unsupported on this platform!
#endif
namespace i18n {
namespace phonenumbers {
using std::string;
class RegExp;
class RegExpCache {
private:
#ifdef USE_TR1_UNORDERED_MAP
typedef std::tr1::unordered_map<string, const RegExp*> CacheImpl;
#elif defined(USE_HASH_MAP)
typedef base::hash_map<string, const RegExp*> CacheImpl;
#endif
public:
explicit RegExpCache(size_t min_items);
~RegExpCache();
const RegExp& GetRegExp(const string& pattern);
private:
base::Lock lock_; // protects cache_impl_
scoped_ptr<CacheImpl> cache_impl_; // protected by lock_
friend class RegExpCacheTest_CacheConstructor_Test;
DISALLOW_COPY_AND_ASSIGN(RegExpCache);
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_REGEXP_CACHE_H_
// Copyright (C) 2011 Google Inc.
//
// 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: Fredrik Roubert
#include <cstddef>
#include <string>
#include <gtest/gtest.h>
#include "regexp_adapter.h"
#include "regexp_cache.h"
namespace i18n {
namespace phonenumbers {
using std::string;
class RegExpCacheTest : public testing::Test {
protected:
static const size_t min_items_ = 2;
RegExpCacheTest() : cache_(min_items_) {}
virtual ~RegExpCacheTest() {}
RegExpCache cache_;
};
TEST_F(RegExpCacheTest, CacheConstructor) {
ASSERT_TRUE(cache_.cache_impl_ != NULL);
EXPECT_TRUE(cache_.cache_impl_->empty());
}
TEST_F(RegExpCacheTest, GetRegExp) {
static const string pattern1("foo");
static const string pattern2("foo");
const RegExp& regexp1 = cache_.GetRegExp(pattern1);
// "foo" has been cached therefore we must get the same object.
const RegExp& regexp2 = cache_.GetRegExp(pattern2);
EXPECT_TRUE(&regexp1 == &regexp2);
}
} // namespace phonenumbers
} // namespace i18n
// Copyright (C) 2011 Google Inc.
//
// 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.
#ifndef I18N_PHONENUMBERS_REGION_CODE_H_
#define I18N_PHONENUMBERS_REGION_CODE_H_
#include <string>
namespace i18n {
namespace phonenumbers {
using std::string;
class RegionCode {
public:
// Returns a region code string representing the "unknown" region.
static const string& GetUnknown() {
static const string s = "ZZ";
return s;
}
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_REGION_CODE_H_
#include <gtest/gtest.h>
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
// Copyright (C) 2011 Google Inc.
//
// 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.
#ifndef I18N_PHONENUMBERS_STL_UTIL_H_
#define I18N_PHONENUMBERS_STL_UTIL_H_
namespace i18n {
namespace phonenumbers {
// Compares the first attribute of two pairs.
struct OrderByFirst {
template <typename T>
bool operator()(const T& p1, const T& p2) const {
return p1.first < p2.first;
}
};
// Deletes the second attribute (pointer type expected) of the pairs contained
// in the provided range.
template <typename ForwardIterator>
void STLDeleteContainerPairSecondPointers(const ForwardIterator& begin,
const ForwardIterator& end) {
for (ForwardIterator it = begin; it != end; ++it) {
delete it->second;
}
}
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_STL_UTIL_H_
These files come from lib9 (http://code.google.com/p/go/source/browse).
Copyright (C) 2011 Google Inc.
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.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment