From 1e3cc4b1d6f57ac44f3e954fbdc2e49e2228c397 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Thu, 19 Jun 2014 16:31:50 +0000 Subject: Include string in address_metadata.{h,cc}. Visual Studio 2013 needs `#include ` to compile address_metadata. TBR=roubert@google.com Review URL: https://codereview.appspot.com/109090046 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@294 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/include/libaddressinput/address_metadata.h | 2 ++ cpp/src/address_metadata.cc | 1 + 2 files changed, 3 insertions(+) diff --git a/cpp/include/libaddressinput/address_metadata.h b/cpp/include/libaddressinput/address_metadata.h index 269f982..cbe72db 100644 --- a/cpp/include/libaddressinput/address_metadata.h +++ b/cpp/include/libaddressinput/address_metadata.h @@ -17,6 +17,8 @@ #include +#include + namespace i18n { namespace addressinput { diff --git a/cpp/src/address_metadata.cc b/cpp/src/address_metadata.cc index 59030ef..2310f2e 100644 --- a/cpp/src/address_metadata.cc +++ b/cpp/src/address_metadata.cc @@ -17,6 +17,7 @@ #include #include +#include #include "region_data_constants.h" #include "rule.h" -- cgit v1.2.3 From fc1f6dd0d327c108cd8b0f7ed194099d5324d2f6 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Thu, 19 Jun 2014 16:40:29 +0000 Subject: Forward declare RE2ptr as struct. VS2013 says: - re2ptr.h(37) :error C2220: warning treated as error - no 'object' file generated - re2ptr.h(37) : warning C4099: 'i18n::addressinput::RE2ptr' : type name first seen using 'class' now seen using 'struct' - rule.h(36) : see declaration of 'i18n::addressinput::RE2ptr' TBR=roubert@google.com Review URL: https://codereview.appspot.com/104260043 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@295 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/src/post_box_matchers.h | 2 +- cpp/src/rule.h | 2 +- cpp/test/post_box_matchers_test.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/post_box_matchers.h b/cpp/src/post_box_matchers.h index 8f9f44b..c269f11 100644 --- a/cpp/src/post_box_matchers.h +++ b/cpp/src/post_box_matchers.h @@ -22,8 +22,8 @@ namespace i18n { namespace addressinput { -class RE2ptr; class Rule; +struct RE2ptr; class PostBoxMatchers { public: diff --git a/cpp/src/rule.h b/cpp/src/rule.h index c722932..38f20b3 100644 --- a/cpp/src/rule.h +++ b/cpp/src/rule.h @@ -33,7 +33,7 @@ namespace i18n { namespace addressinput { class Json; -class RE2ptr; +struct RE2ptr; // Stores address metadata addressing rules, to be used for determining the // layout of an address input widget or for address validation. Sample usage: diff --git a/cpp/test/post_box_matchers_test.cc b/cpp/test/post_box_matchers_test.cc index d89ee0b..eb9230c 100644 --- a/cpp/test/post_box_matchers_test.cc +++ b/cpp/test/post_box_matchers_test.cc @@ -23,7 +23,7 @@ namespace i18n { namespace addressinput { -class RE2ptr; +struct RE2ptr; } // namespace addressinput } // namespace i18n -- cgit v1.2.3 From 8a5ea9e2e8b5642281fa679b70266b80a4bf039d Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Tue, 24 Jun 2014 16:44:10 +0000 Subject: Compile libaddressinput in Visual Studio. R=roubert@google.com Review URL: https://codereview.appspot.com/109120043 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@296 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/include/libaddressinput/address_input_helper.h | 2 +- cpp/include/libaddressinput/address_normalizer.h | 2 +- cpp/libaddressinput.gypi | 1 + cpp/src/address_formatter.cc | 37 ++++++++----------- cpp/src/lookup_key.cc | 26 +++++-------- cpp/src/util/cctype_tolower_equal.cc | 43 ++++++++++++++++++++++ cpp/src/util/cctype_tolower_equal.h | 35 ++++++++++++++++++ cpp/src/validating_util.cc | 5 ++- cpp/test/address_input_helper_test.cc | 2 +- cpp/test/fake_downloader_test.cc | 7 +++- cpp/test/fake_storage_test.cc | 7 +++- cpp/test/null_storage_test.cc | 5 ++- cpp/test/retriever_test.cc | 7 +++- cpp/test/rule_retriever_test.cc | 7 +++- cpp/test/validating_storage_test.cc | 7 +++- 15 files changed, 138 insertions(+), 55 deletions(-) create mode 100644 cpp/src/util/cctype_tolower_equal.cc create mode 100644 cpp/src/util/cctype_tolower_equal.h diff --git a/cpp/include/libaddressinput/address_input_helper.h b/cpp/include/libaddressinput/address_input_helper.h index ce52cf9..043d3fc 100644 --- a/cpp/include/libaddressinput/address_input_helper.h +++ b/cpp/include/libaddressinput/address_input_helper.h @@ -23,9 +23,9 @@ namespace i18n { namespace addressinput { class LookupKey; -class Node; class PreloadSupplier; struct AddressData; +struct Node; class AddressInputHelper { public: diff --git a/cpp/include/libaddressinput/address_normalizer.h b/cpp/include/libaddressinput/address_normalizer.h index 6bd3366..06b7eb2 100644 --- a/cpp/include/libaddressinput/address_normalizer.h +++ b/cpp/include/libaddressinput/address_normalizer.h @@ -21,9 +21,9 @@ namespace i18n { namespace addressinput { -class AddressData; class PreloadSupplier; class StringCompare; +struct AddressData; class AddressNormalizer { public: diff --git a/cpp/libaddressinput.gypi b/cpp/libaddressinput.gypi index 8d9030f..03ecaf9 100644 --- a/cpp/libaddressinput.gypi +++ b/cpp/libaddressinput.gypi @@ -40,6 +40,7 @@ 'src/retriever.cc', 'src/rule.cc', 'src/rule_retriever.cc', + 'src/util/cctype_tolower_equal.cc', 'src/util/json.cc', 'src/util/md5.cc', 'src/util/string_compare.cc', diff --git a/cpp/src/address_formatter.cc b/cpp/src/address_formatter.cc index 29f3486..f4fc04d 100644 --- a/cpp/src/address_formatter.cc +++ b/cpp/src/address_formatter.cc @@ -14,20 +14,20 @@ #include -#include +#include +#include #include #include +#include #include #include -#include -#include - #include "format_element.h" #include "language.h" #include "region_data_constants.h" #include "rule.h" +#include "util/cctype_tolower_equal.h" namespace i18n { namespace addressinput { @@ -66,15 +66,6 @@ const char* kLanguagesThatUseAnArabicComma[] = { "uz" }; -// Case insensitive matcher for language tags. -struct LanguageMatcher { - LanguageMatcher(const std::string& tag) : tag(tag) {} - std::string tag; - bool operator() (const std::string& s) { - return strcasecmp(tag.c_str(), s.c_str()) == 0; - } -}; - std::string GetLineSeparatorForLanguage(const std::string& language_tag) { Language address_language(language_tag); @@ -87,20 +78,22 @@ std::string GetLineSeparatorForLanguage(const std::string& language_tag) { const std::string& base_language = address_language.base; if (std::find_if(kLanguagesThatUseSpace, kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace), - LanguageMatcher(base_language)) != + std::bind2nd(EqualToTolowerString(), base_language)) != kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace)) { return kSpaceSeparator; - } else if (std::find_if(kLanguagesThatHaveNoSeparator, - kLanguagesThatHaveNoSeparator + - arraysize(kLanguagesThatHaveNoSeparator), - LanguageMatcher(base_language)) != + } else if (std::find_if( + kLanguagesThatHaveNoSeparator, + kLanguagesThatHaveNoSeparator + + arraysize(kLanguagesThatHaveNoSeparator), + std::bind2nd(EqualToTolowerString(), base_language)) != kLanguagesThatHaveNoSeparator + arraysize(kLanguagesThatHaveNoSeparator)) { return ""; - } else if (std::find_if(kLanguagesThatUseAnArabicComma, - kLanguagesThatUseAnArabicComma + - arraysize(kLanguagesThatUseAnArabicComma), - LanguageMatcher(base_language)) != + } else if (std::find_if( + kLanguagesThatUseAnArabicComma, + kLanguagesThatUseAnArabicComma + + arraysize(kLanguagesThatUseAnArabicComma), + std::bind2nd(EqualToTolowerString(), base_language)) != kLanguagesThatUseAnArabicComma + arraysize(kLanguagesThatUseAnArabicComma)) { return kArabicCommaSeparator; diff --git a/cpp/src/lookup_key.cc b/cpp/src/lookup_key.cc index b6f73fc..fbd9a50 100644 --- a/cpp/src/lookup_key.cc +++ b/cpp/src/lookup_key.cc @@ -14,20 +14,22 @@ #include "lookup_key.h" +#include +#include +#include + #include #include +#include #include #include #include #include -#include -#include -#include - #include "language.h" #include "region_data_constants.h" #include "rule.h" +#include "util/cctype_tolower_equal.h" namespace i18n { namespace addressinput { @@ -39,15 +41,6 @@ const char kDashDelim[] = "--"; const char kData[] = "data"; const char kUnknown[] = "ZZ"; -// Case insensitive matcher for language tags. -struct LanguageMatcher { - LanguageMatcher(const std::string& tag) : tag(tag) { } - std::string tag; - bool operator() (const std::string& s) { - return strcasecmp(tag.c_str(), s.c_str()) == 0; - } -}; - // Assume the language_tag has had "Latn" script removed when this is called. bool ShouldSetLanguageForKey(const std::string& language_tag, const std::string& region_code) { @@ -69,10 +62,9 @@ bool ShouldSetLanguageForKey(const std::string& language_tag, return false; } // Finally, only return true if the language is one of the remaining ones. - return std::find_if(languages.begin() + 1, - languages.end(), - LanguageMatcher(language_tag)) - != languages.end(); + return std::find_if(languages.begin() + 1, languages.end(), + std::bind2nd(EqualToTolowerString(), language_tag)) != + languages.end(); } } // namespace diff --git a/cpp/src/util/cctype_tolower_equal.cc b/cpp/src/util/cctype_tolower_equal.cc new file mode 100644 index 0000000..0adbba9 --- /dev/null +++ b/cpp/src/util/cctype_tolower_equal.cc @@ -0,0 +1,43 @@ +// Copyright (C) 2014 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 "cctype_tolower_equal.h" + +#include +#include +#include +#include + +namespace i18n { +namespace addressinput { + +namespace { + +struct EqualToTolowerChar + : public std::binary_function { + result_type operator()(first_argument_type a, second_argument_type b) const { + return std::tolower(a) == std::tolower(b); + } +}; + +} // namespace + +EqualToTolowerString::result_type EqualToTolowerString::operator()( + const first_argument_type& a, const second_argument_type& b) const { + return std::equal(a.begin(), a.end(), b.begin(), EqualToTolowerChar()); +} + +} // addressinput +} // i18n diff --git a/cpp/src/util/cctype_tolower_equal.h b/cpp/src/util/cctype_tolower_equal.h new file mode 100644 index 0000000..106087e --- /dev/null +++ b/cpp/src/util/cctype_tolower_equal.h @@ -0,0 +1,35 @@ +// Copyright (C) 2014 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_ADDRESSINPUT_UTIL_CCTYPE_TOLOWER_EQUAL_H_ +#define I18N_ADDRESSINPUT_UTIL_CCTYPE_TOLOWER_EQUAL_H_ + +#include +#include + +namespace i18n { +namespace addressinput { + +// Performs case insensitive comparison of |a| and |b| by calling std::tolower() +// from . +struct EqualToTolowerString + : public std::binary_function { + result_type operator()(const first_argument_type& a, + const second_argument_type& b) const; +}; + +} // addressinput +} // i18n + +#endif // I18N_ADDRESSINPUT_UTIL_CCTYPE_TOLOWER_EQUAL_H_ diff --git a/cpp/src/validating_util.cc b/cpp/src/validating_util.cc index 6b52e8b..df3fc06 100644 --- a/cpp/src/validating_util.cc +++ b/cpp/src/validating_util.cc @@ -84,7 +84,10 @@ bool UnwrapHeader(const char* header_prefix, void ValidatingUtil::Wrap(time_t timestamp, std::string* data) { assert(data != NULL); char timestamp_string[2 + 3 * sizeof timestamp]; - snprintf(timestamp_string, sizeof timestamp_string, "%ld", timestamp); + int size = std::sprintf(timestamp_string, "%ld", timestamp); + assert(size > 0); + assert(size < sizeof timestamp_string); + (void)size; std::string header; header.append(kTimestampPrefix, kTimestampPrefixLength); diff --git a/cpp/test/address_input_helper_test.cc b/cpp/test/address_input_helper_test.cc index 84a2286..bb683da 100644 --- a/cpp/test/address_input_helper_test.cc +++ b/cpp/test/address_input_helper_test.cc @@ -326,7 +326,7 @@ TEST_F(AddressInputHelperMockDataTest, "{\"data/KR\": " // The top-level ZIP expression must be present for sub-key matches to be // evaluated. - "{\"id\":\"data/KR\", \"sub_keys\":\"A~B\", \"zip\":\"\\\\d\{5}\"}, " + "{\"id\":\"data/KR\", \"sub_keys\":\"A~B\", \"zip\":\"\\\\d{5}\"}, " "\"data/KR/A\": " "{\"id\":\"data/KR/A\", \"sub_keys\":\"A1~A2\"}, " "\"data/KR/A/A1\": " diff --git a/cpp/test/fake_downloader_test.cc b/cpp/test/fake_downloader_test.cc index 2d88acc..6468277 100644 --- a/cpp/test/fake_downloader_test.cc +++ b/cpp/test/fake_downloader_test.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -27,7 +28,6 @@ namespace { -using i18n::addressinput::BuildCallback; using i18n::addressinput::Downloader; using i18n::addressinput::FakeDownloader; using i18n::addressinput::RegionDataConstants; @@ -40,7 +40,8 @@ class FakeDownloaderTest : public testing::TestWithParam { virtual ~FakeDownloaderTest() {} Downloader::Callback* BuildCallback() { - return ::BuildCallback(this, &FakeDownloaderTest::OnDownloaded); + return i18n::addressinput::BuildCallback( + this, &FakeDownloaderTest::OnDownloaded); } FakeDownloader downloader_; @@ -58,6 +59,8 @@ class FakeDownloaderTest : public testing::TestWithParam { delete data; } } + + DISALLOW_COPY_AND_ASSIGN(FakeDownloaderTest); }; // Returns testing::AssertionSuccess if |data| is valid downloaded data for diff --git a/cpp/test/fake_storage_test.cc b/cpp/test/fake_storage_test.cc index 49663ca..f950ee4 100644 --- a/cpp/test/fake_storage_test.cc +++ b/cpp/test/fake_storage_test.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -25,7 +26,6 @@ namespace { -using i18n::addressinput::BuildCallback; using i18n::addressinput::FakeStorage; using i18n::addressinput::scoped_ptr; using i18n::addressinput::Storage; @@ -37,7 +37,8 @@ class FakeStorageTest : public testing::Test { virtual ~FakeStorageTest() {} Storage::Callback* BuildCallback() { - return ::BuildCallback(this, &FakeStorageTest::OnDataReady); + return i18n::addressinput::BuildCallback( + this, &FakeStorageTest::OnDataReady); } FakeStorage storage_; @@ -57,6 +58,8 @@ class FakeStorageTest : public testing::Test { delete data; } } + + DISALLOW_COPY_AND_ASSIGN(FakeStorageTest); }; TEST_F(FakeStorageTest, GetWithoutPutReturnsEmptyData) { diff --git a/cpp/test/null_storage_test.cc b/cpp/test/null_storage_test.cc index dca0803..e586568 100644 --- a/cpp/test/null_storage_test.cc +++ b/cpp/test/null_storage_test.cc @@ -25,7 +25,6 @@ namespace { -using i18n::addressinput::BuildCallback; using i18n::addressinput::NullStorage; using i18n::addressinput::scoped_ptr; using i18n::addressinput::Storage; @@ -33,9 +32,11 @@ using i18n::addressinput::Storage; class NullStorageTest : public testing::Test { protected: NullStorageTest() {} + virtual ~NullStorageTest() {} Storage::Callback* BuildCallback() { - return ::BuildCallback(this, &NullStorageTest::OnDataReady); + return i18n::addressinput::BuildCallback( + this, &NullStorageTest::OnDataReady); } NullStorage storage_; diff --git a/cpp/test/retriever_test.cc b/cpp/test/retriever_test.cc index aff418c..513e799 100644 --- a/cpp/test/retriever_test.cc +++ b/cpp/test/retriever_test.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,6 @@ namespace { -using i18n::addressinput::BuildCallback; using i18n::addressinput::FakeDownloader; using i18n::addressinput::MockDownloader; using i18n::addressinput::NullStorage; @@ -68,7 +68,8 @@ class RetrieverTest : public testing::Test { virtual ~RetrieverTest() {} Retriever::Callback* BuildCallback() { - return ::BuildCallback(this, &RetrieverTest::OnDataReady); + return i18n::addressinput::BuildCallback( + this, &RetrieverTest::OnDataReady); } Retriever retriever_; @@ -84,6 +85,8 @@ class RetrieverTest : public testing::Test { key_ = key; data_ = data; } + + DISALLOW_COPY_AND_ASSIGN(RetrieverTest); }; TEST_F(RetrieverTest, RetrieveData) { diff --git a/cpp/test/rule_retriever_test.cc b/cpp/test/rule_retriever_test.cc index ecfb0c8..9a32df3 100644 --- a/cpp/test/rule_retriever_test.cc +++ b/cpp/test/rule_retriever_test.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -28,7 +29,6 @@ namespace { -using i18n::addressinput::BuildCallback; using i18n::addressinput::FakeDownloader; using i18n::addressinput::NullStorage; using i18n::addressinput::Retriever; @@ -50,7 +50,8 @@ class RuleRetrieverTest : public testing::Test { virtual ~RuleRetrieverTest() {} RuleRetriever::Callback* BuildCallback() { - return ::BuildCallback(this, &RuleRetrieverTest::OnRuleReady); + return i18n::addressinput::BuildCallback( + this, &RuleRetrieverTest::OnRuleReady); } RuleRetriever rule_retriever_; @@ -66,6 +67,8 @@ class RuleRetrieverTest : public testing::Test { key_ = key; rule_.CopyFrom(rule); } + + DISALLOW_COPY_AND_ASSIGN(RuleRetrieverTest); }; TEST_F(RuleRetrieverTest, ExistingRule) { diff --git a/cpp/test/validating_storage_test.cc b/cpp/test/validating_storage_test.cc index ced22dc..f786117 100644 --- a/cpp/test/validating_storage_test.cc +++ b/cpp/test/validating_storage_test.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -31,7 +32,6 @@ namespace { -using i18n::addressinput::BuildCallback; using i18n::addressinput::FakeStorage; using i18n::addressinput::scoped_ptr; using i18n::addressinput::Storage; @@ -57,7 +57,8 @@ class ValidatingStorageTest : public testing::Test { virtual ~ValidatingStorageTest() {} ValidatingStorage::Callback* BuildCallback() { - return ::BuildCallback(this, &ValidatingStorageTest::OnDataReady); + return i18n::addressinput::BuildCallback( + this, &ValidatingStorageTest::OnDataReady); } Storage* const wrapped_storage_; // Owned by |storage_|. @@ -76,6 +77,8 @@ class ValidatingStorageTest : public testing::Test { delete data; } } + + DISALLOW_COPY_AND_ASSIGN(ValidatingStorageTest); }; TEST_F(ValidatingStorageTest, GoodData) { -- cgit v1.2.3 From 10f9a352e49e80a6061bdc354fc833dacf94a5e4 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Tue, 24 Jun 2014 23:31:28 +0000 Subject: Change \u to \\u in region_data_constants.cc This is a temporary workaround for building libaddressinput in Chromium on Windows until the new region_data_constants.cc is generated. TBR=roubert@google.com Review URL: https://codereview.appspot.com/101460046 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@297 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/src/region_data_constants.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc index cabee28..d12bafc 100644 --- a/cpp/src/region_data_constants.cc +++ b/cpp/src/region_data_constants.cc @@ -119,7 +119,7 @@ std::map InitRegionData() { "\"languages\":\"nl~pap\"" "}")); region_data.insert(std::make_pair("AX", "{" - "\"fmt\":\"%O%n%N%n%A%nAX-%Z %C%n\u00c5LAND\"," + "\"fmt\":\"%O%n%N%n%A%nAX-%Z %C%n\\u00c5LAND\"," "\"require\":\"ACZ\"," "\"zipex\":\"22150,22550,22240,22710,22270,22730,22430\"," "\"posturl\":\"http://www.posten.ax/department.con\?iPage=123\"," @@ -634,7 +634,7 @@ std::map InitRegionData() { "\"languages\":\"ar\"" "}")); region_data.insert(std::make_pair("JP", "{" - "\"fmt\":\"\u3012%Z%n%S%C%n%A%n%O%n%N\"," + "\"fmt\":\"\\u3012%Z%n%S%C%n%A%n%O%n%N\"," "\"lfmt\":\"%N%n%O%n%A%n%C, %S%n%Z\"," "\"require\":\"ACSZ\"," "\"state_name_type\":\"prefecture\"," -- cgit v1.2.3 -- cgit v1.2.3 From 771cc560df04dc201a90012c15b5814c33f6d5d8 Mon Sep 17 00:00:00 2001 From: "lararennie@google.com" Date: Sat, 28 Jun 2014 18:22:59 +0000 Subject: Adding code to handle locality_name_type and show a custom locality label if necessary. git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@299 38ededc0-08b8-5190-f2ac-b31f878777ad --- .../android/i18n/addressinput/AddressDataKey.java | 8 ++++++-- .../android/i18n/addressinput/AddressWidget.java | 23 +++++++++++++++++++++- .../i18n/addressinput/RegionDataConstants.java | 2 ++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/java/src/com/android/i18n/addressinput/AddressDataKey.java b/java/src/com/android/i18n/addressinput/AddressDataKey.java index 33ffd74..a4766af 100644 --- a/java/src/com/android/i18n/addressinput/AddressDataKey.java +++ b/java/src/com/android/i18n/addressinput/AddressDataKey.java @@ -55,12 +55,16 @@ enum AddressDataKey { * use with the latin script, such as in China. */ LFMT, + /** + * Indicates the type of the name used for the locality (city) field. + */ + LOCALITY_NAME_TYPE, /** * Indicates which fields must be present in a valid address. */ REQUIRE, /** - * Indicates the name used for the admin areas for a particular region. + * Indicates the type of the name used for the state (administrative area) field. */ STATE_NAME_TYPE, /** @@ -90,7 +94,7 @@ enum AddressDataKey { */ ZIP, /** - * Indicates the name used for the postal code for a particular region. + * Indicates the type of the name used for the ZIP (postal code) field. */ ZIP_NAME_TYPE; diff --git a/java/src/com/android/i18n/addressinput/AddressWidget.java b/java/src/com/android/i18n/addressinput/AddressWidget.java index 2ebfeef..76cd12a 100644 --- a/java/src/com/android/i18n/addressinput/AddressWidget.java +++ b/java/src/com/android/i18n/addressinput/AddressWidget.java @@ -81,11 +81,16 @@ public class AddressWidget implements AdapterView.OnItemSelectedListener { private ScriptType mScript; + // The appropriate label that should be applied to the locality (city) field of the current + // country. Examples include "city" or "district". + private String mLocalityLabel; + // The appropriate label that should be applied to the admin area field of the current country. // Examples include "state", "province", "emirate", etc. private String mAdminLabel; private static final Map ADMIN_LABELS; + private static final Map LOCALITY_LABELS; private static final Map ADMIN_ERROR_MESSAGES; private static final FormOptions SHOW_ALL_FIELDS = new FormOptions.Builder().build(); @@ -113,6 +118,11 @@ public class AddressWidget implements AdapterView.OnItemSelectedListener { adminLabelMap.put("state", R.string.i18n_state_label); ADMIN_LABELS = Collections.unmodifiableMap(adminLabelMap); + Map localityLabelMap = new HashMap(2); + localityLabelMap.put("city", R.string.i18n_locality_label); + localityLabelMap.put("district", R.string.i18n_dependent_locality_label); + LOCALITY_LABELS = Collections.unmodifiableMap(localityLabelMap); + Map adminErrorMap = new HashMap(15); adminErrorMap.put("area", R.string.invalid_area); adminErrorMap.put("county", R.string.invalid_county_label); @@ -266,7 +276,7 @@ public class AddressWidget implements AdapterView.OnItemSelectedListener { // Set up AddressField.LOCALITY AddressUiComponent localityUi = new AddressUiComponent(AddressField.LOCALITY); - localityUi.setFieldName(mContext.getString(R.string.i18n_locality_label)); + localityUi.setFieldName(getLocalityFieldName(countryNode)); mInputWidgets.put(AddressField.LOCALITY, localityUi); // Set up AddressField.DEPENDENT_LOCALITY @@ -330,6 +340,17 @@ public class AddressWidget implements AdapterView.OnItemSelectedListener { return zipName; } + private String getLocalityFieldName(AddressVerificationNodeData countryNode) { + String localityLabelType = countryNode.get(AddressDataKey.LOCALITY_NAME_TYPE); + mLocalityLabel = localityLabelType; + Integer result = LOCALITY_LABELS.get(localityLabelType); + if (result == null) { + // Fallback to city. + result = R.string.i18n_locality_label; + } + return mContext.getString(result); + } + private String getAdminAreaFieldName(AddressVerificationNodeData countryNode) { String adminLabelType = countryNode.get(AddressDataKey.STATE_NAME_TYPE); mAdminLabel = adminLabelType; diff --git a/java/src/com/android/i18n/addressinput/RegionDataConstants.java b/java/src/com/android/i18n/addressinput/RegionDataConstants.java index 48affab..946fc24 100644 --- a/java/src/com/android/i18n/addressinput/RegionDataConstants.java +++ b/java/src/com/android/i18n/addressinput/RegionDataConstants.java @@ -1124,6 +1124,7 @@ class RegionDataConstants { "name", "TURKEY", "fmt", "%N%n%O%n%A%n%Z %C/%S", "require", "ACZ", + "locality_name_type", "district", }), TT(new String[]{ "name", "TRINIDAD AND TOBAGO", @@ -1269,6 +1270,7 @@ class RegionDataConstants { "upper", "C", "zip_name_type", "postal", "state_name_type", "province", + "locality_name_type", "city", }); private String jsonString; -- cgit v1.2.3 From 4e10bb9dd340ddf1dcfb1b4ed04d30c73f86e6ff Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Mon, 7 Jul 2014 22:44:33 +0000 Subject: Add equality comparison to EqualToTolowerString. Chromium browser tests on Windows in debug mode have exposed that std::equal is not safe. It should be used only after a length comparison. (Bot failures can be seen at http://goo.gl/qvaBg3, http://goo.gl/j89rgZ, and http://goo.gl/CxcyYm.) TBR=roubert@google.com Review URL: https://codereview.appspot.com/106480044 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@300 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/src/util/cctype_tolower_equal.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/src/util/cctype_tolower_equal.cc b/cpp/src/util/cctype_tolower_equal.cc index 0adbba9..819138f 100644 --- a/cpp/src/util/cctype_tolower_equal.cc +++ b/cpp/src/util/cctype_tolower_equal.cc @@ -36,7 +36,8 @@ struct EqualToTolowerChar EqualToTolowerString::result_type EqualToTolowerString::operator()( const first_argument_type& a, const second_argument_type& b) const { - return std::equal(a.begin(), a.end(), b.begin(), EqualToTolowerChar()); + return a.size() == b.size() && + std::equal(a.begin(), a.end(), b.begin(), EqualToTolowerChar()); } } // addressinput -- cgit v1.2.3 From 39fc575f34f8024ae785ec597a3125d8d00ebd0a Mon Sep 17 00:00:00 2001 From: "lararennie@google.com" Date: Wed, 9 Jul 2014 07:35:10 +0000 Subject: Updated data for Andorra/Russia, new label for Russia, small formatting fixes (Java). git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@301 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/res/messages.grdp | 6 ++++ cpp/src/region_data_constants.cc | 8 ++--- cpp/src/rule.cc | 2 ++ java/res/values/address_strings.xml | 7 ++++ .../android/i18n/addressinput/AddressWidget.java | 2 ++ .../i18n/addressinput/FormatInterpreter.java | 24 +++++++------ .../i18n/addressinput/RegionDataConstants.java | 11 +++--- .../android/i18n/addressinput/ClientDataTest.java | 2 +- .../i18n/addressinput/FormatInterpreterTest.java | 42 +++++++++++++++++++++- 9 files changed, 82 insertions(+), 22 deletions(-) diff --git a/cpp/res/messages.grdp b/cpp/res/messages.grdp index 1e1bcf2..c04449a 100644 --- a/cpp/res/messages.grdp +++ b/cpp/res/messages.grdp @@ -84,6 +84,12 @@ limitations under the License. Island)."> Island + + Oblast + InitRegionData() { "\"languages\":\"sr-Cyrl~sr-Latn\"" "}")); region_data.insert(std::make_pair("RU", "{" - "\"fmt\":\"%Z %C %n%A%n%O%n%N\"," + "\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\"," "\"require\":\"ACZ\"," + "\"state_name_type\":\"oblast\"," "\"zipex\":\"125075,247112,103375\"," "\"posturl\":\"http://info.russianpost.ru/servlet/department\"," "\"languages\":\"ru\"" diff --git a/cpp/src/rule.cc b/cpp/src/rule.cc index e25142f..b4d03ca 100644 --- a/cpp/src/rule.cc +++ b/cpp/src/rule.cc @@ -72,6 +72,8 @@ NameMessageIdMap InitAdminAreaMessageIds() { "emirate", IDS_LIBADDRESSINPUT_EMIRATE)); message_ids.insert(std::make_pair( "island", IDS_LIBADDRESSINPUT_ISLAND)); + message_ids.insert(std::make_pair( + "oblast", IDS_LIBADDRESSINPUT_OBLAST)); message_ids.insert(std::make_pair( "parish", IDS_LIBADDRESSINPUT_PARISH)); message_ids.insert(std::make_pair( diff --git a/java/res/values/address_strings.xml b/java/res/values/address_strings.xml index 57b34c4..f12247a 100644 --- a/java/res/values/address_strings.xml +++ b/java/res/values/address_strings.xml @@ -80,6 +80,9 @@ Island + + Oblast + Parish @@ -140,6 +143,10 @@ (e.g., Bahama) is entered incorrectly by the user [CHAR LIMIT=30] --> Invalid island + + Invalid oblast + Invalid parish diff --git a/java/src/com/android/i18n/addressinput/AddressWidget.java b/java/src/com/android/i18n/addressinput/AddressWidget.java index 76cd12a..c377e2c 100644 --- a/java/src/com/android/i18n/addressinput/AddressWidget.java +++ b/java/src/com/android/i18n/addressinput/AddressWidget.java @@ -112,6 +112,7 @@ public class AddressWidget implements AdapterView.OnItemSelectedListener { adminLabelMap.put("do_si", R.string.i18n_do_si); adminLabelMap.put("emirate", R.string.i18n_emirate); adminLabelMap.put("island", R.string.i18n_island); + adminLabelMap.put("oblast", R.string.i18n_oblast); adminLabelMap.put("parish", R.string.i18n_parish); adminLabelMap.put("prefecture", R.string.i18n_prefecture); adminLabelMap.put("province", R.string.i18n_province); @@ -131,6 +132,7 @@ public class AddressWidget implements AdapterView.OnItemSelectedListener { adminErrorMap.put("do_si", R.string.invalid_do_si); adminErrorMap.put("emirate", R.string.invalid_emirate); adminErrorMap.put("island", R.string.invalid_island); + adminErrorMap.put("oblast", R.string.invalid_oblast); adminErrorMap.put("parish", R.string.invalid_parish); adminErrorMap.put("prefecture", R.string.invalid_prefecture); adminErrorMap.put("province", R.string.invalid_province); diff --git a/java/src/com/android/i18n/addressinput/FormatInterpreter.java b/java/src/com/android/i18n/addressinput/FormatInterpreter.java index ffd19b1..ed7b2ac 100644 --- a/java/src/com/android/i18n/addressinput/FormatInterpreter.java +++ b/java/src/com/android/i18n/addressinput/FormatInterpreter.java @@ -155,15 +155,16 @@ class FormatInterpreter { List lines = new ArrayList(); StringBuilder currentLine = new StringBuilder(); - for (String substr : getFormatSubStrings(scriptType, regionCode)) { - if (substr.equals(NEW_LINE)) { - String normalizedStr = removeAllRedundantSpaces(currentLine.toString()); + for (String formatSymbol : getFormatSubStrings(scriptType, regionCode)) { + if (formatSymbol.equals(NEW_LINE)) { + String normalizedStr = + removeRedundantSpacesAndLeadingPunctuation(currentLine.toString()); if (normalizedStr.length() > 0) { lines.add(normalizedStr); currentLine.setLength(0); } - } else if (substr.startsWith("%")) { - char c = substr.charAt(1); + } else if (formatSymbol.startsWith("%")) { + char c = formatSymbol.charAt(1); AddressField field = AddressField.of(c); Util.checkNotNull(field, "null address field for character " + c); @@ -203,10 +204,10 @@ class FormatInterpreter { currentLine.append(value); } } else { - currentLine.append(substr); + currentLine.append(formatSymbol); } } - String normalizedStr = removeAllRedundantSpaces(currentLine.toString()); + String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString()); if (normalizedStr.length() > 0) { lines.add(normalizedStr); } @@ -242,13 +243,16 @@ class FormatInterpreter { return parts; } - private String removeAllRedundantSpaces(String str) { + private static String removeRedundantSpacesAndLeadingPunctuation(String str) { + // Remove leading commas and other punctuation that might have been added by the formatter + // in the case of missing data. + str = str.replaceFirst("^[-,\\s]+", ""); str = str.trim(); str = str.replaceAll(" +", " "); return str; } - private String getFormatString(ScriptType scriptType, String regionCode) { + private static String getFormatString(ScriptType scriptType, String regionCode) { String format = (scriptType == ScriptType.LOCAL) ? getJsonValue(regionCode, AddressDataKey.FMT) : getJsonValue(regionCode, AddressDataKey.LFMT); @@ -258,7 +262,7 @@ class FormatInterpreter { return format; } - private String getJsonValue(String regionCode, AddressDataKey key) { + private static String getJsonValue(String regionCode, AddressDataKey key) { Util.checkNotNull(regionCode); String jsonString = RegionDataConstants.getCountryFormatMap().get(regionCode); Util.checkNotNull(jsonString, "no json data for region code " + regionCode); diff --git a/java/src/com/android/i18n/addressinput/RegionDataConstants.java b/java/src/com/android/i18n/addressinput/RegionDataConstants.java index 946fc24..18b1fd8 100644 --- a/java/src/com/android/i18n/addressinput/RegionDataConstants.java +++ b/java/src/com/android/i18n/addressinput/RegionDataConstants.java @@ -41,10 +41,8 @@ class RegionDataConstants { "name", "ANDORRA", "lang", "ca", "languages", "ca", - "fmt", "%N%n%O%n%A%n%Z %S", - "require", "AS", - "upper", "S", - "state_name_type", "parish", + "fmt", "%N%n%O%n%A%n%Z %C", + "require", "A", }), AE(new String[]{ "name", "UNITED ARAB EMIRATES", @@ -977,8 +975,9 @@ class RegionDataConstants { }), RU(new String[]{ "name", "RUSSIAN FEDERATION", - "fmt", "%Z %C %n%A%n%O%n%N", + "fmt", "%N%n%O%n%A%n%C%n%S%n%Z", "require", "ACZ", + "state_name_type", "oblast", "upper", "AC", }), RW(new String[]{ @@ -1168,7 +1167,7 @@ class RegionDataConstants { "name", "UNITED STATES", "lang", "en", "languages", "en", - "fmt", "%N%n%O%n%A%n%C %S %Z", + "fmt", "%N%n%O%n%A%n%C, %S %Z", "require", "ACSZ", "upper", "CS", "zip_name_type", "zip", diff --git a/java/test/com/android/i18n/addressinput/ClientDataTest.java b/java/test/com/android/i18n/addressinput/ClientDataTest.java index 570434e..b18d726 100644 --- a/java/test/com/android/i18n/addressinput/ClientDataTest.java +++ b/java/test/com/android/i18n/addressinput/ClientDataTest.java @@ -78,6 +78,6 @@ public class ClientDataTest extends AsyncTestCase { // data from there. assertNotNull(data); String unitedStatesFormatInfo = data.get(AddressDataKey.FMT); - assertEquals("%N%n%O%n%A%n%C %S %Z", unitedStatesFormatInfo); + assertEquals("%N%n%O%n%A%n%C, %S %Z", unitedStatesFormatInfo); } } diff --git a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java index 50372ed..f5bac79 100644 --- a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java +++ b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java @@ -147,7 +147,7 @@ public class FormatInterpreterTest extends TestCase { public void testUsEnvelopeAddress() { List expected = new ArrayList(); expected.add("1098 Alta Ave"); - expected.add("Mt View CA 94043"); + expected.add("Mt View, CA 94043"); List real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS); @@ -189,4 +189,44 @@ public class FormatInterpreterTest extends TestCase { List real = formatInterpreter.getEnvelopeAddress(address); assertEquals(expected, real); } + + public void testEnvelopeAddressLeadingPostPrefix() { + List expected = new ArrayList(); + expected.add("CH-8047 Herrliberg"); + AddressData address = new AddressData.Builder().setCountry("CH") + .setPostalCode("8047") + .setLocality("Herrliberg") + .build(); + + List real = formatInterpreter.getEnvelopeAddress(address); + assertEquals(expected, real); + } + + public void testSvAddress() { + final AddressData svAddress = new AddressData.Builder().setCountry("SV") + .setAdminArea("Ahuachapán") + .setLocality("Ahuachapán") + .setAddressLine1("Some Street 12") + .build(); + + List expected = new ArrayList(); + expected.add("Some Street 12"); + expected.add("Ahuachapán"); + expected.add("Ahuachapán"); + + List real = formatInterpreter.getEnvelopeAddress(svAddress); + assertEquals(expected, real); + + final AddressData svAddressWithPostCode = new AddressData.Builder(svAddress) + .setPostalCode("CP 2101") + .build(); + + expected = new ArrayList(); + expected.add("Some Street 12"); + expected.add("CP 2101-Ahuachapán"); + expected.add("Ahuachapán"); + + real = formatInterpreter.getEnvelopeAddress(svAddressWithPostCode); + assertEquals(expected, real); + } } -- cgit v1.2.3 From dcaf3df8a8051485562f94565cac2baa71dafe7d Mon Sep 17 00:00:00 2001 From: "keghani@google.com" Date: Wed, 9 Jul 2014 13:45:51 +0000 Subject: Update Denmark format string: swap recipient name with organization name. git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@302 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/src/region_data_constants.cc | 2 +- java/src/com/android/i18n/addressinput/RegionDataConstants.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc index 8c552d3..0a1f78b 100644 --- a/cpp/src/region_data_constants.cc +++ b/cpp/src/region_data_constants.cc @@ -328,7 +328,7 @@ std::map InitRegionData() { "\"languages\":\"ar~fr\"" "}")); region_data.insert(std::make_pair("DK", "{" - "\"fmt\":\"%O%n%N%n%A%n%Z %C\"," + "\"fmt\":\"%N%n%O%n%A%n%Z %C\"," "\"require\":\"ACZ\"," "\"zipex\":\"8660,1566\"," "\"posturl\":\"http://www.postdanmark.dk/da/Privat/Kundeservice/postnummerkort/Sider/Find-postnummer.aspx\"," diff --git a/java/src/com/android/i18n/addressinput/RegionDataConstants.java b/java/src/com/android/i18n/addressinput/RegionDataConstants.java index 18b1fd8..4f4c5b7 100644 --- a/java/src/com/android/i18n/addressinput/RegionDataConstants.java +++ b/java/src/com/android/i18n/addressinput/RegionDataConstants.java @@ -309,7 +309,7 @@ class RegionDataConstants { }), DK(new String[]{ "name", "DENMARK", - "fmt", "%O%n%N%n%A%n%Z %C", + "fmt", "%N%n%O%n%A%n%Z %C", "require", "ACZ", }), DM(new String[]{ -- cgit v1.2.3 From f924b7dfea039ad262f25c2d19fb9bd4905b96e8 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Thu, 10 Jul 2014 17:58:38 +0000 Subject: Avoid string copying in json.cc. The following two methods: bool Json::HasStringValueForKey(const std::string& key) const; std::string Json::GetStringValueForKey(const std::string& key) const; have been replaced with a single method: bool Json::GetStringValueForKey(const std::string& key, std::string* value) const; to avoid copying possibly large strings. BUG=8 R=roubert@google.com Review URL: https://codereview.appspot.com/112940044 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@303 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/src/preload_supplier.cc | 4 +-- cpp/src/rule.cc | 77 +++++++++++++++++---------------------------- cpp/src/util/json.cc | 22 ++++++------- cpp/src/util/json.h | 14 +++------ cpp/test/util/json_test.cc | 42 +++++++++++++++---------- 5 files changed, 70 insertions(+), 89 deletions(-) diff --git a/cpp/src/preload_supplier.cc b/cpp/src/preload_supplier.cc index 31325bd..c613d3c 100644 --- a/cpp/src/preload_supplier.cc +++ b/cpp/src/preload_supplier.cc @@ -105,6 +105,7 @@ class Helper { (void)status; // Prevent unused variable if assert() is optimized away. Json json; + std::string id; std::vector sub_rules; if (!success) { @@ -124,11 +125,10 @@ class Helper { } const Json& value = json.GetDictionaryValueForKey(*it); - if (!value.HasStringValueForKey("id")) { + if (!value.GetStringValueForKey("id", &id)) { success = false; goto callback; } - const std::string& id = value.GetStringValueForKey("id"); assert(*it == id); // Sanity check. size_t depth = std::count(id.begin(), id.end(), '/') - 1; diff --git a/cpp/src/rule.cc b/cpp/src/rule.cc index b4d03ca..4d1cff5 100644 --- a/cpp/src/rule.cc +++ b/cpp/src/rule.cc @@ -38,20 +38,6 @@ namespace { typedef std::map NameMessageIdMap; -const char kAdminAreaNameTypeKey[] = "state_name_type"; -const char kFormatKey[] = "fmt"; -const char kIdKey[] = "id"; -const char kLanguagesKey[] = "languages"; -const char kLatinFormatKey[] = "lfmt"; -const char kLatinNameKey[] = "lname"; -const char kNameKey[] = "name"; -const char kPostalCodeNameTypeKey[] = "zip_name_type"; -const char kRequireKey[] = "require"; -const char kSubKeysKey[] = "sub_keys"; -const char kZipKey[] = "zip"; -const char kPostalCodeExampleKey[] = "zipex"; -const char kPostServiceUrlKey[] = "posturl"; - // Used as a separator in a list of items. For example, the list of supported // languages can be "de~fr~it". const char kSeparator = '~'; @@ -182,36 +168,33 @@ bool Rule::ParseSerializedRule(const std::string& serialized_rule) { } void Rule::ParseJsonRule(const Json& json) { - if (json.HasStringValueForKey(kIdKey)) { - id_ = json.GetStringValueForKey(kIdKey); + std::string value; + if (json.GetStringValueForKey("id", &value)) { + id_.swap(value); } - if (json.HasStringValueForKey(kFormatKey)) { - ParseFormatRule(json.GetStringValueForKey(kFormatKey), &format_); + if (json.GetStringValueForKey("fmt", &value)) { + ParseFormatRule(value, &format_); } - if (json.HasStringValueForKey(kLatinFormatKey)) { - ParseFormatRule(json.GetStringValueForKey(kLatinFormatKey), &latin_format_); + if (json.GetStringValueForKey("lfmt", &value)) { + ParseFormatRule(value, &latin_format_); } - if (json.HasStringValueForKey(kRequireKey)) { - ParseAddressFieldsRequired( - json.GetStringValueForKey(kRequireKey), &required_); + if (json.GetStringValueForKey("require", &value)) { + ParseAddressFieldsRequired(value, &required_); } - if (json.HasStringValueForKey(kSubKeysKey)) { - SplitString( - json.GetStringValueForKey(kSubKeysKey), kSeparator, &sub_keys_); + if (json.GetStringValueForKey("sub_keys", &value)) { + SplitString(value, kSeparator, &sub_keys_); } - if (json.HasStringValueForKey(kLanguagesKey)) { - SplitString( - json.GetStringValueForKey(kLanguagesKey), kSeparator, &languages_); + if (json.GetStringValueForKey("languages", &value)) { + SplitString(value, kSeparator, &languages_); } sole_postal_code_.clear(); - if (json.HasStringValueForKey(kZipKey)) { - const std::string& zip = json.GetStringValueForKey(kZipKey); + if (json.GetStringValueForKey("zip", &value)) { // The "zip" field in the JSON data is used in two different ways to // validate the postal code. At the country level, the "zip" field indicates // a Java compatible regular expression corresponding to all postal codes in @@ -225,7 +208,7 @@ void Rule::ParseJsonRule(const Json& json) { // RE2::FullMatch() to perform matching against the entire string. RE2::Options options; options.set_never_capture(true); - RE2* matcher = new RE2("^(" + zip + ")", options); + RE2* matcher = new RE2("^(" + value + ")", options); if (matcher->ok()) { postal_code_matcher_.reset(new RE2ptr(matcher)); } else { @@ -234,37 +217,35 @@ void Rule::ParseJsonRule(const Json& json) { } // If the "zip" field is not a regular expression, then it is the sole // postal code for this rule. - if (!ContainsRegExSpecialCharacters(zip)) { - sole_postal_code_ = zip; + if (!ContainsRegExSpecialCharacters(value)) { + sole_postal_code_.swap(value); } } - if (json.HasStringValueForKey(kAdminAreaNameTypeKey)) { + if (json.GetStringValueForKey("state_name_type", &value)) { admin_area_name_message_id_ = - GetMessageIdFromName(json.GetStringValueForKey(kAdminAreaNameTypeKey), - GetAdminAreaMessageIds()); + GetMessageIdFromName(value, GetAdminAreaMessageIds()); } - if (json.HasStringValueForKey(kPostalCodeNameTypeKey)) { + if (json.GetStringValueForKey("zip_name_type", &value)) { postal_code_name_message_id_ = - GetMessageIdFromName(json.GetStringValueForKey(kPostalCodeNameTypeKey), - GetPostalCodeMessageIds()); + GetMessageIdFromName(value, GetPostalCodeMessageIds()); } - if (json.HasStringValueForKey(kNameKey)) { - name_ = json.GetStringValueForKey(kNameKey); + if (json.GetStringValueForKey("name", &value)) { + name_.swap(value); } - if (json.HasStringValueForKey(kLatinNameKey)) { - latin_name_ = json.GetStringValueForKey(kLatinNameKey); + if (json.GetStringValueForKey("lname", &value)) { + latin_name_.swap(value); } - if (json.HasStringValueForKey(kPostalCodeExampleKey)) { - postal_code_example_ = json.GetStringValueForKey(kPostalCodeExampleKey); + if (json.GetStringValueForKey("zipex", &value)) { + postal_code_example_.swap(value); } - if (json.HasStringValueForKey(kPostServiceUrlKey)) { - post_service_url_ = json.GetStringValueForKey(kPostServiceUrlKey); + if (json.GetStringValueForKey("posturl", &value)) { + post_service_url_.swap(value); } } diff --git a/cpp/src/util/json.cc b/cpp/src/util/json.cc index d819bb2..352c62b 100644 --- a/cpp/src/util/json.cc +++ b/cpp/src/util/json.cc @@ -139,23 +139,19 @@ const std::vector& Json::GetKeys() const { return impl_->GetKeys(); } -bool Json::HasStringValueForKey(const std::string& key) const { - assert(impl_ != NULL); - - // Member is owned by impl_. - const Value::Member* member = impl_->FindMember(key); - return member != NULL && member->value.IsString(); -} - -std::string Json::GetStringValueForKey(const std::string& key) const { +bool Json::GetStringValueForKey(const std::string& key, + std::string* value) const { assert(impl_ != NULL); + assert(value != NULL); // Member is owned by impl_. const Value::Member* member = impl_->FindMember(key.c_str()); - assert(member != NULL); - assert(member->value.IsString()); - return std::string(member->value.GetString(), - member->value.GetStringLength()); + if (member == NULL || !member->value.IsString()) { + return false; + } + + value->assign(member->value.GetString(), member->value.GetStringLength()); + return true; } bool Json::HasDictionaryValueForKey(const std::string& key) const { diff --git a/cpp/src/util/json.h b/cpp/src/util/json.h index 1fbf500..90565e6 100644 --- a/cpp/src/util/json.h +++ b/cpp/src/util/json.h @@ -43,15 +43,11 @@ class Json { // successfully in ParseObject() before invoking this method. const std::vector& GetKeys() const; - // Returns true if the parsed JSON contains a string value for |key|. The JSON - // object must be parsed successfully in ParseObject() before invoking this - // method. - bool HasStringValueForKey(const std::string& key) const; - - // Returns the string value for the |key|. The |key| must be present and its - // value must be of string type, i.e., HasStringValueForKey(key) must return - // true before invoking this method. - std::string GetStringValueForKey(const std::string& key) const; + // Returns true if the parsed JSON contains a string value for |key|. Sets + // |value| to the string value of the |key|. The JSON object must be parsed + // successfully in ParseObject() before invoking this method. The |value| + // parameter should not be NULL. + bool GetStringValueForKey(const std::string& key, std::string* value) const; // Returns true if the parsed JSON contains a dictionary value for |key|. The // JSON object must be parsed successfully in ParseObject() before invoking diff --git a/cpp/test/util/json_test.cc b/cpp/test/util/json_test.cc index f6eb389..a3b9f80 100644 --- a/cpp/test/util/json_test.cc +++ b/cpp/test/util/json_test.cc @@ -32,8 +32,9 @@ TEST(JsonTest, EmptyStringIsNotValid) { TEST(JsonTest, EmptyDictionaryContainsNoKeys) { Json json; ASSERT_TRUE(json.ParseObject("{}")); - EXPECT_FALSE(json.HasStringValueForKey("key")); - EXPECT_FALSE(json.HasStringValueForKey(std::string())); + std::string not_checked; + EXPECT_FALSE(json.GetStringValueForKey("key", ¬_checked)); + EXPECT_FALSE(json.GetStringValueForKey(std::string(), ¬_checked)); } TEST(JsonTest, InvalidJsonIsNotValid) { @@ -44,35 +45,40 @@ TEST(JsonTest, InvalidJsonIsNotValid) { TEST(JsonTest, OneKeyIsValid) { Json json; ASSERT_TRUE(json.ParseObject("{\"key\": \"value\"}")); - ASSERT_TRUE(json.HasStringValueForKey("key")); - EXPECT_EQ("value", json.GetStringValueForKey("key")); + std::string value; + EXPECT_TRUE(json.GetStringValueForKey("key", &value)); + EXPECT_EQ("value", value); } TEST(JsonTest, EmptyStringKeyIsNotInObject) { Json json; ASSERT_TRUE(json.ParseObject("{\"key\": \"value\"}")); - EXPECT_FALSE(json.HasStringValueForKey(std::string())); + std::string not_checked; + EXPECT_FALSE(json.GetStringValueForKey(std::string(), ¬_checked)); } TEST(JsonTest, EmptyKeyIsValid) { Json json; ASSERT_TRUE(json.ParseObject("{\"\": \"value\"}")); - ASSERT_TRUE(json.HasStringValueForKey(std::string())); - EXPECT_EQ("value", json.GetStringValueForKey(std::string())); + std::string value; + EXPECT_TRUE(json.GetStringValueForKey(std::string(), &value)); + EXPECT_EQ("value", value); } TEST(JsonTest, EmptyValueIsValid) { Json json; ASSERT_TRUE(json.ParseObject("{\"key\": \"\"}")); - ASSERT_TRUE(json.HasStringValueForKey("key")); - EXPECT_TRUE(json.GetStringValueForKey("key").empty()); + std::string value; + EXPECT_TRUE(json.GetStringValueForKey("key", &value)); + EXPECT_TRUE(value.empty()); } TEST(JsonTest, Utf8EncodingIsValid) { Json json; ASSERT_TRUE(json.ParseObject("{\"key\": \"Ü\"}")); - ASSERT_TRUE(json.HasStringValueForKey("key")); - EXPECT_EQ("Ü", json.GetStringValueForKey("key")); + std::string value; + EXPECT_TRUE(json.GetStringValueForKey("key", &value)); + EXPECT_EQ("Ü", value); } TEST(JsonTest, InvalidUtf8IsNotValid) { @@ -89,11 +95,12 @@ TEST(JsonTest, NullInMiddleIsNotValid) { TEST(JsonTest, TwoKeysAreValid) { Json json; ASSERT_TRUE(json.ParseObject("{\"key1\": \"value1\", \"key2\": \"value2\"}")); - ASSERT_TRUE(json.HasStringValueForKey("key1")); - EXPECT_EQ("value1", json.GetStringValueForKey("key1")); + std::string value; + EXPECT_TRUE(json.GetStringValueForKey("key1", &value)); + EXPECT_EQ("value1", value); - ASSERT_TRUE(json.HasStringValueForKey("key2")); - EXPECT_EQ("value2", json.GetStringValueForKey("key2")); + EXPECT_TRUE(json.GetStringValueForKey("key2", &value)); + EXPECT_EQ("value2", value); } TEST(JsonTest, ListIsNotValid) { @@ -122,8 +129,9 @@ TEST(JsonTest, DictionaryFound) { ASSERT_TRUE(json.ParseObject("{\"key\":{\"inner_key\":\"value\"}}")); ASSERT_TRUE(json.HasDictionaryValueForKey("key")); const Json& sub_json = json.GetDictionaryValueForKey("key"); - ASSERT_TRUE(sub_json.HasStringValueForKey("inner_key")); - EXPECT_EQ("value", sub_json.GetStringValueForKey("inner_key")); + std::string value; + EXPECT_TRUE(sub_json.GetStringValueForKey("inner_key", &value)); + EXPECT_EQ("value", value); } TEST(JsonTest, DictionariesHaveKeys) { -- cgit v1.2.3 From a57ef0537f86a6ef2288016e767ea095afc11334 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Fri, 11 Jul 2014 01:30:08 +0000 Subject: Move kStringCompare from file-level to method level static. Chromium prohibits static initializers. It uses the following tool to print out the list of static initializers: https://code.google.com/p/chromium/codesearch#chromium/src/tools/linux/dump-static-initializers.py Running the tool on out/Release/chrome linked with libaddressinput results in the following output: preload_supplier.cc (initializer offset 0x9e4a20 size 0x39) .str2+0x40 i18n::addressinput::(anonymous namespace)::IndexLess::kStringCompare i18n::addressinput::StringCompare::StringCompare() __asan_after_dynamic_init __asan_before_dynamic_init __interceptor___cxa_atexit TBR=roubert@google.com Review URL: https://codereview.appspot.com/114720043 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@304 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/src/preload_supplier.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/src/preload_supplier.cc b/cpp/src/preload_supplier.cc index c613d3c..3f3dc0e 100644 --- a/cpp/src/preload_supplier.cc +++ b/cpp/src/preload_supplier.cc @@ -53,15 +53,11 @@ class IndexLess : public std::binary_function { public: result_type operator()(const first_argument_type& a, const second_argument_type& b) const { + static const StringCompare kStringCompare; return kStringCompare.NaturalLess(a, b); } - - private: - static const StringCompare kStringCompare; }; -const StringCompare IndexLess::kStringCompare; - } // namespace class IndexMap : public std::map {}; -- cgit v1.2.3 From 790e435e19c39de8c6d57ef82480fd44571f9003 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Sat, 12 Jul 2014 01:36:05 +0000 Subject: Expose GetLineSeparatorForLanguage in address_formatter.h Chromium uses the separator to collapse multi-line parts of autofill profile into a single line, street address lines, names, emails, and phone numbers. TBR=lararennie@google.com Review URL: https://codereview.appspot.com/116750043 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@305 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/include/libaddressinput/address_formatter.h | 4 ++ cpp/src/address_formatter.cc | 80 ++++++++++++------------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/cpp/include/libaddressinput/address_formatter.h b/cpp/include/libaddressinput/address_formatter.h index e267884..3ac94c3 100644 --- a/cpp/include/libaddressinput/address_formatter.h +++ b/cpp/include/libaddressinput/address_formatter.h @@ -45,6 +45,10 @@ void GetFormattedNationalAddressLine( void GetStreetAddressLinesAsSingleLine( const AddressData& address_data, std::string* line); +// Returns the separator used for collapsing multiple parts of an address into a +// single line. +std::string GetLineSeparatorForLanguage(const std::string& language_tag); + } // namespace addressinput } // namespace i18n diff --git a/cpp/src/address_formatter.cc b/cpp/src/address_formatter.cc index f4fc04d..da5bd07 100644 --- a/cpp/src/address_formatter.cc +++ b/cpp/src/address_formatter.cc @@ -66,46 +66,6 @@ const char* kLanguagesThatUseAnArabicComma[] = { "uz" }; -std::string GetLineSeparatorForLanguage(const std::string& language_tag) { - Language address_language(language_tag); - - // First deal with explicit script tags. - if (address_language.has_latin_script) { - return kCommaSeparator; - } - - // Now guess something appropriate based on the base language. - const std::string& base_language = address_language.base; - if (std::find_if(kLanguagesThatUseSpace, - kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace), - std::bind2nd(EqualToTolowerString(), base_language)) != - kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace)) { - return kSpaceSeparator; - } else if (std::find_if( - kLanguagesThatHaveNoSeparator, - kLanguagesThatHaveNoSeparator + - arraysize(kLanguagesThatHaveNoSeparator), - std::bind2nd(EqualToTolowerString(), base_language)) != - kLanguagesThatHaveNoSeparator + - arraysize(kLanguagesThatHaveNoSeparator)) { - return ""; - } else if (std::find_if( - kLanguagesThatUseAnArabicComma, - kLanguagesThatUseAnArabicComma + - arraysize(kLanguagesThatUseAnArabicComma), - std::bind2nd(EqualToTolowerString(), base_language)) != - kLanguagesThatUseAnArabicComma + - arraysize(kLanguagesThatUseAnArabicComma)) { - return kArabicCommaSeparator; - } - // Either the language is a latin-script language, or no language was - // specified. In the latter case we still return ", " as the most common - // separator in use. In countries that don't use this, e.g. Thailand, - // addresses are often written in latin script where this would still be - // appropriate, so this is a reasonable default in the absence of information. - return kCommaSeparator; -} - void CombineLinesForLanguage( const std::vector& lines, const std::string& language_tag, std::string *line) { @@ -186,5 +146,45 @@ void GetStreetAddressLinesAsSingleLine( address_data.address_line, address_data.language_code, line); } +std::string GetLineSeparatorForLanguage(const std::string& language_tag) { + Language address_language(language_tag); + + // First deal with explicit script tags. + if (address_language.has_latin_script) { + return kCommaSeparator; + } + + // Now guess something appropriate based on the base language. + const std::string& base_language = address_language.base; + if (std::find_if(kLanguagesThatUseSpace, + kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace), + std::bind2nd(EqualToTolowerString(), base_language)) != + kLanguagesThatUseSpace + arraysize(kLanguagesThatUseSpace)) { + return kSpaceSeparator; + } else if (std::find_if( + kLanguagesThatHaveNoSeparator, + kLanguagesThatHaveNoSeparator + + arraysize(kLanguagesThatHaveNoSeparator), + std::bind2nd(EqualToTolowerString(), base_language)) != + kLanguagesThatHaveNoSeparator + + arraysize(kLanguagesThatHaveNoSeparator)) { + return ""; + } else if (std::find_if( + kLanguagesThatUseAnArabicComma, + kLanguagesThatUseAnArabicComma + + arraysize(kLanguagesThatUseAnArabicComma), + std::bind2nd(EqualToTolowerString(), base_language)) != + kLanguagesThatUseAnArabicComma + + arraysize(kLanguagesThatUseAnArabicComma)) { + return kArabicCommaSeparator; + } + // Either the language is a latin-script language, or no language was + // specified. In the latter case we still return ", " as the most common + // separator in use. In countries that don't use this, e.g. Thailand, + // addresses are often written in latin script where this would still be + // appropriate, so this is a reasonable default in the absence of information. + return kCommaSeparator; +} + } // namespace addressinput } // namespace i18n -- cgit v1.2.3