61 lines
1.5 KiB
Ruby
61 lines
1.5 KiB
Ruby
class String
|
|
|
|
def ^( key )
|
|
b1 = self.unpack("C*")
|
|
b2 = key.unpack("C*")
|
|
mul = (b1.length.to_f / b2.length.to_f).ceil
|
|
b2 = b2 * mul
|
|
b1.zip(b2).map{ |a,b| a^b }.pack("C*")
|
|
end
|
|
|
|
def fmtstr(value, index, **options)
|
|
# initialize
|
|
bytes = 1
|
|
@fmt_size = 0 unless defined? @fmt_size
|
|
# set by user input
|
|
bytes = options[:bytes] if options.has_key? :bytes
|
|
@fmt_size = options[:fmt_size] if options.has_key? :fmt_size
|
|
|
|
fail "Invalid size." if bytes == 3 or bytes > 4 or bytes == 0
|
|
|
|
result = self
|
|
times = (value.size / bytes.to_f).ceil
|
|
|
|
times.times do
|
|
target = fmtstr_parse value, bytes
|
|
if (c = fmtstr_calc(@fmt_size, target, bytes)) > 0
|
|
result << "%#{c}c"
|
|
@fmt_size += c
|
|
end
|
|
result << "%#{index}$#{bytes == 4 ? "" : "h" * (3-bytes)}n"
|
|
index += 1
|
|
value = value[bytes..-1]
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
private
|
|
def fmtstr_calc(from, to, scale)
|
|
base = 256 ** scale
|
|
|
|
count = 0
|
|
count = to - (from % base)
|
|
count += base if count < 0
|
|
count
|
|
end
|
|
|
|
def fmtstr_parse(v, bytes)
|
|
result = 0
|
|
v = v.ljust bytes, "\x00"
|
|
if bytes == 1
|
|
result = v.unpack("C")[0]
|
|
elsif bytes == 2
|
|
result = v.unpack("S<")[0]
|
|
elsif bytes == 4
|
|
result = v.unpack("L<")[0]
|
|
end
|
|
result
|
|
end
|
|
end
|