some upgrades
This commit is contained in:
+28
-13
@@ -1,10 +1,14 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "rpmlib.h"
|
#include "rpmlib.h"
|
||||||
#include "stdint.h"
|
#ifdef SELF_TEST
|
||||||
#include "stdio.h"
|
#undef NDEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
#include "set.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#define CACHE_SIZE 256
|
#define CACHE_SIZE 256
|
||||||
@@ -343,16 +347,27 @@ static int char_to_num(char c) {
|
|||||||
return 0xee; // invalid character
|
return 0xee; // invalid character
|
||||||
}
|
}
|
||||||
|
|
||||||
// надо посмотреть, насколько в действительности это делает хуже
|
static char* put6bits(int c, char* bit_pt) {
|
||||||
static char* putnbits(int n, int c, char* bit_pt) {
|
*bit_pt++ = (c >> 0) & 1;
|
||||||
for (int i = 0; i < n; ++i) {
|
*bit_pt++ = (c >> 1) & 1;
|
||||||
*bit_pt++ = (c >> i) & 1;
|
*bit_pt++ = (c >> 2) & 1;
|
||||||
}
|
*bit_pt++ = (c >> 3) & 1;
|
||||||
|
*bit_pt++ = (c >> 4) & 1;
|
||||||
|
*bit_pt++ = (c >> 5) & 1;
|
||||||
|
|
||||||
return bit_pt;
|
return bit_pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main base62 decoding routine: unpack base62 string into bitv[].
|
static char* put4bits(int c, char* bit_pt) {
|
||||||
|
*bit_pt++ = (c >> 0) & 1;
|
||||||
|
*bit_pt++ = (c >> 1) & 1;
|
||||||
|
*bit_pt++ = (c >> 2) & 1;
|
||||||
|
*bit_pt++ = (c >> 3) & 1;
|
||||||
|
|
||||||
|
return bit_pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main base62 decoding routine: unpack base62 string into bit_pt[].
|
||||||
static int decode_base62(const char* base62_str, char* bit_pt) {
|
static int decode_base62(const char* base62_str, char* bit_pt) {
|
||||||
char* bit_start = bit_pt;
|
char* bit_start = bit_pt;
|
||||||
|
|
||||||
@@ -361,7 +376,7 @@ static int decode_base62(const char* base62_str, char* bit_pt) {
|
|||||||
if (num6b == 0xee) return -1;
|
if (num6b == 0xee) return -1;
|
||||||
|
|
||||||
if (num6b < 61) {
|
if (num6b < 61) {
|
||||||
bit_pt = putnbits(6, num6b, bit_pt);
|
bit_pt = put6bits(num6b, bit_pt);
|
||||||
} else {
|
} else {
|
||||||
assert(num6b == 61);
|
assert(num6b == 61);
|
||||||
// 61 62 63 cases
|
// 61 62 63 cases
|
||||||
@@ -375,8 +390,8 @@ static int decode_base62(const char* base62_str, char* bit_pt) {
|
|||||||
num4b &= ~mask; // low bits
|
num4b &= ~mask; // low bits
|
||||||
assert(num2b != mask); // not both bits set
|
assert(num2b != mask); // not both bits set
|
||||||
|
|
||||||
bit_pt = putnbits(6, 61 + (num2b >> 4), bit_pt); // 61 + (0|1|2) in high bits
|
bit_pt = put6bits(61 + (num2b >> 4), bit_pt); // 61 + (0|1|2) in high bits
|
||||||
bit_pt = putnbits(4, num4b, bit_pt);
|
bit_pt = put4bits(num4b, bit_pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
num6b = char_to_num(*base62_str++);
|
num6b = char_to_num(*base62_str++);
|
||||||
@@ -510,13 +525,13 @@ static int cache_decode_set(const char* str, const unsigned** hash_pt) {
|
|||||||
// decode
|
// decode
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
int cnt = decode_set_size(str);
|
int cnt = decode_set_size(str);
|
||||||
ent = xmalloc(sizeof(*ent) + len + 1 + (cnt + SENTINELS) * sizeof(unsigned));
|
ent = malloc(sizeof(*ent) + len + 1 + (cnt + SENTINELS) * sizeof(unsigned));
|
||||||
ent->hash_arr = (unsigned*)(ent + 1);
|
ent->hash_arr = (unsigned*)(ent + 1);
|
||||||
ent->str = (char*)(ent->hash_arr + cnt + SENTINELS);
|
ent->str = (char*)(ent->hash_arr + cnt + SENTINELS);
|
||||||
|
|
||||||
cnt = ent->cnt = decode_set(str, ent->hash_arr);
|
cnt = ent->cnt = decode_set(str, ent->hash_arr);
|
||||||
if (cnt <= 0) {
|
if (cnt <= 0) {
|
||||||
_free(ent);
|
free(ent);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
#include "stdint.h"
|
|
||||||
#include "stdio.h"
|
|
||||||
#include "system.h"
|
|
||||||
|
|
||||||
struct set {
|
|
||||||
size_t cnt;
|
|
||||||
struct symbols {
|
|
||||||
const char* str;
|
|
||||||
uint64_t hash;
|
|
||||||
}* symbols_v;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct set* set_new() {
|
|
||||||
// should we use x___ funcs?
|
|
||||||
struct set* set = xmalloc(sizeof *set);
|
|
||||||
set->cnt = 0;
|
|
||||||
set->symbols_v = NULL;
|
|
||||||
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_add(struct set* set, const char* sym) {
|
|
||||||
const int delta = 1024;
|
|
||||||
|
|
||||||
if (set->cnt % delta == 0) {
|
|
||||||
set->symbols_v = xrealloc(set->symbols_v, sizeof(*set->symbols_v) * (set->cnt + delta));
|
|
||||||
}
|
|
||||||
|
|
||||||
set->symbols_v[set->cnt].str = xstrdup(sym);
|
|
||||||
set->symbols_v[set->cnt].hash = 0;
|
|
||||||
set->cnt++;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct set* set_free(struct set* set) {
|
|
||||||
if (set) {
|
|
||||||
for (size_t i = 0; i < set->cnt; ++i) {
|
|
||||||
_free((char*)set->symbols_v[i].str);
|
|
||||||
}
|
|
||||||
|
|
||||||
_free(set->symbols_v);
|
|
||||||
set = _free(set);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
uint64_t hash(const char* str) {
|
|
||||||
uint64_t h = 0xcbf29ce484222325ULL;
|
|
||||||
|
|
||||||
while (*str) {
|
|
||||||
h ^= (uint64_t)(unsigned char)(*str++);
|
|
||||||
h *= 0x100000001b3ULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmp(const void* arg1, const void* arg2) {
|
|
||||||
const struct symbols* s1 = (const struct symbols*)arg1;
|
|
||||||
const struct symbols* s2 = (const struct symbols*)arg2;
|
|
||||||
|
|
||||||
if (s1->hash > s2->hash) return 1;
|
|
||||||
if (s2->hash > s1->hash) return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* set_fini(struct set* set, int bpp) {
|
|
||||||
// Implementation for finalizing the set
|
|
||||||
|
|
||||||
assert(set != NULL);
|
|
||||||
assert(set->cnt > 0);
|
|
||||||
assert(bpp >= 10 && bpp <= 63);
|
|
||||||
|
|
||||||
uint64_t mask = (1ULL << bpp) - 1;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < set->cnt; ++i) {
|
|
||||||
set->symbols_v[i].hash = hash(set->symbols_v[i].str) & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(set->symbols_v, set->cnt, sizeof *set->symbols_v, cmp);
|
|
||||||
|
|
||||||
// warn on hash collizions
|
|
||||||
for (size_t i = 0; i < set->cnt - 1; ++i) {
|
|
||||||
if (set->symbols_v[i].hash != set->symbols_v[i + 1].hash) continue;
|
|
||||||
if (!strcmp(set->symbols_v[i].str, set->symbols_v[i + 1].str)) continue;
|
|
||||||
|
|
||||||
fprintf(stderr, "warning: hash collision: %s %s\n", set->symbols_v[i].str,
|
|
||||||
set->symbols_v[i + 1].str);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t unique_hash[set->cnt];
|
|
||||||
size_t unique_cnt = 0;
|
|
||||||
|
|
||||||
// delete duplicates
|
|
||||||
for (size_t i = 0; i < set->cnt; ++i) {
|
|
||||||
while (i + 1 < set->cnt && set->symbols_v[i].hash == set->symbols_v[i + 1].hash) {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
unique_hash[unique_cnt++] = set->symbols_v[i].hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user