mini_phone 1.0.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f19ec27523bfdcd42b72b4421441b4016b4bf86c94f91f527e10bf5a33d1a16
4
- data.tar.gz: 7ab2cf83930eaa1c35f7bf2a2faa7afded85238b8a69bf8822013f3f33ee274a
3
+ metadata.gz: 9fb40430cfcb4a6d8cc44557e7fb84622fe20cf14819c14f10a919dc5b9880e7
4
+ data.tar.gz: 5ad868da4e69d3b0ef3b91687863547ea876ec01e0bd2d7ae2e9bea1c8e16668
5
5
  SHA512:
6
- metadata.gz: 853cc1202032f2c6f2fec744de57bfdabac907116fd1495060b65c5d51da060dbf317f253ca3179787f2de9162c7961e83d3f1c39909bbf7ae252262dcfaf7e4
7
- data.tar.gz: 3965cf5f9798b3529eab55f0eb24b3532950f306005fca4655589d8d27c925028115a976fa623af6ca16e715aa6f8f9993cd8716779356f5c194b7cc5f7d4e6f
6
+ metadata.gz: df02fd332486b4b1c2775420377d2b478324b1b25de950268279ce6dd1875373dd4c7bc798300b0446cee72d7581d7338f4a0725d811a0ff317b7209bdebb4a7
7
+ data.tar.gz: a4130f908c91d8369665ec31174857ab6a2e7dc07b85f97008560a3d057db23a49dc39b85e53d0f61a290e0f89c8b320b2f5023041b0b19704bf66f9363ed672
@@ -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 in the the Google's native C++
4
- [libphonenumber](https://github.com/google/libphonenumber) for extemely
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 t0 50x faster than other Ruby phone number
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 # +14043841399
27
- phone_number.national # (404) 384-1399
28
- phone_number.international # +1 404-384-1399
29
- phone_number.rfc3966 # tel:+1-404-384-1384
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['+12423651234').type # :fixed_line
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) so in many cases it can be a
69
- drop in replacement. It has a smaller feature set, so if you need it it not a
70
- drop in replacement for every use case. If there is a feature you need, open
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 t0 50x faster than other libraries. To run
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/[USERNAME]/mini_phone. This project is intended to be a
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/[USERNAME]/mini_phone/blob/master/CODE_OF_CONDUCT.md).
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/[USERNAME]/mini_phone/blob/master/CODE_OF_CONDUCT.md).
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
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ bundle exec rake compile
6
+ exec ruby "$(dirname "$0")/memory.rb" | ttyplot
@@ -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
- PhoneNumber phone_number;
18
- std::string raw_phone_number;
19
- std::string raw_country_code;
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 *phone_util = PhoneNumberUtil::GetInstance();
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->ParseAndKeepRawInput(phone_number, country_code, &parsed_number);
53
+ auto result = phone_util.ParseAndKeepRawInput(phone_number, country_code, &parsed_number);
30
54
 
31
- if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util->IsValidNumber(parsed_number)) {
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 *phone_util = PhoneNumberUtil::GetInstance();
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->Parse(phone_number, country_code, &parsed_number);
106
+ auto result = phone_util.Parse(phone_number, country_code, &parsed_number);
65
107
 
66
- if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util->IsPossibleNumber(parsed_number)) {
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
- PhoneNumberInfo *phone_number_info = new PhoneNumberInfo();
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
- /* wrap */
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
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
183
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
133
184
 
134
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
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->Parse(phone_number, country_code, &parsed_number);
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 = parsed_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
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
204
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
154
205
 
155
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
156
- PhoneNumber parsed_number = phone_number_info->phone_number;
157
- phone_util->Format(parsed_number, fmt, &formatted_number);
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
- std::string formatted_number;
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
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
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
- phone_util->FormatByPattern(phone_number_info->phone_number, PhoneNumberUtil::NATIONAL, raw_national_format,
206
- &formatted_number);
285
+ int code = phone_number_info->phone_number->country_code();
207
286
 
208
- VALUE result = rb_str_new(formatted_number.c_str(), formatted_number.size());
287
+ VALUE result = INT2NUM(code);
209
288
 
210
- return rb_iv_set(self, "@raw_national", result);
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
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
325
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
221
326
 
222
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
327
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
223
328
 
224
- if (phone_util->IsValidNumber(phone_number_info->phone_number)) {
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
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
347
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
243
348
 
244
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
349
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
245
350
 
246
- if (phone_util->IsPossibleNumber(phone_number_info->phone_number)) {
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
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
265
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
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->GetRegionCodeForCountryCode(phone_number_info->phone_number.country_code(), &code);
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 *phone_util = PhoneNumberUtil::GetInstance();
384
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
295
385
 
296
386
  PhoneNumberInfo *self_phone_number_info;
297
- Data_Get_Struct(self, PhoneNumberInfo, self_phone_number_info);
387
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, self_phone_number_info);
298
388
 
299
389
  PhoneNumberInfo *other_phone_number_info;
300
- Data_Get_Struct(other, PhoneNumberInfo, other_phone_number_info);
301
- if (phone_util->IsNumberMatch(other_phone_number_info->phone_number, self_phone_number_info->phone_number)) {
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
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
315
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
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->GetNumberType(phone_number_info->phone_number)) {
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
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniPhone
4
- VERSION = '1.0.3'
4
+ VERSION = '1.1.1'
5
5
  end
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.0.3
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-08 00:00:00.000000000 Z
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