barby 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|