class Alexandria::Scanners::CueCat

Public Instance Methods

decode(data) click to toggle source

Decodes CueCat input into ISBN The following code is adapted from Skip Rosebaugh’s public domain perl implementation.

# File lib/alexandria/scanners/cue_cat.rb, line 51
def decode(data)
  data = data.chomp
  fields = data.split(".")
  fields.shift # First part is gibberish
  fields.shift # Second part is cuecat serial number
  type, code = fields.map { |field| decode_field(field) }

  if type == "IB5"
    type = "IBN"
    code = code[0, 13]
  end

  begin
    if Library.valid_upc? code
      isbn13 = Library.canonicalise_ean(code)
      code = isbn13
      type = "IBN"
    end
  rescue StandardError
    log.debug { "Cannot translate UPC (#{type}) code #{code} to ISBN" }
  end

  return code if type == "IBN"

  raise format(_("Don't know how to handle type %<type>s (barcode: %<code>s)"),
               type: type, code: code)
end
display_name() click to toggle source
# File lib/alexandria/scanners/cue_cat.rb, line 32
def display_name
  "CueCat"
end
match?(data) click to toggle source

Checks if data looks like cuecat input

# File lib/alexandria/scanners/cue_cat.rb, line 37
def match?(data)
  data = data.chomp
  return false if data[-1] != "."

  fields = data.split(".")
  return false if fields.size != 4
  return false if fields[2].size != 4

  true
end
name() click to toggle source
# File lib/alexandria/scanners/cue_cat.rb, line 28
def name
  "CueCat"
end

Private Instance Methods

calc(values) click to toggle source
# File lib/alexandria/scanners/cue_cat.rb, line 92
def calc(values)
  result = ""
  until values.empty?
    num = ((values[0] << 6 | values[1]) << 6 | values[2]) << 6 | values[3]
    result += ((num >> 16) ^ 67).chr
    result += ((num >> 8 & 255) ^ 67).chr
    result += ((num & 255) ^ 67).chr

    values = values[4, values.length]
  end
  result
end
decode_field(encoded) click to toggle source
# File lib/alexandria/scanners/cue_cat.rb, line 81
def decode_field(encoded)
  seq = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-"

  chars   = encoded.chars
  values  = chars.map { |c| seq.index(c) }

  padding = pad(values)
  result  = calc(values)
  result[0, result.length - padding]
end
pad(array) click to toggle source
# File lib/alexandria/scanners/cue_cat.rb, line 105
def pad(array)
  length = array.length % 4

  if length.nonzero?
    raise _("Error parsing CueCat input") if length == 1

    length = 4 - length
    length.times { array.push(0) }
  end

  length
end