ipconverter 0.1.1 → 0.2.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
  SHA1:
3
- metadata.gz: cf2a5bcd16c2e1debc4e76243f377950e2e29886
4
- data.tar.gz: e23960bd3f703c5a0e61eed15256ae7ac069cf79
3
+ metadata.gz: a5c6788e7c3fc69744f0dc2f24403f73eca1ca1f
4
+ data.tar.gz: 2698334ced4e0b518741dc61ab0920e79476ab0a
5
5
  SHA512:
6
- metadata.gz: 68b2fb9ad042f6c2dbca75ef28eae042d2df7a4a34371637e94b6e71ceae060157a8a0c3706d44fcbced43db9bb2ca3efcda03d95716fdcee693b49371dc3f11
7
- data.tar.gz: 58f602f002d910d26c07563a82c4d10a95b06cc2be2fc05f0fac13a1c23cfb4030f499321652ec8d2a09489c8465e0859cb1f6495b9070f7a1ebaae05d7df216
6
+ metadata.gz: ae82161f4019c9223c3d1daca44cede206c70a2909503c7d077bbff8be044e081fb9e48209ce387ad8ad6ec13f5d6732a6b9963b3fbacd13c9023fba19d1cd4f
7
+ data.tar.gz: 740c071a89938af5001e5a62a27161c7859352cd6184b168595e8209b65928f8c348ab1e8b8f7c13bc3c376bd0ca2788c93b497aa732cc619f12add4fed50b07
@@ -0,0 +1,23 @@
1
+ require 'benchmark'
2
+ require 'ipaddr'
3
+ require 'ipconverter'
4
+
5
+ def ruby_shift(ip)
6
+ [
7
+ (ip >> 24) & 255,
8
+ (ip >> 16) & 255,
9
+ (ip >> 8) & 255,
10
+ (ip >> 0) & 255
11
+ ].join('.')
12
+ end
13
+
14
+ ips = 0..999999
15
+
16
+ puts 'iterations: 1,000,000'
17
+
18
+ Benchmark.bmbm do |x|
19
+ x.report('IPAddr#to_s') { ips.each { |ip| IPAddr.new(ip, Socket::AF_INET).to_s } }
20
+ x.report('Ruby shifts') { ips.each { |ip| ruby_shift(ip) } }
21
+ x.report('C shifts') { ips.each { |ip| IpConverter.int_to_str(ip) } }
22
+ x.report('noop') { ips.each { |ip| ip } }
23
+ end
@@ -29,7 +29,7 @@ ips = []
29
29
  end
30
30
  end
31
31
 
32
- puts 'iterations: ' + ips.length
32
+ puts 'iterations: 1,000,000'
33
33
 
34
34
  Benchmark.bmbm do |x|
35
35
  x.report('IPAddr#to_i') { ips.each { |ip| IPAddr.new(ip).to_i } }
@@ -1,12 +1,15 @@
1
1
  #include <ruby.h>
2
2
  #include "ipconverter.h"
3
3
 
4
+ #define MAX_IP_INT 4294967295
5
+
4
6
  // Module name
5
7
  VALUE IpConverter = Qnil;
6
8
 
7
9
  void Init_ipconverter() {
8
10
  IpConverter = rb_define_module("IpConverter");
9
11
  rb_define_method(IpConverter, "str_to_int", method_str_to_int, 1);
12
+ rb_define_method(IpConverter, "int_to_str", method_int_to_str, 1);
10
13
  }
11
14
 
12
15
  /*
@@ -68,3 +71,40 @@ ip_string_to_long(char c_string[], uint32_t *result) {
68
71
  return 1;
69
72
  }
70
73
 
74
+ /*
75
+ * call-seq:
76
+ * IpConverter.int_to_str(ip_addr_integer) -> String
77
+ *
78
+ * Converts the passed integer into an IPv4 address string.
79
+ *
80
+ * Raises ArugmentError if number is negative, or greater than the maximum
81
+ * possible value for an IPv4 address (4294967295)
82
+ *
83
+ * Example:
84
+ * IpConverter.int_to_str(3232236033)
85
+ * => "192.168.2.1"
86
+ *
87
+ */
88
+ VALUE
89
+ method_int_to_str(VALUE _module_, VALUE ip_fixnum) {
90
+ char c_string[16];
91
+ int64_t ip = NUM2LL(ip_fixnum);
92
+ if (ip > MAX_IP_INT || ip < 0) {
93
+ rb_raise(rb_eArgError, "IP address integer out of range");
94
+ }
95
+ ip_long_to_string((uint32_t)ip, c_string);
96
+ return rb_str_new2(c_string);
97
+ }
98
+
99
+ // This one is a void because the bounds checking is done with the uint32_t
100
+ // type already.
101
+ static void
102
+ ip_long_to_string(uint32_t ip, char c_string[]) {
103
+ uint8_t bytes[4];
104
+ bytes[0] = ip & 0xFF;
105
+ bytes[1] = (ip >> 8) & 0xFF;
106
+ bytes[2] = (ip >> 16) & 0xFF;
107
+ bytes[3] = (ip >> 24) & 0xFF;
108
+
109
+ sprintf(c_string, "%d.%d.%d.%d", bytes[3], bytes[2], bytes[1], bytes[0]);
110
+ }
@@ -1,3 +1,7 @@
1
1
  VALUE method_str_to_int(VALUE, VALUE);
2
2
  static int ip_string_to_long(char[], uint32_t*);
3
+
4
+ VALUE method_int_to_str(VALUE, VALUE);
5
+ static void ip_long_to_string(uint32_t, char[]);
6
+
3
7
  void Init_ipconverter();
@@ -8,4 +8,5 @@ require 'ipconverter/ipconverter'
8
8
  #
9
9
  module IpConverter
10
10
  module_function :str_to_int
11
+ module_function :int_to_str
11
12
  end
@@ -1,3 +1,3 @@
1
1
  module IpConverter
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -2,6 +2,7 @@ require 'ipconverter'
2
2
  require 'minitest/autorun'
3
3
 
4
4
  class TestIpConverter < MiniTest::Test
5
+ MAX_IP_INT = 4294967295
5
6
  def setup
6
7
  end
7
8
 
@@ -13,7 +14,7 @@ class TestIpConverter < MiniTest::Test
13
14
  def test_largest_ip
14
15
  int = IpConverter.str_to_int '255.255.255.255'
15
16
  # maximum 32-bit integer
16
- assert_equal int, 256 * 256 * 256 * 256 - 1
17
+ assert_equal int, MAX_IP_INT
17
18
  end
18
19
 
19
20
  def test_handles_spaces
@@ -36,4 +37,20 @@ class TestIpConverter < MiniTest::Test
36
37
  def test_junk
37
38
  assert_raises(ArgumentError) { IpConverter.str_to_int 'junk' }
38
39
  end
40
+
41
+ def test_int_to_str_0
42
+ assert_equal "0.0.0.0", IpConverter.int_to_str(0)
43
+ end
44
+
45
+ def test_int_to_str_max
46
+ assert_equal "255.255.255.255", IpConverter.int_to_str(MAX_IP_INT)
47
+ end
48
+
49
+ def test_int_to_str_negative
50
+ assert_raises(ArgumentError) { IpConverter.int_to_str -1 }
51
+ end
52
+
53
+ def test_int_to_str_too_big
54
+ assert_raises(ArgumentError) { IpConverter.int_to_str(MAX_IP_INT + 1) }
55
+ end
39
56
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ipconverter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Scott
@@ -81,7 +81,8 @@ files:
81
81
  - LICENSE.txt
82
82
  - README.md
83
83
  - Rakefile
84
- - bench.rb
84
+ - benchmark/int_to_str.rb
85
+ - benchmark/str_to_int.rb
85
86
  - ext/ipconverter/extconf.rb
86
87
  - ext/ipconverter/ipconverter.c
87
88
  - ext/ipconverter/ipconverter.h