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 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