lib/id_pack/lz_string.rb
module IdPack
module LZString
KEY_STR_BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".freeze
KEY_STR_URI_SAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$".freeze
class << self
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
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
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
def compress_to_utf16(input)
return "" if input.nil?
_compress(input, 15) do |a|
[a + 32].pack 'U'
end + " "
end
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
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
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
def compress_to_encoded_uri_component(input)
return "" if input.nil?
_compress(input, 6) do |a|
KEY_STR_URI_SAFE[a]
end
end
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
def compress(uncompressed)
_compress(uncompressed, 16) do |a|
[a].pack 'U'
end
end
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
def decompress(compressed)
return "" if compressed.nil?
return null if compressed == ""
_decompress(compressed.length, 32768) do |index|
compressed[index].ord
end
end
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
end
end
end