Current section

Files

Jump to
elibphonenumber c_src phonenumber_util_nif.cpp
Raw

c_src/phonenumber_util_nif.cpp

#include <erl_nif.h>
#include <phonenumbers/phonenumberutil.h>
#include <phonenumbers/phonenumber.pb.h>
#include <memory>
#include <iostream>
#include <set>
#include <string>
using namespace i18n::phonenumbers;
struct atoms
{
ERL_NIF_TERM atomTrue;
ERL_NIF_TERM atomFalse;
ERL_NIF_TERM atomFixedLine;
ERL_NIF_TERM atomMobile;
ERL_NIF_TERM atomFixedLineOrMobile;
ERL_NIF_TERM atomTollFree;
ERL_NIF_TERM atomPremiumRate;
ERL_NIF_TERM atomSharedCost;
ERL_NIF_TERM atomVoip;
ERL_NIF_TERM atomPersonalNumber;
ERL_NIF_TERM atomPager;
ERL_NIF_TERM atomUan;
ERL_NIF_TERM atomVoiceMail;
ERL_NIF_TERM atomUnknown;
ERL_NIF_TERM atomIsPossible;
ERL_NIF_TERM atomInvalidContryCode;
ERL_NIF_TERM atomTooShort;
ERL_NIF_TERM atomTooLong;
ERL_NIF_TERM atomFromNumberWithPlusSign;
ERL_NIF_TERM atomFromNumberWithIdd;
ERL_NIF_TERM atomFromNumberWithoutPlusSign;
ERL_NIF_TERM atomFromDefaultCountry;
ERL_NIF_TERM atomInvalidNumber;
ERL_NIF_TERM atomNoMatch;
ERL_NIF_TERM atomShortNsmMatch;
ERL_NIF_TERM atomNsmMatch;
ERL_NIF_TERM atomExactMatch;
ERL_NIF_TERM atomFormatE164;
ERL_NIF_TERM atomFormatInternational;
ERL_NIF_TERM atomFormatNational;
ERL_NIF_TERM atomFormatRFC3966;
ERL_NIF_TERM atomPhoneNumber;
} ATOMS;
ERL_NIF_TERM make_atom(ErlNifEnv* env, const char* name)
{
ERL_NIF_TERM ret;
if(enif_make_existing_atom(env, name, &ret, ERL_NIF_LATIN1))
return ret;
return enif_make_atom(env, name);
}
int on_nif_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
ATOMS.atomTrue = make_atom(env, "true");
ATOMS.atomFalse = make_atom(env, "false");
ATOMS.atomFixedLine = make_atom(env, "fixed_line");
ATOMS.atomMobile = make_atom(env, "mobile");
ATOMS.atomFixedLineOrMobile = make_atom(env, "fixed_line_or_mobile");
ATOMS.atomTollFree = make_atom(env, "toll_free");
ATOMS.atomPremiumRate = make_atom(env, "premium_rate");
ATOMS.atomSharedCost = make_atom(env, "shared_cost");
ATOMS.atomVoip = make_atom(env, "voip");
ATOMS.atomPersonalNumber = make_atom(env, "personal_number");
ATOMS.atomPager = make_atom(env, "pager");
ATOMS.atomUan = make_atom(env, "uan");
ATOMS.atomVoiceMail = make_atom(env, "voicemail");
ATOMS.atomUnknown = make_atom(env, "unknown");
ATOMS.atomIsPossible = make_atom(env, "is_possible");
ATOMS.atomInvalidContryCode = make_atom(env, "invalid_country_code");
ATOMS.atomTooShort = make_atom(env, "too_short");
ATOMS.atomTooLong = make_atom(env, "too_long");
ATOMS.atomFromNumberWithPlusSign = make_atom(env, "from_number_with_plus_sign");
ATOMS.atomFromNumberWithIdd = make_atom(env, "from_number_with_idd");
ATOMS.atomFromNumberWithoutPlusSign = make_atom(env, "from_number_without_plus_sign");
ATOMS.atomFromDefaultCountry = make_atom(env, "from_default_country");
ATOMS.atomInvalidNumber = make_atom(env, "invalid_number");
ATOMS.atomNoMatch = make_atom(env, "no_match");
ATOMS.atomShortNsmMatch = make_atom(env, "short_nsn_match");
ATOMS.atomNsmMatch = make_atom(env, "nsn_match");
ATOMS.atomExactMatch = make_atom(env, "exact_match");
ATOMS.atomFormatE164 = make_atom(env, "e164");
ATOMS.atomFormatInternational = make_atom(env, "international");
ATOMS.atomFormatNational = make_atom(env, "national");
ATOMS.atomFormatRFC3966 = make_atom(env, "rfc3966");
ATOMS.atomPhoneNumber = make_atom(env, "phonenumber");
*priv_data = NULL;
return 0;
}
static bool term_to_phonenumber_format(const ERL_NIF_TERM term, PhoneNumberUtil::PhoneNumberFormat* number_format)
{
bool return_value = true;
if(enif_is_identical(ATOMS.atomFormatE164, term))
*number_format = PhoneNumberUtil::E164;
else if(enif_is_identical(ATOMS.atomFormatInternational, term))
*number_format = PhoneNumberUtil::INTERNATIONAL;
else if(enif_is_identical(ATOMS.atomFormatNational, term))
*number_format = PhoneNumberUtil::NATIONAL;
else if(enif_is_identical(ATOMS.atomFormatRFC3966, term))
*number_format = PhoneNumberUtil::RFC3966;
else
return_value = false;
return return_value;
}
static bool term_to_phonenumber_country_code_source(const ERL_NIF_TERM term, PhoneNumber::CountryCodeSource* country_code_source)
{
bool return_value = true;
if(enif_is_identical(ATOMS.atomFromNumberWithPlusSign, term))
*country_code_source = PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN;
else if(enif_is_identical(ATOMS.atomFromNumberWithIdd, term))
*country_code_source = PhoneNumber::FROM_NUMBER_WITH_IDD;
else if(enif_is_identical(ATOMS.atomFromNumberWithoutPlusSign, term))
*country_code_source = PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN;
else if(enif_is_identical(ATOMS.atomFromDefaultCountry, term))
*country_code_source = PhoneNumber::FROM_DEFAULT_COUNTRY;
else
return_value = false;
return return_value;
}
static bool term_to_phonenumber_type(const ERL_NIF_TERM term, PhoneNumberUtil::PhoneNumberType* type)
{
bool return_value = true;
if(enif_is_identical(ATOMS.atomFixedLine, term))
*type = PhoneNumberUtil::FIXED_LINE;
else if(enif_is_identical(ATOMS.atomMobile, term))
*type = PhoneNumberUtil::MOBILE;
else if(enif_is_identical(ATOMS.atomFixedLineOrMobile, term))
*type = PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
else if(enif_is_identical(ATOMS.atomTollFree, term))
*type = PhoneNumberUtil::TOLL_FREE;
else if(enif_is_identical(ATOMS.atomPremiumRate, term))
*type = PhoneNumberUtil::PREMIUM_RATE;
else if(enif_is_identical(ATOMS.atomSharedCost, term))
*type = PhoneNumberUtil::SHARED_COST;
else if(enif_is_identical(ATOMS.atomVoip, term))
*type = PhoneNumberUtil::VOIP;
else if(enif_is_identical(ATOMS.atomPersonalNumber, term))
*type = PhoneNumberUtil::PERSONAL_NUMBER;
else if(enif_is_identical(ATOMS.atomPager, term))
*type = PhoneNumberUtil::PAGER;
else if(enif_is_identical(ATOMS.atomUan, term))
*type = PhoneNumberUtil::UAN;
else if(enif_is_identical(ATOMS.atomVoiceMail, term))
*type = PhoneNumberUtil::VOICEMAIL;
else if(enif_is_identical(ATOMS.atomUnknown, term))
*type = PhoneNumberUtil::UNKNOWN;
else
return_value = false;
return return_value;
}
static bool term_to_boolean(const ERL_NIF_TERM term, bool* boolean)
{
if(enif_is_identical(term, ATOMS.atomTrue))
{
*boolean = true;
return true;
}
if(enif_is_identical(term, ATOMS.atomFalse))
{
*boolean = false;
return true;
}
return false;
}
static ERL_NIF_TERM boolean_to_term(bool boolean)
{
return boolean ? ATOMS.atomTrue : ATOMS.atomFalse;
}
static ERL_NIF_TERM phonenumber_type_to_term(PhoneNumberUtil::PhoneNumberType type)
{
switch(type)
{
case PhoneNumberUtil::FIXED_LINE:
return ATOMS.atomFixedLine;
case PhoneNumberUtil::MOBILE:
return ATOMS.atomMobile;
case PhoneNumberUtil::FIXED_LINE_OR_MOBILE:
return ATOMS.atomFixedLineOrMobile;
case PhoneNumberUtil::TOLL_FREE:
return ATOMS.atomTollFree;
case PhoneNumberUtil::PREMIUM_RATE:
return ATOMS.atomPremiumRate;
case PhoneNumberUtil::SHARED_COST:
return ATOMS.atomSharedCost;
case PhoneNumberUtil::VOIP:
return ATOMS.atomVoip;
case PhoneNumberUtil::PERSONAL_NUMBER:
return ATOMS.atomPersonalNumber;
case PhoneNumberUtil::PAGER:
return ATOMS.atomPager;
case PhoneNumberUtil::UAN:
return ATOMS.atomUan;
case PhoneNumberUtil::VOICEMAIL:
return ATOMS.atomVoiceMail;
case PhoneNumberUtil::UNKNOWN:
return ATOMS.atomUnknown;
}
return ATOMS.atomUnknown;
}
static ERL_NIF_TERM phonenumber_validation_result_to_term(PhoneNumberUtil::ValidationResult validation_result)
{
switch(validation_result)
{
case PhoneNumberUtil::IS_POSSIBLE:
return ATOMS.atomIsPossible;
case PhoneNumberUtil::INVALID_COUNTRY_CODE:
return ATOMS.atomInvalidContryCode;
case PhoneNumberUtil::TOO_SHORT:
return ATOMS.atomTooShort;
case PhoneNumberUtil::TOO_LONG:
return ATOMS.atomTooLong;
}
return ATOMS.atomInvalidContryCode;
}
static ERL_NIF_TERM phonenumber_country_code_source_to_term(ErlNifEnv* env, PhoneNumber::CountryCodeSource country_code_source)
{
switch(country_code_source)
{
case PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN:
return ATOMS.atomFromNumberWithPlusSign;
case PhoneNumber::FROM_NUMBER_WITH_IDD:
return ATOMS.atomFromNumberWithIdd;
case PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN:
return ATOMS.atomFromNumberWithoutPlusSign;
case PhoneNumber::FROM_DEFAULT_COUNTRY:
return ATOMS.atomFromDefaultCountry;
}
return ATOMS.atomFromDefaultCountry;
}
static ERL_NIF_TERM phonenumber_match_type_to_term(PhoneNumberUtil::MatchType match_type)
{
switch(match_type)
{
case PhoneNumberUtil::INVALID_NUMBER:
return ATOMS.atomInvalidNumber;
case PhoneNumberUtil::NO_MATCH:
return ATOMS.atomNoMatch;
case PhoneNumberUtil::SHORT_NSN_MATCH:
return ATOMS.atomShortNsmMatch;
case PhoneNumberUtil::NSN_MATCH:
return ATOMS.atomNsmMatch;
case PhoneNumberUtil::EXACT_MATCH:
return ATOMS.atomExactMatch;
}
return ATOMS.atomInvalidNumber;
}
static ERL_NIF_TERM phonenumber_to_term(ErlNifEnv* env, PhoneNumber phoneNumber)
{
unsigned char *buffer;
ERL_NIF_TERM raw_input;
ERL_NIF_TERM extension;
ERL_NIF_TERM preferred_domestic_carrier_code;
// required int32 country_code = 1;
ERL_NIF_TERM has_country_code = boolean_to_term(phoneNumber.has_country_code());
ERL_NIF_TERM country_code = enif_make_int(env, phoneNumber.country_code());
// required uint64 national_number = 2;
ERL_NIF_TERM has_national_number = boolean_to_term(phoneNumber.has_national_number());
ERL_NIF_TERM national_number = enif_make_ulong(env, phoneNumber.national_number());
// optional string extension = 3;
ERL_NIF_TERM has_extension = boolean_to_term(phoneNumber.has_extension());
buffer = enif_make_new_binary(env, phoneNumber.extension().size(), &extension);
std::copy(phoneNumber.extension().begin(), phoneNumber.extension().end(), buffer);
// optional bool italian_leading_zero = 4;
ERL_NIF_TERM has_italian_leading_zero = boolean_to_term(phoneNumber.has_italian_leading_zero());
ERL_NIF_TERM italian_leading_zero = boolean_to_term(phoneNumber.italian_leading_zero());
// optional int32 number_of_leading_zeros = 8 [default = 1];
ERL_NIF_TERM has_number_of_leading_zeros = boolean_to_term(phoneNumber.has_number_of_leading_zeros());
ERL_NIF_TERM number_of_leading_zeros = enif_make_int(env, phoneNumber.number_of_leading_zeros());
// optional string raw_input = 5;
ERL_NIF_TERM has_raw_input = boolean_to_term(phoneNumber.has_raw_input());
buffer = enif_make_new_binary(env, phoneNumber.raw_input().size(), &raw_input);
std::copy(phoneNumber.raw_input().begin(), phoneNumber.raw_input().end(), buffer);
// optional .i18n.phonenumbers.PhoneNumber.CountryCodeSource country_code_source = 6;
ERL_NIF_TERM has_country_code_source = boolean_to_term(phoneNumber.has_country_code_source());
ERL_NIF_TERM country_code_source = phonenumber_country_code_source_to_term(env, phoneNumber.country_code_source());
// optional string preferred_domestic_carrier_code = 7;
ERL_NIF_TERM has_preferred_domestic_carrier_code = boolean_to_term(phoneNumber.has_preferred_domestic_carrier_code());
buffer = enif_make_new_binary(env, phoneNumber.preferred_domestic_carrier_code().size(), &preferred_domestic_carrier_code);
std::copy(phoneNumber.preferred_domestic_carrier_code().begin(), phoneNumber.preferred_domestic_carrier_code().end(), buffer);
return enif_make_tuple(env, 17,
ATOMS.atomPhoneNumber,
has_country_code,
country_code,
has_national_number,
national_number,
has_extension,
extension,
has_number_of_leading_zeros,
number_of_leading_zeros,
has_italian_leading_zero,
italian_leading_zero,
has_raw_input,
raw_input,
has_country_code_source,
country_code_source,
has_preferred_domestic_carrier_code,
preferred_domestic_carrier_code);
}
static bool term_to_phonenumber(ErlNifEnv* env, const ERL_NIF_TERM term, PhoneNumber* phoneNumber)
{
int integer;
unsigned long longer; //FIXME should be unsingned long long
bool boolean;
ErlNifBinary bin;
int PhoneNumberElems;
const ERL_NIF_TERM* array;
// Get Term
if (!enif_get_tuple(env, term, &PhoneNumberElems, &array) || PhoneNumberElems != 17)
return false;
// required int32 country_code = 1;
if (!enif_get_int(env, array[2], &integer))
return false;
phoneNumber->set_country_code(integer);
// required uint64 national_number = 2;
if (!enif_get_ulong(env, array[4], &longer))
return false;
phoneNumber->set_national_number(longer);
// optional string extension = 3;
if (!term_to_boolean(array[5], &boolean))
return false;
if (boolean)
{
if (!enif_inspect_iolist_as_binary(env, array[6], &bin))
return false;
phoneNumber->set_extension(std::string ( (char*) bin.data, bin.size));
}
// optional int32 number_of_leading_zeros = 8 [default = 1];
if (!term_to_boolean(array[7], &boolean))
return false;
if (boolean)
{
if (!enif_get_int(env, array[8], &integer))
return false;
phoneNumber->set_number_of_leading_zeros(integer);
}
// optional bool italian_leading_zero = 4;
if (!term_to_boolean(array[9], &boolean))
return false;
if (boolean)
{
if (!term_to_boolean(array[10], &boolean))
return false;
phoneNumber->set_italian_leading_zero(boolean);
}
// optional string raw_input = 5;
if (!term_to_boolean(array[11], &boolean))
return false;
if (boolean)
{
if (!enif_inspect_iolist_as_binary(env, array[12], &bin))
return false;
phoneNumber->set_raw_input(std::string ( (char*) bin.data, bin.size));
}
// optional .i18n.phonenumbers.PhoneNumber.CountryCodeSource country_code_source = 6;
if (!term_to_boolean(array[13], &boolean))
return false;
if (boolean)
{
PhoneNumber::CountryCodeSource country_code_source;
if (!term_to_phonenumber_country_code_source(array[14], &country_code_source))
return false;
phoneNumber->set_country_code_source(country_code_source);
}
// Get Preferred Domestic Carrier Code
if (!term_to_boolean(array[15], &boolean))
return false;
if (boolean)
{
if (!enif_inspect_iolist_as_binary(env, array[16], &bin))
return false;
phoneNumber->set_preferred_domestic_carrier_code(std::string ( (char*) bin.data, bin.size));
}
return true;
}
// NIF functions
static ERL_NIF_TERM GetSupportedRegions_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
set<string> regions;
phone_util_->GetSupportedRegions(&regions);
unsigned int cnt = regions.size();
ERL_NIF_TERM arr[cnt];
unsigned int i = 0;
ERL_NIF_TERM ret;
unsigned char *region;
for (set<string>::iterator it=regions.begin(); it!=regions.end(); ++it, i++)
{
region = enif_make_new_binary(env, it->size(), &ret);
std::copy(it->begin(), it->end(), region);
arr[i] = ret;
ret = 0;
}
return enif_make_list_from_array(env, arr, cnt);
}
static ERL_NIF_TERM IsAlphaNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string str( (char*) bin.data, bin.size);
return boolean_to_term(phone_util_->IsAlphaNumber(str));
}
static ERL_NIF_TERM ConvertAlphaCharactersInNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string str( (char*) bin.data, bin.size);
phone_util_->ConvertAlphaCharactersInNumber(&str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM NormalizeDigitsOnly_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string str( (char*) bin.data, bin.size);
phone_util_->NormalizeDigitsOnly(&str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM NormalizeDiallableCharsOnly_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string str( (char*) bin.data, bin.size);
phone_util_->NormalizeDiallableCharsOnly(&str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM GetNationalSignificantNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string str;
phone_util_->GetNationalSignificantNumber(phoneNumber, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM GetLengthOfGeographicalAreaCode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
return enif_make_int(env, phone_util_->GetLengthOfGeographicalAreaCode(phoneNumber));
}
static ERL_NIF_TERM GetLengthOfNationalDestinationCode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
return enif_make_int(env, phone_util_->GetLengthOfNationalDestinationCode(phoneNumber));
}
static ERL_NIF_TERM GetCountryMobileToken_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
int code;
if (!enif_get_int(env, argv[0], &code))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string mobile_token;
phone_util_->GetCountryMobileToken(code, &mobile_token);
ERL_NIF_TERM ret;
unsigned char *token = enif_make_new_binary(env, mobile_token.size(), &ret);
std::copy(mobile_token.begin(), mobile_token.end(), token);
return ret;
}
static ERL_NIF_TERM Format_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil::PhoneNumberFormat phoneNumberFormat;
if (!term_to_phonenumber_format(argv[1], &phoneNumberFormat))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string str;
phone_util_->Format(phoneNumber, phoneNumberFormat, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM FormatNationalNumberWithPreferredCarrierCode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string fb_carrier_code( (char*) bin.data, bin.size);
std::string str;
phone_util_->FormatNationalNumberWithPreferredCarrierCode(phoneNumber, fb_carrier_code, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM FormatNationalNumberWithCarrierCode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string carrier_code( (char*) bin.data, bin.size);
std::string str;
phone_util_->FormatNationalNumberWithCarrierCode(phoneNumber, carrier_code, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM FormatNumberForMobileDialing_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
bool with_formatting;
if (!term_to_boolean(argv[2], &with_formatting))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_calling_from( (char*) bin.data, bin.size);
std::string str;
phone_util_->FormatNumberForMobileDialing(phoneNumber, region_calling_from, with_formatting, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM FormatOutOfCountryCallingNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string calling_from( (char*) bin.data, bin.size);
std::string str;
phone_util_->FormatOutOfCountryCallingNumber(phoneNumber, calling_from, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM FormatInOriginalFormat_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code( (char*) bin.data, bin.size);
std::string str;
phone_util_->FormatInOriginalFormat(phoneNumber, region_code, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM FormatOutOfCountryKeepingAlphaChars_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string calling_from( (char*) bin.data, bin.size);
std::string str;
phone_util_->FormatOutOfCountryKeepingAlphaChars(phoneNumber, calling_from, &str);
ERL_NIF_TERM ret;
unsigned char *number = enif_make_new_binary(env, str.size(), &ret);
std::copy(str.begin(), str.end(), number);
return ret;
}
static ERL_NIF_TERM TruncateTooLongNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
phone_util_->TruncateTooLongNumber(&phoneNumber);
return phonenumber_to_term(env, phoneNumber);
}
static ERL_NIF_TERM GetNumberType_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
return phonenumber_type_to_term(phone_util_->GetNumberType(phoneNumber));
}
static ERL_NIF_TERM IsValidNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
return boolean_to_term(phone_util_->IsValidNumber(phoneNumber));
}
static ERL_NIF_TERM IsValidNumberForRegion_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[1], &bin))
return enif_make_badarg(env);
std::string region_code( (char*) bin.data, bin.size);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
return boolean_to_term(phone_util_->IsValidNumberForRegion(phoneNumber, region_code));
}
static ERL_NIF_TERM GetRegionCodeForNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
std::string region_code;
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
phone_util_->GetRegionCodeForNumber(phoneNumber, &region_code);
ERL_NIF_TERM ret;
unsigned char *region = enif_make_new_binary(env, region_code.size(), &ret);
std::copy(region_code.begin(), region_code.end(), region);
return ret;
}
static ERL_NIF_TERM GetCountryCodeForRegion_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code( (char*) bin.data, bin.size);
return enif_make_int(env, phone_util_->GetCountryCodeForRegion(region_code));
}
static ERL_NIF_TERM GetRegionCodeForCountryCode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
int code;
if (!enif_get_int(env, argv[0], &code))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code;
phone_util_->GetRegionCodeForCountryCode(code, &region_code);
ERL_NIF_TERM ret;
unsigned char *region = enif_make_new_binary(env, region_code.size(), &ret);
std::copy(region_code.begin(), region_code.end(), region);
return ret;
}
static ERL_NIF_TERM GetRegionCodesForCountryCallingCode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
int code;
if (!enif_get_int(env, argv[0], &code))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
list<string> regions;
phone_util_->GetRegionCodesForCountryCallingCode(code, &regions);
unsigned int cnt = regions.size();
ERL_NIF_TERM arr[cnt];
unsigned int i = 0;
ERL_NIF_TERM ret;
unsigned char *region;
for (list<string>::iterator it=regions.begin(); it!=regions.end(); ++it, i++)
{
region = enif_make_new_binary(env, it->size(), &ret);
std::copy(it->begin(), it->end(), region);
arr[i] = ret;
ret = 0;
}
return enif_make_list_from_array(env, arr, cnt);
}
static ERL_NIF_TERM IsNANPACountry_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary regionCodeNif;
if (!enif_inspect_iolist_as_binary(env, argv[0], &regionCodeNif))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code( (char*) regionCodeNif.data, regionCodeNif.size);
return boolean_to_term(phone_util_->IsNANPACountry(region_code));
}
static ERL_NIF_TERM GetNddPrefixForRegion_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary regionCodeNif;
if (!enif_inspect_iolist_as_binary(env, argv[0], &regionCodeNif))
return enif_make_badarg(env);
bool stripNonDigits;
if (!term_to_boolean(argv[1], &stripNonDigits))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code( (char*) regionCodeNif.data, regionCodeNif.size);
std::string national_prefix;
phone_util_->GetNddPrefixForRegion(region_code, stripNonDigits, &national_prefix);
ERL_NIF_TERM ret;
unsigned char *prefix = enif_make_new_binary(env, national_prefix.size(), &ret);
std::copy(national_prefix.begin(), national_prefix.end(), prefix);
return ret;
}
static ERL_NIF_TERM IsPossibleNumberWithReason_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
PhoneNumberUtil::ValidationResult validation_result = phone_util_->IsPossibleNumberWithReason(phoneNumber);
return phonenumber_validation_result_to_term(validation_result);
}
static ERL_NIF_TERM IsPossibleNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber;
if (!term_to_phonenumber(env, argv[0], &phoneNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
return boolean_to_term(phone_util_->IsPossibleNumber(phoneNumber));
}
static ERL_NIF_TERM IsPossibleNumberForString_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary nifNumber;
if (!enif_inspect_iolist_as_binary(env, argv[0], &nifNumber))
return enif_make_badarg(env);
ErlNifBinary nifRegionDialingFrom;
if (!enif_inspect_iolist_as_binary(env, argv[1], &nifRegionDialingFrom))
return enif_make_badarg(env);
PhoneNumber phoneNumber;
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_dialing_from( (char*) nifRegionDialingFrom.data, nifRegionDialingFrom.size);
std::string number( (char*) nifNumber.data, nifNumber.size);
return boolean_to_term(phone_util_->IsPossibleNumberForString(number, region_dialing_from));
}
static ERL_NIF_TERM GetExampleNumber_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumber phoneNumber;
std::string region_code( (char*) bin.data, bin.size);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
if (phone_util_->GetExampleNumber(region_code, &phoneNumber))
return phonenumber_to_term(env, phoneNumber);
return ATOMS.atomFalse;
}
static ERL_NIF_TERM GetExampleNumberForType_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return enif_make_badarg(env);
PhoneNumberUtil::PhoneNumberType type;
if (!term_to_phonenumber_type(argv[1], &type))
return enif_make_badarg(env);
PhoneNumber phoneNumber;
std::string region_code( (char*) bin.data, bin.size);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
if (phone_util_->GetExampleNumberForType(region_code, type, &phoneNumber))
return phonenumber_to_term(env, phoneNumber);
return ATOMS.atomFalse;
}
static ERL_NIF_TERM GetExampleNumberForNonGeoEntity_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
int code;
if (!enif_get_int(env, argv[0], &code))
return enif_make_badarg(env);
PhoneNumber phoneNumber;
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
if (phone_util_->GetExampleNumberForNonGeoEntity(code, &phoneNumber))
return phonenumber_to_term(env, phoneNumber);
return ATOMS.atomFalse;
}
static ERL_NIF_TERM Parse_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary numberToParse;
if (!enif_inspect_iolist_as_binary(env, argv[0], &numberToParse))
return enif_make_badarg(env);
ErlNifBinary defaultRegion;
if (!enif_inspect_iolist_as_binary(env, argv[1], &defaultRegion))
return enif_make_badarg(env);
PhoneNumber phoneNumber;
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code( (char*) defaultRegion.data, defaultRegion.size);
std::string number_to_parse( (char*) numberToParse.data, numberToParse.size);
phone_util_->Parse(number_to_parse, region_code, &phoneNumber);
return phonenumber_to_term(env, phoneNumber);
}
static ERL_NIF_TERM ParseAndKeepRawInput_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary numberToParse;
if (!enif_inspect_iolist_as_binary(env, argv[0], &numberToParse))
return enif_make_badarg(env);
ErlNifBinary defaultRegion;
if (!enif_inspect_iolist_as_binary(env, argv[1], &defaultRegion))
return enif_make_badarg(env);
PhoneNumber phoneNumber;
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string region_code( (char*) defaultRegion.data, defaultRegion.size);
std::string number_to_parse( (char*) numberToParse.data, numberToParse.size);
phone_util_->ParseAndKeepRawInput(number_to_parse, region_code, &phoneNumber);
return phonenumber_to_term(env, phoneNumber);
}
static ERL_NIF_TERM IsNumberMatch_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber1;
if (!term_to_phonenumber(env, argv[0], &phoneNumber1))
return enif_make_badarg(env);
PhoneNumber phoneNumber2;
if (!term_to_phonenumber(env, argv[1], &phoneNumber2))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
PhoneNumberUtil::MatchType match_type = phone_util_->IsNumberMatch(phoneNumber1, phoneNumber2);
return phonenumber_match_type_to_term(match_type);
}
static ERL_NIF_TERM IsNumberMatchWithTwoStrings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary nifFirstNumber;
if (!enif_inspect_iolist_as_binary(env, argv[0], &nifFirstNumber))
return enif_make_badarg(env);
ErlNifBinary nifSecondNumber;
if (!enif_inspect_iolist_as_binary(env, argv[1], &nifSecondNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string first_number( (char*) nifFirstNumber.data, nifFirstNumber.size);
std::string second_number( (char*) nifSecondNumber.data, nifSecondNumber.size);
PhoneNumberUtil::MatchType match_type =phone_util_->IsNumberMatchWithTwoStrings(first_number, second_number);
return phonenumber_match_type_to_term(match_type);
}
static ERL_NIF_TERM IsNumberMatchWithOneString_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
PhoneNumber phoneNumber1;
if (!term_to_phonenumber(env, argv[0], &phoneNumber1))
return enif_make_badarg(env);
ErlNifBinary nifSecondNumber;
if (!enif_inspect_iolist_as_binary(env, argv[1], &nifSecondNumber))
return enif_make_badarg(env);
PhoneNumberUtil *phone_util_ = PhoneNumberUtil::GetInstance();
std::string second_number( (char*) nifSecondNumber.data, nifSecondNumber.size);
PhoneNumberUtil::MatchType match_type = phone_util_->IsNumberMatchWithOneString(phoneNumber1, second_number);
return phonenumber_match_type_to_term(match_type);
}
static ErlNifFunc nif_funcs[] =
{
{"get_supported_regions", 0, GetSupportedRegions_nif},
{"is_alpha_number", 1, IsAlphaNumber_nif},
{"convert_alpha_characters_in_number", 1, ConvertAlphaCharactersInNumber_nif},
{"normalize_digits_only", 1, NormalizeDigitsOnly_nif},
{"normalize_diallable_chars_only", 1, NormalizeDiallableCharsOnly_nif},
{"get_national_significant_number", 1, GetNationalSignificantNumber_nif},
{"get_length_of_geograpical_area_code", 1, GetLengthOfGeographicalAreaCode_nif},
{"get_length_of_national_destination_code", 1, GetLengthOfNationalDestinationCode_nif},
{"get_country_mobile_token", 1, GetCountryMobileToken_nif},
{"format", 2, Format_nif},
{"format_national_number_with_carrier_code", 2, FormatNationalNumberWithCarrierCode_nif},
{"format_national_number_with_preferred_carrier_code", 2, FormatNationalNumberWithPreferredCarrierCode_nif},
{"format_number_for_mobile_dialing", 3, FormatNumberForMobileDialing_nif},
{"format_out_of_country_calling_number", 2, FormatOutOfCountryCallingNumber_nif},
{"format_in_original_format", 2, FormatInOriginalFormat_nif},
{"format_out_of_country_keeping_alpha_chars", 2, FormatOutOfCountryKeepingAlphaChars_nif},
{"truncate_too_long_number", 1, TruncateTooLongNumber_nif},
{"get_number_type", 1, GetNumberType_nif},
{"is_valid_number", 1, IsValidNumber_nif},
{"is_valid_number_for_region", 2, IsValidNumberForRegion_nif},
{"get_region_code_for_number", 1, GetRegionCodeForNumber_nif},
{"get_country_code_for_region", 1, GetCountryCodeForRegion_nif},
{"get_region_code_for_country_code", 1, GetRegionCodeForCountryCode_nif},
{"get_region_codes_for_country_calling_code", 1, GetRegionCodesForCountryCallingCode_nif},
{"is_nanpa_country", 1, IsNANPACountry_nif},
{"get_ndd_prefix_for_region", 2, GetNddPrefixForRegion_nif},
{"is_possible_number_with_reason", 1, IsPossibleNumberWithReason_nif},
{"is_possible_number", 1, IsPossibleNumber_nif},
{"is_possible_number_for_string", 2, IsPossibleNumberForString_nif},
{"get_example_number", 1, GetExampleNumber_nif},
{"get_example_number_for_type", 2, GetExampleNumberForType_nif},
{"get_example_number_for_non_geo_entity", 1, GetExampleNumberForNonGeoEntity_nif},
{"parse", 2, Parse_nif},
{"parse_and_keep_raw_input", 2, ParseAndKeepRawInput_nif},
{"is_number_match", 2, IsNumberMatch_nif},
{"is_number_match_with_two_strings", 2, IsNumberMatchWithTwoStrings_nif},
{"is_number_match_with_one_string", 2, IsNumberMatchWithOneString_nif}
};
ERL_NIF_INIT(phonenumber_util, nif_funcs, on_nif_load, NULL, NULL, NULL)