barby 0.1.2 → 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.
- data/bin/barby +40 -0
- data/lib/barby.rb +3 -0
- data/lib/barby/barcode.rb +6 -0
- data/lib/barby/barcode/code_128.rb +16 -3
- data/lib/barby/barcode/code_25.rb +161 -0
- data/lib/barby/barcode/code_25_interleaved.rb +73 -0
- data/lib/barby/barcode/code_93.rb +225 -0
- data/lib/barby/barcode/qr_code.rb +93 -0
- data/lib/barby/outputter.rb +56 -2
- data/lib/barby/outputter/ascii_outputter.rb +20 -1
- data/lib/barby/outputter/cairo_outputter.rb +38 -7
- data/lib/barby/outputter/pdfwriter_outputter.rb +44 -35
- data/lib/barby/outputter/png_outputter.rb +48 -16
- data/lib/barby/outputter/prawn_outputter.rb +100 -0
- data/lib/barby/outputter/rmagick_outputter.rb +48 -20
- data/lib/barby/vendor.rb +3 -0
- data/vendor/rqrcode/CHANGELOG +21 -0
- data/vendor/rqrcode/COPYING +19 -0
- data/vendor/rqrcode/README +98 -0
- data/vendor/rqrcode/Rakefile +65 -0
- data/vendor/rqrcode/lib/rqrcode.rb +13 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/array.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/array/behavior.rb +9 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/integer.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/integer/bitwise.rb +11 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode.rb +4 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_8bit_byte.rb +35 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_bit_buffer.rb +56 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_code.rb +421 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_math.rb +63 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_polynomial.rb +78 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_rs_block.rb +134 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_util.rb +254 -0
- data/vendor/rqrcode/test/runtest.rb +78 -0
- data/vendor/rqrcode/test/test_data.rb +21 -0
- metadata +86 -44
data/bin/barby
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
#$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
6
|
+
require 'barby'
|
7
|
+
|
8
|
+
options = {
|
9
|
+
:outputter => 'Png',
|
10
|
+
:outputter_method => 'to_png'
|
11
|
+
}
|
12
|
+
|
13
|
+
ARGV.options do |o|
|
14
|
+
o.banner = " Usage: #{File.basename(__FILE__)} [OPTIONS] data"
|
15
|
+
o.define_head ' Generates barcodes and prints the generated output to STDOUT'
|
16
|
+
|
17
|
+
o.separator ''
|
18
|
+
o.separator ' EXPERIMENTAL'
|
19
|
+
o.separator ''
|
20
|
+
|
21
|
+
o.on('-b', '--barcode=ClassName', String, 'Barcode type'){|v| options[:barcode] = v }
|
22
|
+
o.on('-o', '--outputter=ClassName', String, 'Outputter'){|v| options[:outputter] = v }
|
23
|
+
o.on('-m', '--method=method_name', String, 'Outputter method'){|v| options[:outputter_method] = v }
|
24
|
+
|
25
|
+
o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
|
26
|
+
|
27
|
+
o.parse!
|
28
|
+
end
|
29
|
+
|
30
|
+
#p STDIN.read
|
31
|
+
#exit
|
32
|
+
|
33
|
+
require "barby/outputter/#{options[:outputter].gsub(/[A-Z]/){|c| '_'+c.downcase }[1..-1]}_outputter"
|
34
|
+
|
35
|
+
barcode_class = Barby.const_get(options[:barcode])
|
36
|
+
barcode = barcode_class.new($*.empty? ? STDIN.read.chomp : $*)
|
37
|
+
outputter_class = Barby.const_get("#{options[:outputter]}Outputter")
|
38
|
+
outputter = outputter_class.new(barcode)
|
39
|
+
|
40
|
+
print eval("outputter.#{options[:outputter_method]}(#{ENV['OPTIONS']})")
|
data/lib/barby.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
require 'barby/vendor'
|
1
2
|
require 'barby/version'
|
2
3
|
|
3
4
|
require 'barby/barcode'
|
4
5
|
require 'barby/barcode/code_128'
|
5
6
|
require 'barby/barcode/gs1_128'
|
6
7
|
require 'barby/barcode/code_39'
|
8
|
+
require 'barby/barcode/code_93'
|
7
9
|
require 'barby/barcode/ean_13'
|
8
10
|
require 'barby/barcode/ean_8'
|
9
11
|
require 'barby/barcode/bookland'
|
12
|
+
require 'barby/barcode/qr_code'
|
10
13
|
|
11
14
|
require 'barby/outputter'
|
data/lib/barby/barcode.rb
CHANGED
@@ -4,6 +4,19 @@ module Barby
|
|
4
4
|
|
5
5
|
|
6
6
|
#Code 128 barcodes
|
7
|
+
#
|
8
|
+
#Note that you must provide a type for each object, either by passing a string
|
9
|
+
#as a second parameter to Code128.new or by instantiating one of the child classes.
|
10
|
+
#
|
11
|
+
#You can switch type by using the CODEA, CODEB and CODEC characters:
|
12
|
+
#
|
13
|
+
# "\305" => A
|
14
|
+
# "\306" => B
|
15
|
+
# "\307" => C
|
16
|
+
#
|
17
|
+
#As an example, here's one that starts out as type A and then switches to B and then C:
|
18
|
+
#
|
19
|
+
# Code128A.new("ABC123\306def\3074567")
|
7
20
|
class Code128 < Barcode1D
|
8
21
|
|
9
22
|
ENCODINGS = {
|
@@ -47,7 +60,7 @@ module Barby
|
|
47
60
|
|
48
61
|
VALUES = {
|
49
62
|
'A' => {
|
50
|
-
0 => "
|
63
|
+
0 => " ", 1 => "!", 2 => "\"",
|
51
64
|
3 => "#", 4 => "$", 5 => "%",
|
52
65
|
6 => "&", 7 => "'", 8 => "(",
|
53
66
|
9 => ")", 10 => "*", 11 => "+",
|
@@ -80,13 +93,13 @@ module Barby
|
|
80
93
|
90 => "\032", 91 => "\e", 92 => "\034",
|
81
94
|
93 => "\035", 94 => "\036", 95 => "\037",
|
82
95
|
96 => "\303", 97 => "\302", 98 => "SHIFT",
|
83
|
-
99 => "\307",
|
96
|
+
99 => "\307", 100 => "\306", 101 => "\304",
|
84
97
|
102 => "\301", 103 => "STARTA", 104 => "STARTB",
|
85
98
|
105 => "STARTC"
|
86
99
|
}.invert,
|
87
100
|
|
88
101
|
'B' => {
|
89
|
-
0 => "
|
102
|
+
0 => " ", 1 => "!", 2 => "\"", 3 => "#", 4 => "$", 5 => "%",
|
90
103
|
6 => "&", 7 => "'", 8 => "(", 9 => ")", 10 => "*", 11 => "+",
|
91
104
|
12 => ",", 13 => "-", 14 => ".", 15 => "/", 16 => "0", 17 => "1",
|
92
105
|
18 => "2", 19 => "3", 20 => "4", 21 => "5", 22 => "6", 23 => "7",
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'barby/barcode'
|
2
|
+
|
3
|
+
module Barby
|
4
|
+
|
5
|
+
|
6
|
+
#Standard/Industrial 2 of 5, non-interleaved
|
7
|
+
#
|
8
|
+
#Checksum not included by default, to include it,
|
9
|
+
#set include_checksum = true
|
10
|
+
class Code25 < Barcode1D
|
11
|
+
|
12
|
+
WIDE = W = true
|
13
|
+
NARROW = N = false
|
14
|
+
|
15
|
+
START_ENCODING = [W,W,N]
|
16
|
+
STOP_ENCODING = [W,N,W]
|
17
|
+
|
18
|
+
ENCODINGS = {
|
19
|
+
0 => [N,N,W,W,N],
|
20
|
+
1 => [W,N,N,N,W],
|
21
|
+
2 => [N,W,N,N,W],
|
22
|
+
3 => [W,W,N,N,N],
|
23
|
+
4 => [N,N,W,N,W],
|
24
|
+
5 => [W,N,W,N,N],
|
25
|
+
6 => [N,W,W,N,N],
|
26
|
+
7 => [N,N,N,W,W],
|
27
|
+
8 => [W,N,N,W,N],
|
28
|
+
9 => [N,W,N,W,N]
|
29
|
+
}
|
30
|
+
|
31
|
+
attr_accessor :data, :narrow_width, :wide_width, :space_width, :include_checksum
|
32
|
+
|
33
|
+
|
34
|
+
def initialize(data)
|
35
|
+
self.data = data
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def data_encoding
|
40
|
+
digit_encodings.join
|
41
|
+
end
|
42
|
+
|
43
|
+
def data_encoding_with_checksum
|
44
|
+
data_encoding+checksum_encoding
|
45
|
+
end
|
46
|
+
|
47
|
+
def encoding
|
48
|
+
start_encoding+(include_checksum? ? data_encoding_with_checksum : data_encoding)+stop_encoding
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def characters
|
53
|
+
data.split(//)
|
54
|
+
end
|
55
|
+
|
56
|
+
def digits
|
57
|
+
characters.map{|c| c.to_i }
|
58
|
+
end
|
59
|
+
|
60
|
+
def even_and_odd_digits
|
61
|
+
alternater = false
|
62
|
+
digits.reverse.partition{ alternater = !alternater }
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def digit_encodings
|
67
|
+
digits.map{|d| encoding_for(d) }
|
68
|
+
end
|
69
|
+
alias character_encodings digit_encodings
|
70
|
+
|
71
|
+
|
72
|
+
#Returns the encoding for a single digit
|
73
|
+
def encoding_for(digit)
|
74
|
+
encoding_for_bars(ENCODINGS[digit])
|
75
|
+
end
|
76
|
+
|
77
|
+
#Generate encoding for an array of W,N
|
78
|
+
def encoding_for_bars(*bars)
|
79
|
+
wide, narrow, space = wide_encoding, narrow_encoding, space_encoding
|
80
|
+
bars.flatten.inject '' do |enc,bar|
|
81
|
+
enc + (bar == WIDE ? wide : narrow) + space
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
#Mod10
|
87
|
+
def checksum
|
88
|
+
evens, odds = even_and_odd_digits
|
89
|
+
sum = odds.inject(0){|sum,d| sum + d } + evens.inject(0){|sum,d| sum + (d*3) }
|
90
|
+
sum %= 10
|
91
|
+
sum.zero? ? 0 : 10-sum
|
92
|
+
end
|
93
|
+
|
94
|
+
def checksum_encoding
|
95
|
+
encoding_for(checksum)
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
#The width of a narrow bar in xdims
|
100
|
+
def narrow_width
|
101
|
+
@narrow_width || 1
|
102
|
+
end
|
103
|
+
|
104
|
+
#The width of a wide bar in xdims
|
105
|
+
#By default three times as wide as a narrow bar
|
106
|
+
def wide_width
|
107
|
+
@wide_width || narrow_width*3
|
108
|
+
end
|
109
|
+
|
110
|
+
#The width of the space between the bars in xdims
|
111
|
+
#By default the same width as a narrow bar
|
112
|
+
#
|
113
|
+
#A space serves only as a separator for the bars,
|
114
|
+
#there is no encoded meaning in them
|
115
|
+
def space_width
|
116
|
+
@space_width || narrow_width
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def include_checksum?
|
121
|
+
include_checksum
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
def data=(data)
|
126
|
+
@data = "#{data}"
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def start_encoding
|
131
|
+
encoding_for_bars(START_ENCODING)
|
132
|
+
end
|
133
|
+
|
134
|
+
def stop_encoding
|
135
|
+
#Removes trailing space generated by encoding_for_bars
|
136
|
+
encoding_for_bars(STOP_ENCODING).gsub(/0+$/, '')
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
def narrow_encoding
|
141
|
+
'1' * narrow_width
|
142
|
+
end
|
143
|
+
|
144
|
+
def wide_encoding
|
145
|
+
'1' * wide_width
|
146
|
+
end
|
147
|
+
|
148
|
+
def space_encoding
|
149
|
+
'0' * space_width
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def valid?
|
154
|
+
data =~ /^[0-9]*$/
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'barby/barcode/code_25'
|
2
|
+
|
3
|
+
module Barby
|
4
|
+
|
5
|
+
class Code25Interleaved < Code25
|
6
|
+
|
7
|
+
START_ENCODING = [N,N,N,N]
|
8
|
+
STOP_ENCODING = [W,N,N]
|
9
|
+
|
10
|
+
|
11
|
+
def data_encoding
|
12
|
+
digit_pair_encodings.join
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def character_pairs
|
17
|
+
chars = characters
|
18
|
+
pairs = Array.new((chars.size/2.0).ceil){ [] }
|
19
|
+
chars.each_with_index{|c,i| pairs[(i/2.0).floor] << c }
|
20
|
+
pairs
|
21
|
+
end
|
22
|
+
|
23
|
+
def digit_pairs
|
24
|
+
d = digits
|
25
|
+
pairs = Array.new((d.size/2.0).ceil){ [] }
|
26
|
+
d.each_with_index{|dd,i| pairs[(i/2.0).floor] << dd }
|
27
|
+
pairs
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def digit_pair_encodings
|
32
|
+
digit_pairs.map{|p| encoding_for_pair(p) }
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def encoding_for_pair(pair)
|
37
|
+
bars, spaces = ENCODINGS[pair.first], ENCODINGS[pair.last]
|
38
|
+
bars.zip(spaces).inject '' do |enc,p|
|
39
|
+
bar, space = *p
|
40
|
+
enc + ('1' * (bar == WIDE ? wide_width : narrow_width)) +
|
41
|
+
('0' * (space == WIDE ? wide_width : narrow_width))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#def encoding_for_bars(*bars_and_spaces)
|
46
|
+
# bar = false
|
47
|
+
# bars_and_spaces.flatten.inject '' do |enc,bar_or_space|
|
48
|
+
# bar = !bar
|
49
|
+
# enc + (bar ? '1' : '0')*(bar_or_space == WIDE ? wide_width : narrow_width)
|
50
|
+
# end
|
51
|
+
#end
|
52
|
+
|
53
|
+
|
54
|
+
def start_encoding
|
55
|
+
bar = false
|
56
|
+
START_ENCODING.inject '' do |enc,bar_or_space|
|
57
|
+
bar = !bar
|
58
|
+
enc << (bar ? '1' : '0') * (bar_or_space == WIDE ? wide_width : narrow_width)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def stop_encoding
|
63
|
+
bar = false
|
64
|
+
STOP_ENCODING.inject '' do |enc,bar_or_space|
|
65
|
+
bar = !bar
|
66
|
+
enc << (bar ? '1' : '0') * (bar_or_space == WIDE ? wide_width : narrow_width)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'barby/barcode'
|
2
|
+
|
3
|
+
module Barby
|
4
|
+
|
5
|
+
class Code93 < Barcode1D
|
6
|
+
|
7
|
+
SHIFT_DOLLAR = "\301" # ($)
|
8
|
+
SHIFT_PERCENT = "\302" # (%)
|
9
|
+
SHIFT_SLASH = "\303" # (/)
|
10
|
+
SHIFT_PLUS = "\304" # (+)
|
11
|
+
|
12
|
+
SHIFT_CHARACTERS = [SHIFT_DOLLAR, SHIFT_PERCENT, SHIFT_SLASH, SHIFT_PLUS]
|
13
|
+
|
14
|
+
ENCODINGS = {
|
15
|
+
"0" => "100010100", "1" => "101001000",
|
16
|
+
"2" => "101000100", "3" => "101000010",
|
17
|
+
"4" => "100101000", "5" => "100100100",
|
18
|
+
"6" => "100100010", "7" => "101010000",
|
19
|
+
"8" => "100010010", "9" => "100001010",
|
20
|
+
"A" => "110101000", "B" => "110100100",
|
21
|
+
"C" => "110100010", "D" => "110010100",
|
22
|
+
"E" => "110010010", "F" => "110001010",
|
23
|
+
"G" => "101101000", "H" => "101100100",
|
24
|
+
"I" => "101100010", "J" => "100110100",
|
25
|
+
"K" => "100011010", "L" => "101011000",
|
26
|
+
"M" => "101001100", "N" => "101000110",
|
27
|
+
"O" => "100101100", "P" => "100010110",
|
28
|
+
"Q" => "110110100", "R" => "110110010",
|
29
|
+
"S" => "110101100", "T" => "110100110",
|
30
|
+
"U" => "110010110", "V" => "110011010",
|
31
|
+
"W" => "101101100", "X" => "101100110",
|
32
|
+
"Y" => "100110110", "Z" => "100111010",
|
33
|
+
"-" => "100101110", "." => "111010100",
|
34
|
+
" " => "111010010", "$" => "111001010",
|
35
|
+
"/" => "101101110", "+" => "101110110",
|
36
|
+
"%" => "110101110",
|
37
|
+
SHIFT_DOLLAR => "100100110",
|
38
|
+
SHIFT_PERCENT => "111011010",
|
39
|
+
SHIFT_SLASH => "111010110",
|
40
|
+
SHIFT_PLUS => "100110010"
|
41
|
+
}
|
42
|
+
|
43
|
+
EXTENDED_MAPPING = {
|
44
|
+
"\000" => "\302U", " " => " ", "@" => "\302V", "`" => "\302W",
|
45
|
+
"\001" => "\301A", "!" => "\303A", "A" => "A", "a" => "\304A",
|
46
|
+
"\002" => "\301B", '"' => "\303B", "B" => "B", "b" => "\304B",
|
47
|
+
"\003" => "\301C", "#" => "\303C", "C" => "C", "c" => "\304C",
|
48
|
+
"\004" => "\301D", "$" => "\303D", "D" => "D", "d" => "\304D",
|
49
|
+
"\005" => "\301E", "%" => "\303E", "E" => "E", "e" => "\304E",
|
50
|
+
"\006" => "\301F", "&" => "\303F", "F" => "F", "f" => "\304F",
|
51
|
+
"\007" => "\301G", "'" => "\303G", "G" => "G", "g" => "\304G",
|
52
|
+
"\010" => "\301H", "(" => "\303H", "H" => "H", "h" => "\304H",
|
53
|
+
"\011" => "\301I", ")" => "\303I", "I" => "I", "i" => "\304I",
|
54
|
+
"\012" => "\301J", "*" => "\303J", "J" => "J", "j" => "\304J",
|
55
|
+
"\013" => "\301K", "/" => "\303K", "K" => "K", "k" => "\304K",
|
56
|
+
"\014" => "\301L", "," => "\303L", "L" => "L", "l" => "\304L",
|
57
|
+
"\015" => "\301M", "-" => "-", "M" => "M", "m" => "\304M",
|
58
|
+
"\016" => "\301N", "." => ".", "N" => "N", "n" => "\304N",
|
59
|
+
"\017" => "\301O", "+" => "\303O", "O" => "O", "o" => "\304O",
|
60
|
+
"\020" => "\301P", "0" => "0", "P" => "P", "p" => "\304P",
|
61
|
+
"\021" => "\301Q", "1" => "1", "Q" => "Q", "q" => "\304Q",
|
62
|
+
"\022" => "\301R", "2" => "2", "R" => "R", "r" => "\304R",
|
63
|
+
"\023" => "\301S", "3" => "3", "S" => "S", "s" => "\304S",
|
64
|
+
"\024" => "\301T", "4" => "4", "T" => "T", "t" => "\304T",
|
65
|
+
"\025" => "\301U", "5" => "5", "U" => "U", "u" => "\304U",
|
66
|
+
"\026" => "\301V", "6" => "6", "V" => "V", "v" => "\304V",
|
67
|
+
"\027" => "\301W", "7" => "7", "W" => "W", "w" => "\304W",
|
68
|
+
"\030" => "\301X", "8" => "8", "X" => "X", "x" => "\304X",
|
69
|
+
"\031" => "\301Y", "9" => "9", "Y" => "Y", "y" => "\304Y",
|
70
|
+
"\032" => "\301Z", ":" => "\303Z", "Z" => "Z", "z" => "\304Z",
|
71
|
+
"\033" => "\302A", ";" => "\302F", "[" => "\302K", "{" => "\302P",
|
72
|
+
"\034" => "\302B", "<" => "\302G", "\\" => "\302L", "|" => "\302Q",
|
73
|
+
"\035" => "\302C", "=" => "\302H", "]" => "\302M", "}" => "\302R",
|
74
|
+
"\036" => "\302D", ">" => "\302I", "^" => "\302N", "~" => "\302S",
|
75
|
+
"\037" => "\302E", "?" => "\302J", "_" => "\302O", "\177" => "\302T"
|
76
|
+
}
|
77
|
+
|
78
|
+
EXTENDED_CHARACTERS = EXTENDED_MAPPING.keys - ENCODINGS.keys
|
79
|
+
|
80
|
+
CHARACTERS = {
|
81
|
+
0 => "0", 1 => "1", 2 => "2", 3 => "3",
|
82
|
+
4 => "4", 5 => "5", 6 => "6", 7 => "7",
|
83
|
+
8 => "8", 9 => "9", 10 => "A", 11 => "B",
|
84
|
+
12 => "C", 13 => "D", 14 => "E", 15 => "F",
|
85
|
+
16 => "G", 17 => "H", 18 => "I", 19 => "J",
|
86
|
+
20 => "K", 21 => "L", 22 => "M", 23 => "N",
|
87
|
+
24 => "O", 25 => "P", 26 => "Q", 27 => "R",
|
88
|
+
28 => "S", 29 => "T", 30 => "U", 31 => "V",
|
89
|
+
32 => "W", 33 => "X", 34 => "Y", 35 => "Z",
|
90
|
+
36 => "-", 37 => ".", 38 => " ", 39 => "$",
|
91
|
+
40 => "/", 41 => "+", 42 => "%",
|
92
|
+
43 => SHIFT_DOLLAR, 44 => SHIFT_PERCENT,
|
93
|
+
45 => SHIFT_SLASH, 46 => SHIFT_PLUS
|
94
|
+
}
|
95
|
+
|
96
|
+
VALUES = CHARACTERS.invert
|
97
|
+
|
98
|
+
START_ENCODING = '101011110' # *
|
99
|
+
STOP_ENCODING = '101011110'
|
100
|
+
TERMINATE_ENCODING = '1'
|
101
|
+
|
102
|
+
attr_accessor :data
|
103
|
+
|
104
|
+
|
105
|
+
def initialize(data)
|
106
|
+
self.data = data
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def extended?
|
111
|
+
raw_characters.any?{|c| EXTENDED_CHARACTERS.include?(c) }
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def raw_characters
|
116
|
+
data.split(//)
|
117
|
+
end
|
118
|
+
|
119
|
+
def characters
|
120
|
+
raw_characters.map{|c| EXTENDED_MAPPING[c].split(//) }.flatten
|
121
|
+
end
|
122
|
+
|
123
|
+
def encoded_characters
|
124
|
+
characters.map{|c| ENCODINGS[c] }
|
125
|
+
end
|
126
|
+
alias character_encodings encoded_characters
|
127
|
+
|
128
|
+
|
129
|
+
def start_encoding
|
130
|
+
START_ENCODING
|
131
|
+
end
|
132
|
+
|
133
|
+
#The stop encoding includes the termination bar
|
134
|
+
def stop_encoding
|
135
|
+
STOP_ENCODING+TERMINATE_ENCODING
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
def encoding
|
140
|
+
start_encoding+data_encoding_with_checksums+stop_encoding
|
141
|
+
end
|
142
|
+
|
143
|
+
def data_encoding
|
144
|
+
character_encodings.join
|
145
|
+
end
|
146
|
+
|
147
|
+
def data_encoding_with_checksums
|
148
|
+
(character_encodings + checksum_encodings).join
|
149
|
+
end
|
150
|
+
|
151
|
+
def checksum_encodings
|
152
|
+
checksum_characters.map{|c| ENCODINGS[c] }
|
153
|
+
end
|
154
|
+
|
155
|
+
def checksum_encoding
|
156
|
+
checksum_encodings.join
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def checksums
|
161
|
+
[c_checksum, k_checksum]
|
162
|
+
end
|
163
|
+
|
164
|
+
def checksum_characters
|
165
|
+
checksums.map{|s| CHARACTERS[s] }
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
#Returns the values used for computing the C checksum
|
170
|
+
#in the "right" order (i.e. reversed)
|
171
|
+
def checksum_values
|
172
|
+
characters.map{|c| VALUES[c] }.reverse
|
173
|
+
end
|
174
|
+
|
175
|
+
#Returns the normal checksum plus the c_checksum
|
176
|
+
#This is used for calculating the k_checksum
|
177
|
+
def checksum_values_with_c_checksum
|
178
|
+
[c_checksum] + checksum_values
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
#Calculates the C checksum based on checksum_values
|
183
|
+
def c_checksum
|
184
|
+
sum = 0
|
185
|
+
checksum_values.each_with_index do |value, index|
|
186
|
+
sum += ((index % 20) + 1) * value
|
187
|
+
end
|
188
|
+
sum % 47
|
189
|
+
end
|
190
|
+
|
191
|
+
def c_checksum_character
|
192
|
+
CHARACTERS[c_checksum]
|
193
|
+
end
|
194
|
+
|
195
|
+
def c_checksum_encoding
|
196
|
+
ENCODINGS[c_checksum_character]
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
#Calculates the K checksum based on checksum_values_with_c_checksum
|
201
|
+
def k_checksum
|
202
|
+
sum = 0
|
203
|
+
checksum_values_with_c_checksum.each_with_index do |value, index|
|
204
|
+
sum += ((index % 15) + 1) * value
|
205
|
+
end
|
206
|
+
sum % 47
|
207
|
+
end
|
208
|
+
|
209
|
+
def k_checksum_character
|
210
|
+
CHARACTERS[k_checksum]
|
211
|
+
end
|
212
|
+
|
213
|
+
def k_checksum_encoding
|
214
|
+
ENCODINGS[k_checksum_character]
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
def valid?
|
219
|
+
characters.all?{|c| ENCODINGS.include?(c) }
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|