ipaddr_list 0.0.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.
- data/ChangeLog +4 -0
- data/README +32 -0
- data/Rakefile +55 -0
- data/lib/ipaddr_list.rb +179 -0
- data/spec/ipaddr_list_spec.rb +5 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +4 -0
- data/tasks/basic_config.rake +22 -0
- data/tasks/basic_tasks.rake +139 -0
- metadata +74 -0
data/ChangeLog
ADDED
data/README
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
= ipaddr_list
|
3
|
+
|
4
|
+
seach ip address area faster than linear search IPAddr's Array.
|
5
|
+
|
6
|
+
== Synopsis
|
7
|
+
|
8
|
+
require 'ipaddr_list'
|
9
|
+
|
10
|
+
list = IPAddrList.new(['192.168.2.3/24', '192.168.0.100/24'], :BinarySearch)
|
11
|
+
list.add('192.168.1.100/24')
|
12
|
+
list.include?('192.168.0.30') #=> true
|
13
|
+
|
14
|
+
== Description
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
=== Archive Installation
|
19
|
+
|
20
|
+
rake install
|
21
|
+
|
22
|
+
=== Gem Installation
|
23
|
+
|
24
|
+
gem install ipaddr_list
|
25
|
+
|
26
|
+
== Features/Problems
|
27
|
+
|
28
|
+
== Copyright
|
29
|
+
|
30
|
+
Author:: Keiji, Yoshimi <walf443 at gmail.com>
|
31
|
+
Copyright:: Copyright (c) 2008 Keiji, Yoshimi
|
32
|
+
License:: you can redistribute it and/or modify it under the same terms as Ruby itself.
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/contrib/rubyforgepublisher'
|
9
|
+
require 'rake/contrib/sshpublisher'
|
10
|
+
require 'fileutils'
|
11
|
+
include FileUtils
|
12
|
+
|
13
|
+
load File.join(File.dirname(__FILE__), 'tasks', 'basic_config.rake')
|
14
|
+
|
15
|
+
NAME = "ipaddr_list"
|
16
|
+
DESCRIPTION = <<-"END_DESCRIPTION"
|
17
|
+
|
18
|
+
END_DESCRIPTION
|
19
|
+
BIN_FILES = %w( )
|
20
|
+
VERS = "0.0.1"
|
21
|
+
|
22
|
+
EXTRA_RDOC_FILES = []
|
23
|
+
HECKLE_ROOT_MODULES = ["IPAddrList"]
|
24
|
+
|
25
|
+
SPEC = Gem::Specification.new do |s|
|
26
|
+
s.name = NAME
|
27
|
+
s.version = VERS
|
28
|
+
s.platform = Gem::Platform::RUBY
|
29
|
+
s.has_rdoc = true
|
30
|
+
s.extra_rdoc_files = DEFAULT_EXTRA_RDOC_FILES + EXTRA_RDOC_FILES
|
31
|
+
s.rdoc_options += RDOC_OPTS + ['--title', "#{NAME} documentation"]
|
32
|
+
s.summary = DESCRIPTION
|
33
|
+
s.description = DESCRIPTION
|
34
|
+
s.author = AUTHOR
|
35
|
+
s.email = EMAIL
|
36
|
+
s.homepage = HOMEPATH
|
37
|
+
s.executables = BIN_FILES
|
38
|
+
s.rubyforge_project = RUBYFORGE_PROJECT
|
39
|
+
s.bindir = "bin"
|
40
|
+
s.require_path = "lib"
|
41
|
+
s.autorequire = ""
|
42
|
+
s.test_files = Dir["spec/*_spec.rb"]
|
43
|
+
|
44
|
+
#s.add_dependency('activesupport', '>=1.3.1')
|
45
|
+
#s.required_ruby_version = '>= 1.8.2'
|
46
|
+
|
47
|
+
if Gem::RubyGemsVersion >= "1.2"
|
48
|
+
s.add_development_dependency('rspec', '>=1.1.4')
|
49
|
+
end
|
50
|
+
|
51
|
+
s.files = PKG_FILES + EXTRA_RDOC_FILES
|
52
|
+
s.extensions = EXTENSIONS
|
53
|
+
end
|
54
|
+
|
55
|
+
import File.join(File.dirname(__FILE__), 'tasks', 'basic_tasks.rake')
|
data/lib/ipaddr_list.rb
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
|
2
|
+
require 'ipaddr'
|
3
|
+
|
4
|
+
# taking method from 1.9.0 for comparing IPAddr instance.
|
5
|
+
if RUBY_VERSION < '1.9.0'
|
6
|
+
class IPAddr
|
7
|
+
# This code come from Ruby 1.9
|
8
|
+
# Compares the ipaddr with another.
|
9
|
+
def <=>(other)
|
10
|
+
other = coerce_other(other)
|
11
|
+
|
12
|
+
return nil if other.family != @family
|
13
|
+
|
14
|
+
return @addr <=> other.to_i
|
15
|
+
end
|
16
|
+
include Comparable
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def coerce_other(other)
|
21
|
+
case other
|
22
|
+
when IPAddr
|
23
|
+
other
|
24
|
+
when String
|
25
|
+
self.class.new(other)
|
26
|
+
else
|
27
|
+
self.class.new(other, @family)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# SYNOPSIS
|
35
|
+
#
|
36
|
+
# require 'ipaddr_list'
|
37
|
+
# list = IPAddrList.new(['192.168.2.3/24', '192.168.0.100/24'], :BinarySearch)
|
38
|
+
# list.add('192.168.1.100/24')
|
39
|
+
# list.include?('192.168.0.30') #=> true
|
40
|
+
#
|
41
|
+
#
|
42
|
+
class IPAddrList
|
43
|
+
module Algorithm
|
44
|
+
# base interface for algorithm module. algorithm module should include this.
|
45
|
+
module Lint
|
46
|
+
# called automatically from IPAddrList#initialize.
|
47
|
+
# you should implement how save ip address list.
|
48
|
+
def after_init ip_list=[]
|
49
|
+
raise NotImprementedError
|
50
|
+
end
|
51
|
+
|
52
|
+
# abstract method. your should implement adding iterating ip address list.
|
53
|
+
def each &block
|
54
|
+
raise NotImprementedError
|
55
|
+
end
|
56
|
+
|
57
|
+
include Enumerable
|
58
|
+
|
59
|
+
# abstract method. you should implement adding ip address to ip address list.
|
60
|
+
def add ip
|
61
|
+
raise NotImprementedError
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# slow and simple. It's for just benchmarking script.
|
66
|
+
module LinearSearch
|
67
|
+
include Lint
|
68
|
+
|
69
|
+
def after_init ip_list=[]
|
70
|
+
@ip_list = ip_list.map {|item|
|
71
|
+
if item.kind_of? IPAddr
|
72
|
+
item
|
73
|
+
else
|
74
|
+
IPAddr.new(item.to_s)
|
75
|
+
end
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def add ip
|
80
|
+
unless ip.kind_of? IPAddr
|
81
|
+
ip = IPAddr.new(ip.to_s)
|
82
|
+
end
|
83
|
+
@ip_list.push ip
|
84
|
+
end
|
85
|
+
|
86
|
+
$LinearCount = 0
|
87
|
+
def each &block
|
88
|
+
@ip_list.each(&block)
|
89
|
+
end
|
90
|
+
|
91
|
+
def include? ip
|
92
|
+
if ip.kind_of? IPAddr
|
93
|
+
ipaddr = ip
|
94
|
+
else
|
95
|
+
ipaddr = IPAddr.new(ip)
|
96
|
+
end
|
97
|
+
@ip_list.any? {|item| item.include? ipaddr }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# searching ipaddress with binary search.
|
102
|
+
module BinarySearch
|
103
|
+
include Lint
|
104
|
+
|
105
|
+
def after_init ip_list=[]
|
106
|
+
@ip_list = ip_list.map {|item|
|
107
|
+
if item.kind_of? IPAddr
|
108
|
+
item
|
109
|
+
else
|
110
|
+
IPAddr.new(item.to_s)
|
111
|
+
end
|
112
|
+
}.sort
|
113
|
+
end
|
114
|
+
|
115
|
+
def add ip
|
116
|
+
unless ip.kind_of? IPAddr
|
117
|
+
ip = IPAddr.new(ip.to_s)
|
118
|
+
end
|
119
|
+
@ip_list.push(ip)
|
120
|
+
@ip_list = @ip_list.sort
|
121
|
+
end
|
122
|
+
|
123
|
+
def each &block
|
124
|
+
@ip_list.each(&block)
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
def include? ip
|
129
|
+
binary_search ip do |ipaddr, range|
|
130
|
+
range.any? {|idx| @ip_list[idx].include? ipaddr }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# binary search
|
135
|
+
# SEE ALSO: http://dsas.blog.klab.org/archives/51293334.html
|
136
|
+
def binary_search ip, &block
|
137
|
+
ipaddr = IPAddr.new(ip)
|
138
|
+
min_idx = 0
|
139
|
+
max_idx = @ip_list.size - 1
|
140
|
+
if @ip_list[max_idx] > ipaddr
|
141
|
+
min_idx = max_idx
|
142
|
+
elsif @ip_list[min_idx] < ipaddr
|
143
|
+
max_idx = min_idx
|
144
|
+
else
|
145
|
+
span = max_idx - min_idx
|
146
|
+
while ( ( span ) > 7 ) do
|
147
|
+
middle_idx = span / 2 + min_idx
|
148
|
+
middle_ip = @ip_list[ middle_idx ]
|
149
|
+
if ipaddr >= middle_ip
|
150
|
+
min_idx = middle_idx
|
151
|
+
else
|
152
|
+
max_idx = middle_idx
|
153
|
+
end
|
154
|
+
|
155
|
+
span = max_idx - min_idx
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
block.call(ipaddr, min_idx..max_idx)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def initialize ip_list, algorithm=IPAddrList::Algorithm::BinarySearch
|
165
|
+
unless algorithm.kind_of? Module
|
166
|
+
algorithm = IPAddrList::Algorithm.const_get(algorithm.to_s)
|
167
|
+
end
|
168
|
+
self.extend(algorithm)
|
169
|
+
@algorithm = algorithm
|
170
|
+
after_init ip_list
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
if $0 == __FILE__
|
175
|
+
ip_list = IPAddrList.new(['192.168.2.3/24', '192.168.0.100/24'], :BinarySearch)
|
176
|
+
ip_list.add('192.168.1.10/24')
|
177
|
+
p ip_list.include?('192.168.1.1')
|
178
|
+
p ip_list.include?('192.168.0.100')
|
179
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-Du -c -fs
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
AUTHOR = "Keiji, Yoshimi"
|
2
|
+
EMAIL = "walf443 at gmail.com"
|
3
|
+
RUBYFORGE_PROJECT = "akasakarb"
|
4
|
+
RUBYFORGE_PROJECT_ID = 4314
|
5
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
6
|
+
RDOC_OPTS = [
|
7
|
+
"--charset", "utf-8",
|
8
|
+
"--opname", "index.html",
|
9
|
+
"--line-numbers",
|
10
|
+
"--main", "README",
|
11
|
+
"--inline-source",
|
12
|
+
'--exclude', '^(example|extras)/'
|
13
|
+
]
|
14
|
+
DEFAULT_EXTRA_RDOC_FILES = ['README', 'ChangeLog']
|
15
|
+
PKG_FILES = [ 'Rakefile' ] +
|
16
|
+
DEFAULT_EXTRA_RDOC_FILES +
|
17
|
+
Dir.glob('{bin,lib,test,spec,doc,tasks,script,generator,templates,extras,website}/**/*') +
|
18
|
+
Dir.glob('ext/**/*.{h,c,rb}') +
|
19
|
+
Dir.glob('examples/**/*.rb') +
|
20
|
+
Dir.glob('tools/*.rb')
|
21
|
+
|
22
|
+
EXTENSIONS = FileList['ext/**/extconf.rb'].to_a
|
@@ -0,0 +1,139 @@
|
|
1
|
+
|
2
|
+
REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
3
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
4
|
+
|
5
|
+
Rake::GemPackageTask.new(SPEC) do |p|
|
6
|
+
p.need_tar = true
|
7
|
+
p.gem_spec = SPEC
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => [:spec]
|
11
|
+
task :test => [:spec]
|
12
|
+
task :package => [:clean]
|
13
|
+
|
14
|
+
require 'spec/rake/spectask'
|
15
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
16
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
17
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
18
|
+
t.warning = true
|
19
|
+
t.rcov = true
|
20
|
+
t.rcov_dir = 'doc/output/coverage'
|
21
|
+
t.rcov_opts = ['--exclude', 'spec,\.autotest']
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Heckle each module and class in turn"
|
25
|
+
task :heckle => :spec do
|
26
|
+
root_modules = HECKLE_ROOT_MODULES
|
27
|
+
spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
|
29
|
+
current_module, current_method = nil, nil
|
30
|
+
heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
|
31
|
+
unhandled_mutations = 0
|
32
|
+
|
33
|
+
root_modules.each do |root_module|
|
34
|
+
IO.popen("heckle #{root_module} -t #{spec_files}") do |pipe|
|
35
|
+
while line = pipe.gets
|
36
|
+
line = line.chomp
|
37
|
+
|
38
|
+
if line =~ /^\*\*\* ((?:\w+(?:::)?)+)#(\w+)/
|
39
|
+
current_module, current_method = $1, $2
|
40
|
+
elsif line == "The following mutations didn't cause test failures:"
|
41
|
+
heckle_caught_modules[current_module] << current_method
|
42
|
+
elsif line == "+++ mutation"
|
43
|
+
unhandled_mutations += 1
|
44
|
+
end
|
45
|
+
|
46
|
+
puts line
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if unhandled_mutations > 0
|
52
|
+
error_message_lines = ["*************\n"]
|
53
|
+
|
54
|
+
error_message_lines <<
|
55
|
+
"Heckle found #{unhandled_mutations} " +
|
56
|
+
"mutation#{"s" unless unhandled_mutations == 1} " +
|
57
|
+
"that didn't cause spec violations\n"
|
58
|
+
|
59
|
+
heckle_caught_modules.each do |mod, methods|
|
60
|
+
error_message_lines <<
|
61
|
+
"#{mod} contains the following poorly-specified methods:"
|
62
|
+
methods.each do |m|
|
63
|
+
error_message_lines << " - #{m}"
|
64
|
+
end
|
65
|
+
error_message_lines << ""
|
66
|
+
end
|
67
|
+
|
68
|
+
error_message_lines <<
|
69
|
+
"Get your act together and come back " +
|
70
|
+
"when your specs are doing their job!"
|
71
|
+
|
72
|
+
puts "*************"
|
73
|
+
raise error_message_lines.join("\n")
|
74
|
+
else
|
75
|
+
puts "Well done! Your code withstood a heckling."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
require 'spec/rake/verify_rcov'
|
80
|
+
RCov::VerifyTask.new(:rcov => :spec) do |t|
|
81
|
+
t.index_html = "doc/output/coverage/index.html"
|
82
|
+
t.threshold = 100
|
83
|
+
end
|
84
|
+
|
85
|
+
task :install do
|
86
|
+
name = "#{NAME}-#{VERS}.gem"
|
87
|
+
sh %{rake package}
|
88
|
+
sh %{sudo gem install pkg/#{name}}
|
89
|
+
end
|
90
|
+
|
91
|
+
task :uninstall => [:clean] do
|
92
|
+
sh %{sudo gem uninstall #{NAME}}
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
Rake::RDocTask.new do |rdoc|
|
97
|
+
rdoc.rdoc_dir = 'html'
|
98
|
+
rdoc.options += RDOC_OPTS
|
99
|
+
rdoc.template = "resh"
|
100
|
+
#rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
101
|
+
if ENV['DOC_FILES']
|
102
|
+
rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
|
103
|
+
else
|
104
|
+
rdoc.rdoc_files.include('README', 'ChangeLog')
|
105
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
106
|
+
rdoc.rdoc_files.include('ext/**/*.c')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
desc "Publish to RubyForge"
|
111
|
+
task :rubyforge => [:rdoc, :package] do
|
112
|
+
require 'rubyforge'
|
113
|
+
Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'yoshimi').upload
|
114
|
+
end
|
115
|
+
|
116
|
+
desc 'Package and upload the release to rubyforge.'
|
117
|
+
task :release => [:clean, :package] do |t|
|
118
|
+
require 'rubyforge'
|
119
|
+
v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
|
120
|
+
abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
|
121
|
+
pkg = "pkg/#{NAME}-#{VERS}"
|
122
|
+
|
123
|
+
rf = RubyForge.new
|
124
|
+
puts "Logging in"
|
125
|
+
rf.login
|
126
|
+
|
127
|
+
c = rf.userconfig
|
128
|
+
# c["release_notes"] = description if description
|
129
|
+
# c["release_changes"] = changes if changes
|
130
|
+
c["preformatted"] = true
|
131
|
+
|
132
|
+
files = [
|
133
|
+
"#{pkg}.tgz",
|
134
|
+
"#{pkg}.gem"
|
135
|
+
].compact
|
136
|
+
|
137
|
+
puts "Releasing #{NAME} v. #{VERS}"
|
138
|
+
rf.add_release RUBYFORGE_PROJECT_ID, RUBYFORGE_PACKAGE_ID, VERS, *files
|
139
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ipaddr_list
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Keiji, Yoshimi
|
8
|
+
autorequire: ""
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-13 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ""
|
17
|
+
email: walf443 at gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- ChangeLog
|
25
|
+
files:
|
26
|
+
- Rakefile
|
27
|
+
- README
|
28
|
+
- ChangeLog
|
29
|
+
- lib/ipaddr_list.rb
|
30
|
+
- spec/ipaddr_list_spec.rb
|
31
|
+
- spec/spec.opts
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- doc/output
|
34
|
+
- tasks/basic_config.rake
|
35
|
+
- tasks/basic_tasks.rake
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://akasakarb.rubyforge.org
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --charset
|
41
|
+
- utf-8
|
42
|
+
- --opname
|
43
|
+
- index.html
|
44
|
+
- --line-numbers
|
45
|
+
- --main
|
46
|
+
- README
|
47
|
+
- --inline-source
|
48
|
+
- --exclude
|
49
|
+
- ^(example|extras)/
|
50
|
+
- --title
|
51
|
+
- ipaddr_list documentation
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project: akasakarb
|
69
|
+
rubygems_version: 1.0.1
|
70
|
+
signing_key:
|
71
|
+
specification_version: 2
|
72
|
+
summary: ""
|
73
|
+
test_files:
|
74
|
+
- spec/ipaddr_list_spec.rb
|