Cleaned up indentation & comments
This commit is contained in:
parent
dcb98bede6
commit
8b94ed59e6
|
@ -6,7 +6,7 @@
|
||||||
#include "phonenumbers/phonenumberutil.h"
|
#include "phonenumbers/phonenumberutil.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "short_phone_number.h"
|
#include "short_phone_number.h"
|
||||||
|
@ -14,24 +14,24 @@ extern "C" {
|
||||||
using namespace i18n::phonenumbers;
|
using namespace i18n::phonenumbers;
|
||||||
|
|
||||||
static const char* parseErrorMessage(PhoneNumberUtil::ErrorType error) {
|
static const char* parseErrorMessage(PhoneNumberUtil::ErrorType error) {
|
||||||
using PNU = i18n::phonenumbers::PhoneNumberUtil;
|
using PNU = i18n::phonenumbers::PhoneNumberUtil;
|
||||||
switch(error) {
|
switch(error) {
|
||||||
case PNU::NO_PARSING_ERROR:
|
case PNU::NO_PARSING_ERROR:
|
||||||
return "Parsed successfully";
|
return "Parsed successfully";
|
||||||
case PNU::INVALID_COUNTRY_CODE_ERROR:
|
case PNU::INVALID_COUNTRY_CODE_ERROR:
|
||||||
return "Invalid country code";
|
return "Invalid country code";
|
||||||
case PNU::NOT_A_NUMBER:
|
case PNU::NOT_A_NUMBER:
|
||||||
return "String does not appear to contain a phone number";
|
return "String does not appear to contain a phone number";
|
||||||
case PNU::TOO_SHORT_AFTER_IDD:
|
case PNU::TOO_SHORT_AFTER_IDD:
|
||||||
return "Too short after IDD";
|
return "Too short after IDD";
|
||||||
case PNU::TOO_SHORT_NSN:
|
case PNU::TOO_SHORT_NSN:
|
||||||
return "National number is too short";
|
return "National number is too short";
|
||||||
case PNU::TOO_LONG_NSN:
|
case PNU::TOO_LONG_NSN:
|
||||||
return "National number is too long";
|
return "National number is too long";
|
||||||
default:
|
default:
|
||||||
//We have some generic parsing error.
|
//We have some generic parsing error.
|
||||||
return "Unable to parse number";
|
return "Unable to parse number";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -39,9 +39,9 @@ static const char* parseErrorMessage(PhoneNumberUtil::ErrorType error) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void reportOutOfMemory() {
|
void reportOutOfMemory() {
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||||
errmsg("Out of memory")));
|
errmsg("Out of memory")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -51,42 +51,42 @@ void reportOutOfMemory() {
|
||||||
* depending on the type of the exception
|
* depending on the type of the exception
|
||||||
*/
|
*/
|
||||||
void reportException(const std::exception& exception) {
|
void reportException(const std::exception& exception) {
|
||||||
{
|
{
|
||||||
const std::bad_alloc* bad_alloc = dynamic_cast<const std::bad_alloc*>(&exception);
|
const std::bad_alloc* bad_alloc = dynamic_cast<const std::bad_alloc*>(&exception);
|
||||||
if(bad_alloc != nullptr) {
|
if(bad_alloc != nullptr) {
|
||||||
reportOutOfMemory();
|
reportOutOfMemory();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const PhoneNumberTooLongException* too_long =
|
const PhoneNumberTooLongException* too_long =
|
||||||
dynamic_cast<const PhoneNumberTooLongException*>(&exception);
|
dynamic_cast<const PhoneNumberTooLongException*>(&exception);
|
||||||
if(too_long != nullptr) {
|
if(too_long != nullptr) {
|
||||||
std::string phone_number = too_long->number_string();
|
std::string phone_number = too_long->number_string();
|
||||||
phone_number += '\0';
|
phone_number += '\0';
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("phone number '%s' is too long", phone_number.data()),
|
errmsg("phone number '%s' is too long", phone_number.data()),
|
||||||
errdetail("%s", exception.what())));
|
errdetail("%s", exception.what())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we don't have a special way to handle this exception, report
|
//If we don't have a special way to handle this exception, report
|
||||||
//a generic error.
|
//a generic error.
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
|
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
|
||||||
errmsg("C++ exception: %s", typeid(exception).name()),
|
errmsg("C++ exception: %s", typeid(exception).name()),
|
||||||
errdetail("%s", exception.what())));
|
errdetail("%s", exception.what())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void reportParseError(const char* phone_number, PhoneNumberUtil::ErrorType err) {
|
void reportParseError(const char* phone_number, PhoneNumberUtil::ErrorType err) {
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("unable to parse '%s' as a phone number", phone_number),
|
errmsg("unable to parse '%s' as a phone number", phone_number),
|
||||||
errdetail("%s", parseErrorMessage(err))));
|
errdetail("%s", parseErrorMessage(err))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void logInfo(const char* msg) {
|
void logInfo(const char* msg) {
|
||||||
ereport(INFO,
|
ereport(INFO,
|
||||||
(errcode(ERRCODE_SUCCESSFUL_COMPLETION),
|
(errcode(ERRCODE_SUCCESSFUL_COMPLETION),
|
||||||
errmsg("%s", msg)));
|
errmsg("%s", msg)));
|
||||||
}
|
}
|
||||||
|
|
6
mask.h
6
mask.h
|
@ -1,14 +1,14 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template<typename T> constexpr T mask(size_t bits, size_t offset = 0) {
|
template<typename T> constexpr T mask(size_t bits, size_t offset = 0) {
|
||||||
return (((T)1 << bits) - 1) << offset;
|
return (((T)1 << bits) - 1) << offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> constexpr T getMasked(T data, size_t bits, size_t offset) {
|
template<typename T> constexpr T getMasked(T data, size_t bits, size_t offset) {
|
||||||
return (data >> offset) & mask<T>(bits);
|
return (data >> offset) & mask<T>(bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: support typeof(data) != typeof(value)?
|
//TODO: support typeof(data) != typeof(value)?
|
||||||
template<typename T> constexpr T setMasked(T data, T value, size_t bits, size_t offset) {
|
template<typename T> constexpr T setMasked(T data, T value, size_t bits, size_t offset) {
|
||||||
return (data & ~mask<T>(bits, offset)) | ((value & mask<T>(bits)) << offset);
|
return (data & ~mask<T>(bits, offset)) | ((value & mask<T>(bits)) << offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#include "phonenumbers/phonenumberutil.h"
|
#include "phonenumbers/phonenumberutil.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "libpq/pqformat.h"
|
#include "libpq/pqformat.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "error_handling.h"
|
#include "error_handling.h"
|
||||||
|
@ -16,6 +16,9 @@ using namespace i18n::phonenumbers;
|
||||||
|
|
||||||
static const PhoneNumberUtil* const phoneUtil = PhoneNumberUtil::GetInstance();
|
static const PhoneNumberUtil* const phoneUtil = PhoneNumberUtil::GetInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clips a value to the given (inclusive) range
|
||||||
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T clip(const T& n, const T& lower, const T& upper) {
|
T clip(const T& n, const T& lower, const T& upper) {
|
||||||
return std::max(lower, std::min(n, upper));
|
return std::max(lower, std::min(n, upper));
|
||||||
|
@ -25,36 +28,39 @@ T clip(const T& n, const T& lower, const T& upper) {
|
||||||
* Utility functions
|
* Utility functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a text object to a C-style string
|
||||||
|
*/
|
||||||
static char* textToCString(const text* text) {
|
static char* textToCString(const text* text) {
|
||||||
size_t len = VARSIZE(text) - VARHDRSZ;
|
size_t len = VARSIZE(text) - VARHDRSZ;
|
||||||
char* str = (char*)palloc(len + 1);
|
char* str = (char*)palloc(len + 1);
|
||||||
memcpy(str, VARDATA(text), len);
|
memcpy(str, VARDATA(text), len);
|
||||||
str[len] = '\0';
|
str[len] = '\0';
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Internal function used by phone_number_in and parse_phone_number
|
//Internal function used by phone_number_in and parse_phone_number
|
||||||
//TODO: take a std::string to minimize copying?
|
//TODO: take a std::string to minimize copying?
|
||||||
ShortPhoneNumber* parsePhoneNumber(const char* number_str, const char* country) {
|
ShortPhoneNumber* parsePhoneNumber(const char* number_str, const char* country) {
|
||||||
PhoneNumber number;
|
PhoneNumber number;
|
||||||
ShortPhoneNumber* short_number;
|
ShortPhoneNumber* short_number;
|
||||||
|
|
||||||
short_number = (ShortPhoneNumber*)palloc0(sizeof(ShortPhoneNumber));
|
short_number = (ShortPhoneNumber*)palloc0(sizeof(ShortPhoneNumber));
|
||||||
if(short_number == nullptr) {
|
if(short_number == nullptr) {
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
PhoneNumberUtil::ErrorType error;
|
PhoneNumberUtil::ErrorType error;
|
||||||
error = phoneUtil->Parse(number_str, country, &number);
|
error = phoneUtil->Parse(number_str, country, &number);
|
||||||
if(error == PhoneNumberUtil::NO_PARSING_ERROR) {
|
if(error == PhoneNumberUtil::NO_PARSING_ERROR) {
|
||||||
//Initialize short_number using placement new.
|
//Initialize short_number using placement new.
|
||||||
new(short_number) ShortPhoneNumber(number);
|
new(short_number) ShortPhoneNumber(number);
|
||||||
return short_number;
|
return short_number;
|
||||||
} else {
|
} else {
|
||||||
reportParseError(number_str, error);
|
reportParseError(number_str, error);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
//TODO: check number validity.
|
//TODO: check number validity.
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check null args (PG_ARGISNULL) and make non-strict?
|
//TODO: check null args (PG_ARGISNULL) and make non-strict?
|
||||||
|
@ -64,232 +70,232 @@ ShortPhoneNumber* parsePhoneNumber(const char* number_str, const char* country)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef PG_MODULE_MAGIC
|
#ifdef PG_MODULE_MAGIC
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_in);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_in);
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT Datum
|
||||||
phone_number_in(PG_FUNCTION_ARGS) {
|
phone_number_in(PG_FUNCTION_ARGS) {
|
||||||
try {
|
try {
|
||||||
const char *number_str = PG_GETARG_CSTRING(0);
|
const char *number_str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
//TODO: use international format instead.
|
//TODO: use international format instead.
|
||||||
ShortPhoneNumber* number = parsePhoneNumber(number_str, "US");
|
ShortPhoneNumber* number = parsePhoneNumber(number_str, "US");
|
||||||
if(number) {
|
if(number) {
|
||||||
PG_RETURN_POINTER(number);
|
PG_RETURN_POINTER(number);
|
||||||
} else {
|
} else {
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
reportException(e);
|
reportException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(parse_phone_number);
|
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(parse_phone_number);
|
||||||
parse_phone_number(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const text* number_text = PG_GETARG_TEXT_P(0);
|
|
||||||
const text* country_text = PG_GETARG_TEXT_P(1);
|
|
||||||
|
|
||||||
char* number_str = textToCString(number_text);
|
PGDLLEXPORT Datum
|
||||||
char* country = textToCString(country_text);
|
parse_phone_number(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const text* number_text = PG_GETARG_TEXT_P(0);
|
||||||
|
const text* country_text = PG_GETARG_TEXT_P(1);
|
||||||
|
|
||||||
ShortPhoneNumber* number = parsePhoneNumber(number_str, country);
|
char* number_str = textToCString(number_text);
|
||||||
//TODO: prevent leaks.
|
char* country = textToCString(country_text);
|
||||||
pfree(number_str);
|
|
||||||
pfree(country);
|
|
||||||
if(number) {
|
|
||||||
PG_RETURN_POINTER(number);
|
|
||||||
} else {
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
}
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
reportException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_out);
|
ShortPhoneNumber* number = parsePhoneNumber(number_str, country);
|
||||||
|
//TODO: prevent leaks.
|
||||||
|
pfree(number_str);
|
||||||
|
pfree(country);
|
||||||
|
if(number) {
|
||||||
|
PG_RETURN_POINTER(number);
|
||||||
|
} else {
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_out);
|
||||||
phone_number_out(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* short_number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
PhoneNumber number = *short_number;
|
|
||||||
|
|
||||||
std::string formatted;
|
PGDLLEXPORT Datum
|
||||||
phoneUtil->Format(number, PhoneNumberUtil::INTERNATIONAL, &formatted);
|
phone_number_out(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* short_number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
PhoneNumber number = *short_number;
|
||||||
|
|
||||||
//Copy the formatted number to a C-style string.
|
std::string formatted;
|
||||||
//We must use the PostgreSQL allocator, not new/malloc.
|
phoneUtil->Format(number, PhoneNumberUtil::INTERNATIONAL, &formatted);
|
||||||
size_t len = formatted.length();
|
|
||||||
char* result = (char*)palloc(len + 1);
|
|
||||||
if(result == nullptr) {
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
memcpy(result, formatted.data(), len);
|
|
||||||
result[len] = '\0';
|
|
||||||
|
|
||||||
PG_RETURN_CSTRING(result);
|
//Copy the formatted number to a C-style string.
|
||||||
} catch (const std::exception& e) {
|
//We must use the PostgreSQL allocator, not new/malloc.
|
||||||
reportException(e);
|
size_t len = formatted.length();
|
||||||
}
|
char* result = (char*)palloc(len + 1);
|
||||||
|
if(result == nullptr) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
memcpy(result, formatted.data(), len);
|
||||||
|
result[len] = '\0';
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_CSTRING(result);
|
||||||
}
|
} catch (const std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_recv);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_recv);
|
||||||
phone_number_recv(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
StringInfo buf = (StringInfo)PG_GETARG_POINTER(0);
|
|
||||||
ShortPhoneNumber* number;
|
|
||||||
|
|
||||||
number = (ShortPhoneNumber*)palloc(sizeof(ShortPhoneNumber));
|
PGDLLEXPORT Datum
|
||||||
//TODO: make portable (fix endianness issues, etc.).
|
phone_number_recv(PG_FUNCTION_ARGS) {
|
||||||
pq_copymsgbytes(buf, (char*)number, sizeof(ShortPhoneNumber));
|
try {
|
||||||
PG_RETURN_POINTER(number);
|
StringInfo buf = (StringInfo)PG_GETARG_POINTER(0);
|
||||||
} catch (const std::exception& e) {
|
ShortPhoneNumber* number;
|
||||||
reportException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
number = (ShortPhoneNumber*)palloc(sizeof(ShortPhoneNumber));
|
||||||
}
|
//TODO: make portable (fix endianness issues, etc.).
|
||||||
|
pq_copymsgbytes(buf, (char*)number, sizeof(ShortPhoneNumber));
|
||||||
|
PG_RETURN_POINTER(number);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_send);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_send);
|
||||||
phone_number_send(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber *number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
StringInfoData buf;
|
|
||||||
|
|
||||||
pq_begintypsend(&buf);
|
PGDLLEXPORT Datum
|
||||||
pq_sendbytes(&buf, (const char*)number, sizeof(ShortPhoneNumber));
|
phone_number_send(PG_FUNCTION_ARGS) {
|
||||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
try {
|
||||||
} catch (const std::exception& e) {
|
const ShortPhoneNumber *number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
reportException(e);
|
StringInfoData buf;
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
pq_begintypsend(&buf);
|
||||||
}
|
pq_sendbytes(&buf, (const char*)number, sizeof(ShortPhoneNumber));
|
||||||
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_equal);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_equal);
|
||||||
phone_number_equal(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(*number1 == *number2);
|
PGDLLEXPORT Datum
|
||||||
} catch(std::exception& e) {
|
phone_number_equal(PG_FUNCTION_ARGS) {
|
||||||
reportException(e);
|
try {
|
||||||
}
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_BOOL(*number1 == *number2);
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_not_equal);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_not_equal);
|
||||||
phone_number_not_equal(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(*number1 != *number2);
|
PGDLLEXPORT Datum
|
||||||
} catch(std::exception& e) {
|
phone_number_not_equal(PG_FUNCTION_ARGS) {
|
||||||
reportException(e);
|
try {
|
||||||
}
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_BOOL(*number1 != *number2);
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_less);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_less);
|
||||||
phone_number_less(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(number1->compare_fast(*number2) < 0);
|
PGDLLEXPORT Datum
|
||||||
} catch(std::exception& e) {
|
phone_number_less(PG_FUNCTION_ARGS) {
|
||||||
reportException(e);
|
try {
|
||||||
}
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_BOOL(number1->compare_fast(*number2) < 0);
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_less_or_equal);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_less_or_equal);
|
||||||
phone_number_less_or_equal(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(number1->compare_fast(*number2) <= 0);
|
PGDLLEXPORT Datum
|
||||||
} catch(std::exception& e) {
|
phone_number_less_or_equal(PG_FUNCTION_ARGS) {
|
||||||
reportException(e);
|
try {
|
||||||
}
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_BOOL(number1->compare_fast(*number2) <= 0);
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_greater);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_greater);
|
||||||
phone_number_greater(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(number1->compare_fast(*number2) > 0);
|
PGDLLEXPORT Datum
|
||||||
} catch(std::exception& e) {
|
phone_number_greater(PG_FUNCTION_ARGS) {
|
||||||
reportException(e);
|
try {
|
||||||
}
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_BOOL(number1->compare_fast(*number2) > 0);
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_greater_or_equal);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_greater_or_equal);
|
||||||
phone_number_greater_or_equal(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(number1->compare_fast(*number2) >= 0);
|
PGDLLEXPORT Datum
|
||||||
} catch(std::exception& e) {
|
phone_number_greater_or_equal(PG_FUNCTION_ARGS) {
|
||||||
reportException(e);
|
try {
|
||||||
}
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_BOOL(number1->compare_fast(*number2) >= 0);
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_cmp);
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
PGDLLEXPORT Datum
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_cmp);
|
||||||
phone_number_cmp(PG_FUNCTION_ARGS) {
|
|
||||||
try {
|
|
||||||
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
|
||||||
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
|
||||||
|
|
||||||
int64 compared = number1->compare_fast(*number2);
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_cmp(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
PG_RETURN_INT32(clip<int64>(compared, -1, 1));
|
int64 compared = number1->compare_fast(*number2);
|
||||||
} catch(std::exception& e) {
|
|
||||||
reportException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_INT32(clip<int64>(compared, -1, 1));
|
||||||
}
|
} catch(std::exception& e) {
|
||||||
|
reportException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ CREATE TYPE phone_number (
|
||||||
--Cast definitions
|
--Cast definitions
|
||||||
|
|
||||||
CREATE CAST (phone_number AS text)
|
CREATE CAST (phone_number AS text)
|
||||||
WITH INOUT;
|
WITH INOUT;
|
||||||
|
|
||||||
--Operator definitions
|
--Operator definitions
|
||||||
|
|
||||||
|
@ -42,16 +42,18 @@ CREATE FUNCTION phone_number_equal(phone_number, phone_number) RETURNS bool
|
||||||
LANGUAGE c IMMUTABLE STRICT
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
AS 'pg_libphonenumber', 'phone_number_equal';
|
AS 'pg_libphonenumber', 'phone_number_equal';
|
||||||
|
|
||||||
|
-- TODO: make these operators strict.
|
||||||
|
|
||||||
CREATE OPERATOR = (
|
CREATE OPERATOR = (
|
||||||
leftarg = phone_number,
|
leftarg = phone_number,
|
||||||
rightarg = phone_number,
|
rightarg = phone_number,
|
||||||
procedure = phone_number_equal,
|
procedure = phone_number_equal,
|
||||||
commutator = =,
|
commutator = =,
|
||||||
negator = <>,
|
negator = <>,
|
||||||
restrict = eqsel,
|
restrict = eqsel,
|
||||||
join = eqjoinsel,
|
join = eqjoinsel,
|
||||||
hashes = true,
|
hashes = true,
|
||||||
merges = true
|
merges = true
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_not_equal(phone_number, phone_number) RETURNS bool
|
CREATE FUNCTION phone_number_not_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
@ -59,13 +61,13 @@ CREATE FUNCTION phone_number_not_equal(phone_number, phone_number) RETURNS bool
|
||||||
AS 'pg_libphonenumber', 'phone_number_not_equal';
|
AS 'pg_libphonenumber', 'phone_number_not_equal';
|
||||||
|
|
||||||
CREATE OPERATOR <> (
|
CREATE OPERATOR <> (
|
||||||
leftarg = phone_number,
|
leftarg = phone_number,
|
||||||
rightarg = phone_number,
|
rightarg = phone_number,
|
||||||
procedure = phone_number_not_equal,
|
procedure = phone_number_not_equal,
|
||||||
commutator = <>,
|
commutator = <>,
|
||||||
negator = =,
|
negator = =,
|
||||||
restrict = neqsel,
|
restrict = neqsel,
|
||||||
join = neqjoinsel
|
join = neqjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_less(phone_number, phone_number) RETURNS bool
|
CREATE FUNCTION phone_number_less(phone_number, phone_number) RETURNS bool
|
||||||
|
@ -73,13 +75,13 @@ CREATE FUNCTION phone_number_less(phone_number, phone_number) RETURNS bool
|
||||||
AS 'pg_libphonenumber', 'phone_number_less';
|
AS 'pg_libphonenumber', 'phone_number_less';
|
||||||
|
|
||||||
CREATE OPERATOR < (
|
CREATE OPERATOR < (
|
||||||
leftarg = phone_number,
|
leftarg = phone_number,
|
||||||
rightarg = phone_number,
|
rightarg = phone_number,
|
||||||
procedure = phone_number_less,
|
procedure = phone_number_less,
|
||||||
commutator = >,
|
commutator = >,
|
||||||
negator = >=,
|
negator = >=,
|
||||||
restrict = scalarltsel,
|
restrict = scalarltsel,
|
||||||
join = scalarltjoinsel
|
join = scalarltjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_less_or_equal(phone_number, phone_number) RETURNS bool
|
CREATE FUNCTION phone_number_less_or_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
@ -87,13 +89,13 @@ CREATE FUNCTION phone_number_less_or_equal(phone_number, phone_number) RETURNS b
|
||||||
AS 'pg_libphonenumber', 'phone_number_less_or_equal';
|
AS 'pg_libphonenumber', 'phone_number_less_or_equal';
|
||||||
|
|
||||||
CREATE OPERATOR <= (
|
CREATE OPERATOR <= (
|
||||||
leftarg = phone_number,
|
leftarg = phone_number,
|
||||||
rightarg = phone_number,
|
rightarg = phone_number,
|
||||||
procedure = phone_number_less_or_equal,
|
procedure = phone_number_less_or_equal,
|
||||||
commutator = >=,
|
commutator = >=,
|
||||||
negator = >,
|
negator = >,
|
||||||
restrict = scalarltsel,
|
restrict = scalarltsel,
|
||||||
join = scalarltjoinsel
|
join = scalarltjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_greater(phone_number, phone_number) RETURNS bool
|
CREATE FUNCTION phone_number_greater(phone_number, phone_number) RETURNS bool
|
||||||
|
@ -101,13 +103,13 @@ CREATE FUNCTION phone_number_greater(phone_number, phone_number) RETURNS bool
|
||||||
AS 'pg_libphonenumber', 'phone_number_greater';
|
AS 'pg_libphonenumber', 'phone_number_greater';
|
||||||
|
|
||||||
CREATE OPERATOR > (
|
CREATE OPERATOR > (
|
||||||
leftarg = phone_number,
|
leftarg = phone_number,
|
||||||
rightarg = phone_number,
|
rightarg = phone_number,
|
||||||
procedure = phone_number_greater,
|
procedure = phone_number_greater,
|
||||||
commutator = >,
|
commutator = >,
|
||||||
negator = <=,
|
negator = <=,
|
||||||
restrict = scalargtsel,
|
restrict = scalargtsel,
|
||||||
join = scalargtjoinsel
|
join = scalargtjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_greater_or_equal(phone_number, phone_number) RETURNS bool
|
CREATE FUNCTION phone_number_greater_or_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
@ -115,13 +117,13 @@ CREATE FUNCTION phone_number_greater_or_equal(phone_number, phone_number) RETURN
|
||||||
AS 'pg_libphonenumber', 'phone_number_greater_or_equal';
|
AS 'pg_libphonenumber', 'phone_number_greater_or_equal';
|
||||||
|
|
||||||
CREATE OPERATOR >= (
|
CREATE OPERATOR >= (
|
||||||
leftarg = phone_number,
|
leftarg = phone_number,
|
||||||
rightarg = phone_number,
|
rightarg = phone_number,
|
||||||
procedure = phone_number_greater_or_equal,
|
procedure = phone_number_greater_or_equal,
|
||||||
commutator = >=,
|
commutator = >=,
|
||||||
negator = <,
|
negator = <,
|
||||||
restrict = scalargtsel,
|
restrict = scalargtsel,
|
||||||
join = scalargtjoinsel
|
join = scalargtjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_cmp(phone_number, phone_number) RETURNS integer
|
CREATE FUNCTION phone_number_cmp(phone_number, phone_number) RETURNS integer
|
||||||
|
@ -129,13 +131,13 @@ CREATE FUNCTION phone_number_cmp(phone_number, phone_number) RETURNS integer
|
||||||
AS 'pg_libphonenumber', 'phone_number_cmp';
|
AS 'pg_libphonenumber', 'phone_number_cmp';
|
||||||
|
|
||||||
CREATE OPERATOR CLASS phone_number_ops
|
CREATE OPERATOR CLASS phone_number_ops
|
||||||
DEFAULT FOR TYPE phone_number USING btree AS
|
DEFAULT FOR TYPE phone_number USING btree AS
|
||||||
OPERATOR 1 <,
|
OPERATOR 1 <,
|
||||||
OPERATOR 2 <=,
|
OPERATOR 2 <=,
|
||||||
OPERATOR 3 =,
|
OPERATOR 3 =,
|
||||||
OPERATOR 4 >=,
|
OPERATOR 4 >=,
|
||||||
OPERATOR 5 >,
|
OPERATOR 5 >,
|
||||||
FUNCTION 1 phone_number_cmp(phone_number, phone_number);
|
FUNCTION 1 phone_number_cmp(phone_number, phone_number);
|
||||||
|
|
||||||
--General functions
|
--General functions
|
||||||
|
|
||||||
|
|
|
@ -6,45 +6,44 @@ using namespace i18n::phonenumbers;
|
||||||
const PhoneNumberUtil* const PhoneNumberTooLongException::phoneUtil = PhoneNumberUtil::GetInstance();
|
const PhoneNumberUtil* const PhoneNumberTooLongException::phoneUtil = PhoneNumberUtil::GetInstance();
|
||||||
|
|
||||||
PhoneNumberTooLongException::PhoneNumberTooLongException(const PhoneNumber& number, const char* msg) :
|
PhoneNumberTooLongException::PhoneNumberTooLongException(const PhoneNumber& number, const char* msg) :
|
||||||
_number(number), std::runtime_error(msg) {};
|
_number(number), std::runtime_error(msg) {};
|
||||||
|
|
||||||
std::string PhoneNumberTooLongException::number_string() const {
|
std::string PhoneNumberTooLongException::number_string() const {
|
||||||
std::string formatted;
|
std::string formatted;
|
||||||
phoneUtil->Format(number(), PhoneNumberUtil::INTERNATIONAL, &formatted);
|
phoneUtil->Format(number(), PhoneNumberUtil::INTERNATIONAL, &formatted);
|
||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortPhoneNumber::ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number) {
|
ShortPhoneNumber::ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number) {
|
||||||
uint32 country_code = number.country_code();
|
uint32 country_code = number.country_code();
|
||||||
if(country_code > MAX_COUNTRY_CODE) {
|
if(country_code > MAX_COUNTRY_CODE) {
|
||||||
throw PhoneNumberTooLongException(number, "Country code is too long");
|
throw PhoneNumberTooLongException(number, "Country code is too long");
|
||||||
}
|
}
|
||||||
this->country_code(country_code);
|
this->country_code(country_code);
|
||||||
|
|
||||||
uint64 national_number = number.national_number();
|
uint64 national_number = number.national_number();
|
||||||
if(national_number > MAX_NATIONAL_NUMBER) {
|
if(national_number > MAX_NATIONAL_NUMBER) {
|
||||||
throw PhoneNumberTooLongException(number, "National number is too long");
|
throw PhoneNumberTooLongException(number, "National number is too long");
|
||||||
}
|
}
|
||||||
this->national_number(national_number);
|
this->national_number(national_number);
|
||||||
|
|
||||||
if(number.has_number_of_leading_zeros()) {
|
if(number.has_number_of_leading_zeros()) {
|
||||||
uint32 leading_zeros = number.number_of_leading_zeros();
|
uint32 leading_zeros = number.number_of_leading_zeros();
|
||||||
if(leading_zeros > MAX_LEADING_ZEROS) {
|
if(leading_zeros > MAX_LEADING_ZEROS) {
|
||||||
throw PhoneNumberTooLongException(number, "Too many leading zeros");
|
throw PhoneNumberTooLongException(number, "Too many leading zeros");
|
||||||
}
|
}
|
||||||
this->leading_zeros(leading_zeros);
|
this->leading_zeros(leading_zeros);
|
||||||
} else {
|
} else {
|
||||||
this->leading_zeros(0);
|
this->leading_zeros(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortPhoneNumber::operator PhoneNumber() const {
|
ShortPhoneNumber::operator PhoneNumber() const {
|
||||||
PhoneNumber number;
|
PhoneNumber number;
|
||||||
number.set_country_code(country_code());
|
number.set_country_code(country_code());
|
||||||
number.set_national_number(national_number());
|
number.set_national_number(national_number());
|
||||||
int32 leading_zeros = this->leading_zeros();
|
int32 leading_zeros = this->leading_zeros();
|
||||||
number.set_italian_leading_zero(leading_zeros > 0);
|
number.set_italian_leading_zero(leading_zeros > 0);
|
||||||
number.set_number_of_leading_zeros(leading_zeros);
|
number.set_number_of_leading_zeros(leading_zeros);
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,94 +6,96 @@
|
||||||
#include "mask.h"
|
#include "mask.h"
|
||||||
|
|
||||||
class PhoneNumberTooLongException : public std::runtime_error {
|
class PhoneNumberTooLongException : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
PhoneNumberTooLongException(const i18n::phonenumbers::PhoneNumber& number, const char* msg);
|
PhoneNumberTooLongException(const i18n::phonenumbers::PhoneNumber& number, const char* msg);
|
||||||
|
|
||||||
i18n::phonenumbers::PhoneNumber number() const {
|
i18n::phonenumbers::PhoneNumber number() const {
|
||||||
return _number;
|
return _number;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: just get the number string from which the PhoneNumber was parsed? (if it exists...)
|
//TODO: just get the number string from which the PhoneNumber was parsed? (if it exists...)
|
||||||
std::string number_string() const;
|
std::string number_string() const;
|
||||||
private:
|
private:
|
||||||
i18n::phonenumbers::PhoneNumber _number;
|
i18n::phonenumbers::PhoneNumber _number;
|
||||||
|
|
||||||
static const i18n::phonenumbers::PhoneNumberUtil* const phoneUtil;
|
static const i18n::phonenumbers::PhoneNumberUtil* const phoneUtil;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a phone number (packed into a 64-bit integer)
|
||||||
|
*/
|
||||||
class ShortPhoneNumber {
|
class ShortPhoneNumber {
|
||||||
public:
|
public:
|
||||||
enum : size_t {
|
enum : size_t {
|
||||||
MAX_COUNTRY_CODE = 999,
|
MAX_COUNTRY_CODE = 999,
|
||||||
MAX_LEADING_ZEROS = 15,
|
MAX_LEADING_ZEROS = 15,
|
||||||
//15 digits
|
//15 digits
|
||||||
MAX_NATIONAL_NUMBER = 999999999999999,
|
MAX_NATIONAL_NUMBER = 999999999999999,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : size_t {
|
|
||||||
COUNTRY_CODE_BITS = 10,
|
|
||||||
LEADING_ZEROS_BITS = 4,
|
|
||||||
NATIONAL_NUMBER_BITS = 50,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum : size_t {
|
|
||||||
COUNTRY_CODE_OFFSET = 0,
|
|
||||||
LEADING_ZEROS_OFFSET = COUNTRY_CODE_OFFSET + COUNTRY_CODE_BITS,
|
|
||||||
NATIONAL_NUMBER_OFFSET = LEADING_ZEROS_OFFSET + LEADING_ZEROS_BITS,
|
|
||||||
};
|
|
||||||
|
|
||||||
ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number);
|
enum : size_t {
|
||||||
|
COUNTRY_CODE_BITS = 10,
|
||||||
|
LEADING_ZEROS_BITS = 4,
|
||||||
|
NATIONAL_NUMBER_BITS = 50,
|
||||||
|
};
|
||||||
|
|
||||||
bool operator == (const ShortPhoneNumber other) const {
|
enum : size_t {
|
||||||
return this->_data == other._data;
|
COUNTRY_CODE_OFFSET = 0,
|
||||||
}
|
LEADING_ZEROS_OFFSET = COUNTRY_CODE_OFFSET + COUNTRY_CODE_BITS,
|
||||||
|
NATIONAL_NUMBER_OFFSET = LEADING_ZEROS_OFFSET + LEADING_ZEROS_BITS,
|
||||||
bool operator != (const ShortPhoneNumber other) const {
|
};
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator i18n::phonenumbers::PhoneNumber() const;
|
ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number);
|
||||||
|
|
||||||
/*
|
bool operator == (const ShortPhoneNumber other) const {
|
||||||
* Compares to another PhoneNumber using a fast collation heuristic
|
return this->_data == other._data;
|
||||||
*
|
}
|
||||||
* May not produce intuitive results for numbers with the same
|
|
||||||
* country code but different lengths
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* - <0 (if a < b)
|
|
||||||
* - 0 (if a == b)
|
|
||||||
* - >0 (if a > b)
|
|
||||||
*/
|
|
||||||
google::protobuf::int64 compare_fast(ShortPhoneNumber other) const {
|
|
||||||
return other._data - this->_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
google::protobuf::uint32 country_code() const {
|
bool operator != (const ShortPhoneNumber other) const {
|
||||||
return getMasked(_data, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void country_code(google::protobuf::uint32 value) {
|
operator i18n::phonenumbers::PhoneNumber() const;
|
||||||
_data = setMasked(_data, (google::protobuf::uint64)value, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
google::protobuf::uint64 national_number() const {
|
/*
|
||||||
return getMasked(_data, NATIONAL_NUMBER_BITS, NATIONAL_NUMBER_OFFSET);
|
* Compares to another PhoneNumber using a fast collation heuristic
|
||||||
}
|
*
|
||||||
|
* May not produce intuitive results for numbers with the same
|
||||||
|
* country code but different lengths
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* - <0 (if a < b)
|
||||||
|
* - 0 (if a == b)
|
||||||
|
* - >0 (if a > b)
|
||||||
|
*/
|
||||||
|
google::protobuf::int64 compare_fast(ShortPhoneNumber other) const {
|
||||||
|
return other._data - this->_data;
|
||||||
|
}
|
||||||
|
|
||||||
void national_number(google::protobuf::uint64 value) {
|
google::protobuf::uint32 country_code() const {
|
||||||
_data = setMasked(_data, value, NATIONAL_NUMBER_BITS, NATIONAL_NUMBER_OFFSET);
|
return getMasked(_data, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
google::protobuf::uint64 leading_zeros() const {
|
void country_code(google::protobuf::uint32 value) {
|
||||||
return getMasked(_data, LEADING_ZEROS_BITS, LEADING_ZEROS_OFFSET);
|
_data = setMasked(_data, (google::protobuf::uint64)value, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void leading_zeros(google::protobuf::uint64 value) {
|
google::protobuf::uint64 national_number() const {
|
||||||
_data = setMasked(_data, value, LEADING_ZEROS_BITS, LEADING_ZEROS_OFFSET);
|
return getMasked(_data, NATIONAL_NUMBER_BITS, NATIONAL_NUMBER_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void national_number(google::protobuf::uint64 value) {
|
||||||
google::protobuf::uint64 _data;
|
_data = setMasked(_data, value, NATIONAL_NUMBER_BITS, NATIONAL_NUMBER_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
google::protobuf::uint64 leading_zeros() const {
|
||||||
|
return getMasked(_data, LEADING_ZEROS_BITS, LEADING_ZEROS_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void leading_zeros(google::protobuf::uint64 value) {
|
||||||
|
_data = setMasked(_data, value, LEADING_ZEROS_BITS, LEADING_ZEROS_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
google::protobuf::uint64 _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
#include "../short_phone_number.h"
|
#include "../short_phone_number.h"
|
||||||
|
|
||||||
int main(int argc, const char** argv) {
|
int main(int argc, const char** argv) {
|
||||||
std::cout << sizeof(ShortPhoneNumber) << std::endl;
|
std::cout << sizeof(ShortPhoneNumber) << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue