Class: Barby::Code128

Inherits:
Barcode1D show all
Defined in:
lib/barby/barcode/code_128.rb

Overview

Code 128 barcodes

Note that you must provide a type for each object, either by passing a string as a second parameter to Code128.new or by instantiating one of the child classes.

You can switch type by using the CODEA, CODEB and CODEC characters:

“305” => A “306” => B “307” => C

As an example, here’s one that starts out as type A and then switches to B and then C:

Code128A.new("ABC123\306def\3074567")

Direct Known Subclasses

Code128A, Code128B, Code128C, GS1128

Constant Summary collapse

ENCODINGS =
{
  0 => "11011001100", 1 => "11001101100", 2 => "11001100110",
  3 => "10010011000", 4 => "10010001100", 5 => "10001001100",
  6 => "10011001000", 7 => "10011000100", 8 => "10001100100",
  9 => "11001001000", 10 => "11001000100", 11 => "11000100100",
  12 => "10110011100", 13 => "10011011100", 14 => "10011001110",
  15 => "10111001100", 16 => "10011101100", 17 => "10011100110",
  18 => "11001110010", 19 => "11001011100", 20 => "11001001110",
  21 => "11011100100", 22 => "11001110100", 23 => "11101101110",
  24 => "11101001100", 25 => "11100101100", 26 => "11100100110",
  27 => "11101100100", 28 => "11100110100", 29 => "11100110010",
  30 => "11011011000", 31 => "11011000110", 32 => "11000110110",
  33 => "10100011000", 34 => "10001011000", 35 => "10001000110",
  36 => "10110001000", 37 => "10001101000", 38 => "10001100010",
  39 => "11010001000", 40 => "11000101000", 41 => "11000100010",
  42 => "10110111000", 43 => "10110001110", 44 => "10001101110",
  45 => "10111011000", 46 => "10111000110", 47 => "10001110110",
  48 => "11101110110", 49 => "11010001110", 50 => "11000101110",
  51 => "11011101000", 52 => "11011100010", 53 => "11011101110",
  54 => "11101011000", 55 => "11101000110", 56 => "11100010110",
  57 => "11101101000", 58 => "11101100010", 59 => "11100011010",
  60 => "11101111010", 61 => "11001000010", 62 => "11110001010",
  63 => "10100110000", 64 => "10100001100", 65 => "10010110000",
  66 => "10010000110", 67 => "10000101100", 68 => "10000100110",
  69 => "10110010000", 70 => "10110000100", 71 => "10011010000",
  72 => "10011000010", 73 => "10000110100", 74 => "10000110010",
  75 => "11000010010", 76 => "11001010000", 77 => "11110111010",
  78 => "11000010100", 79 => "10001111010", 80 => "10100111100",
  81 => "10010111100", 82 => "10010011110", 83 => "10111100100",
  84 => "10011110100", 85 => "10011110010", 86 => "11110100100",
  87 => "11110010100", 88 => "11110010010", 89 => "11011011110",
  90 => "11011110110", 91 => "11110110110", 92 => "10101111000",
  93 => "10100011110", 94 => "10001011110", 95 => "10111101000",
  96 => "10111100010", 97 => "11110101000", 98 => "11110100010",
  99 => "10111011110", 100 => "10111101110", 101 => "11101011110",
  102 => "11110101110", 103 => "11010000100", 104 => "11010010000",
  105 => "11010011100"
}
VALUES =
{
  'A' => {
    0 => " ",      1 => "!",        2 => "\"",
    3 => "#",       4 => "$",        5 => "%",
    6 => "&",       7 => "'",        8 => "(",
    9 => ")",       10 => "*",       11 => "+",
    12 => ",",      13 => "-",       14 => ".",
    15 => "/",      16 => "0",       17 => "1",
    18 => "2",      19 => "3",       20 => "4",
    21 => "5",      22 => "6",       23 => "7",
    24 => "8",      25 => "9",       26 => ":",
    27 => ";",      28 => "<",       29 => "=",
    30 => ">",      31 => "?",       32 => "@",
    33 => "A",      34 => "B",       35 => "C",
    36 => "D",      37 => "E",       38 => "F",
    39 => "G",      40 => "H",       41 => "I",
    42 => "J",      43 => "K",       44 => "L",
    45 => "M",      46 => "N",       47 => "O",
    48 => "P",      49 => "Q",       50 => "R",
    51 => "S",      52 => "T",       53 => "U",
    54 => "V",      55 => "W",       56 => "X",
    57 => "Y",      58 => "Z",       59 => "[",
    60 => "\\",     61 => "]",       62 => "^",
    63 => "_",      64 => "\000",    65 => "\001",
    66 => "\002",   67 => "\003",    68 => "\004",
    69 => "\005",   70 => "\006",    71 => "\a",
    72 => "\b",     73 => "\t",      74 => "\n",
    75 => "\v",     76 => "\f",      77 => "\r",
    78 => "\016",   79 => "\017",    80 => "\020",
    81 => "\021",   82 => "\022",    83 => "\023",
    84 => "\024",   85 => "\025",    86 => "\026",
    87 => "\027",   88 => "\030",    89 => "\031",
    90 => "\032",   91 => "\e",      92 => "\034",
    93 => "\035",   94 => "\036",    95 => "\037",
    96 => "\303",   97 => "\302",    98 => "SHIFT",
    99 => "\307",   100 => "\306",   101 => "\304",
    102 => "\301",  103 => "STARTA", 104 => "STARTB",
    105 => "STARTC"
  }.invert,

  'B' => {
    0 => " ", 1 => "!", 2 => "\"", 3 => "#", 4 => "$", 5 => "%",
    6 => "&", 7 => "'", 8 => "(", 9 => ")", 10 => "*", 11 => "+",
    12 => ",", 13 => "-", 14 => ".", 15 => "/", 16 => "0", 17 => "1",
    18 => "2", 19 => "3", 20 => "4", 21 => "5", 22 => "6", 23 => "7",
    24 => "8", 25 => "9", 26 => ":", 27 => ";", 28 => "<", 29 => "=",
    30 => ">", 31 => "?", 32 => "@", 33 => "A", 34 => "B", 35 => "C",
    36 => "D", 37 => "E", 38 => "F", 39 => "G", 40 => "H", 41 => "I",
    42 => "J", 43 => "K", 44 => "L", 45 => "M", 46 => "N", 47 => "O",
    48 => "P", 49 => "Q", 50 => "R", 51 => "S", 52 => "T", 53 => "U",
    54 => "V", 55 => "W", 56 => "X", 57 => "Y", 58 => "Z", 59 => "[",
    60 => "\\", 61 => "]", 62 => "^", 63 => "_", 64 => "`", 65 => "a",
    66 => "b", 67 => "c", 68 => "d", 69 => "e", 70 => "f", 71 => "g",
    72 => "h", 73 => "i", 74 => "j", 75 => "k", 76 => "l", 77 => "m",
    78 => "n", 79 => "o", 80 => "p", 81 => "q", 82 => "r", 83 => "s",
    84 => "t", 85 => "u", 86 => "v", 87 => "w", 88 => "x", 89 => "y",
    90 => "z", 91 => "{", 92 => "|", 93 => "}", 94 => "~", 95 => "\177",
    96 => "\303", 97 => "\302", 98 => "SHIFT", 99 => "\307", 100 => "\304",
    101 => "\305", 102 => "\301", 103 => "STARTA", 104 => "STARTB",
    105 => "STARTC",
  }.invert,

  'C' => {
    0 => "00", 1 => "01", 2 => "02", 3 => "03", 4 => "04", 5 => "05",
    6 => "06", 7 => "07", 8 => "08", 9 => "09", 10 => "10", 11 => "11",
    12 => "12", 13 => "13", 14 => "14", 15 => "15", 16 => "16", 17 => "17",
    18 => "18", 19 => "19", 20 => "20", 21 => "21", 22 => "22", 23 => "23",
    24 => "24", 25 => "25", 26 => "26", 27 => "27", 28 => "28", 29 => "29",
    30 => "30", 31 => "31", 32 => "32", 33 => "33", 34 => "34", 35 => "35",
    36 => "36", 37 => "37", 38 => "38", 39 => "39", 40 => "40", 41 => "41",
    42 => "42", 43 => "43", 44 => "44", 45 => "45", 46 => "46", 47 => "47",
    48 => "48", 49 => "49", 50 => "50", 51 => "51", 52 => "52", 53 => "53",
    54 => "54", 55 => "55", 56 => "56", 57 => "57", 58 => "58", 59 => "59",
    60 => "60", 61 => "61", 62 => "62", 63 => "63", 64 => "64", 65 => "65",
    66 => "66", 67 => "67", 68 => "68", 69 => "69", 70 => "70", 71 => "71",
    72 => "72", 73 => "73", 74 => "74", 75 => "75", 76 => "76", 77 => "77",
    78 => "78", 79 => "79", 80 => "80", 81 => "81", 82 => "82", 83 => "83",
    84 => "84", 85 => "85", 86 => "86", 87 => "87", 88 => "88", 89 => "89",
    90 => "90", 91 => "91", 92 => "92", 93 => "93", 94 => "94", 95 => "95",
    96 => "96", 97 => "97", 98 => "98", 99 => "99", 100 => "\306", 101 => "\305",
    102 => "\301", 103 => "STARTA", 104 => "STARTB", 105 => "STARTC"
  }.invert
}
FNC1 =
"\xc1"
FNC2 =
"\xc2"
FNC3 =
"\xc3"
FNC4 =
"\xc4"
CODEA =
"\xc5"
CODEB =
"\xc6"
CODEC =
"\xc7"
STOP =
'11000111010'
TERMINATE =
'11'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Barcode

#method_missing, #outputter_class_for, #outputter_for, outputters, register_outputter, #two_dimensional?

Constructor Details

#initialize(data, type) ⇒ Code128

Returns a new instance of Code128.

Raises:

  • (ArgumentError)


159
160
161
162
163
# File 'lib/barby/barcode/code_128.rb', line 159

def initialize(data, type)
  self.type = type
  self.data = "#{data}"
  raise ArgumentError, 'Data not valid' unless valid?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Barby::Barcode

Instance Attribute Details

#typeObject

Returns the value of attribute type.



156
157
158
# File 'lib/barby/barcode/code_128.rb', line 156

def type
  @type
end

Instance Method Details

#change_code_encoding_for(barcode) ⇒ Object

Find the encoding to change to the character set in barcode



345
346
347
# File 'lib/barby/barcode/code_128.rb', line 345

def change_code_encoding_for(barcode)
  encodings[change_code_number_for(barcode)]
end

#change_code_for(barcode) ⇒ Object

Find the character that changes the character set to the one represented in barcode



334
335
336
# File 'lib/barby/barcode/code_128.rb', line 334

def change_code_for(barcode)
  change_code_for_class(barcode.class)
end

#change_code_for_class(klass) ⇒ Object



328
329
330
# File 'lib/barby/barcode/code_128.rb', line 328

def change_code_for_class(klass)
  {Code128A => CODEA, Code128B => CODEB, Code128C => CODEC}[klass]
end

#change_code_number_for(barcode) ⇒ Object

Find the numeric value for the character that changes the character set to the one represented in barcode



340
341
342
# File 'lib/barby/barcode/code_128.rb', line 340

def change_code_number_for(barcode)
  values[change_code_for(barcode)]
end

#charactersObject

Get an array of the individual characters for this barcode. Special characters like FNC1 will be present. Characters from extras are not present.



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/barby/barcode/code_128.rb', line 237

def characters
  chars = data.split(//n)

  if type == 'C'
    result = []
    count = 0
    while count < chars.size
      if chars[count] =~ /^\d$/
        result << "#{chars[count]}#{chars[count+1]}"
        count += 2
      else
        result << chars[count]
        count += 1
      end
    end
    result
  else
    chars
  end
end

#checksumObject

Calculate the checksum for the data in this barcode. The data includes data from extras.



285
286
287
288
289
290
291
# File 'lib/barby/barcode/code_128.rb', line 285

def checksum
  pos = 0
  (numbers+extra_numbers).inject(start_num) do |sum,number|
    pos += 1
    sum + (number * pos)
  end % 103
end

#checksum_encodingObject

Get the encoding for the checksum



294
295
296
# File 'lib/barby/barcode/code_128.rb', line 294

def checksum_encoding
  encodings[checksum]
end

#class_for(character) ⇒ Object



349
350
351
352
353
354
355
356
357
358
# File 'lib/barby/barcode/code_128.rb', line 349

def class_for(character)
  case character
  when 'A' then Code128A
  when 'B' then Code128B
  when 'C' then Code128C
  when CODEA then Code128A
  when CODEB then Code128B
  when CODEC then Code128C
  end
end

#dataObject



178
179
180
# File 'lib/barby/barcode/code_128.rb', line 178

def data
  @data
end

#data=(data) ⇒ Object

Set the data for this barcode. If the barcode changes character set, an extra will be created.



209
210
211
212
213
# File 'lib/barby/barcode/code_128.rb', line 209

def data=(data)
  data, *extra = data.split(/([#{CODEA+CODEB+CODEC}])/n)
  @data = data || ''
  self.extra = extra.join unless extra.empty?
end

#data_encodingObject

Returns the encoding for the data part of this barcode, without any extras



264
265
266
267
268
# File 'lib/barby/barcode/code_128.rb', line 264

def data_encoding
  characters.map do |char|
    encoding_for char
  end.join
end

#data_encoding_with_extra_encodingObject

Returns the data encoding of this barcode and extras.



271
272
273
# File 'lib/barby/barcode/code_128.rb', line 271

def data_encoding_with_extra_encoding
  data_encoding+extra_encoding
end

#encodingObject

Return the encoding of this barcode as a string of 1 and 0



259
260
261
# File 'lib/barby/barcode/code_128.rb', line 259

def encoding
  start_encoding+data_encoding+extra_encoding+checksum_encoding+stop_encoding
end

#encoding_for(char) ⇒ Object

Find the encoding for the specified character for this barcode



324
325
326
# File 'lib/barby/barcode/code_128.rb', line 324

def encoding_for(char)
  encodings[values[char]]
end

#encodingsObject



314
315
316
# File 'lib/barby/barcode/code_128.rb', line 314

def encodings
  ENCODINGS
end

#extraObject

An “extra” is present if the barcode changes character set. If a 128A barcode changes to C, the extra will be an instance of Code128C. Extras can themselves have an extra if the barcode changes character set again. It’s like a linked list, and when there are no more extras, the barcode ends with that object. Most barcodes probably don’t change charsets and don’t have extras.



221
222
223
# File 'lib/barby/barcode/code_128.rb', line 221

def extra
  @extra
end

#extra=(extra) ⇒ Object

Set the extra for this barcode. The argument is a string starting with the “change character set” symbol. The string may contain several character sets, in which case the extra will itself have an extra.

Raises:

  • (ArgumentError)


228
229
230
231
232
# File 'lib/barby/barcode/code_128.rb', line 228

def extra=(extra)
  raise ArgumentError, "Extra must begin with \\305, \\306 or \\307" unless extra =~ /^[#{CODEA+CODEB+CODEC}]/n
  type, data = extra[0,1], extra[1..-1]
  @extra = class_for(type).new(data)
end

#extra_encodingObject

Returns the data encoding of this barcode’s extra and its extra until the barcode ends.



277
278
279
280
# File 'lib/barby/barcode/code_128.rb', line 277

def extra_encoding
  return '' unless extra
  change_code_encoding_for(extra) + extra.data_encoding + extra.extra_encoding
end

#extra_numbersObject

Returns the numeric values for extras



309
310
311
312
# File 'lib/barby/barcode/code_128.rb', line 309

def extra_numbers
  return [] unless extra
  [change_code_number_for(extra)] + extra.numbers + extra.extra_numbers
end

#full_dataObject

Returns the data for this barcode plus that for the entire extra chain, excluding all change codes



184
185
186
# File 'lib/barby/barcode/code_128.rb', line 184

def full_data
  data + full_extra_data
end

#full_data_with_change_codesObject

Returns the data for this barcode plus that for the entire extra chain, including all change codes prefixing each extra



190
191
192
# File 'lib/barby/barcode/code_128.rb', line 190

def full_data_with_change_codes
  data + full_extra_data_with_change_code
end

#full_extra_dataObject

Returns the full_data for the extra or an empty string if there is no extra



195
196
197
198
# File 'lib/barby/barcode/code_128.rb', line 195

def full_extra_data
  return '' unless extra
  extra.full_data
end

#full_extra_data_with_change_codeObject

Returns the full_data for the extra with the change code for the extra prepended. If there is no extra, an empty string is returned



202
203
204
205
# File 'lib/barby/barcode/code_128.rb', line 202

def full_extra_data_with_change_code
  return '' unless extra
  change_code_for(extra) + extra.full_data_with_change_codes
end

#numbersObject

Returns the numeric values for the characters in the barcode in an array



302
303
304
305
306
# File 'lib/barby/barcode/code_128.rb', line 302

def numbers
  characters.map do |char|
    values[char]
  end
end

#start_encodingObject



375
376
377
# File 'lib/barby/barcode/code_128.rb', line 375

def start_encoding
  encodings[start_num]
end

#start_numObject



371
372
373
# File 'lib/barby/barcode/code_128.rb', line 371

def start_num
  values["START#{type}"]
end

#stop_encodingObject

The start encoding starts the barcode



319
320
321
# File 'lib/barby/barcode/code_128.rb', line 319

def stop_encoding
  STOP+TERMINATE
end

#to_sObject



173
174
175
# File 'lib/barby/barcode/code_128.rb', line 173

def to_s
  full_data
end

#valid?Boolean

Is the data in this barcode valid? Does a lookup of every character and checks if it exists in the character set. An empty data string will also be reported as invalid.

Returns:

  • (Boolean)


363
364
365
# File 'lib/barby/barcode/code_128.rb', line 363

def valid?
  characters.any? && characters.all?{|c| values.include?(c) }
end

#valuesObject



367
368
369
# File 'lib/barby/barcode/code_128.rb', line 367

def values
  VALUES[type]
end