public_suffix 2.0.5 → 4.0.7
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 +5 -5
- data/.github/FUNDING.yml +12 -0
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/release.yml +16 -0
- data/.github/workflows/tests.yml +28 -0
- data/.gitignore +5 -8
- data/.rubocop.yml +19 -1
- data/{.rubocop_defaults.yml → .rubocop_opinionated.yml} +62 -34
- data/CHANGELOG.md +156 -54
- data/Gemfile +9 -5
- data/LICENSE.txt +1 -1
- data/README.md +44 -15
- data/Rakefile +9 -4
- data/SECURITY.md +104 -0
- data/bin/console +15 -0
- data/data/list.txt +3163 -973
- data/lib/public_suffix/domain.rb +4 -4
- data/lib/public_suffix/errors.rb +3 -1
- data/lib/public_suffix/list.rb +78 -117
- data/lib/public_suffix/rule.rb +54 -62
- data/lib/public_suffix/version.rb +8 -3
- data/lib/public_suffix.rb +38 -32
- data/public_suffix.gemspec +9 -5
- data/test/.empty +2 -0
- data/test/acceptance_test.rb +43 -31
- data/test/benchmarks/bm_find.rb +66 -0
- data/test/benchmarks/bm_find_all.rb +102 -0
- data/test/benchmarks/bm_names.rb +91 -0
- data/test/benchmarks/bm_select.rb +26 -0
- data/test/benchmarks/bm_select_incremental.rb +25 -0
- data/test/benchmarks/bm_valid.rb +101 -0
- data/test/profilers/domain_profiler.rb +12 -0
- data/test/profilers/find_profiler.rb +12 -0
- data/test/profilers/find_profiler_jp.rb +12 -0
- data/test/{initialization_profiler.rb → profilers/initialization_profiler.rb} +1 -1
- data/test/profilers/list_profsize.rb +11 -0
- data/test/profilers/object_binsize.rb +57 -0
- data/test/psl_test.rb +7 -4
- data/test/test_helper.rb +3 -14
- data/test/unit/domain_test.rb +17 -15
- data/test/unit/errors_test.rb +2 -0
- data/test/unit/list_test.rb +54 -72
- data/test/unit/public_suffix_test.rb +24 -22
- data/test/unit/rule_test.rb +77 -79
- metadata +32 -70
- data/.ruby-gemset +0 -1
- data/.travis.yml +0 -23
- data/test/benchmark_helper.rb +0 -4
- data/test/execution_profiler.rb +0 -14
- data/test/performance_benchmark.rb +0 -38
data/lib/public_suffix.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = Public Suffix
|
2
4
|
#
|
3
5
|
# Domain name parser based on the Public Suffix List.
|
4
6
|
#
|
5
|
-
# Copyright (c) 2009-
|
7
|
+
# Copyright (c) 2009-2022 Simone Carletti <weppos@weppos.net>
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
require_relative "public_suffix/domain"
|
10
|
+
require_relative "public_suffix/version"
|
11
|
+
require_relative "public_suffix/errors"
|
12
|
+
require_relative "public_suffix/rule"
|
13
|
+
require_relative "public_suffix/list"
|
12
14
|
|
13
15
|
# PublicSuffix is a Ruby domain name parser based on the Public Suffix List.
|
14
16
|
#
|
@@ -20,46 +22,48 @@ require "public_suffix/list"
|
|
20
22
|
# but was originally created to meet the needs of browser manufacturers.
|
21
23
|
module PublicSuffix
|
22
24
|
|
23
|
-
DOT = "."
|
24
|
-
BANG = "!"
|
25
|
-
STAR = "*"
|
25
|
+
DOT = "."
|
26
|
+
BANG = "!"
|
27
|
+
STAR = "*"
|
26
28
|
|
27
29
|
# Parses +name+ and returns the {PublicSuffix::Domain} instance.
|
28
30
|
#
|
29
31
|
# @example Parse a valid domain
|
30
32
|
# PublicSuffix.parse("google.com")
|
31
|
-
# # => #<PublicSuffix::Domain
|
33
|
+
# # => #<PublicSuffix::Domain:0x007fec2e51e588 @sld="google", @tld="com", @trd=nil>
|
32
34
|
#
|
33
35
|
# @example Parse a valid subdomain
|
34
36
|
# PublicSuffix.parse("www.google.com")
|
35
|
-
# # => #<PublicSuffix::Domain
|
37
|
+
# # => #<PublicSuffix::Domain:0x007fec276d4cf8 @sld="google", @tld="com", @trd="www">
|
36
38
|
#
|
37
39
|
# @example Parse a fully qualified domain
|
38
40
|
# PublicSuffix.parse("google.com.")
|
39
|
-
# # => #<PublicSuffix::Domain
|
41
|
+
# # => #<PublicSuffix::Domain:0x007fec257caf38 @sld="google", @tld="com", @trd=nil>
|
40
42
|
#
|
41
43
|
# @example Parse a fully qualified domain (subdomain)
|
42
44
|
# PublicSuffix.parse("www.google.com.")
|
43
|
-
# # => #<PublicSuffix::Domain
|
45
|
+
# # => #<PublicSuffix::Domain:0x007fec27b6bca8 @sld="google", @tld="com", @trd="www">
|
44
46
|
#
|
45
|
-
# @example Parse an invalid domain
|
47
|
+
# @example Parse an invalid (unlisted) domain
|
46
48
|
# PublicSuffix.parse("x.yz")
|
47
|
-
# # => PublicSuffix::
|
49
|
+
# # => #<PublicSuffix::Domain:0x007fec2f49bec0 @sld="x", @tld="yz", @trd=nil>
|
50
|
+
#
|
51
|
+
# @example Parse an invalid (unlisted) domain with strict checking (without applying the default * rule)
|
52
|
+
# PublicSuffix.parse("x.yz", default_rule: nil)
|
53
|
+
# # => PublicSuffix::DomainInvalid: `x.yz` is not a valid domain
|
48
54
|
#
|
49
55
|
# @example Parse an URL (not supported, only domains)
|
50
56
|
# PublicSuffix.parse("http://www.google.com")
|
51
|
-
# # => PublicSuffix::DomainInvalid
|
57
|
+
# # => PublicSuffix::DomainInvalid: http://www.google.com is not expected to contain a scheme
|
52
58
|
#
|
53
59
|
#
|
54
|
-
# @param [
|
55
|
-
# @param [PublicSuffix::List]
|
56
|
-
# @param [Boolean]
|
60
|
+
# @param name [#to_s] The domain name or fully qualified domain name to parse.
|
61
|
+
# @param list [PublicSuffix::List] The rule list to search, defaults to the default {PublicSuffix::List}
|
62
|
+
# @param ignore_private [Boolean]
|
57
63
|
# @return [PublicSuffix::Domain]
|
58
64
|
#
|
59
|
-
# @raise [PublicSuffix::DomainInvalid]
|
60
|
-
#
|
61
|
-
# @raise [PublicSuffix::DomainNotAllowed]
|
62
|
-
# If a rule for +domain+ is found, but the rule doesn't allow +domain+.
|
65
|
+
# @raise [PublicSuffix::DomainInvalid] If domain is not a valid domain.
|
66
|
+
# @raise [PublicSuffix::DomainNotAllowed] If a rule for +domain+ is found, but the rule doesn't allow +domain+.
|
63
67
|
def self.parse(name, list: List.default, default_rule: list.default_rule, ignore_private: false)
|
64
68
|
what = normalize(name)
|
65
69
|
raise what if what.is_a?(DomainInvalid)
|
@@ -73,6 +77,7 @@ module PublicSuffix
|
|
73
77
|
if rule.decompose(what).last.nil?
|
74
78
|
raise DomainNotAllowed, "`#{what}` is not allowed according to Registry policy"
|
75
79
|
end
|
80
|
+
|
76
81
|
# rubocop:enable Style/IfUnlessModifier
|
77
82
|
|
78
83
|
decompose(what, rule)
|
@@ -95,11 +100,11 @@ module PublicSuffix
|
|
95
100
|
# PublicSuffix.valid?("example.tldnotlisted")
|
96
101
|
# # => true
|
97
102
|
#
|
98
|
-
# @example Validate a not-
|
99
|
-
# PublicSuffix.valid?("example.
|
100
|
-
# # => false
|
101
|
-
# PublicSuffix.valid?("www.example.do")
|
103
|
+
# @example Validate a not-listed domain with strict checking (without applying the default * rule)
|
104
|
+
# PublicSuffix.valid?("example.tldnotlisted")
|
102
105
|
# # => true
|
106
|
+
# PublicSuffix.valid?("example.tldnotlisted", default_rule: nil)
|
107
|
+
# # => false
|
103
108
|
#
|
104
109
|
# @example Validate a fully qualified domain
|
105
110
|
# PublicSuffix.valid?("google.com.")
|
@@ -112,8 +117,8 @@ module PublicSuffix
|
|
112
117
|
# # => false
|
113
118
|
#
|
114
119
|
#
|
115
|
-
# @param [
|
116
|
-
# @param [Boolean]
|
120
|
+
# @param name [#to_s] The domain name or fully qualified domain name to validate.
|
121
|
+
# @param ignore_private [Boolean]
|
117
122
|
# @return [Boolean]
|
118
123
|
def self.valid?(name, list: List.default, default_rule: list.default_rule, ignore_private: false)
|
119
124
|
what = normalize(name)
|
@@ -128,9 +133,9 @@ module PublicSuffix
|
|
128
133
|
#
|
129
134
|
# This method doesn't raise. Instead, it returns nil if the domain is not valid for whatever reason.
|
130
135
|
#
|
131
|
-
# @param [
|
132
|
-
# @param [PublicSuffix::List]
|
133
|
-
# @param [Boolean]
|
136
|
+
# @param name [#to_s] The domain name or fully qualified domain name to parse.
|
137
|
+
# @param list [PublicSuffix::List] The rule list to search, defaults to the default {PublicSuffix::List}
|
138
|
+
# @param ignore_private [Boolean]
|
134
139
|
# @return [String]
|
135
140
|
def self.domain(name, **options)
|
136
141
|
parse(name, **options).domain
|
@@ -165,6 +170,7 @@ module PublicSuffix
|
|
165
170
|
return DomainInvalid.new("Name is blank") if name.empty?
|
166
171
|
return DomainInvalid.new("Name starts with a dot") if name.start_with?(DOT)
|
167
172
|
return DomainInvalid.new("%s is not expected to contain a scheme" % name) if name.include?("://")
|
173
|
+
|
168
174
|
name
|
169
175
|
end
|
170
176
|
|
data/public_suffix.gemspec
CHANGED
@@ -12,14 +12,18 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.description = "PublicSuffix can parse and decompose a domain name into top level domain, domain and subdomains."
|
13
13
|
s.licenses = ["MIT"]
|
14
14
|
|
15
|
-
s.
|
15
|
+
s.metadata = {
|
16
|
+
"bug_tracker_uri" => "https://github.com/weppos/publicsuffix-ruby/issues",
|
17
|
+
"changelog_uri" => "https://github.com/weppos/publicsuffix-ruby/blob/master/CHANGELOG.md",
|
18
|
+
"documentation_uri" => "https://rubydoc.info/gems/#{s.name}/#{s.version}",
|
19
|
+
"homepage_uri" => s.homepage,
|
20
|
+
"source_code_uri" => "https://github.com/weppos/publicsuffix-ruby/tree/v#{s.version}",
|
21
|
+
}
|
22
|
+
|
23
|
+
s.required_ruby_version = ">= 2.3"
|
16
24
|
|
17
25
|
s.require_paths = ["lib"]
|
18
26
|
s.files = `git ls-files`.split("\n")
|
19
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
28
|
s.extra_rdoc_files = %w( LICENSE.txt )
|
21
|
-
|
22
|
-
s.add_development_dependency "rake"
|
23
|
-
s.add_development_dependency "mocha"
|
24
|
-
s.add_development_dependency "yard"
|
25
29
|
end
|
data/test/.empty
ADDED
data/test/acceptance_test.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "test_helper"
|
2
4
|
|
3
5
|
class AcceptanceTest < Minitest::Test
|
4
6
|
|
5
7
|
VALID_CASES = [
|
6
|
-
|
7
|
-
|
8
|
+
["example.com", "example.com", [nil, "example", "com"]],
|
9
|
+
["foo.example.com", "example.com", ["foo", "example", "com"]],
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
["verybritish.co.uk", "verybritish.co.uk", [nil, "verybritish", "co.uk"]],
|
12
|
+
["foo.verybritish.co.uk", "verybritish.co.uk", ["foo", "verybritish", "co.uk"]],
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
["parliament.uk", "parliament.uk", [nil, "parliament", "uk"]],
|
15
|
+
["foo.parliament.uk", "parliament.uk", ["foo", "parliament", "uk"]],
|
14
16
|
].freeze
|
15
17
|
|
16
18
|
def test_valid
|
@@ -19,7 +21,11 @@ class AcceptanceTest < Minitest::Test
|
|
19
21
|
trd, sld, tld = results
|
20
22
|
assert_equal tld, parsed.tld, "Invalid tld for `#{name}`"
|
21
23
|
assert_equal sld, parsed.sld, "Invalid sld for `#{name}`"
|
22
|
-
|
24
|
+
if trd.nil?
|
25
|
+
assert_nil parsed.trd, "Invalid trd for `#{name}`"
|
26
|
+
else
|
27
|
+
assert_equal trd, parsed.trd, "Invalid trd for `#{name}`"
|
28
|
+
end
|
23
29
|
|
24
30
|
assert_equal domain, PublicSuffix.domain(input)
|
25
31
|
assert PublicSuffix.valid?(input)
|
@@ -28,10 +34,10 @@ class AcceptanceTest < Minitest::Test
|
|
28
34
|
|
29
35
|
|
30
36
|
INVALID_CASES = [
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
["nic.bd", PublicSuffix::DomainNotAllowed],
|
38
|
+
[nil, PublicSuffix::DomainInvalid],
|
39
|
+
["", PublicSuffix::DomainInvalid],
|
40
|
+
[" ", PublicSuffix::DomainInvalid],
|
35
41
|
].freeze
|
36
42
|
|
37
43
|
def test_invalid
|
@@ -43,16 +49,16 @@ class AcceptanceTest < Minitest::Test
|
|
43
49
|
|
44
50
|
|
45
51
|
REJECTED_CASES = [
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
["www. .com", true],
|
53
|
+
["foo.co..uk", true],
|
54
|
+
["goo,gle.com", true],
|
55
|
+
["-google.com", true],
|
56
|
+
["google-.com", true],
|
57
|
+
|
58
|
+
# This case was covered in GH-15.
|
59
|
+
# I decided to cover this case because it's not easily reproducible with URI.parse
|
60
|
+
# and can lead to several false positives.
|
61
|
+
["http://google.com", false],
|
56
62
|
].freeze
|
57
63
|
|
58
64
|
def test_rejected
|
@@ -66,9 +72,9 @@ class AcceptanceTest < Minitest::Test
|
|
66
72
|
|
67
73
|
|
68
74
|
CASE_CASES = [
|
69
|
-
|
70
|
-
|
71
|
-
|
75
|
+
["Www.google.com", %w( www google com )],
|
76
|
+
["www.Google.com", %w( www google com )],
|
77
|
+
["www.google.Com", %w( www google com )],
|
72
78
|
].freeze
|
73
79
|
|
74
80
|
def test_ignore_case
|
@@ -84,35 +90,41 @@ class AcceptanceTest < Minitest::Test
|
|
84
90
|
|
85
91
|
|
86
92
|
INCLUDE_PRIVATE_CASES = [
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
93
|
+
["blogspot.com", true, "blogspot.com"],
|
94
|
+
["blogspot.com", false, nil],
|
95
|
+
["subdomain.blogspot.com", true, "blogspot.com"],
|
96
|
+
["subdomain.blogspot.com", false, "subdomain.blogspot.com"],
|
91
97
|
].freeze
|
92
98
|
|
99
|
+
# rubocop:disable Style/CombinableLoops
|
93
100
|
def test_ignore_private
|
94
101
|
# test domain and parse
|
95
102
|
INCLUDE_PRIVATE_CASES.each do |given, ignore_private, expected|
|
96
|
-
|
103
|
+
if expected.nil?
|
104
|
+
assert_nil PublicSuffix.domain(given, ignore_private: ignore_private)
|
105
|
+
else
|
106
|
+
assert_equal expected, PublicSuffix.domain(given, ignore_private: ignore_private)
|
107
|
+
end
|
97
108
|
end
|
98
109
|
# test valid?
|
99
110
|
INCLUDE_PRIVATE_CASES.each do |given, ignore_private, expected|
|
100
111
|
assert_equal !expected.nil?, PublicSuffix.valid?(given, ignore_private: ignore_private)
|
101
112
|
end
|
102
113
|
end
|
114
|
+
# rubocop:enable Style/CombinableLoops
|
103
115
|
|
104
116
|
|
105
117
|
def valid_uri?(name)
|
106
118
|
uri = URI.parse(name)
|
107
119
|
!uri.host.nil?
|
108
|
-
rescue
|
120
|
+
rescue StandardError
|
109
121
|
false
|
110
122
|
end
|
111
123
|
|
112
124
|
def valid_domain?(name)
|
113
125
|
uri = URI.parse(name)
|
114
126
|
!uri.host.nil? && uri.scheme.nil?
|
115
|
-
rescue
|
127
|
+
rescue StandardError
|
116
128
|
false
|
117
129
|
end
|
118
130
|
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require_relative "../../lib/public_suffix"
|
3
|
+
|
4
|
+
NAME_SHORT = "example.de"
|
5
|
+
NAME_MEDIUM = "www.subdomain.example.de"
|
6
|
+
NAME_LONG = "one.two.three.four.five.example.de"
|
7
|
+
NAME_WILD = "one.two.three.four.five.example.bd"
|
8
|
+
NAME_EXCP = "one.two.three.four.five.www.ck"
|
9
|
+
|
10
|
+
IAAA = "www.example.ac"
|
11
|
+
IZZZ = "www.example.zone"
|
12
|
+
|
13
|
+
PAAA = "one.two.three.four.five.example.beep.pl"
|
14
|
+
PZZZ = "one.two.three.four.five.example.now.sh"
|
15
|
+
|
16
|
+
JP = "www.yokoshibahikari.chiba.jp"
|
17
|
+
IT = "www.example.it"
|
18
|
+
COM = "www.example.com"
|
19
|
+
|
20
|
+
TIMES = (ARGV.first || 50_000).to_i
|
21
|
+
|
22
|
+
# Initialize
|
23
|
+
PublicSuffixList = PublicSuffix::List.default
|
24
|
+
PublicSuffixList.find("example.com")
|
25
|
+
|
26
|
+
Benchmark.bmbm(25) do |x|
|
27
|
+
x.report("NAME_SHORT") do
|
28
|
+
TIMES.times { PublicSuffixList.find(NAME_SHORT) != nil }
|
29
|
+
end
|
30
|
+
x.report("NAME_MEDIUM") do
|
31
|
+
TIMES.times { PublicSuffixList.find(NAME_MEDIUM) != nil }
|
32
|
+
end
|
33
|
+
x.report("NAME_LONG") do
|
34
|
+
TIMES.times { PublicSuffixList.find(NAME_LONG) != nil }
|
35
|
+
end
|
36
|
+
x.report("NAME_WILD") do
|
37
|
+
TIMES.times { PublicSuffixList.find(NAME_WILD) != nil }
|
38
|
+
end
|
39
|
+
x.report("NAME_EXCP") do
|
40
|
+
TIMES.times { PublicSuffixList.find(NAME_EXCP) != nil }
|
41
|
+
end
|
42
|
+
|
43
|
+
x.report("IAAA") do
|
44
|
+
TIMES.times { PublicSuffixList.find(IAAA) != nil }
|
45
|
+
end
|
46
|
+
x.report("IZZZ") do
|
47
|
+
TIMES.times { PublicSuffixList.find(IZZZ) != nil }
|
48
|
+
end
|
49
|
+
|
50
|
+
x.report("PAAA") do
|
51
|
+
TIMES.times { PublicSuffixList.find(PAAA) != nil }
|
52
|
+
end
|
53
|
+
x.report("PZZZ") do
|
54
|
+
TIMES.times { PublicSuffixList.find(PZZZ) != nil }
|
55
|
+
end
|
56
|
+
|
57
|
+
x.report("JP") do
|
58
|
+
TIMES.times { PublicSuffixList.find(JP) != nil }
|
59
|
+
end
|
60
|
+
x.report("IT") do
|
61
|
+
TIMES.times { PublicSuffixList.find(IT) != nil }
|
62
|
+
end
|
63
|
+
x.report("COM") do
|
64
|
+
TIMES.times { PublicSuffixList.find(COM) != nil }
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require_relative "../../lib/public_suffix"
|
3
|
+
|
4
|
+
NAME_SHORT = "example.de"
|
5
|
+
NAME_MEDIUM = "www.subdomain.example.de"
|
6
|
+
NAME_LONG = "one.two.three.four.five.example.de"
|
7
|
+
NAME_WILD = "one.two.three.four.five.example.bd"
|
8
|
+
NAME_EXCP = "one.two.three.four.five.www.ck"
|
9
|
+
|
10
|
+
IAAA = "www.example.ac"
|
11
|
+
IZZZ = "www.example.zone"
|
12
|
+
|
13
|
+
PAAA = "one.two.three.four.five.example.beep.pl"
|
14
|
+
PZZZ = "one.two.three.four.five.example.now.sh"
|
15
|
+
|
16
|
+
JP = "www.yokoshibahikari.chiba.jp"
|
17
|
+
IT = "www.example.it"
|
18
|
+
COM = "www.example.com"
|
19
|
+
|
20
|
+
TIMES = (ARGV.first || 50_000).to_i
|
21
|
+
|
22
|
+
# Initialize
|
23
|
+
PublicSuffixList = PublicSuffix::List.default
|
24
|
+
PublicSuffixList.find("example.com")
|
25
|
+
|
26
|
+
Benchmark.bmbm(25) do |x|
|
27
|
+
x.report("NAME_SHORT") do
|
28
|
+
TIMES.times { PublicSuffixList.find(NAME_SHORT) != nil }
|
29
|
+
end
|
30
|
+
x.report("NAME_SHORT (noprivate)") do
|
31
|
+
TIMES.times { PublicSuffixList.find(NAME_SHORT, ignore_private: true) != nil }
|
32
|
+
end
|
33
|
+
x.report("NAME_MEDIUM") do
|
34
|
+
TIMES.times { PublicSuffixList.find(NAME_MEDIUM) != nil }
|
35
|
+
end
|
36
|
+
x.report("NAME_MEDIUM (noprivate)") do
|
37
|
+
TIMES.times { PublicSuffixList.find(NAME_MEDIUM, ignore_private: true) != nil }
|
38
|
+
end
|
39
|
+
x.report("NAME_LONG") do
|
40
|
+
TIMES.times { PublicSuffixList.find(NAME_LONG) != nil }
|
41
|
+
end
|
42
|
+
x.report("NAME_LONG (noprivate)") do
|
43
|
+
TIMES.times { PublicSuffixList.find(NAME_LONG, ignore_private: true) != nil }
|
44
|
+
end
|
45
|
+
x.report("NAME_WILD") do
|
46
|
+
TIMES.times { PublicSuffixList.find(NAME_WILD) != nil }
|
47
|
+
end
|
48
|
+
x.report("NAME_WILD (noprivate)") do
|
49
|
+
TIMES.times { PublicSuffixList.find(NAME_WILD, ignore_private: true) != nil }
|
50
|
+
end
|
51
|
+
x.report("NAME_EXCP") do
|
52
|
+
TIMES.times { PublicSuffixList.find(NAME_EXCP) != nil }
|
53
|
+
end
|
54
|
+
x.report("NAME_EXCP (noprivate)") do
|
55
|
+
TIMES.times { PublicSuffixList.find(NAME_EXCP, ignore_private: true) != nil }
|
56
|
+
end
|
57
|
+
|
58
|
+
x.report("IAAA") do
|
59
|
+
TIMES.times { PublicSuffixList.find(IAAA) != nil }
|
60
|
+
end
|
61
|
+
x.report("IAAA (noprivate)") do
|
62
|
+
TIMES.times { PublicSuffixList.find(IAAA, ignore_private: true) != nil }
|
63
|
+
end
|
64
|
+
x.report("IZZZ") do
|
65
|
+
TIMES.times { PublicSuffixList.find(IZZZ) != nil }
|
66
|
+
end
|
67
|
+
x.report("IZZZ (noprivate)") do
|
68
|
+
TIMES.times { PublicSuffixList.find(IZZZ, ignore_private: true) != nil }
|
69
|
+
end
|
70
|
+
|
71
|
+
x.report("PAAA") do
|
72
|
+
TIMES.times { PublicSuffixList.find(PAAA) != nil }
|
73
|
+
end
|
74
|
+
x.report("PAAA (noprivate)") do
|
75
|
+
TIMES.times { PublicSuffixList.find(PAAA, ignore_private: true) != nil }
|
76
|
+
end
|
77
|
+
x.report("PZZZ") do
|
78
|
+
TIMES.times { PublicSuffixList.find(PZZZ) != nil }
|
79
|
+
end
|
80
|
+
x.report("PZZZ (noprivate)") do
|
81
|
+
TIMES.times { PublicSuffixList.find(PZZZ, ignore_private: true) != nil }
|
82
|
+
end
|
83
|
+
|
84
|
+
x.report("JP") do
|
85
|
+
TIMES.times { PublicSuffixList.find(JP) != nil }
|
86
|
+
end
|
87
|
+
x.report("JP (noprivate)") do
|
88
|
+
TIMES.times { PublicSuffixList.find(JP, ignore_private: true) != nil }
|
89
|
+
end
|
90
|
+
x.report("IT") do
|
91
|
+
TIMES.times { PublicSuffixList.find(IT) != nil }
|
92
|
+
end
|
93
|
+
x.report("IT (noprivate)") do
|
94
|
+
TIMES.times { PublicSuffixList.find(IT, ignore_private: true) != nil }
|
95
|
+
end
|
96
|
+
x.report("COM") do
|
97
|
+
TIMES.times { PublicSuffixList.find(COM) != nil }
|
98
|
+
end
|
99
|
+
x.report("COM (noprivate)") do
|
100
|
+
TIMES.times { PublicSuffixList.find(COM, ignore_private: true) != nil }
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
|
3
|
+
STRING = "www.subdomain.example.com"
|
4
|
+
ARRAY = %w(
|
5
|
+
com
|
6
|
+
example.com
|
7
|
+
subdomain.example.com
|
8
|
+
www.subdomain.example.com
|
9
|
+
)
|
10
|
+
|
11
|
+
def tokenizer1(string)
|
12
|
+
parts = string.split(".").reverse!
|
13
|
+
index = 0
|
14
|
+
query = parts[index]
|
15
|
+
names = []
|
16
|
+
|
17
|
+
loop do
|
18
|
+
names << query
|
19
|
+
|
20
|
+
index += 1
|
21
|
+
break if index >= parts.size
|
22
|
+
query = parts[index] + "." + query
|
23
|
+
end
|
24
|
+
names
|
25
|
+
end
|
26
|
+
|
27
|
+
def tokenizer2(string)
|
28
|
+
parts = string.split(".")
|
29
|
+
index = parts.size - 1
|
30
|
+
query = parts[index]
|
31
|
+
names = []
|
32
|
+
|
33
|
+
loop do
|
34
|
+
names << query
|
35
|
+
|
36
|
+
index -= 1
|
37
|
+
break if index < 0
|
38
|
+
query = parts[index] + "." + query
|
39
|
+
end
|
40
|
+
names
|
41
|
+
end
|
42
|
+
|
43
|
+
def tokenizer3(string)
|
44
|
+
isx = string.size
|
45
|
+
idx = string.size - 1
|
46
|
+
names = []
|
47
|
+
|
48
|
+
loop do
|
49
|
+
isx = string.rindex(".", isx - 1) || -1
|
50
|
+
names << string[isx + 1, idx - isx]
|
51
|
+
|
52
|
+
break if isx <= 0
|
53
|
+
end
|
54
|
+
names
|
55
|
+
end
|
56
|
+
|
57
|
+
def tokenizer4(string)
|
58
|
+
isx = string.size
|
59
|
+
idx = string.size - 1
|
60
|
+
names = []
|
61
|
+
|
62
|
+
loop do
|
63
|
+
isx = string.rindex(".", isx - 1) || -1
|
64
|
+
names << string[(isx+1)..idx]
|
65
|
+
|
66
|
+
break if isx <= 0
|
67
|
+
end
|
68
|
+
names
|
69
|
+
end
|
70
|
+
|
71
|
+
(x = tokenizer1(STRING)) == ARRAY or fail("tokenizer1 failed: #{x.inspect}")
|
72
|
+
(x = tokenizer2(STRING)) == ARRAY or fail("tokenizer2 failed: #{x.inspect}")
|
73
|
+
(x = tokenizer3(STRING)) == ARRAY or fail("tokenizer3 failed: #{x.inspect}")
|
74
|
+
(x = tokenizer4(STRING)) == ARRAY or fail("tokenizer4 failed: #{x.inspect}")
|
75
|
+
|
76
|
+
Benchmark.ips do |x|
|
77
|
+
x.report("tokenizer1") do
|
78
|
+
tokenizer1(STRING).is_a?(Array)
|
79
|
+
end
|
80
|
+
x.report("tokenizer2") do
|
81
|
+
tokenizer2(STRING).is_a?(Array)
|
82
|
+
end
|
83
|
+
x.report("tokenizer3") do
|
84
|
+
tokenizer3(STRING).is_a?(Array)
|
85
|
+
end
|
86
|
+
x.report("tokenizer4") do
|
87
|
+
tokenizer4(STRING).is_a?(Array)
|
88
|
+
end
|
89
|
+
|
90
|
+
x.compare!
|
91
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require_relative "../../lib/public_suffix"
|
3
|
+
|
4
|
+
JP = "www.yokoshibahikari.chiba.jp"
|
5
|
+
|
6
|
+
TIMES = (ARGV.first || 50_000).to_i
|
7
|
+
|
8
|
+
# Initialize
|
9
|
+
class PublicSuffix::List
|
10
|
+
public :select
|
11
|
+
end
|
12
|
+
PublicSuffixList = PublicSuffix::List.default
|
13
|
+
PublicSuffixList.select("example.jp")
|
14
|
+
PublicSuffixList.find("example.jp")
|
15
|
+
|
16
|
+
Benchmark.bmbm(25) do |x|
|
17
|
+
x.report("JP select") do
|
18
|
+
TIMES.times { PublicSuffixList.select(JP) }
|
19
|
+
end
|
20
|
+
x.report("JP find") do
|
21
|
+
TIMES.times { PublicSuffixList.find(JP) }
|
22
|
+
end
|
23
|
+
# x.report("JP (noprivate)") do
|
24
|
+
# TIMES.times { PublicSuffixList.find(JP, ignore_private: true) != nil }
|
25
|
+
# end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require_relative "../../lib/public_suffix"
|
3
|
+
|
4
|
+
JP = "www.yokoshibahikari.chiba.jp"
|
5
|
+
|
6
|
+
TIMES = (ARGV.first || 50_000).to_i
|
7
|
+
|
8
|
+
# Initialize
|
9
|
+
class PublicSuffix::List
|
10
|
+
public :select
|
11
|
+
end
|
12
|
+
PublicSuffixList = PublicSuffix::List.default
|
13
|
+
PublicSuffixList.select("example.jp")
|
14
|
+
|
15
|
+
Benchmark.bmbm(25) do |x|
|
16
|
+
x.report("select jp") do
|
17
|
+
TIMES.times { PublicSuffixList.select("jp") }
|
18
|
+
end
|
19
|
+
x.report("select example.jp") do
|
20
|
+
TIMES.times { PublicSuffixList.select("example.jp") }
|
21
|
+
end
|
22
|
+
x.report("select www.example.jp") do
|
23
|
+
TIMES.times { PublicSuffixList.select("www.example.jp") }
|
24
|
+
end
|
25
|
+
end
|