mini_phone 1.0.2 → 1.1.0

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