Browse Source

loading metadata from file added

pull/3185/head
Denys Ponomarenko 2 years ago
parent
commit
f20f72b20e
6 changed files with 171 additions and 27 deletions
  1. +1
    -1
      cpp/CMakeLists.txt
  2. +102
    -19
      cpp/src/phonenumbers/phonenumberutil.cc
  3. +8
    -0
      cpp/src/phonenumbers/phonenumberutil.h
  4. +43
    -5
      cpp/src/phonenumbers/shortnumberinfo.cc
  5. +7
    -1
      cpp/src/phonenumbers/shortnumberinfo.h
  6. +10
    -1
      cpp/test/phonenumbers/phonenumberutil_test.cc

+ 1
- 1
cpp/CMakeLists.txt View File

@ -151,7 +151,7 @@ if (USE_BOOST)
if (WIN32) if (WIN32)
set (Boost_USE_STATIC_LIBS ON) set (Boost_USE_STATIC_LIBS ON)
endif () endif ()
find_package (Boost 1.40.0 COMPONENTS date_time system thread)
find_package (Boost 1.40.0 COMPONENTS date_time system filesystem thread)
if (NOT Boost_FOUND) if (NOT Boost_FOUND)
print_error ("Boost Date_Time/System/Thread" "Boost") print_error ("Boost Date_Time/System/Thread" "Boost")
endif () endif ()


+ 102
- 19
cpp/src/phonenumbers/phonenumberutil.cc View File

@ -21,7 +21,7 @@
#include <map> #include <map>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <boost/filesystem.hpp>
#include <unicode/uchar.h> #include <unicode/uchar.h>
#include <unicode/utf8.h> #include <unicode/utf8.h>
@ -34,7 +34,6 @@
#include "phonenumbers/matcher_api.h" #include "phonenumbers/matcher_api.h"
#include "phonenumbers/metadata.h" #include "phonenumbers/metadata.h"
#include "phonenumbers/normalize_utf8.h" #include "phonenumbers/normalize_utf8.h"
#include "phonenumbers/phonemetadata.pb.h"
#include "phonenumbers/phonenumber.h" #include "phonenumbers/phonenumber.h"
#include "phonenumbers/phonenumber.pb.h" #include "phonenumbers/phonenumber.pb.h"
#include "phonenumbers/regex_based_matcher.h" #include "phonenumbers/regex_based_matcher.h"
@ -47,6 +46,8 @@
#include "phonenumbers/utf/unicodetext.h" #include "phonenumbers/utf/unicodetext.h"
#include "phonenumbers/utf/utf.h" #include "phonenumbers/utf/utf.h"
#include <fstream>
namespace i18n { namespace i18n {
namespace phonenumbers { namespace phonenumbers {
@ -121,6 +122,21 @@ const char kPossibleCharsAfterExtLabel[] =
"[:\\.\xEF\xBC\x8E]?[ \xC2\xA0\\t,-]*"; "[:\\.\xEF\xBC\x8E]?[ \xC2\xA0\\t,-]*";
const char kOptionalExtSuffix[] = "#?"; const char kOptionalExtSuffix[] = "#?";
const string METADATA_FILE_NAME = "metadata.dat";
#ifdef ISTREAM_DATA_PROVIDER
bool LoadMetadataFromFile(const string& fileName, PhoneMetadataCollection* metadata) {
std::fstream input(fileName.c_str(), std::ios::in | std::ios::binary);
if (!input) {
LOG(ERROR) << "metadata file not found.";
} else if (!metadata->ParseFromIstream(&input)) {
LOG(ERROR) << "Could not parse binary data from file.";
return false;
}
return true;
}
#else
bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) { bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
if (!metadata->ParseFromArray(metadata_get(), metadata_size())) { if (!metadata->ParseFromArray(metadata_get(), metadata_size())) {
LOG(ERROR) << "Could not parse binary data."; LOG(ERROR) << "Could not parse binary data.";
@ -128,6 +144,7 @@ bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
} }
return true; return true;
} }
#endif // ISTREAM_DATA_PROVIDER
// Returns a pointer to the description inside the metadata of the appropriate // Returns a pointer to the description inside the metadata of the appropriate
// type. // type.
@ -846,25 +863,62 @@ class PhoneNumberRegExpsAndMappings {
DISALLOW_COPY_AND_ASSIGN(PhoneNumberRegExpsAndMappings); DISALLOW_COPY_AND_ASSIGN(PhoneNumberRegExpsAndMappings);
}; };
// Private constructor. Also takes care of initialisation.
PhoneNumberUtil::PhoneNumberUtil()
: logger_(Logger::set_logger_impl(new NullLogger())),
matcher_api_(new RegexBasedMatcher()),
reg_exps_(new PhoneNumberRegExpsAndMappings),
country_calling_code_to_region_code_map_(
new std::vector<IntRegionsPair>()),
nanpa_regions_(new absl::node_hash_set<string>()),
region_to_metadata_map_(new absl::node_hash_map<string, PhoneMetadata>()),
country_code_to_non_geographical_metadata_map_(
new absl::node_hash_map<int, PhoneMetadata>) {
Logger::set_logger_impl(logger_.get());
// TODO: Update the java version to put the contents of the init
// method inside the constructor as well to keep both in sync.
#ifdef ISTREAM_DATA_PROVIDER
void PhoneNumberUtil::ClearMetadata() {
country_code_to_non_geographical_metadata_map_->clear();
region_to_metadata_map_->clear();
gtl::STLDeleteContainerPairSecondPointers(
country_calling_code_to_region_code_map_->begin(),
country_calling_code_to_region_code_map_->end());
country_calling_code_to_region_code_map_->clear();
nanpa_regions_->clear();
}
bool UpdateMetadataFile(const string& filepath) {
boost::filesystem::path path_to = boost::filesystem::current_path();
path_to += "/";
path_to += METADATA_FILE_NAME;
boost::filesystem::path path_bk = path_to;
path_bk += ".bak";
boost::system::error_code ec;
boost::filesystem::copy(path_to.string(), path_bk.string(), ec);
if (ec) {
LOG(DFATAL) << "Could not create backup copy of metadata file." << ec.message();
return false;
}
boost::filesystem::rename(filepath, path_to.string(), ec);
if(ec) {
LOG(DFATAL) << "Could not rename metadata file." << ec.message();
return false;
}
boost::filesystem::remove(path_bk, ec);
if(ec) {
LOG(DFATAL) << "Could not remove metadata file." << ec.message();
}
return true;
}
bool PhoneNumberUtil::ReloadMetadata(const string& filepath) {
ClearMetadata();
PhoneMetadataCollection metadata_collection; PhoneMetadataCollection metadata_collection;
if (!LoadCompiledInMetadata(&metadata_collection)) {
LOG(DFATAL) << "Could not parse compiled-in metadata.";
return;
if (!LoadMetadataFromFile(filepath, &metadata_collection)) {
LOG(DFATAL) << "Could not parse metadata from file.";
return false;
}
LoadMetadataFromCollection(metadata_collection);
if(!UpdateMetadataFile(filepath)){
LOG(DFATAL) << "Could not update metadata file.";
return false;
} }
return true;
}
#endif // ISTREAM_DATA_PROVIDER
void PhoneNumberUtil::LoadMetadataFromCollection(const PhoneMetadataCollection& metadata_collection) {
// Storing data in a temporary map to make it easier to find other regions // Storing data in a temporary map to make it easier to find other regions
// that share a country calling code when inserting data. // that share a country calling code when inserting data.
std::map<int, std::list<string>* > country_calling_code_to_region_map; std::map<int, std::list<string>* > country_calling_code_to_region_map;
@ -913,6 +967,35 @@ PhoneNumberUtil::PhoneNumberUtil()
country_calling_code_to_region_code_map_->end(), OrderByFirst()); country_calling_code_to_region_code_map_->end(), OrderByFirst());
} }
// Private constructor. Also takes care of initialisation.
PhoneNumberUtil::PhoneNumberUtil()
: logger_(Logger::set_logger_impl(new NullLogger())),
matcher_api_(new RegexBasedMatcher()),
reg_exps_(new PhoneNumberRegExpsAndMappings),
country_calling_code_to_region_code_map_(
new std::vector<IntRegionsPair>()),
nanpa_regions_(new absl::node_hash_set<string>()),
region_to_metadata_map_(new absl::node_hash_map<string, PhoneMetadata>()),
country_code_to_non_geographical_metadata_map_(
new absl::node_hash_map<int, PhoneMetadata>) {
Logger::set_logger_impl(logger_.get());
// TODO: Update the java version to put the contents of the init
// method inside the constructor as well to keep both in sync.
PhoneMetadataCollection metadata_collection;
#ifdef ISTREAM_DATA_PROVIDER
if (!LoadMetadataFromFile(METADATA_FILE_NAME, &metadata_collection)) {
LOG(DFATAL) << "Could not parse metadata from file.";
return;
}
#else
if (!LoadCompiledInMetadata(&metadata_collection)) {
LOG(DFATAL) << "Could not parse compiled-in metadata.";
return;
}
#endif // ISTREAM_DATA_PROVIDER
LoadMetadataFromCollection(metadata_collection);
}
PhoneNumberUtil::~PhoneNumberUtil() { PhoneNumberUtil::~PhoneNumberUtil() {
gtl::STLDeleteContainerPairSecondPointers( gtl::STLDeleteContainerPairSecondPointers(
country_calling_code_to_region_code_map_->begin(), country_calling_code_to_region_code_map_->begin(),


+ 8
- 0
cpp/src/phonenumbers/phonenumberutil.h View File

@ -30,6 +30,7 @@
#include "phonenumbers/base/memory/singleton.h" #include "phonenumbers/base/memory/singleton.h"
#include "phonenumbers/phonenumber.pb.h" #include "phonenumbers/phonenumber.pb.h"
#include "phonenumbers/phonemetadata.pb.h"
#include "absl/container/node_hash_set.h" #include "absl/container/node_hash_set.h"
#include "absl/container/node_hash_map.h" #include "absl/container/node_hash_map.h"
@ -67,6 +68,11 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
friend class ShortNumberInfoTest; friend class ShortNumberInfoTest;
friend class Singleton<PhoneNumberUtil>; friend class Singleton<PhoneNumberUtil>;
#ifdef ISTREAM_DATA_PROVIDER
void ClearMetadata();
public:
bool ReloadMetadata(const string& fileName);
#endif // ISTREAM_DATA_PROVIDER
public: public:
~PhoneNumberUtil(); ~PhoneNumberUtil();
static const char kRegionCodeForNonGeoEntity[]; static const char kRegionCodeForNonGeoEntity[];
@ -818,10 +824,12 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// PhoneMetadata for that country calling code. Examples of the country // PhoneMetadata for that country calling code. Examples of the country
// calling codes include 800 (International Toll Free Service) and 808 // calling codes include 800 (International Toll Free Service) and 808
// (International Shared Cost Service). // (International Shared Cost Service).
scoped_ptr<absl::node_hash_map<int, PhoneMetadata> > scoped_ptr<absl::node_hash_map<int, PhoneMetadata> >
country_code_to_non_geographical_metadata_map_; country_code_to_non_geographical_metadata_map_;
PhoneNumberUtil(); PhoneNumberUtil();
void LoadMetadataFromCollection(const PhoneMetadataCollection& metadata_collection);
// Returns a regular expression for the possible extensions that may be found // Returns a regular expression for the possible extensions that may be found
// in a number, for use when matching. // in a number, for use when matching.


+ 43
- 5
cpp/src/phonenumbers/shortnumberinfo.cc View File

@ -26,6 +26,7 @@
#include "phonenumbers/regex_based_matcher.h" #include "phonenumbers/regex_based_matcher.h"
#include "phonenumbers/region_code.h" #include "phonenumbers/region_code.h"
#include "phonenumbers/short_metadata.h" #include "phonenumbers/short_metadata.h"
#include <fstream>
namespace i18n { namespace i18n {
namespace phonenumbers { namespace phonenumbers {
@ -34,6 +35,30 @@ using google::protobuf::RepeatedField;
using std::map; using std::map;
using std::string; using std::string;
#ifdef ISTREAM_DATA_PROVIDER
bool LoadMetadataFromFile(string fileName, PhoneMetadataCollection* metadata) {
std::fstream input(fileName.c_str(), std::ios::in | std::ios::binary);
if (!input) {
LOG(ERROR) << "metadata file not found.";
} else if (!metadata->ParseFromIstream(&input)) {
LOG(ERROR) << "Could not parse binary data from file.";
return false;
}
return true;
}
void ShortNumberInfo::ClearMetadata(){
region_to_short_metadata_map_->clear();
regions_where_emergency_numbers_must_be_exact_->clear();
}
void ShortNumberInfo::ReloadMetadata() {
ClearMetadata();
LoadMetadata();
}
#else
bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) { bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
if (!metadata->ParseFromArray(short_metadata_get(), short_metadata_size())) { if (!metadata->ParseFromArray(short_metadata_get(), short_metadata_size())) {
LOG(ERROR) << "Could not parse binary data."; LOG(ERROR) << "Could not parse binary data.";
@ -41,17 +66,22 @@ bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
} }
return true; return true;
} }
#endif // ISTREAM_DATA_PROVIDER
ShortNumberInfo::ShortNumberInfo()
: phone_util_(*PhoneNumberUtil::GetInstance()),
matcher_api_(new RegexBasedMatcher()),
region_to_short_metadata_map_(new absl::flat_hash_map<string, PhoneMetadata>()),
regions_where_emergency_numbers_must_be_exact_(new absl::flat_hash_set<string>()) {
void ShortNumberInfo::LoadMetadata() {
PhoneMetadataCollection metadata_collection; PhoneMetadataCollection metadata_collection;
#ifdef ISTREAM_DATA_PROVIDER
const string metadataInputFile = "metadata_short.dat";
if (!LoadMetadataFromFile(metadataInputFile, &metadata_collection)) {
LOG(DFATAL) << "Could not parse metadata from file.";
return;
}
#else
if (!LoadCompiledInMetadata(&metadata_collection)) { if (!LoadCompiledInMetadata(&metadata_collection)) {
LOG(DFATAL) << "Could not parse compiled-in metadata."; LOG(DFATAL) << "Could not parse compiled-in metadata.";
return; return;
} }
#endif // ISTREAM_DATA_PROVIDER
for (const auto& metadata : metadata_collection.metadata()) { for (const auto& metadata : metadata_collection.metadata()) {
const string& region_code = metadata.id(); const string& region_code = metadata.id();
region_to_short_metadata_map_->insert(std::make_pair(region_code, metadata)); region_to_short_metadata_map_->insert(std::make_pair(region_code, metadata));
@ -61,6 +91,14 @@ ShortNumberInfo::ShortNumberInfo()
regions_where_emergency_numbers_must_be_exact_->insert("NI"); regions_where_emergency_numbers_must_be_exact_->insert("NI");
} }
ShortNumberInfo::ShortNumberInfo()
: phone_util_(*PhoneNumberUtil::GetInstance()),
matcher_api_(new RegexBasedMatcher()),
region_to_short_metadata_map_(new absl::flat_hash_map<string, PhoneMetadata>()),
regions_where_emergency_numbers_must_be_exact_(new absl::flat_hash_set<string>()) {
LoadMetadata();
}
ShortNumberInfo::~ShortNumberInfo() {} ShortNumberInfo::~ShortNumberInfo() {}
// Returns a pointer to the phone metadata for the appropriate region or NULL // Returns a pointer to the phone metadata for the appropriate region or NULL


+ 7
- 1
cpp/src/phonenumbers/shortnumberinfo.h View File

@ -46,7 +46,12 @@ class ShortNumberInfo {
public: public:
ShortNumberInfo(); ShortNumberInfo();
~ShortNumberInfo(); ~ShortNumberInfo();
#ifdef ISTREAM_DATA_PROVIDER
private:
void ClearMetadata();
public:
void ReloadMetadata();
#endif // ISTREAM_DATA_PROVIDER
// Cost categories of short numbers. // Cost categories of short numbers.
enum ShortNumberCost { enum ShortNumberCost {
TOLL_FREE, TOLL_FREE,
@ -206,6 +211,7 @@ class ShortNumberInfo {
bool MatchesEmergencyNumberHelper(const string& number, bool MatchesEmergencyNumberHelper(const string& number,
const string& region_code, const string& region_code,
bool allow_prefix_match) const; bool allow_prefix_match) const;
void LoadMetadata();
DISALLOW_COPY_AND_ASSIGN(ShortNumberInfo); DISALLOW_COPY_AND_ASSIGN(ShortNumberInfo);
}; };


+ 10
- 1
cpp/test/phonenumbers/phonenumberutil_test.cc View File

@ -118,7 +118,11 @@ class PhoneNumberUtilTest : public testing::Test {
phone_util_.Parse(number_to_parse, RegionCode::ZZ(), &actual_number)); phone_util_.Parse(number_to_parse, RegionCode::ZZ(), &actual_number));
} }
const PhoneNumberUtil& phone_util_;
void ReloadMetadata(const string fileName) {
phone_util_.ReloadMetadata(fileName);
}
PhoneNumberUtil& phone_util_;
private: private:
DISALLOW_COPY_AND_ASSIGN(PhoneNumberUtilTest); DISALLOW_COPY_AND_ASSIGN(PhoneNumberUtilTest);
@ -159,6 +163,11 @@ TEST_F(PhoneNumberUtilTest, InterchangeInvalidCodepoints) {
} }
} }
TEST_F(PhoneNumberUtilTest, ReloadMetadata) {
const string filename = "metadata.dat";
EXPECT_TRUE(phone_util_.ReloadMetadata(filename));
}
TEST_F(PhoneNumberUtilTest, GetSupportedRegions) { TEST_F(PhoneNumberUtilTest, GetSupportedRegions) {
std::set<string> regions; std::set<string> regions;


Loading…
Cancel
Save