fix base62

This commit is contained in:
2026-07-15 01:27:37 +03:00
parent cf02a6db8d
commit 402fbaf58a
+41 -21
View File
@@ -1,3 +1,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "stdint.h" #include "stdint.h"
#include "stdio.h" #include "stdio.h"
#include "system.h" #include "system.h"
@@ -78,7 +82,7 @@ int cmp(const void* arg1, const void* arg2) {
static int log2i(int n) { static int log2i(int n) {
int m = 0; int m = 0;
while (n / 2) m++; while (n /= 2) m++;
return m; return m;
} }
@@ -179,41 +183,57 @@ static int encode_golomb(int cnt, const unsigned* delta_arr_pt, int Mshift, char
* to another 'Z' (which would require high bits set to "11"). This is * to another 'Z' (which would require high bits set to "11"). This is
* how multiple escapes are avoided. * how multiple escapes are avoided.
*/ */
static char* bits_to_char(int c, char* base62) {
assert(c >= 0 && c <= 61);
if (c < 10) {
*base62++ = c + '0';
} else if (c < 36) {
*base62++ = c - 10 + 'a';
} else if (c < 62) {
*base62++ = c - 36 + 'A';
}
return base62;
}
// заполняет с младших, в случае Z - ставит в старшие
static int encode_base62(int bit_cnt, const char* bit_arr_pt, char* base62_str_pt) { static int encode_base62(int bit_cnt, const char* bit_arr_pt, char* base62_str_pt) {
char* base62_start = base62_str_pt; char* base62_start = base62_str_pt;
// int bits_Z = 0; // bits from Z-escape; // из-за этого заполнения я не знаю, как написать лучше...
int bits_cnt = 0;
unsigned bits_buf = 1; // 1 bit as marker int bits2 = 0; // number of high bits set
int bits6 = 0; // number of regular bits set
int num6b = 0; // pending 6-bit number
while (bit_cnt-- > 0) { while (bit_cnt-- > 0) {
bits_buf <<= 1; num6b |= (*bit_arr_pt++ << bits6++);
bits_buf |= *bit_arr_pt++;
if (!(bits_buf & (1 << 6))) continue; if (bits6 + bits2 < 6) continue;
bits_buf &= ~(1 << 6); // remove flag if (num6b >= 61) { // 61 62 63 cases
if (bits_buf >= 61) { // 61 62 63 cases
base62_str_pt = bits_to_char(61, base62_str_pt); base62_str_pt = bits_to_char(61, base62_str_pt);
bits_buf = (1 << 2) | (bits_buf - 61); // 1 (00|01|10) bits2 = 2;
num6b = (num6b - 61) << 4; // (0|16|32) in high bits
} else { } else {
base62_str_pt = bits_to_char(bits_buf, base62_str_pt); assert(num6b < 61);
bits_buf = 1; base62_str_pt = bits_to_char(num6b, base62_str_pt);
} bits2 = 0;
num6b = 0;
} }
// flush buffer bits6 = 0;
if (bits_buf != 1) { }
unsigned sliding_one = 1 << 6;
while (sliding_one > bits_buf) sliding_one >>= 1;
bits_buf &= ~sliding_one; // remove flag
assert(bits_buf < 61); // should not be 61 62 63 cases if (bits6 + bits2) {
base62_str_pt = bits_to_char(bits_buf, base62_str_pt); assert(num6b < 61);
base62_str_pt = bits_to_char(num6b, base62_str_pt);
} }
*base62_str_pt = '\0'; *base62_str_pt = '\0';
return base62_str_pt - base62_start; return base62_str_pt - base62_start;
} }