mini_phone 1.0.2 → 1.1.0

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: 54303715ea62a3242c279007d693c6e50727f63a584bd180ec64b385fd5c5368
4
- data.tar.gz: 9fee829e59cdbc304eea3a2e88a86c8e53264e38ab6cde0aaf31261a6dd5d03c
3
+ metadata.gz: 89fa88b742202101e6bb0204bad2fd20545946a19447d227f61312dd1f9e251c
4
+ data.tar.gz: 49a1d96d9a61aa00c24b88c7e6d3b51dab2929f9ec12043ce2508fc6af374da2
5
5
  SHA512:
6
- metadata.gz: 43829b6078b48ac2a5ed3e69662a9c0cd8b3bc42d2b744d9836b080eaa604a8a33486f445ead9506c3663714853b914203811af781ca71a3804c0ca0a358b9b1
7
- data.tar.gz: 759f0d9dd79035372a50bc19b049f05d897df905cce531eaf5b71b738cf611d3179e8256c9b072b4c59a05573496d3c721946b7b4d266fe7dab7991169a33719
6
+ metadata.gz: 5e719bb7cade41a127cd601f06ca5f2529dae2994112c89bf56ace37202230a2c4a3fae7c0738632d78d032cae0f6b7d1e20365a48f57f0ff046bc0241b2f023
7
+ data.tar.gz: f4ba0f376645bea9b1c25c94f5ba696d744988a1e11a44ff4081af0435165b7a573e24f3101b12dd652add2dccf2e23596bf75ed21b43a5e2fd0a44b1772ef35
@@ -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
@@ -9,7 +9,7 @@ RSpec::Core::RakeTask.new(:spec)
9
9
 
10
10
  task build: :compile
11
11
 
12
- task default: %i[clobber compile spec]
12
+ task default: %i[clobber compile spec lint]
13
13
 
14
14
  spec = Gem::Specification.load(File.expand_path('mini_phone.gemspec', __dir__))
15
15
 
@@ -28,7 +28,16 @@ task bench: %i[clobber compile] do
28
28
  end
29
29
  end
30
30
 
31
- task :deploy do
31
+ task :lint do
32
+ sh 'bundle exec rubocop'
33
+ end
34
+
35
+ task :format do
36
+ sh 'bundle exec rubocop -A'
37
+ sh 'clang-format -i ext/**/*.{h,cc}'
38
+ end
39
+
40
+ task deploy: :default do
32
41
  sh 'code -w ./lib/mini_phone/version.rb'
33
42
  version = `ruby -r ./lib/mini_phone/version.rb -e 'print MiniPhone::VERSION'`.strip
34
43
  sh "git commit -am 'Bump to v#{version} :confetti_ball:'"
@@ -67,3 +76,21 @@ namespace :publish do
67
76
  push_to_github_registry(g)
68
77
  end
69
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
@@ -1,28 +1,58 @@
1
1
  #include "mini_phone.h"
2
+ #include "phonenumbers/phonemetadata.pb.h"
3
+ #include "phonenumbers/phonenumber.pb.h"
2
4
  #include "phonenumbers/phonenumberutil.h"
3
5
 
4
6
  using namespace ::i18n::phonenumbers;
5
7
 
8
+ using google::protobuf::RepeatedPtrField;
9
+
6
10
  static VALUE rb_mMiniPhone;
7
11
 
8
12
  static VALUE rb_cPhoneNumber;
9
13
 
10
- extern "C" struct PhoneNumberInfo {
11
- PhoneNumber phone_number;
12
- std::string raw_phone_number;
13
- std::string raw_country_code;
14
+ static RepeatedPtrField<NumberFormat> raw_national_format;
15
+ static RepeatedPtrField<NumberFormat> dasherized_national_format;
16
+
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,
14
40
  };
15
41
 
16
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
+
17
47
  PhoneNumber parsed_number;
18
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
48
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
19
49
 
20
50
  std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
21
51
  std::string country_code(RSTRING_PTR(cc), RSTRING_LEN(cc));
22
52
 
23
- auto result = phone_util->ParseAndKeepRawInput(phone_number, country_code, &parsed_number);
53
+ auto result = phone_util.ParseAndKeepRawInput(phone_number, country_code, &parsed_number);
24
54
 
25
- if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util->IsValidNumber(parsed_number)) {
55
+ if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util.IsValidNumber(parsed_number)) {
26
56
  return Qtrue;
27
57
  } else {
28
58
  return Qfalse;
@@ -35,6 +65,20 @@ extern "C" VALUE rb_is_phone_number_valid(VALUE self, VALUE str) {
35
65
  return is_phone_number_valid(self, str, def_cc);
36
66
  }
37
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
+
38
82
  extern "C" VALUE rb_is_phone_number_valid_for_country(VALUE self, VALUE str, VALUE cc) {
39
83
  return is_phone_number_valid(self, str, cc);
40
84
  }
@@ -48,16 +92,20 @@ extern "C" VALUE rb_is_phone_number_invalid_for_country(VALUE self, VALUE str, V
48
92
  }
49
93
 
50
94
  extern "C" VALUE rb_is_phone_number_possible(VALUE self, VALUE str) {
95
+ if (NIL_P(str)) {
96
+ return Qnil;
97
+ }
98
+
51
99
  PhoneNumber parsed_number;
52
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
100
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
53
101
 
54
102
  VALUE def_cc = rb_iv_get(rb_mMiniPhone, "@default_country");
55
103
  std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
56
104
  std::string country_code(RSTRING_PTR(def_cc), RSTRING_LEN(def_cc));
57
105
 
58
- auto result = phone_util->Parse(phone_number, country_code, &parsed_number);
106
+ auto result = phone_util.Parse(phone_number, country_code, &parsed_number);
59
107
 
60
- if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util->IsPossibleNumber(parsed_number)) {
108
+ if (result == PhoneNumberUtil::NO_PARSING_ERROR && phone_util.IsPossibleNumber(parsed_number)) {
61
109
  return Qtrue;
62
110
  } else {
63
111
  return Qfalse;
@@ -69,27 +117,36 @@ extern "C" VALUE rb_is_phone_number_impossible(VALUE self, VALUE str) {
69
117
  }
70
118
 
71
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
+
72
124
  return rb_iv_set(self, "@default_country", str_code);
73
125
  }
74
126
 
75
127
  extern "C" VALUE rb_get_default_country(VALUE self) { return rb_iv_get(self, "@default_country"); }
76
128
 
77
- extern "C" void rb_phone_number_dealloc(PhoneNumberInfo *phone_number_info) { delete phone_number_info; }
78
-
79
129
  extern "C" VALUE rb_phone_number_parse(int argc, VALUE *argv, VALUE self) {
80
130
  return rb_class_new_instance(argc, argv, rb_cPhoneNumber);
81
131
  }
82
132
 
83
133
  extern "C" VALUE rb_phone_number_alloc(VALUE self) {
84
- 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;
85
139
 
86
- /* wrap */
87
- 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);
88
141
  }
89
142
 
90
143
  static inline VALUE rb_phone_number_nullify_ivars(VALUE self) {
91
144
  rb_iv_set(self, "@national", Qnil);
145
+ rb_iv_set(self, "@raw_national", Qnil);
146
+ rb_iv_set(self, "@dasherized_national", Qnil);
92
147
  rb_iv_set(self, "@international", Qnil);
148
+ rb_iv_set(self, "@raw_international", Qnil);
149
+ rb_iv_set(self, "@dasherized_international", Qnil);
93
150
  rb_iv_set(self, "@e164", Qnil);
94
151
  rb_iv_set(self, "@country_code", Qnil);
95
152
  rb_iv_set(self, "@region_code", Qnil);
@@ -97,6 +154,7 @@ static inline VALUE rb_phone_number_nullify_ivars(VALUE self) {
97
154
  rb_iv_set(self, "@type", Qnil);
98
155
  rb_iv_set(self, "@valid", Qfalse);
99
156
  rb_iv_set(self, "@possible", Qfalse);
157
+ rb_iv_set(self, "@area_code", Qnil);
100
158
 
101
159
  return Qtrue;
102
160
  }
@@ -122,19 +180,19 @@ extern "C" VALUE rb_phone_number_initialize(int argc, VALUE *argv, VALUE self) {
122
180
  PhoneNumberInfo *phone_number_info;
123
181
  PhoneNumber parsed_number;
124
182
 
125
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
183
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
126
184
 
127
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
185
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
128
186
 
129
187
  std::string phone_number(RSTRING_PTR(str), RSTRING_LEN(str));
130
188
  std::string country_code(RSTRING_PTR(def_cc), RSTRING_LEN(def_cc));
131
189
 
132
- auto result = phone_util->Parse(phone_number, country_code, &parsed_number);
190
+ auto result = phone_util.Parse(phone_number, country_code, &parsed_number);
133
191
 
134
192
  if (result != PhoneNumberUtil::NO_PARSING_ERROR) {
135
193
  rb_phone_number_nullify_ivars(self);
136
194
  } else {
137
- phone_number_info->phone_number = parsed_number;
195
+ phone_number_info->phone_number->Swap(&parsed_number);
138
196
  }
139
197
 
140
198
  return self;
@@ -143,11 +201,11 @@ extern "C" VALUE rb_phone_number_initialize(int argc, VALUE *argv, VALUE self) {
143
201
  static inline VALUE rb_phone_number_format(VALUE self, PhoneNumberUtil::PhoneNumberFormat fmt) {
144
202
  std::string formatted_number;
145
203
  PhoneNumberInfo *phone_number_info;
146
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
204
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
147
205
 
148
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
149
- PhoneNumber parsed_number = phone_number_info->phone_number;
150
- 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);
151
209
 
152
210
  return rb_str_new(formatted_number.c_str(), formatted_number.size());
153
211
  }
@@ -185,6 +243,78 @@ extern "C" VALUE rb_phone_number_rfc3966(VALUE self) {
185
243
  return rb_iv_set(self, "@rfc3966", rb_phone_number_format(self, PhoneNumberUtil::PhoneNumberFormat::RFC3966));
186
244
  }
187
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
+
257
+ extern "C" VALUE rb_phone_number_raw_national(VALUE self) {
258
+ if (rb_ivar_defined(self, rb_intern("@raw_national"))) {
259
+ return rb_iv_get(self, "@raw_national");
260
+ }
261
+
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
+
282
+ PhoneNumberInfo *phone_number_info;
283
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
284
+
285
+ int code = phone_number_info->phone_number->country_code();
286
+
287
+ VALUE result = INT2NUM(code);
288
+
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);
316
+ }
317
+
188
318
  extern "C" VALUE rb_phone_number_valid_eh(VALUE self) {
189
319
  if (rb_ivar_defined(self, rb_intern("@valid"))) {
190
320
  return rb_iv_get(self, "@valid");
@@ -192,11 +322,11 @@ extern "C" VALUE rb_phone_number_valid_eh(VALUE self) {
192
322
 
193
323
  std::string formatted_number;
194
324
  PhoneNumberInfo *phone_number_info;
195
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
325
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
196
326
 
197
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
327
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
198
328
 
199
- if (phone_util->IsValidNumber(phone_number_info->phone_number)) {
329
+ if (phone_util.IsValidNumber(*phone_number_info->phone_number)) {
200
330
  return rb_iv_set(self, "@valid", Qtrue);
201
331
  } else {
202
332
  return rb_iv_set(self, "@valid", Qfalse);
@@ -214,11 +344,11 @@ extern "C" VALUE rb_phone_number_possible_eh(VALUE self) {
214
344
 
215
345
  std::string formatted_number;
216
346
  PhoneNumberInfo *phone_number_info;
217
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
347
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, phone_number_info);
218
348
 
219
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
349
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
220
350
 
221
- if (phone_util->IsPossibleNumber(phone_number_info->phone_number)) {
351
+ if (phone_util.IsPossibleNumber(*phone_number_info->phone_number)) {
222
352
  return rb_iv_set(self, "@possible", Qtrue);
223
353
  } else {
224
354
  return rb_iv_set(self, "@possible", Qfalse);
@@ -236,44 +366,30 @@ extern "C" VALUE rb_phone_number_region_code(VALUE self) {
236
366
 
237
367
  PhoneNumberInfo *phone_number_info;
238
368
  std::string code;
239
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
240
- 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());
241
371
 
242
- phone_util->GetRegionCodeForCountryCode(phone_number_info->phone_number.country_code(), &code);
372
+ phone_util.GetRegionCodeForCountryCode(phone_number_info->phone_number->country_code(), &code);
243
373
 
244
374
  VALUE result = rb_str_new(code.c_str(), code.size());
245
375
 
246
376
  return rb_iv_set(self, "@region_code", result);
247
377
  }
248
378
 
249
- extern "C" VALUE rb_phone_number_country_code(VALUE self) {
250
- if (rb_ivar_defined(self, rb_intern("@country_code"))) {
251
- return rb_iv_get(self, "@country_code");
252
- }
253
-
254
- PhoneNumberInfo *phone_number_info;
255
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
256
-
257
- int code = phone_number_info->phone_number.country_code();
258
-
259
- VALUE result = INT2NUM(code);
260
-
261
- return rb_iv_set(self, "@country_code", result);
262
- }
263
-
264
379
  extern "C" VALUE rb_phone_number_eql_eh(VALUE self, VALUE other) {
265
380
  if (!rb_obj_is_instance_of(other, rb_cPhoneNumber)) {
266
381
  return Qfalse;
267
382
  }
268
383
 
269
- PhoneNumberUtil *phone_util = PhoneNumberUtil::GetInstance();
384
+ const PhoneNumberUtil &phone_util(*PhoneNumberUtil::GetInstance());
270
385
 
271
386
  PhoneNumberInfo *self_phone_number_info;
272
- Data_Get_Struct(self, PhoneNumberInfo, self_phone_number_info);
387
+ TypedData_Get_Struct(self, PhoneNumberInfo, &phone_number_info_type, self_phone_number_info);
273
388
 
274
389
  PhoneNumberInfo *other_phone_number_info;
275
- Data_Get_Struct(other, PhoneNumberInfo, other_phone_number_info);
276
- 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)) {
277
393
  return Qtrue;
278
394
  } else {
279
395
  return Qfalse;
@@ -286,14 +402,14 @@ extern "C" VALUE rb_phone_number_type(VALUE self) {
286
402
  }
287
403
 
288
404
  PhoneNumberInfo *phone_number_info;
289
- Data_Get_Struct(self, PhoneNumberInfo, phone_number_info);
290
- 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());
291
407
 
292
408
  VALUE result;
293
409
 
294
410
  // @see
295
411
  // https://github.com/google/libphonenumber/blob/4e9954edea7cf263532c5dd3861a801104c3f012/cpp/src/phonenumbers/phonenumberutil.h#L91
296
- switch (phone_util->GetNumberType(phone_number_info->phone_number)) {
412
+ switch (phone_util.GetNumberType(*phone_number_info->phone_number)) {
297
413
  case PhoneNumberUtil::PREMIUM_RATE:
298
414
  result = rb_intern("premium_rate");
299
415
  break;
@@ -335,7 +451,50 @@ extern "C" VALUE rb_phone_number_type(VALUE self) {
335
451
  return rb_iv_set(self, "@type", ID2SYM(result));
336
452
  }
337
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
+ static inline void setup_formats() {
484
+ // Raw
485
+ NumberFormat *raw_fmt = raw_national_format.Add();
486
+ raw_fmt->set_pattern("(\\d{3})(\\d{3})(\\d{4})");
487
+ raw_fmt->set_format("$1$2$3");
488
+
489
+ // Dasherized
490
+ NumberFormat *dsh_fmt = dasherized_national_format.Add();
491
+ dsh_fmt->set_pattern("(\\d{3})(\\d{3})(\\d{4})");
492
+ dsh_fmt->set_format("$1-$2-$3");
493
+ }
494
+
338
495
  extern "C" void Init_mini_phone(void) {
496
+ setup_formats();
497
+
339
498
  rb_mMiniPhone = rb_define_module("MiniPhone");
340
499
 
341
500
  // Unknown
@@ -350,11 +509,13 @@ extern "C" void Init_mini_phone(void) {
350
509
  rb_define_module_function(rb_mMiniPhone, "possible?", reinterpret_cast<VALUE (*)(...)>(rb_is_phone_number_valid), 1);
351
510
  rb_define_module_function(rb_mMiniPhone, "impossible?", reinterpret_cast<VALUE (*)(...)>(rb_is_phone_number_invalid),
352
511
  1);
353
- rb_define_module_function(rb_mMiniPhone,
354
- "default_country=", reinterpret_cast<VALUE (*)(...)>(rb_set_default_country), 1);
355
- rb_define_module_function(rb_mMiniPhone, "default_country",
356
- reinterpret_cast<VALUE (*)(...)>(rb_get_default_country), 0);
512
+ rb_define_module_function(rb_mMiniPhone, "default_country=", reinterpret_cast<VALUE (*)(...)>(rb_set_default_country),
513
+ 1);
514
+ rb_define_module_function(rb_mMiniPhone, "default_country", reinterpret_cast<VALUE (*)(...)>(rb_get_default_country),
515
+ 0);
357
516
  rb_define_module_function(rb_mMiniPhone, "parse", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_parse), -1);
517
+ rb_define_module_function(rb_mMiniPhone, "normalize_digits_only",
518
+ reinterpret_cast<VALUE (*)(...)>(rb_normalize_digits_only), 1);
358
519
 
359
520
  rb_cPhoneNumber = rb_define_class_under(rb_mMiniPhone, "PhoneNumber", rb_cObject);
360
521
 
@@ -367,11 +528,21 @@ extern "C" void Init_mini_phone(void) {
367
528
  rb_define_method(rb_cPhoneNumber, "impossible?", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_impossible_eh), 0);
368
529
  rb_define_method(rb_cPhoneNumber, "e164", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_e164), 0);
369
530
  rb_define_method(rb_cPhoneNumber, "national", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_national), 0);
531
+
532
+ rb_define_method(rb_cPhoneNumber, "raw_national", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_raw_national), 0);
533
+ rb_define_method(rb_cPhoneNumber, "raw_international",
534
+ reinterpret_cast<VALUE (*)(...)>(rb_phone_number_raw_international), 0);
535
+ rb_define_method(rb_cPhoneNumber, "dasherized_international",
536
+ reinterpret_cast<VALUE (*)(...)>(rb_phone_number_dasherized_international), 0);
537
+ rb_define_method(rb_cPhoneNumber, "dasherized_national",
538
+ reinterpret_cast<VALUE (*)(...)>(rb_phone_number_dasherized_national), 0);
370
539
  rb_define_method(rb_cPhoneNumber, "international", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_international),
371
540
  0);
372
541
  rb_define_method(rb_cPhoneNumber, "rfc3966", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_rfc3966), 0);
373
542
  rb_define_method(rb_cPhoneNumber, "region_code", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_region_code), 0);
543
+ rb_define_method(rb_cPhoneNumber, "country", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_region_code), 0);
374
544
  rb_define_method(rb_cPhoneNumber, "country_code", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_country_code), 0);
375
545
  rb_define_method(rb_cPhoneNumber, "type", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_type), 0);
546
+ rb_define_method(rb_cPhoneNumber, "area_code", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_area_code), 0);
376
547
  rb_define_method(rb_cPhoneNumber, "eql?", reinterpret_cast<VALUE (*)(...)>(rb_phone_number_eql_eh), 1);
377
548
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniPhone
4
- VERSION = '1.0.2'
4
+ VERSION = '1.1.0'
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.2
4
+ version: 1.1.0
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-16 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