module IdPack::LZString

Constants

KEY_STR_BASE64
KEY_STR_URI_SAFE

Public Class Methods

_compress(uncompressed, bits_per_char) { |context_data_val| ... } click to toggle source
# File lib/id_pack/lz_string.rb, line 121
def _compress(uncompressed, bits_per_char)
  return "" if uncompressed.nil?

  context_dictionary = {}
  context_dictionary_to_create = {}
  context_c = ""
  context_wc = ""
  context_w = ""
  context_enlarge_in = 2
  context_dict_size = 3
  context_num_bits = 2
  context_data = []
  context_data_val = 0
  context_data_position = 0

  uncompressed.length.times do |ii|
    context_c = uncompressed[ii]

    if !context_dictionary[context_c]
      context_dictionary[context_c] = context_dict_size
      context_dict_size += 1
      context_dictionary_to_create[context_c] = true
    end

    context_wc = context_w + context_c

    if context_dictionary[context_wc]
      context_w = context_wc
    else
      if context_dictionary_to_create[context_w]
        if context_w[0].ord < 256
          context_num_bits.times do |_i|
            context_data_val = (context_data_val << 1)

            if context_data_position == bits_per_char - 1
              context_data_position = 0
              context_data.push(yield(context_data_val))
              context_data_val = 0
            else
              context_data_position += 1
            end
          end

          value = context_w[0].ord

          8.times do |_i|
            context_data_val = (context_data_val << 1) | (value & 1)

            if context_data_position == bits_per_char - 1
              context_data_position = 0
              context_data.push(yield(context_data_val))
              context_data_val = 0
            else
              context_data_position += 1
            end

            value = value >> 1
          end
        else
          value = 1

          context_num_bits.times do |_i|
            context_data_val = (context_data_val << 1) | value

            if context_data_position == bits_per_char - 1
              context_data_position = 0
              context_data.push(yield(context_data_val))
              context_data_val = 0
            else
              context_data_position += 1
            end

            value = 0
          end

          value = context_w[0].ord

          16.times do |_i|
            context_data_val = (context_data_val << 1) | (value & 1)

            if context_data_position == bits_per_char - 1
              context_data_position = 0
              context_data.push(yield(context_data_val))
              context_data_val = 0
            else
              context_data_position += 1
            end

            value = value >> 1
          end
        end

        context_enlarge_in -= 1

        if context_enlarge_in.zero?
          context_enlarge_in = 2**context_num_bits
          context_num_bits += 1
        end

        context_dictionary_to_create.delete(context_w)
      else
        value = context_dictionary[context_w]

        context_num_bits.times do |_i|
          context_data_val = (context_data_val << 1) | (value & 1)

          if context_data_position == bits_per_char - 1
            context_data_position = 0
            context_data.push(yield(context_data_val))
            context_data_val = 0
          else
            context_data_position += 1
          end

          value = value >> 1
        end
      end

      context_enlarge_in -= 1

      if context_enlarge_in.zero?
        context_enlarge_in = 2**context_num_bits
        context_num_bits += 1
      end

      context_dictionary[context_wc] = context_dict_size
      context_dict_size += 1
      context_w = context_c.to_s
    end
  end

  if context_w != ""
    if context_dictionary_to_create[context_w]
      if context_w[0].ord < 256
        context_num_bits.times do |_i|
          context_data_val = context_data_val << 1

          if context_data_position == bits_per_char - 1
            context_data_position = 0
            context_data.push(yield(context_data_val))
            context_data_val = 0
          else
            context_data_position += 1
          end
        end

        value = context_w[0].ord

        8.times do |_i|
          context_data_val = (context_data_val << 1) | (value & 1)

          if context_data_position == bits_per_char - 1
            context_data_position = 0
            context_data.push(yield(context_data_val))
            context_data_val = 0
          else
            context_data_position += 1
          end

          value = value >> 1
        end
      else
        value = 1

        context_num_bits.times do |_i|
          context_data_val = (context_data_val << 1) | value

          if context_data_position == bits_per_char - 1
            context_data_position = 0
            context_data.push(yield(context_data_val))
            context_data_val = 0
          else
            context_data_position += 1
          end

          value = 0
        end

        value = context_w[0].ord

        16.times do |_i|
          context_data_val = (context_data_val << 1) | (value & 1)

          if context_data_position == bits_per_char - 1
            context_data_position = 0
            context_data.push(yield(context_data_val))
            context_data_val = 0
          else
            context_data_position += 1
          end

          value = value >> 1
        end
      end

      context_enlarge_in -= 1

      if context_enlarge_in.zero?
        context_enlarge_in = 2**context_num_bits
        context_num_bits += 1
      end

      context_dictionary_to_create.delete(context_w)
    else
      value = context_dictionary[context_w]

      context_num_bits.times do |_i|
        context_data_val = (context_data_val << 1) | (value & 1)

        if context_data_position == bits_per_char - 1
          context_data_position = 0
          context_data.push(yield(context_data_val))
          context_data_val = 0
        else
          context_data_position += 1
        end

        value = value >> 1
      end
    end

    context_enlarge_in -= 1

    if context_enlarge_in.zero?
      context_enlarge_in = 2**context_num_bits
      context_num_bits += 1
    end
  end

  value = 2

  context_num_bits.times do |_i|
    context_data_val = (context_data_val << 1) | (value & 1)

    if context_data_position == bits_per_char - 1
      context_data_position = 0
      context_data.push(yield(context_data_val))
      context_data_val = 0
    else
      context_data_position += 1
    end

    value = value >> 1
  end

  loop do
    context_data_val = (context_data_val << 1)

    if context_data_position == bits_per_char - 1
      context_data.push(yield(context_data_val))
      break
    else
      context_data_position += 1
    end
  end

  context_data.join('')
end
_decompress(length, reset_value) { |0| ... } click to toggle source
# File lib/id_pack/lz_string.rb, line 389
def _decompress(length, reset_value)
  dictionary = []
  enlarge_in = 4
  dict_size = 4
  num_bits = 3
  entry = ""
  result = []
  data = {
    val: yield(0),
    position: reset_value,
    index: 1,
  }

  3.times do |i|
    dictionary[i] = i
  end

  bits = 0
  maxpower = 2**2
  power = 1

  while power != maxpower
    resb = data[:val] & data[:position]
    data[:position] = data[:position] >> 1

    if (data[:position]).zero?
      data[:position] = reset_value
      data[:val] = yield(data[:index])
      data[:index] += 1
    end

    bits |= (resb.positive? ? 1 : 0) * power
    power = power << 1
  end

  case bits
  when 0
    bits = 0
    maxpower = 2**8
    power = 1

    while power != maxpower
      resb = data[:val] & data[:position]
      data[:position] = data[:position] >> 1

      if (data[:position]).zero?
        data[:position] = reset_value
        data[:val] = yield(data[:index])
        data[:index] += 1
      end

      bits |= (resb.positive? ? 1 : 0) * power
      power <<= 1
    end

    c = [bits].pack 'U'
  when 1
    bits = 0
    maxpower = 2**16
    power = 1

    while power != maxpower
      resb = data[:val] & data[:position]
      data[:position] = data[:position] >> 1

      if (data[:position]).zero?
        data[:position] = reset_value
        data[:val] = yield(data[:index])
        data[:index] += 1
      end

      bits |= (resb.positive? ? 1 : 0) * power
      power <<= 1
    end

    c = [bits].pack 'U'
  when 2
    return ""
  end

  dictionary[3] = c
  w = c
  result.push(c)

  loop do
    return "" if data[:index] > length

    bits = 0
    maxpower = 2**num_bits
    power = 1

    while power != maxpower
      resb = data[:val] & data[:position]
      data[:position] = data[:position] >> 1

      if (data[:position]).zero?
        data[:position] = reset_value
        data[:val] = yield(data[:index])
        data[:index] += 1
      end

      bits |= (resb.positive? ? 1 : 0) * power
      power <<= 1
    end

    c = bits

    case bits
    when 0
      bits = 0
      maxpower = 2**8
      power = 1

      while power != maxpower
        resb = data[:val] & data[:position]
        data[:position] >>= 1

        if (data[:position]).zero?
          data[:position] = reset_value
          data[:val] = yield(data[:index])
          data[:index] += 1
        end

        bits |= (resb.positive? ? 1 : 0) * power
        power <<= 1
      end

      dictionary[dict_size] = [bits].pack 'U'
      dict_size += 1
      c = dict_size - 1
      enlarge_in -= 1
    when 1
      bits = 0
      maxpower = 2**16
      power = 1

      while power != maxpower
        resb = data[:val] & data[:position]
        data[:position] >>= 1

        if (data[:position]).zero?
          data[:position] = reset_value
          data[:val] = yield(data[:index])
          data[:index] += 1
        end

        bits |= (resb.positive? ? 1 : 0) * power
        power <<= 1
      end

      dictionary[dict_size] = [bits].pack 'U'
      dict_size += 1
      c = dict_size - 1
      enlarge_in -= 1
    when 2
      return result.join("")
    end

    if enlarge_in.zero?
      enlarge_in = 2**num_bits
      num_bits += 1
    end

    if dictionary[c]
      entry = dictionary[c]
    else
      return nil if c != dict_size

      entry = w + w[0]
    end

    result.push(entry)

    dictionary[dict_size] = w + entry[0]
    dict_size += 1
    enlarge_in -= 1

    w = entry

    if enlarge_in.zero?
      enlarge_in = 2**num_bits
      num_bits += 1
    end
  end
end
compress(uncompressed) click to toggle source
# File lib/id_pack/lz_string.rb, line 115
def compress(uncompressed)
  _compress(uncompressed, 16) do |a|
    [a].pack 'U'
  end
end
compress_to_base64(input) click to toggle source
# File lib/id_pack/lz_string.rb, line 22
def compress_to_base64(input)
  return "" if input.nil?

  res = _compress(input, 6) do |a|
    KEY_STR_BASE64[a]
  end

  case res.length % 4
  when 0 then res
  when 1 then "#{res}==="
  when 2 then "#{res}=="
  when 3 then "#{res}="
  end
end
compress_to_encoded_uri_component(input) click to toggle source
# File lib/id_pack/lz_string.rb, line 96
def compress_to_encoded_uri_component(input)
  return "" if input.nil?

  _compress(input, 6) do |a|
    KEY_STR_URI_SAFE[a]
  end
end
compress_to_uint8_array(uncompressed) click to toggle source
# File lib/id_pack/lz_string.rb, line 63
def compress_to_uint8_array(uncompressed)
  compressed = compress(uncompressed)
  buf = []

  compressed.length.times do |i|
    current_value = compressed[i].ord
    buf[i * 2] = current_value >> 8 # TODO: >>> 8 how to do it in ruby?
    buf[i * 2 + 1] = current_value % 256
  end

  buf
end
compress_to_utf16(input) click to toggle source
# File lib/id_pack/lz_string.rb, line 46
def compress_to_utf16(input)
  return "" if input.nil?

  _compress(input, 15) do |a|
    [a + 32].pack 'U'
  end + " "
end
decompress(compressed) click to toggle source
# File lib/id_pack/lz_string.rb, line 380
def decompress(compressed)
  return "" if compressed.nil?
  return null if compressed == ""

  _decompress(compressed.length, 32768) do |index|
    compressed[index].ord
  end
end
decompress_from_base64(input) click to toggle source
# File lib/id_pack/lz_string.rb, line 37
def decompress_from_base64(input)
  return "" if input.nil?
  return nil if input == ""

  _decompress(input.length, 32) do |index|
    get_base_value(KEY_STR_BASE64, input[index])
  end
end
decompress_from_encoded_uri_component(input) click to toggle source
# File lib/id_pack/lz_string.rb, line 104
def decompress_from_encoded_uri_component(input)
  return "" if input.nil?
  return nil if input == ""

  input.gsub!(/ /, "+")

  _decompress(input.length, 32) do |index|
    get_base_value(KEY_STR_URI_SAFE, input[index])
  end
end
decompress_from_uint8_array(compressed) click to toggle source
# File lib/id_pack/lz_string.rb, line 76
def decompress_from_uint8_array(compressed)
  return decompress(compressed) if compressed.nil?

  buf = []

  (compressed.length / 2).times do |i|
    buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1]
  end

  result = []

  buf.each do |_c|
    result.push(
      [a + 32].pack('U'),
    )
  end

  decompress(result.join(''))
end
decompress_from_utf16(compressed) click to toggle source
# File lib/id_pack/lz_string.rb, line 54
def decompress_from_utf16(compressed)
  return "" if compressed.nil?
  return nil if compressed == ""

  _decompress(compressed.length, 16384) do |index|
    compressed[index].ord - 32
  end
end
get_base_value(alphabet, character) click to toggle source
# File lib/id_pack/lz_string.rb, line 8
def get_base_value(alphabet, character)
  @base_reverse_dic ||= {}

  if !@base_reverse_dic[alphabet]
    @base_reverse_dic[alphabet] = {}

    alphabet.length.times do |i|
      @base_reverse_dic[alphabet][alphabet[i]] = i
    end
  end

  @base_reverse_dic[alphabet][character]
end