9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
# File 'lib/character_set/shared_methods.rb', line 9
def self.included(klass)
klass.class_eval " def self.[](*args)\n new(Array(args))\n end\n\n def self.parse(string)\n codepoints = Parser.codepoints_from_bracket_expression(string)\n result = new(codepoints)\n string.start_with?('[^') ? result.inversion : result\n end\n\n def self.of_property(property_name)\n @regexp_property_values_required ||= require 'regexp_property_values'\n\n property = RegexpPropertyValues[property_name.to_s]\n from_ranges(*property.matched_ranges)\n end\n\n def self.of_regexp(regexp)\n @regexp_parser_required ||= require 'regexp_parser'\n\n root = ::Regexp::Parser.parse(regexp)\n of_expression(root)\n end\n\n def self.of_expression(expression)\n ExpressionConverter.convert(expression)\n end\n\n def initialize(enumerable = [])\n merge(Parser.codepoints_from_enumerable(enumerable))\n end\n\n def replace(enum)\n unless [Array, CharacterSet, Range].include?(enum.class)\n enum = self.class.new(enum)\n end\n clear\n merge(enum)\n end\n\n # stringification methods\n\n def to_s(opts = {}, &block)\n Writer.write(ranges, opts, &block)\n end\n\n def to_s_with_surrogate_alternation\n Writer.write_surrogate_alternation(bmp_part.ranges, astral_part.ranges)\n end\n\n def inspect\n len = length\n \"#<CharacterSet: {\\\#{first(5) * ', '}\\\#{'...' if len > 5}} (size: \\\#{len})>\"\n end\n\n # unicode-plane-related methods\n\n def bmp_part?\n !bmp_part.empty?\n end\n\n def astral_part?\n !astral_part.empty?\n end\n\n def bmp_ratio\n bmp_part.count / count.to_f\n end\n\n def astral_ratio\n astral_part.count / count.to_f\n end\n\n #\n # The following methods are here for `Set` compatibility, but they are\n # comparatively slow. Prefer others.\n #\n def map!\n block_given? or return enum_for(__method__) { size }\n arr = []\n each { |cp| arr << yield(cp) }\n replace(arr)\n end\n alias collect! map!\n\n def reject!(&block)\n block_given? or return enum_for(__method__) { size }\n old_size = size\n delete_if(&block)\n self if size != old_size\n end\n\n def select!(&block)\n block_given? or return enum_for(__method__) { size }\n old_size = size\n keep_if(&block)\n self if size != old_size\n end\n alias filter! select!\n\n def classify\n block_given? or return enum_for(__method__) { size }\n each_with_object({}) { |cp, h| (h[yield(cp)] ||= self.class.new).add(cp) }\n end\n\n def divide(&func)\n block_given? or return enum_for(__method__) { size }\n require 'set'\n\n if func.arity == 2\n require 'tsort'\n\n class << dig = {}\n include TSort\n\n alias tsort_each_node each_key\n def tsort_each_child(node, &block)\n fetch(node).each(&block)\n end\n end\n\n each do |u|\n dig[u] = a = []\n each{ |v| a << v if yield(u, v) }\n end\n\n set = Set.new\n dig.each_strongly_connected_component do |css|\n set.add(self.class.new(css))\n end\n set\n else\n Set.new(classify(&func).values)\n end\n end\n\n # C-extension adapter method. Needs overriding in pure fallback.\n # Parsing kwargs in C is slower, verbose, and kinda deprecated.\n def inversion(include_surrogates: false, upto: 0x10FFFF)\n ext_inversion(include_surrogates, upto)\n end\n RUBY\nend\n", __FILE__, __LINE__ + 1
|