decode WIP
This commit is contained in:
+139
-1
@@ -45,6 +45,22 @@ def int_to_char(value: int) -> str:
|
|||||||
raise ValueError("Value must be in the range [0, 63] for base64 encoding.")
|
raise ValueError("Value must be in the range [0, 63] for base64 encoding.")
|
||||||
|
|
||||||
|
|
||||||
|
def char_to_int(char: str) -> int:
|
||||||
|
"""Convert a base64 character to its corresponding integer value."""
|
||||||
|
if "0" <= char <= "9":
|
||||||
|
return ord(char) - ord("0")
|
||||||
|
elif "a" <= char <= "z":
|
||||||
|
return ord(char) - ord("a") + 10
|
||||||
|
elif "A" <= char <= "Z":
|
||||||
|
return ord(char) - ord("A") + 36
|
||||||
|
elif char == "+":
|
||||||
|
return 62
|
||||||
|
elif char == "/":
|
||||||
|
return 63
|
||||||
|
else:
|
||||||
|
raise ValueError("Character must be a valid base64 character.")
|
||||||
|
|
||||||
|
|
||||||
def encode_golomb_Mshift(cnt: int, bpp: int) -> int:
|
def encode_golomb_Mshift(cnt: int, bpp: int) -> int:
|
||||||
"""Calculate Mshift paramter for encoding."""
|
"""Calculate Mshift paramter for encoding."""
|
||||||
Mshift = bpp - (cnt.bit_length() - 1) - 1
|
Mshift = bpp - (cnt.bit_length() - 1) - 1
|
||||||
@@ -122,10 +138,117 @@ def encode_set(hash_values: List[int], bpp: int) -> str:
|
|||||||
return int_to_char(bpp) + int_to_char(Mshift) + base64_chars
|
return int_to_char(bpp) + int_to_char(Mshift) + base64_chars
|
||||||
|
|
||||||
|
|
||||||
def rpmsetcmp():
|
def decode_base64(encoded_str: str) -> List[int]:
|
||||||
|
"""Decode a base64 string into a list of bits."""
|
||||||
|
bits = []
|
||||||
|
|
||||||
|
for char in encoded_str:
|
||||||
|
value = char_to_int(char)
|
||||||
|
for i in range(6):
|
||||||
|
bits.append((value >> (5 - i)) & 1)
|
||||||
|
|
||||||
|
return bits
|
||||||
|
|
||||||
|
|
||||||
|
def decode_golomb(bits: List[int], Mshift: int) -> List[int]:
|
||||||
|
"""Decode a list of bits encoded with Golomb coding into delta values."""
|
||||||
|
delta_values = []
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < len(bits):
|
||||||
|
q = 0
|
||||||
|
|
||||||
|
while i < len(bits) and bits[i] == 0:
|
||||||
|
q += 1
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if i >= len(bits):
|
||||||
|
if q > 5:
|
||||||
|
raise ValueError("Invalid Golomb encoding: too many leading zeros.")
|
||||||
|
break
|
||||||
|
|
||||||
|
i += 1 # skip the separator bit
|
||||||
|
|
||||||
|
r = 0
|
||||||
|
for j in range(Mshift):
|
||||||
|
if i < len(bits):
|
||||||
|
if bits[i] == 1:
|
||||||
|
r |= 1 << j
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
delta_value = (q << Mshift) | r
|
||||||
|
delta_values.append(delta_value)
|
||||||
|
|
||||||
|
return delta_values
|
||||||
|
|
||||||
|
|
||||||
|
def decode_delta(delta_values: List[int]) -> List[int]:
|
||||||
|
"""Decode a list of delta values into hash values."""
|
||||||
|
last_hash = delta_values[0]
|
||||||
|
hash_values = [last_hash]
|
||||||
|
|
||||||
|
for i in range(1, len(delta_values)):
|
||||||
|
hash_values.append(hash_values[i - 1] + delta_values[i])
|
||||||
|
|
||||||
|
return hash_values
|
||||||
|
|
||||||
|
|
||||||
|
def downsample_set(hash_values: List[int], bpp: int) -> List[int]:
|
||||||
|
"""Reduce a set of (bpp + 1) values to a set of bpp values, keeping it sorted."""
|
||||||
|
# WIP
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def decode_set_init(encoded_str: str) -> Tuple[int, int]:
|
||||||
|
"""Decode the initial part of the set-string to extract bpp and Mshift."""
|
||||||
|
if len(encoded_str) < 2:
|
||||||
|
raise ValueError("Encoded string is too short to contain bpp and Mshift.")
|
||||||
|
|
||||||
|
bpp = char_to_int(encoded_str[0])
|
||||||
|
Mshift = char_to_int(encoded_str[1])
|
||||||
|
|
||||||
|
assert check_bpp(bpp), "bpp must be between 2 and 64"
|
||||||
|
assert check_Mshift(Mshift), "Mshift must be between 1 and 63"
|
||||||
|
|
||||||
|
return bpp, Mshift
|
||||||
|
|
||||||
|
|
||||||
|
def decode_set(encoded_str: str, Mshift: int) -> List[int]:
|
||||||
|
"""Decode the set-string representation into a list of hash values."""
|
||||||
|
data_str = encoded_str[2:]
|
||||||
|
|
||||||
|
str_bits = decode_base64(data_str)
|
||||||
|
str_delta = decode_golomb(str_bits, Mshift)
|
||||||
|
hash_values = decode_delta(str_delta)
|
||||||
|
|
||||||
|
return hash_values
|
||||||
|
|
||||||
|
|
||||||
|
def rpmsetcmp(str1: str, str2: str) -> int:
|
||||||
|
if str1[:3] == "set:":
|
||||||
|
str1 = str1[3:]
|
||||||
|
if str2[:3] == "set:":
|
||||||
|
str2 = str2[3:]
|
||||||
|
|
||||||
|
bpp1, Mshift1 = decode_set_init(str1)
|
||||||
|
bpp2, Mshift2 = decode_set_init(str2)
|
||||||
|
hash_values1 = decode_set(str1, Mshift1)
|
||||||
|
hash_values2 = decode_set(str2, Mshift2)
|
||||||
|
|
||||||
|
while bpp1 > bpp2:
|
||||||
|
hash_values1 = downsample_set(hash_values1, bpp1)
|
||||||
|
bpp1 -= 1
|
||||||
|
|
||||||
|
while bpp2 > bpp1:
|
||||||
|
hash_values2 = downsample_set(hash_values2, bpp2)
|
||||||
|
bpp2 -= 1
|
||||||
|
|
||||||
|
# WIP
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def set_new() -> Set:
|
def set_new() -> Set:
|
||||||
"""Create a new Set instance with cnt initialized to 0 and an empty list of labels."""
|
"""Create a new Set instance with cnt initialized to 0 and an empty list of labels."""
|
||||||
return Set(cnt=0, labels=[])
|
return Set(cnt=0, labels=[])
|
||||||
@@ -190,3 +313,18 @@ if __name__ == "__main__":
|
|||||||
result = set_fini(my_set, 8)
|
result = set_fini(my_set, 8)
|
||||||
print(result)
|
print(result)
|
||||||
set_free(my_set)
|
set_free(my_set)
|
||||||
|
|
||||||
|
# example with comparison
|
||||||
|
set1 = set_new()
|
||||||
|
set_add(set1, "label1")
|
||||||
|
set_add(set1, "label2")
|
||||||
|
str1 = set_fini(set1, 8)
|
||||||
|
set2 = set_new()
|
||||||
|
set_add(set2, "label1")
|
||||||
|
set_add(set2, "label2")
|
||||||
|
set_add(set2, "label3")
|
||||||
|
str2 = set_fini(set2, 8)
|
||||||
|
assert str1 is not None and str2 is not None, "Set strings should not be None"
|
||||||
|
comparison_result = rpmsetcmp(str1, str2)
|
||||||
|
assert comparison_result == -1, "Expected str1 to be less than str2"
|
||||||
|
print(comparison_result)
|
||||||
|
|||||||
Reference in New Issue
Block a user