Moved away from bitfields to increase portability
This commit is contained in:
parent
bca033d1f8
commit
5080bf839e
|
@ -0,0 +1,12 @@
|
||||||
|
template<typename T> constexpr T mask(size_t bits, size_t offset = 0) {
|
||||||
|
return (((T)1 << bits) - 1) << offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> constexpr T getMasked(T data, size_t bits, size_t offset) {
|
||||||
|
return (data >> offset) & mask<T>(bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: support typeof(data) != typeof(value)?
|
||||||
|
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);
|
||||||
|
}
|
|
@ -13,30 +13,31 @@ ShortPhoneNumber::ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number) {
|
||||||
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");
|
||||||
}
|
}
|
||||||
_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");
|
||||||
}
|
}
|
||||||
_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");
|
||||||
}
|
}
|
||||||
_leading_zeros = leading_zeros;
|
this->leading_zeros(leading_zeros);
|
||||||
} else {
|
} else {
|
||||||
_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());
|
||||||
number.set_italian_leading_zero(_leading_zeros > 0);
|
int32 leading_zeros = this->leading_zeros();
|
||||||
number.set_number_of_leading_zeros(_leading_zeros);
|
number.set_italian_leading_zero(leading_zeros > 0);
|
||||||
|
number.set_number_of_leading_zeros(leading_zeros);
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "phonenumbers/phonenumberutil.h"
|
#include "phonenumbers/phonenumberutil.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);
|
||||||
|
@ -20,14 +22,48 @@ class ShortPhoneNumber {
|
||||||
MAX_NATIONAL_NUMBER = 999999999999999,
|
MAX_NATIONAL_NUMBER = 999999999999999,
|
||||||
MAX_LEADING_ZEROS = 15,
|
MAX_LEADING_ZEROS = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum : size_t {
|
||||||
|
COUNTRY_CODE_BITS = 10,
|
||||||
|
NATIONAL_NUMBER_BITS = 50,
|
||||||
|
LEADING_ZEROS_BITS = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum : size_t {
|
||||||
|
COUNTRY_CODE_OFFSET = 0,
|
||||||
|
NATIONAL_NUMBER_OFFSET = COUNTRY_CODE_OFFSET + COUNTRY_CODE_BITS,
|
||||||
|
LEADING_ZEROS_OFFSET = NATIONAL_NUMBER_OFFSET + NATIONAL_NUMBER_BITS,
|
||||||
|
};
|
||||||
|
|
||||||
ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number);
|
ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number);
|
||||||
|
|
||||||
operator i18n::phonenumbers::PhoneNumber() const;
|
operator i18n::phonenumbers::PhoneNumber() const;
|
||||||
|
|
||||||
|
google::protobuf::uint32 country_code() const {
|
||||||
|
return getMasked(_data, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void country_code(google::protobuf::uint32 value) {
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void national_number(google::protobuf::uint64 value) {
|
||||||
|
_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:
|
private:
|
||||||
google::protobuf::uint32 _country_code : 10;
|
google::protobuf::uint64 _data;
|
||||||
google::protobuf::uint64 _national_number : 50;
|
|
||||||
google::protobuf::uint32 _leading_zeros : 4;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue