mini_phone 1.0.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile.dev +9 -0
- data/Gemfile +1 -0
- data/README.md +17 -15
- data/Rakefile +23 -0
- data/debug/memory_plot/memory.rb +33 -0
- data/debug/memory_plot/plot.sh +6 -0
- data/ext/mini_phone/mini_phone.cc +208 -64
- data/lib/mini_phone/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9fb40430cfcb4a6d8cc44557e7fb84622fe20cf14819c14f10a919dc5b9880e7
|
4
|
+
data.tar.gz: 5ad868da4e69d3b0ef3b91687863547ea876ec01e0bd2d7ae2e9bea1c8e16668
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df02fd332486b4b1c2775420377d2b478324b1b25de950268279ce6dd1875373dd4c7bc798300b0446cee72d7581d7338f4a0725d811a0ff317b7209bdebb4a7
|
7
|
+
data.tar.gz: a4130f908c91d8369665ec31174857ab6a2e7dc07b85f97008560a3d057db23a49dc39b85e53d0f61a290e0f89c8b320b2f5023041b0b19704bf66f9363ed672
|
data/Dockerfile.dev
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
FROM ruby:2.7-alpine
|
2
|
+
|
3
|
+
WORKDiR /app
|
4
|
+
|
5
|
+
# RUN apt-get update -y && apt-get install -y valgrind libphonenumber
|
6
|
+
RUN apk add --no-cache libphonenumber-dev valgrind git make libffi-dev build-base
|
7
|
+
COPY Gemfile Gemfile.lock mini_phone.gemspec ./
|
8
|
+
COPY lib/mini_phone/version.rb ./lib/mini_phone/version.rb
|
9
|
+
RUN bundle install -j4
|
data/Gemfile
CHANGED
@@ -7,6 +7,7 @@ gemspec
|
|
7
7
|
|
8
8
|
gem 'rake', require: false
|
9
9
|
# https://github.com/rake-compiler/rake-compiler/pull/166
|
10
|
+
gem 'get_process_mem', require: false
|
10
11
|
gem 'rake-compiler', github: 'larskanis/rake-compiler', branch: 'fix-native-version'
|
11
12
|
gem 'rspec', '~> 3.0', require: false
|
12
13
|
gem 'rspec-github', require: false
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# MiniPhone
|
2
2
|
|
3
|
-
A Ruby gem which plugs directly
|
4
|
-
[libphonenumber](https://github.com/google/libphonenumber) for
|
3
|
+
A Ruby gem which plugs directly into Google's native C++
|
4
|
+
[libphonenumber](https://github.com/google/libphonenumber) for extremely
|
5
5
|
_fast_ and _robust_ phone number parsing, validation, and formatting. On
|
6
|
-
average, most methods are 40x
|
6
|
+
average, most methods are 40x to 50x faster than other Ruby phone number
|
7
7
|
libraries.
|
8
8
|
|
9
9
|
## Usage
|
@@ -23,10 +23,12 @@ MiniPhone.default_country = 'US'
|
|
23
23
|
|
24
24
|
phone_number = MiniPhone.parse('404-384-1399')
|
25
25
|
|
26
|
-
phone_number.e164
|
27
|
-
phone_number.national
|
28
|
-
phone_number.
|
29
|
-
phone_number.
|
26
|
+
phone_number.e164 # +14043841399
|
27
|
+
phone_number.national # (404) 384-1399
|
28
|
+
phone_number.raw_national # 4043841399
|
29
|
+
phone_number.dasherized_national # 404-384-1399
|
30
|
+
phone_number.international # +1 404-384-1399
|
31
|
+
phone_number.rfc3966 # tel:+1-404-384-1384
|
30
32
|
```
|
31
33
|
|
32
34
|
### Checking if a phone number is possible
|
@@ -41,7 +43,7 @@ phone_number.possible? # false
|
|
41
43
|
|
42
44
|
```ruby
|
43
45
|
MiniPhone.parse('+12423570000').type # :mobile
|
44
|
-
MiniPhone.parse
|
46
|
+
MiniPhone.parse('+12423651234').type # :fixed_line
|
45
47
|
```
|
46
48
|
|
47
49
|
The possible types are directly mapped from [this
|
@@ -65,14 +67,14 @@ enum](https://github.com/google/libphonenumber/blob/4e9954edea7cf263532c5dd3861a
|
|
65
67
|
## Compatibility with PhoneLib
|
66
68
|
|
67
69
|
MiniPhone aims to be compatible with
|
68
|
-
[Phonelib](https://github.com/daddyz/phonelib)
|
69
|
-
drop in replacement. It has a smaller feature set, so
|
70
|
-
|
70
|
+
[Phonelib](https://github.com/daddyz/phonelib). In many cases it can be a
|
71
|
+
drop in replacement. It has a smaller feature set, so it is not a
|
72
|
+
replacement for every use case. If there is a feature you need, open
|
71
73
|
an issue and we will try to support it.
|
72
74
|
|
73
75
|
## Benchmarks
|
74
76
|
|
75
|
-
On average, most methods are 40x
|
77
|
+
On average, most methods are 40x to 50x faster than other libraries. To run
|
76
78
|
the benchmarks locally, execute: `bundle exec rake bench`
|
77
79
|
|
78
80
|
```
|
@@ -132,10 +134,10 @@ push git commits and tags, and push the `.gem` file to
|
|
132
134
|
## Contributing
|
133
135
|
|
134
136
|
Bug reports and pull requests are welcome on GitHub at
|
135
|
-
https://github.com/
|
137
|
+
https://github.com/ianks/mini_phone. This project is intended to be a
|
136
138
|
safe, welcoming space for collaboration, and contributors are expected to
|
137
139
|
adhere to the [code of
|
138
|
-
conduct](https://github.com/
|
140
|
+
conduct](https://github.com/ianks/mini_phone/blob/master/CODE_OF_CONDUCT.md).
|
139
141
|
|
140
142
|
## License
|
141
143
|
|
@@ -146,4 +148,4 @@ License](https://opensource.org/licenses/MIT).
|
|
146
148
|
|
147
149
|
Everyone interacting in the MiniPhone project's codebases, issue trackers,
|
148
150
|
chat rooms and mailing lists is expected to follow the [code of
|
149
|
-
conduct](https://github.com/
|
151
|
+
conduct](https://github.com/ianks/mini_phone/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
@@ -32,6 +32,11 @@ task :lint do
|
|
32
32
|
sh 'bundle exec rubocop'
|
33
33
|
end
|
34
34
|
|
35
|
+
task :format do
|
36
|
+
sh 'bundle exec rubocop -A'
|
37
|
+
sh 'clang-format -i ext/**/*.{h,cc}'
|
38
|
+
end
|
39
|
+
|
35
40
|
task deploy: :default do
|
36
41
|
sh 'code -w ./lib/mini_phone/version.rb'
|
37
42
|
version = `ruby -r ./lib/mini_phone/version.rb -e 'print MiniPhone::VERSION'`.strip
|
@@ -71,3 +76,21 @@ namespace :publish do
|
|
71
76
|
push_to_github_registry(g)
|
72
77
|
end
|
73
78
|
end
|
79
|
+
|
80
|
+
desc 'Run valgrind test'
|
81
|
+
|
82
|
+
namespace :debug do
|
83
|
+
desc 'Plot memory'
|
84
|
+
task :memory do
|
85
|
+
sh 'debug/memory_plot/plot.sh'
|
86
|
+
end
|
87
|
+
|
88
|
+
task :valgrind do
|
89
|
+
sh 'docker build --tag mini_phone_dev -f Dockerfile.dev .'
|
90
|
+
args = '--tool=memcheck --num-callers=15 --partial-loads-ok=yes --undef-value-errors=no'
|
91
|
+
script = 'ruby debug/memory_plot/memory.rb --once'
|
92
|
+
cmd = "docker run -it --rm -v #{Dir.pwd}:/app -w /app mini_phone_dev valgrind #{args} #{script}"
|
93
|
+
puts cmd
|
94
|
+
system cmd
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'mini_phone'
|
5
|
+
require 'get_process_mem'
|
6
|
+
|
7
|
+
10.times do
|
8
|
+
GC.start
|
9
|
+
GC.compact
|
10
|
+
end
|
11
|
+
|
12
|
+
$stdout.sync = true
|
13
|
+
|
14
|
+
loop do
|
15
|
+
10_000.times do
|
16
|
+
pn = MiniPhone::PhoneNumber.new('+1 404 388 1299')
|
17
|
+
pn.e164
|
18
|
+
pn.valid?
|
19
|
+
pn.possible?
|
20
|
+
pn.raw_national
|
21
|
+
pn.international
|
22
|
+
pn.country_code
|
23
|
+
pn.area_code
|
24
|
+
end
|
25
|
+
|
26
|
+
4.times { GC.start }
|
27
|
+
|
28
|
+
memory_mb = GetProcessMem.new.mb
|
29
|
+
|
30
|
+
$stdout.puts memory_mb
|
31
|
+
|
32
|
+
break if ARGV.first == '--once'
|
33
|
+
end
|
@@ -12,23 +12,47 @@ static VALUE rb_mMiniPhone;
|
|
12
12
|
static VALUE rb_cPhoneNumber;
|
13
13
|
|
14
14
|
static RepeatedPtrField<NumberFormat> raw_national_format;
|
15
|
+
static RepeatedPtrField<NumberFormat> dasherized_national_format;
|
15
16
|
|
16
|
-
extern "C" struct PhoneNumberInfo {
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
extern "C" struct PhoneNumberInfo { PhoneNumber *phone_number; };
|
18
|
+
|
19
|
+
extern "C" size_t phone_number_info_size(const void *data) { return sizeof(PhoneNumberInfo) + sizeof(PhoneNumber); }
|
20
|
+
|
21
|
+
extern "C" void phone_number_info_free(void *data) {
|
22
|
+
PhoneNumberInfo *phone_number_info = static_cast<PhoneNumberInfo *>(data);
|
23
|
+
phone_number_info->phone_number->~PhoneNumber();
|
24
|
+
xfree(phone_number_info->phone_number);
|
25
|
+
phone_number_info->~PhoneNumberInfo();
|
26
|
+
xfree(data);
|
27
|
+
}
|
28
|
+
|
29
|
+
extern "C" const rb_data_type_t phone_number_info_type = {
|
30
|
+
.wrap_struct_name = "MiniPhone/PhoneNumberInfo",
|
31
|
+
.function =
|
32
|
+
{
|
33
|
+
.dmark = NULL,
|
34
|
+
.dfree = phone_number_info_free,
|
35
|
+
.dsize = phone_number_info_size,
|
36
|
+
},
|
37
|
+
.parent = NULL,
|
38
|
+
.data = NULL,
|
39
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
20
40
|
};
|
21
41
|
|
22
42
|
static inline VALUE is_phone_number_valid(VALUE self, VALUE str, VALUE cc) {
|
43
|
+
if (NIL_P(str) || NIL_P(cc)) {
|
44
|
+
return Qfalse;
|
45
|
+
}
|
46
|
+
|
23
47
|
PhoneNumber parsed_number;
|
24
|
-
PhoneNumberUtil *
|
48
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
25
49
|
|
26
50
|
std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
|
27
51
|
std::string country_code(RSTRING_PTR(cc), RSTRING_LEN(cc));
|
28
52
|
|
29
|
-
auto result = phone_util
|
53
|
+
auto result = phone_util.ParseAndKeepRawInput(phone_number, country_code, &parsed_number);
|
30
54
|
|
31
|
-
if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util
|
55
|
+
if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util.IsValidNumber(parsed_number)) {
|
32
56
|
return Qtrue;
|
33
57
|
} else {
|
34
58
|
return Qfalse;
|
@@ -41,6 +65,20 @@ extern "C" VALUE rb_is_phone_number_valid(VALUE self, VALUE str) {
|
|
41
65
|
return is_phone_number_valid(self, str, def_cc);
|
42
66
|
}
|
43
67
|
|
68
|
+
extern "C" VALUE rb_normalize_digits_only(VALUE self, VALUE str) {
|
69
|
+
if (NIL_P(str)) {
|
70
|
+
return Qnil;
|
71
|
+
}
|
72
|
+
|
73
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
74
|
+
|
75
|
+
std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
|
76
|
+
|
77
|
+
phone_util.NormalizeDigitsOnly(&phone_number);
|
78
|
+
|
79
|
+
return rb_str_new(phone_number.c_str(), phone_number.size());
|
80
|
+
}
|
81
|
+
|
44
82
|
extern "C" VALUE rb_is_phone_number_valid_for_country(VALUE self, VALUE str, VALUE cc) {
|
45
83
|
return is_phone_number_valid(self, str, cc);
|
46
84
|
}
|
@@ -54,16 +92,20 @@ extern "C" VALUE rb_is_phone_number_invalid_for_country(VALUE self, VALUE str, V
|
|
54
92
|
}
|
55
93
|
|
56
94
|
extern "C" VALUE rb_is_phone_number_possible(VALUE self, VALUE str) {
|
95
|
+
if (NIL_P(str)) {
|
96
|
+
return Qnil;
|
97
|
+
}
|
98
|
+
|
57
99
|
PhoneNumber parsed_number;
|
58
|
-
PhoneNumberUtil *
|
100
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
59
101
|
|
60
102
|
VALUE def_cc = rb_iv_get(rb_mMiniPhone, "@default_country");
|
61
103
|
std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
|
62
104
|
std::string country_code(RSTRING_PTR(def_cc), RSTRING_LEN(def_cc));
|
63
105
|
|
64
|
-
auto result = phone_util
|
106
|
+
auto result = phone_util.Parse(phone_number, country_code, &parsed_number);
|
65
107
|
|
66
|
-
if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util
|
108
|
+
if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util.IsPossibleNumber(parsed_number)) {
|
67
109
|
return Qtrue;
|
68
110
|
} else {
|
69
111
|
return Qfalse;
|
@@ -75,28 +117,36 @@ extern "C" VALUE rb_is_phone_number_impossible(VALUE self, VALUE str) {
|
|
75
117
|
}
|
76
118
|
|
77
119
|
extern "C" VALUE rb_set_default_country(VALUE self, VALUE str_code) {
|
120
|
+
if (NIL_P(str_code)) {
|
121
|
+
str_code = rb_str_new("ZZ", 2);
|
122
|
+
}
|
123
|
+
|
78
124
|
return rb_iv_set(self, "@default_country", str_code);
|
79
125
|
}
|
80
126
|
|
81
127
|
extern "C" VALUE rb_get_default_country(VALUE self) { return rb_iv_get(self, "@default_country"); }
|
82
128
|
|
83
|
-
extern "C" void rb_phone_number_dealloc(PhoneNumberInfo *phone_number_info) { delete phone_number_info; }
|
84
|
-
|
85
129
|
extern "C" VALUE rb_phone_number_parse(int argc, VALUE *argv, VALUE self) {
|
86
130
|
return rb_class_new_instance(argc, argv, rb_cPhoneNumber);
|
87
131
|
}
|
88
132
|
|
89
133
|
extern "C" VALUE rb_phone_number_alloc(VALUE self) {
|
90
|
-
|
134
|
+
void *phone_number_data = ALLOC(PhoneNumber);
|
135
|
+
void *data = ALLOC(PhoneNumberInfo);
|
136
|
+
PhoneNumberInfo *phone_number_info = new (data) PhoneNumberInfo();
|
137
|
+
PhoneNumber *phone_number = new (phone_number_data) PhoneNumber();
|
138
|
+
phone_number_info->phone_number = phone_number;
|
91
139
|
|
92
|
-
|
93
|
-
return Data_Wrap_Struct(self, NULL, &rb_phone_number_dealloc, phone_number_info);
|
140
|
+
return TypedData_Wrap_Struct(self, &phone_number_info_type, phone_number_info);
|
94
141
|
}
|
95
142
|
|
96
143
|
static inline VALUE rb_phone_number_nullify_ivars(VALUE self) {
|
97
144
|
rb_iv_set(self, "@national", Qnil);
|
98
145
|
rb_iv_set(self, "@raw_national", Qnil);
|
146
|
+
rb_iv_set(self, "@dasherized_national", Qnil);
|
99
147
|
rb_iv_set(self, "@international", Qnil);
|
148
|
+
rb_iv_set(self, "@raw_international", Qnil);
|
149
|
+
rb_iv_set(self, "@dasherized_international", Qnil);
|
100
150
|
rb_iv_set(self, "@e164", Qnil);
|
101
151
|
rb_iv_set(self, "@country_code", Qnil);
|
102
152
|
rb_iv_set(self, "@region_code", Qnil);
|
@@ -104,6 +154,7 @@ static inline VALUE rb_phone_number_nullify_ivars(VALUE self) {
|
|
104
154
|
rb_iv_set(self, "@type", Qnil);
|
105
155
|
rb_iv_set(self, "@valid", Qfalse);
|
106
156
|
rb_iv_set(self, "@possible", Qfalse);
|
157
|
+
rb_iv_set(self, "@area_code", Qnil);
|
107
158
|
|
108
159
|
return Qtrue;
|
109
160
|
}
|
@@ -129,19 +180,19 @@ extern "C" VALUE rb_phone_number_initialize(int argc, VALUE *argv, VALUE self) {
|
|
129
180
|
PhoneNumberInfo *phone_number_info;
|
130
181
|
PhoneNumber parsed_number;
|
131
182
|
|
132
|
-
|
183
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
133
184
|
|
134
|
-
PhoneNumberUtil *
|
185
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
135
186
|
|
136
187
|
std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
|
137
188
|
std::string country_code(RSTRING_PTR(def_cc), RSTRING_LEN(def_cc));
|
138
189
|
|
139
|
-
auto result = phone_util
|
190
|
+
auto result = phone_util.Parse(phone_number, country_code, &parsed_number);
|
140
191
|
|
141
192
|
if (result != PhoneNumberUtil::NO_PARSING_ERROR) {
|
142
193
|
rb_phone_number_nullify_ivars(self);
|
143
194
|
} else {
|
144
|
-
phone_number_info->phone_number
|
195
|
+
phone_number_info->phone_number->Swap(&parsed_number);
|
145
196
|
}
|
146
197
|
|
147
198
|
return self;
|
@@ -150,11 +201,11 @@ extern "C" VALUE rb_phone_number_initialize(int argc, VALUE *argv, VALUE self) {
|
|
150
201
|
static inline VALUE rb_phone_number_format(VALUE self, PhoneNumberUtil::PhoneNumberFormat fmt) {
|
151
202
|
std::string formatted_number;
|
152
203
|
PhoneNumberInfo *phone_number_info;
|
153
|
-
|
204
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
154
205
|
|
155
|
-
PhoneNumberUtil *
|
156
|
-
PhoneNumber parsed_number = phone_number_info->phone_number;
|
157
|
-
phone_util
|
206
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
207
|
+
PhoneNumber *parsed_number = phone_number_info->phone_number;
|
208
|
+
phone_util.Format(*parsed_number, fmt, &formatted_number);
|
158
209
|
|
159
210
|
return rb_str_new(formatted_number.c_str(), formatted_number.size());
|
160
211
|
}
|
@@ -192,22 +243,76 @@ extern "C" VALUE rb_phone_number_rfc3966(VALUE self) {
|
|
192
243
|
return rb_iv_set(self, "@rfc3966", rb_phone_number_format(self, PhoneNumberUtil::PhoneNumberFormat::RFC3966));
|
193
244
|
}
|
194
245
|
|
246
|
+
VALUE format_by_pattern_national(VALUE self, RepeatedPtrField<NumberFormat> format) {
|
247
|
+
std::string formatted_number;
|
248
|
+
PhoneNumberInfo *phone_number_info;
|
249
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
250
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
251
|
+
|
252
|
+
phone_util.FormatByPattern(*phone_number_info->phone_number, PhoneNumberUtil::NATIONAL, format, &formatted_number);
|
253
|
+
|
254
|
+
return rb_str_new(formatted_number.c_str(), formatted_number.size());
|
255
|
+
}
|
256
|
+
|
195
257
|
extern "C" VALUE rb_phone_number_raw_national(VALUE self) {
|
196
258
|
if (rb_ivar_defined(self, rb_intern("@raw_national"))) {
|
197
259
|
return rb_iv_get(self, "@raw_national");
|
198
260
|
}
|
199
261
|
|
200
|
-
|
262
|
+
VALUE result = format_by_pattern_national(self, raw_national_format);
|
263
|
+
|
264
|
+
return rb_iv_set(self, "@raw_national", result);
|
265
|
+
}
|
266
|
+
|
267
|
+
extern "C" VALUE rb_phone_number_dasherized_national(VALUE self) {
|
268
|
+
if (rb_ivar_defined(self, rb_intern("@dasherized_national"))) {
|
269
|
+
return rb_iv_get(self, "@dasherized_national");
|
270
|
+
}
|
271
|
+
|
272
|
+
VALUE result = format_by_pattern_national(self, dasherized_national_format);
|
273
|
+
|
274
|
+
return rb_iv_set(self, "@dasherized_national", result);
|
275
|
+
}
|
276
|
+
|
277
|
+
extern "C" VALUE rb_phone_number_country_code(VALUE self) {
|
278
|
+
if (rb_ivar_defined(self, rb_intern("@country_code"))) {
|
279
|
+
return rb_iv_get(self, "@country_code");
|
280
|
+
}
|
281
|
+
|
201
282
|
PhoneNumberInfo *phone_number_info;
|
202
|
-
|
203
|
-
Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
|
283
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
204
284
|
|
205
|
-
|
206
|
-
&formatted_number);
|
285
|
+
int code = phone_number_info->phone_number->country_code();
|
207
286
|
|
208
|
-
VALUE result =
|
287
|
+
VALUE result = INT2NUM(code);
|
209
288
|
|
210
|
-
return rb_iv_set(self, "@
|
289
|
+
return rb_iv_set(self, "@country_code", result);
|
290
|
+
}
|
291
|
+
|
292
|
+
extern "C" VALUE rb_phone_number_dasherized_international(VALUE self) {
|
293
|
+
if (rb_ivar_defined(self, rb_intern("@dasherized_international"))) {
|
294
|
+
return rb_iv_get(self, "@dasherized_international");
|
295
|
+
}
|
296
|
+
|
297
|
+
VALUE national = rb_phone_number_dasherized_national(self);
|
298
|
+
VALUE cc = rb_fix2str(rb_phone_number_country_code(self), 10);
|
299
|
+
VALUE dash = rb_str_new("-", 1);
|
300
|
+
VALUE prefix = rb_str_concat(cc, dash);
|
301
|
+
VALUE result = rb_str_concat(prefix, national);
|
302
|
+
|
303
|
+
return rb_iv_set(self, "@dasherized_international", result);
|
304
|
+
}
|
305
|
+
|
306
|
+
extern "C" VALUE rb_phone_number_raw_international(VALUE self) {
|
307
|
+
if (rb_ivar_defined(self, rb_intern("@raw_international"))) {
|
308
|
+
return rb_iv_get(self, "@raw_international");
|
309
|
+
}
|
310
|
+
|
311
|
+
VALUE national = rb_phone_number_raw_national(self);
|
312
|
+
VALUE cc = rb_fix2str(rb_phone_number_country_code(self), 10);
|
313
|
+
VALUE result = rb_str_concat(cc, national);
|
314
|
+
|
315
|
+
return rb_iv_set(self, "@raw_international", result);
|
211
316
|
}
|
212
317
|
|
213
318
|
extern "C" VALUE rb_phone_number_valid_eh(VALUE self) {
|
@@ -217,11 +322,11 @@ extern "C" VALUE rb_phone_number_valid_eh(VALUE self) {
|
|
217
322
|
|
218
323
|
std::string formatted_number;
|
219
324
|
PhoneNumberInfo *phone_number_info;
|
220
|
-
|
325
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
221
326
|
|
222
|
-
PhoneNumberUtil *
|
327
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
223
328
|
|
224
|
-
if (phone_util
|
329
|
+
if (phone_util.IsValidNumber(*phone_number_info->phone_number)) {
|
225
330
|
return rb_iv_set(self, "@valid", Qtrue);
|
226
331
|
} else {
|
227
332
|
return rb_iv_set(self, "@valid", Qfalse);
|
@@ -239,11 +344,11 @@ extern "C" VALUE rb_phone_number_possible_eh(VALUE self) {
|
|
239
344
|
|
240
345
|
std::string formatted_number;
|
241
346
|
PhoneNumberInfo *phone_number_info;
|
242
|
-
|
347
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
243
348
|
|
244
|
-
PhoneNumberUtil *
|
349
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
245
350
|
|
246
|
-
if (phone_util
|
351
|
+
if (phone_util.IsPossibleNumber(*phone_number_info->phone_number)) {
|
247
352
|
return rb_iv_set(self, "@possible", Qtrue);
|
248
353
|
} else {
|
249
354
|
return rb_iv_set(self, "@possible", Qfalse);
|
@@ -261,44 +366,30 @@ extern "C" VALUE rb_phone_number_region_code(VALUE self) {
|
|
261
366
|
|
262
367
|
PhoneNumberInfo *phone_number_info;
|
263
368
|
std::string code;
|
264
|
-
|
265
|
-
PhoneNumberUtil *
|
369
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
370
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
266
371
|
|
267
|
-
phone_util
|
372
|
+
phone_util.GetRegionCodeForCountryCode(phone_number_info->phone_number->country_code(), &code);
|
268
373
|
|
269
374
|
VALUE result = rb_str_new(code.c_str(), code.size());
|
270
375
|
|
271
376
|
return rb_iv_set(self, "@region_code", result);
|
272
377
|
}
|
273
378
|
|
274
|
-
extern "C" VALUE rb_phone_number_country_code(VALUE self) {
|
275
|
-
if (rb_ivar_defined(self, rb_intern("@country_code"))) {
|
276
|
-
return rb_iv_get(self, "@country_code");
|
277
|
-
}
|
278
|
-
|
279
|
-
PhoneNumberInfo *phone_number_info;
|
280
|
-
Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
|
281
|
-
|
282
|
-
int code = phone_number_info->phone_number.country_code();
|
283
|
-
|
284
|
-
VALUE result = INT2NUM(code);
|
285
|
-
|
286
|
-
return rb_iv_set(self, "@country_code", result);
|
287
|
-
}
|
288
|
-
|
289
379
|
extern "C" VALUE rb_phone_number_eql_eh(VALUE self, VALUE other) {
|
290
380
|
if (!rb_obj_is_instance_of(other, rb_cPhoneNumber)) {
|
291
381
|
return Qfalse;
|
292
382
|
}
|
293
383
|
|
294
|
-
PhoneNumberUtil *
|
384
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
295
385
|
|
296
386
|
PhoneNumberInfo *self_phone_number_info;
|
297
|
-
|
387
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, self_phone_number_info);
|
298
388
|
|
299
389
|
PhoneNumberInfo *other_phone_number_info;
|
300
|
-
|
301
|
-
|
390
|
+
TypedData_Get_Struct(other, PhoneNumberInfo, &phone_number_info_type, other_phone_number_info);
|
391
|
+
|
392
|
+
if (phone_util.IsNumberMatch(*other_phone_number_info->phone_number, *self_phone_number_info->phone_number)) {
|
302
393
|
return Qtrue;
|
303
394
|
} else {
|
304
395
|
return Qfalse;
|
@@ -311,14 +402,14 @@ extern "C" VALUE rb_phone_number_type(VALUE self) {
|
|
311
402
|
}
|
312
403
|
|
313
404
|
PhoneNumberInfo *phone_number_info;
|
314
|
-
|
315
|
-
PhoneNumberUtil *
|
405
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
406
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
316
407
|
|
317
408
|
VALUE result;
|
318
409
|
|
319
410
|
// @see
|
320
411
|
// https://github.com/google/libphonenumber/blob/4e9954edea7cf263532c5dd3861a801104c3f012/cpp/src/phonenumbers/phonenumberutil.h#L91
|
321
|
-
switch (phone_util
|
412
|
+
switch (phone_util.GetNumberType(*phone_number_info->phone_number)) {
|
322
413
|
case PhoneNumberUtil::PREMIUM_RATE:
|
323
414
|
result = rb_intern("premium_rate");
|
324
415
|
break;
|
@@ -360,7 +451,52 @@ extern "C" VALUE rb_phone_number_type(VALUE self) {
|
|
360
451
|
return rb_iv_set(self, "@type", ID2SYM(result));
|
361
452
|
}
|
362
453
|
|
454
|
+
extern "C" VALUE rb_phone_number_area_code(VALUE self) {
|
455
|
+
if (rb_ivar_defined(self, rb_intern("@area_code"))) {
|
456
|
+
return rb_iv_get(self, "@area_code");
|
457
|
+
}
|
458
|
+
|
459
|
+
const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
|
460
|
+
PhoneNumberInfo *phone_number_info;
|
461
|
+
TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
|
462
|
+
|
463
|
+
PhoneNumber *number = phone_number_info->phone_number;
|
464
|
+
string national_significant_number;
|
465
|
+
phone_util.GetNationalSignificantNumber(*number, &national_significant_number);
|
466
|
+
string area_code;
|
467
|
+
string subscriber_number;
|
468
|
+
|
469
|
+
int area_code_length = phone_util.GetLengthOfGeographicalAreaCode(*number);
|
470
|
+
if (area_code_length > 0) {
|
471
|
+
area_code = national_significant_number.substr(0, area_code_length);
|
472
|
+
subscriber_number = national_significant_number.substr(area_code_length, string::npos);
|
473
|
+
} else {
|
474
|
+
area_code = "";
|
475
|
+
subscriber_number = national_significant_number;
|
476
|
+
}
|
477
|
+
|
478
|
+
VALUE result = rb_str_new(area_code.c_str(), area_code.size());
|
479
|
+
|
480
|
+
return rb_iv_set(self, "@area_code", result);
|
481
|
+
}
|
482
|
+
|
483
|
+
extern "C" VALUE rb_phone_number_to_s(VALUE self) { return rb_iv_get(self, "@input"); }
|
484
|
+
|
485
|
+
static inline void setup_formats() {
|
486
|
+
// Raw
|
487
|
+
NumberFormat *raw_fmt = raw_national_format.Add();
|
488
|
+
raw_fmt->set_pattern("(\\d{3})(\\d{3})(\\d{4})");
|
489
|
+
raw_fmt->set_format("$1$2$3");
|
490
|
+
|
491
|
+
// Dasherized
|
492
|
+
NumberFormat *dsh_fmt = dasherized_national_format.Add();
|
493
|
+
dsh_fmt->set_pattern("(\\d{3})(\\d{3})(\\d{4})");
|
494
|
+
dsh_fmt->set_format("$1-$2-$3");
|
495
|
+
}
|
496
|
+
|
363
497
|
extern "C" void Init_mini_phone(void) {
|
498
|
+
setup_formats();
|
499
|
+
|
364
500
|
rb_mMiniPhone = rb_define_module("MiniPhone");
|
365
501
|
|
366
502
|
// Unknown
|
@@ -380,6 +516,8 @@ extern "C" void Init_mini_phone(void) {
|
|
380
516
|
rb_define_module_function(rb_mMiniPhone, "default_country", reinterpret_cast<VALUE (*)(...)>(rb_get_default_country),
|
381
517
|
0);
|
382
518
|
rb_define_module_function(rb_mMiniPhone, "parse", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_parse), -1);
|
519
|
+
rb_define_module_function(rb_mMiniPhone, "normalize_digits_only",
|
520
|
+
reinterpret_cast<VALUE (*)(...)>(rb_normalize_digits_only), 1);
|
383
521
|
|
384
522
|
rb_cPhoneNumber = rb_define_class_under(rb_mMiniPhone, "PhoneNumber", rb_cObject);
|
385
523
|
|
@@ -393,15 +531,21 @@ extern "C" void Init_mini_phone(void) {
|
|
393
531
|
rb_define_method(rb_cPhoneNumber, "e164", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_e164), 0);
|
394
532
|
rb_define_method(rb_cPhoneNumber, "national", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_national), 0);
|
395
533
|
|
396
|
-
// Raw National
|
397
|
-
raw_national_format.Add()->set_format("$1$2$3");
|
398
|
-
|
399
534
|
rb_define_method(rb_cPhoneNumber, "raw_national", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_raw_national), 0);
|
535
|
+
rb_define_method(rb_cPhoneNumber, "raw_international",
|
536
|
+
reinterpret_cast<VALUE (*)(...)>(rb_phone_number_raw_international), 0);
|
537
|
+
rb_define_method(rb_cPhoneNumber, "dasherized_international",
|
538
|
+
reinterpret_cast<VALUE (*)(...)>(rb_phone_number_dasherized_international), 0);
|
539
|
+
rb_define_method(rb_cPhoneNumber, "dasherized_national",
|
540
|
+
reinterpret_cast<VALUE (*)(...)>(rb_phone_number_dasherized_national), 0);
|
400
541
|
rb_define_method(rb_cPhoneNumber, "international", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_international),
|
401
542
|
0);
|
402
543
|
rb_define_method(rb_cPhoneNumber, "rfc3966", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_rfc3966), 0);
|
403
544
|
rb_define_method(rb_cPhoneNumber, "region_code", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_region_code), 0);
|
545
|
+
rb_define_method(rb_cPhoneNumber, "country", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_region_code), 0);
|
404
546
|
rb_define_method(rb_cPhoneNumber, "country_code", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_country_code), 0);
|
405
547
|
rb_define_method(rb_cPhoneNumber, "type", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_type), 0);
|
548
|
+
rb_define_method(rb_cPhoneNumber, "area_code", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_area_code), 0);
|
549
|
+
rb_define_method(rb_cPhoneNumber, "to_s", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_to_s), 0);
|
406
550
|
rb_define_method(rb_cPhoneNumber, "eql?", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_eql_eh), 1);
|
407
551
|
}
|
data/lib/mini_phone/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_phone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Ker-Seymer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Plugs directly in the the Google's native C++ [libphonenumber](https://github.com/google/libphonenumber)
|
14
14
|
for extemely _fast_ and _robust_ phone number parsing, validation, and formatting.
|
@@ -22,10 +22,13 @@ extra_rdoc_files: []
|
|
22
22
|
files:
|
23
23
|
- CHANGELOG.md
|
24
24
|
- CODE_OF_CONDUCT.md
|
25
|
+
- Dockerfile.dev
|
25
26
|
- Gemfile
|
26
27
|
- LICENSE.txt
|
27
28
|
- README.md
|
28
29
|
- Rakefile
|
30
|
+
- debug/memory_plot/memory.rb
|
31
|
+
- debug/memory_plot/plot.sh
|
29
32
|
- ext/mini_phone/extconf.rb
|
30
33
|
- ext/mini_phone/mini_phone.cc
|
31
34
|
- ext/mini_phone/mini_phone.h
|