1
+ def expand_binary ( *specs )
2
+ specs . flat_map do |spec |
3
+ values = [ 0 ]
4
+ spec . each_char do |ch |
5
+ case ch
6
+ when '0'
7
+ values = values . map { |v | v <<1 }
8
+ when '1'
9
+ values = values.map { |v| (v<<1)+1 }
10
+ when '_'
11
+ values = values.flat_map { |v| [ v<<1, (v<<1)+1 ] }
12
+ else
13
+ raise "Unknown char"
14
+ end
15
+ end
16
+ values
17
+ end
18
+ end
19
+
20
+ MAX = 1<<12
21
+ possible_values = Array.new(MAX)
22
+ 0.upto(MAX) do |i|
23
+ possible_values[i] = {}
24
+ end
25
+
26
+ categories = {
27
+ "Too Long 1" => { binary: %w{0_______10__} },
28
+ "Too Short" => { binary: %w{11______0___ 11______11__} },
29
+ "5+ Byte" => { binary: %w{11111___10__} },
30
+ "Overlong 2" => { binary: %w{1100000_10__} },
31
+ "Overlong 3" => { binary: %w{11100000100_} },
32
+ "Overlong 4" => { binary: %w{111100001000} },
33
+ "Surrogate" => { binary: %w{11101101101_} },
34
+ "Too Large" => { binary: %w{111101001001 11110100101_ 1111010110__ 1111011_10__} },
35
+ "Two Conts" => { binary: %w{10______10__} },
36
+ }
37
+ categories.each do |(name,category)|
38
+ category[:values] = expand_binary(*category[:binary])
39
+ category[:values].each do |value|
40
+ if possible_values[value][:category]
41
+ raise "Value #{ value . to_s ( 2 ) } already has error #{ possible_values [ value ] [ :category ] } "
42
+ end
43
+ possible_values[value][:category] = name;
44
+ end
45
+ category[:required_bits] = (0..8).map { || 0 }
46
+ category[:bits] = (0..8).map { || 0 }
47
+ end
48
+
49
+ # high1 = [102, 102, 102, 102, 102, 102, 102, 102, 128, 128, 128, 128, 37, 1, 21, 89]
50
+ # low1 = [231, 163, 131, 131, 139, 203, 203, 203, 203, 203, 203, 203, 203, 219, 203, 203]
51
+ # high2 = [25, 25, 25, 25, 25, 25, 25, 25, 230, 174, 186, 186, 25, 25, 25, 25]
52
+ TOO_SHORT = 1<<0
53
+ TOO_LONG = 1<<1
54
+ OVERLONG_3 = 1<<2
55
+ SURROGATE = 1<<4
56
+ OVERLONG_2 = 1<<5
57
+ TWO_CONTS = 1<<7
58
+ TOO_LARGE = 1<<3
59
+ TOO_LARGE_1000 = 1<<6
60
+ OVERLONG_4 = 1<<6
61
+ high1 = [
62
+ TOO_LONG, TOO_LONG, TOO_LONG, TOO_LONG,
63
+ TOO_LONG, TOO_LONG, TOO_LONG, TOO_LONG,
64
+ TWO_CONTS, TWO_CONTS, TWO_CONTS, TWO_CONTS,
65
+ TOO_SHORT | OVERLONG_2,
66
+ TOO_SHORT,
67
+ TOO_SHORT | OVERLONG_3 | SURROGATE,
68
+ TOO_SHORT | TOO_LARGE | TOO_LARGE_1000 | OVERLONG_4
69
+ ]
70
+ CARRY = TOO_SHORT | TOO_LONG | TWO_CONTS
71
+ low1 = [
72
+ CARRY | OVERLONG_3 | OVERLONG_2 | OVERLONG_4,
73
+ CARRY | OVERLONG_2,
74
+ CARRY,
75
+ CARRY,
76
+ CARRY | TOO_LARGE,
77
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
78
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
79
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
80
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
81
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
82
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
83
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
84
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
85
+ CARRY | TOO_LARGE | TOO_LARGE_1000 | SURROGATE,
86
+ CARRY | TOO_LARGE | TOO_LARGE_1000,
87
+ CARRY | TOO_LARGE | TOO_LARGE_1000
88
+ ]
89
+ high2 = [
90
+ TOO_SHORT, TOO_SHORT, TOO_SHORT, TOO_SHORT,
91
+ TOO_SHORT, TOO_SHORT, TOO_SHORT, TOO_SHORT,
92
+ TOO_LONG | OVERLONG_2 | TWO_CONTS | OVERLONG_3 | TOO_LARGE_1000 | OVERLONG_4,
93
+ TOO_LONG | OVERLONG_2 | TWO_CONTS | OVERLONG_3 | TOO_LARGE,
94
+ TOO_LONG | OVERLONG_2 | TWO_CONTS | SURROGATE | TOO_LARGE,
95
+ TOO_LONG | OVERLONG_2 | TWO_CONTS | SURROGATE | TOO_LARGE,
96
+ TOO_SHORT, TOO_SHORT, TOO_SHORT, TOO_SHORT
97
+ ]
98
+ 0.upto(MAX-1) do |value|
99
+ lookup = high1[(value >> 8) & 0x0F] & low1[(value >> 4) & 0x0F] & high2[value & 0x0F]
100
+ category = possible_values[value][:category]
101
+ if lookup != 0
102
+ if !category
103
+ raise "#{ value . to_s ( 2 ) . rjust ( 12 , "0" ) } is not an error or two-cont value, but matches #{ lookup . to_s ( 2 ) . rjust ( 8 , "0" ) } !"
104
+ end
105
+ possible_values[value][:bits] = (0..8).select { |bit| (lookup & (1 << bit)) != 0 }
106
+ if possible_values[value][:bits].size == 1
107
+ categories[category][:required_bits][possible_values[value][:bits][0]] += 1
108
+ end
109
+ possible_values[value][:bits].each do |bit|
110
+ categories[category][:bits][bit] += 1
111
+ end
112
+ else
113
+ if category
114
+ raise "#{ value . to_s ( 2 ) . rjust ( 12 , "0" ) } is a #{ category } , but does not match the lookup tables!"
115
+ end
116
+ end
117
+ end
118
+
119
+ # We now know which bits are required for each category.
120
+
121
+ bits = (0..8).map { || { required_for: {} } }
122
+
123
+ print "| Bit "
124
+ categories.each do |(name, category)|
125
+ print "| #{ name } (#{ category [ :values ] . size } )"
126
+ end
127
+ puts "|"
128
+
129
+ print "|---"
130
+ categories.each do ||
131
+ print "|---"
132
+ end
133
+ puts "|"
134
+
135
+ 0.upto(7) do |bit|
136
+ print "| #{ bit } "
137
+ categories.each do |(name,category)|
138
+ print " | "
139
+ if category[:required_bits][bit] > 0
140
+ if category[:required_bits][bit] == category[:values].size
141
+ print "REQ "
142
+ else
143
+ print "REQ #{ category [ :required_bits ] [ bit ] } / "
144
+ end
145
+ end
146
+ if category[:bits][bit] == category[:values].size
147
+ print "FULL"
148
+ elsif category[:bits][bit] > 0
149
+ print "#{ category [ :bits ] [ bit ] } "
150
+ end
151
+ end
152
+ puts " |"
153
+ end
154
+ # Find out which categories are *covered* by
155
+ # Find which bits are *required* for each category
156
+ #
157
+
158
+
159
+
160
+ # bits.each_with_index do |bit, bit_value|
161
+ # if bit_value[:categories].size == 1
162
+ # end
163
+ # actual_matches.
0 commit comments