blob: some helpers to replace snprintf
snprintf is dog slow. make the blob stuff have some helper functions so we can use them in code paths that are executed often.cute-signatures
parent
ab37bd0b0c
commit
8d1eeb58e4
|
@ -44,13 +44,15 @@ int apk_blob_rsplit(apk_blob_t blob, char split, apk_blob_t *l, apk_blob_t *r);
|
|||
unsigned long apk_blob_hash_seed(apk_blob_t, unsigned long seed);
|
||||
unsigned long apk_blob_hash(apk_blob_t str);
|
||||
int apk_blob_compare(apk_blob_t a, apk_blob_t b);
|
||||
unsigned int apk_blob_parse_uint(apk_blob_t *b, int radix);
|
||||
int apk_blob_parse_char(apk_blob_t *b);
|
||||
|
||||
int apk_blob_for_each_segment(apk_blob_t blob, const char *split,
|
||||
apk_blob_cb cb, void *ctx);
|
||||
|
||||
int apk_hexdump_parse(apk_blob_t to, apk_blob_t from);
|
||||
int apk_hexdump_format(int tolen, char *to, apk_blob_t from);
|
||||
void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal);
|
||||
void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix);
|
||||
void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary);
|
||||
|
||||
void apk_blob_pull_char(apk_blob_t *b, int expected);
|
||||
unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix);
|
||||
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,7 @@ struct tar_header {
|
|||
static int get_octal(char *s, size_t l)
|
||||
{
|
||||
apk_blob_t b = APK_BLOB_PTR_LEN(s, l);
|
||||
return apk_blob_parse_uint(&b, 8);
|
||||
return apk_blob_pull_uint(&b, 8);
|
||||
}
|
||||
|
||||
struct apk_tar_entry_istream {
|
||||
|
|
135
src/blob.c
135
src/blob.c
|
@ -151,62 +151,117 @@ static inline int dx(int c)
|
|||
return -1;
|
||||
}
|
||||
|
||||
unsigned int apk_blob_parse_uint(apk_blob_t *blob, int base)
|
||||
void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal)
|
||||
{
|
||||
if (APK_BLOB_IS_NULL(*to))
|
||||
return;
|
||||
|
||||
if (to->len < literal.len) {
|
||||
*to = APK_BLOB_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(to->ptr, literal.ptr, literal.len);
|
||||
to->ptr += literal.len;
|
||||
to->len -= literal.len;
|
||||
}
|
||||
|
||||
static const char *xd = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix)
|
||||
{
|
||||
char buf[64];
|
||||
char *ptr = &buf[sizeof(buf)-1];
|
||||
|
||||
if (value == 0) {
|
||||
apk_blob_push_blob(to, APK_BLOB_STR("0"));
|
||||
return;
|
||||
}
|
||||
|
||||
while (value != 0) {
|
||||
*(ptr--) = xd[value % radix];
|
||||
value /= radix;
|
||||
}
|
||||
|
||||
apk_blob_push_blob(to, APK_BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1]));
|
||||
}
|
||||
|
||||
void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary)
|
||||
{
|
||||
char *d;
|
||||
int i;
|
||||
|
||||
if (APK_BLOB_IS_NULL(*to))
|
||||
return;
|
||||
|
||||
if (to->len < binary.len * 2) {
|
||||
*to = APK_BLOB_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, d = to->ptr; i < binary.len; i++) {
|
||||
*(d++) = xd[(binary.ptr[i] >> 4) & 0xf];
|
||||
*(d++) = xd[binary.ptr[i] & 0xf];
|
||||
}
|
||||
to->ptr = d;
|
||||
to->len -= binary.len * 2;
|
||||
}
|
||||
|
||||
void apk_blob_pull_char(apk_blob_t *b, int expected)
|
||||
{
|
||||
if (APK_BLOB_IS_NULL(*b))
|
||||
return;
|
||||
if (b->len < 1 || b->ptr[0] != expected) {
|
||||
*b = APK_BLOB_NULL;
|
||||
return;
|
||||
}
|
||||
b->ptr ++;
|
||||
b->len --;
|
||||
}
|
||||
|
||||
unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix)
|
||||
{
|
||||
unsigned int val;
|
||||
int ch;
|
||||
|
||||
val = 0;
|
||||
while (blob->len && blob->ptr[0] != 0) {
|
||||
ch = dx(blob->ptr[0]);
|
||||
if (ch < 0 || ch >= base)
|
||||
while (b->len && b->ptr[0] != 0) {
|
||||
ch = dx(b->ptr[0]);
|
||||
if (ch < 0 || ch >= radix)
|
||||
break;
|
||||
val *= base;
|
||||
val *= radix;
|
||||
val += ch;
|
||||
|
||||
blob->ptr++;
|
||||
blob->len--;
|
||||
b->ptr++;
|
||||
b->len--;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int apk_blob_parse_char(apk_blob_t *blob)
|
||||
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to)
|
||||
{
|
||||
int r;
|
||||
char *s, *d;
|
||||
int i, r1, r2;
|
||||
|
||||
if (blob->len == 0 || blob->ptr == NULL)
|
||||
return -1;
|
||||
r = blob->ptr[0];
|
||||
blob->ptr++;
|
||||
blob->len--;
|
||||
if (APK_BLOB_IS_NULL(*b))
|
||||
return;
|
||||
|
||||
return r;
|
||||
}
|
||||
if (to.len > b->len * 2)
|
||||
goto err;
|
||||
|
||||
int apk_hexdump_parse(apk_blob_t to, apk_blob_t from)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (to.len * 2 != from.len)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < from.len / 2; i++)
|
||||
to.ptr[i] = (dx(from.ptr[i*2]) << 4) + dx(from.ptr[i*2+1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apk_hexdump_format(int tolen, char *to, apk_blob_t from)
|
||||
{
|
||||
static const char *xd = "0123456789abcdef";
|
||||
int i;
|
||||
|
||||
for (i = 0; i < from.len && i*2+2 < tolen; i++) {
|
||||
to[i*2+0] = xd[(from.ptr[i] >> 4) & 0xf];
|
||||
to[i*2+1] = xd[from.ptr[i] & 0xf];
|
||||
for (i = 0, s = b->ptr, d = to.ptr; i < to.len; i++) {
|
||||
r1 = dx(*(s++));
|
||||
if (r1 < 0)
|
||||
goto err;
|
||||
r2 = dx(*(s++));
|
||||
if (r2 < 0)
|
||||
goto err;
|
||||
*(d++) = (r1 << 4) + r2;
|
||||
}
|
||||
to[i*2] = 0;
|
||||
|
||||
return i*2;
|
||||
b->ptr = s;
|
||||
b->len -= to.len * 2;
|
||||
return;
|
||||
err:
|
||||
*b = APK_BLOB_NULL;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ static int cache_clean(struct apk_database *db)
|
|||
struct apk_package *pkg;
|
||||
char path[256];
|
||||
int delete, i;
|
||||
apk_blob_t b;
|
||||
csum_t csum;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", db->root, db->cache_dir);
|
||||
|
@ -88,9 +89,9 @@ static int cache_clean(struct apk_database *db)
|
|||
do {
|
||||
if (strlen(de->d_name) <= sizeof(csum_t)*2+2)
|
||||
break;
|
||||
if (apk_hexdump_parse(APK_BLOB_BUF(csum),
|
||||
APK_BLOB_PTR_LEN(de->d_name,
|
||||
sizeof(csum_t) * 2)) != 0)
|
||||
b = APK_BLOB_PTR_LEN(de->d_name, sizeof(csum_t) * 2);
|
||||
apk_blob_pull_hexdump(&b, APK_BLOB_BUF(csum));
|
||||
if (APK_BLOB_IS_NULL(b))
|
||||
break;
|
||||
if (de->d_name[sizeof(csum_t)*2] != '.')
|
||||
break;
|
||||
|
|
|
@ -454,13 +454,11 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
|
|||
apk_error("FDB directory metadata entry before directory entry");
|
||||
return -1;
|
||||
}
|
||||
diri->uid = apk_blob_parse_uint(&l, 10);
|
||||
if (apk_blob_parse_char(&l) != ':')
|
||||
goto bad_mode;
|
||||
diri->gid = apk_blob_parse_uint(&l, 10);
|
||||
if (apk_blob_parse_char(&l) != ':')
|
||||
goto bad_mode;
|
||||
diri->mode = apk_blob_parse_uint(&l, 8);
|
||||
diri->uid = apk_blob_pull_uint(&l, 10);
|
||||
apk_blob_pull_char(&l, ':');
|
||||
diri->gid = apk_blob_pull_uint(&l, 10);
|
||||
apk_blob_pull_char(&l, ':');
|
||||
diri->mode = apk_blob_pull_uint(&l, 8);
|
||||
break;
|
||||
case 'R':
|
||||
if (diri == NULL) {
|
||||
|
@ -475,21 +473,20 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
|
|||
apk_error("FDB checksum entry before file entry");
|
||||
return -1;
|
||||
}
|
||||
if (apk_hexdump_parse(APK_BLOB_BUF(file->csum), l)) {
|
||||
apk_error("Not a valid checksum");
|
||||
return -1;
|
||||
}
|
||||
|
||||
apk_blob_pull_hexdump(&l, APK_BLOB_BUF(file->csum));
|
||||
break;
|
||||
default:
|
||||
apk_error("FDB entry '%c' unsupported", field);
|
||||
return -1;
|
||||
}
|
||||
if (APK_BLOB_IS_NULL(l)) {
|
||||
apk_error("FDB format error in entry '%c'", field);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
bad_mode:
|
||||
apk_error("FDB bad directory mode entry");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
|
||||
|
@ -499,7 +496,8 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
|
|||
struct apk_db_file *file;
|
||||
struct hlist_node *c1, *c2;
|
||||
char buf[1024];
|
||||
int n = 0, r;
|
||||
apk_blob_t bbuf = APK_BLOB_BUF(buf);
|
||||
int r;
|
||||
|
||||
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
|
||||
r = apk_pkg_write_index_entry(pkg, os);
|
||||
|
@ -507,30 +505,32 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
|
|||
return r;
|
||||
|
||||
hlist_for_each_entry(diri, c1, &pkg->owned_dirs, pkg_dirs_list) {
|
||||
n += snprintf(&buf[n], sizeof(buf)-n,
|
||||
"F:%s\n"
|
||||
"M:%d:%d:%o\n",
|
||||
diri->dir->name,
|
||||
diri->uid, diri->gid, diri->mode);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nM:"));
|
||||
apk_blob_push_uint(&bbuf, diri->uid, 10);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(":"));
|
||||
apk_blob_push_uint(&bbuf, diri->gid, 10);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(":"));
|
||||
apk_blob_push_uint(&bbuf, diri->mode, 8);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
|
||||
|
||||
hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) {
|
||||
n += snprintf(&buf[n], sizeof(buf)-n,
|
||||
"R:%s\n",
|
||||
file->name);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen));
|
||||
if (csum_valid(file->csum)) {
|
||||
n += snprintf(&buf[n], sizeof(buf)-n, "Z:");
|
||||
n += apk_hexdump_format(sizeof(buf)-n, &buf[n],
|
||||
APK_BLOB_BUF(file->csum));
|
||||
n += snprintf(&buf[n], sizeof(buf)-n, "\n");
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nZ:"));
|
||||
apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(file->csum));
|
||||
}
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
|
||||
|
||||
if (os->write(os, buf, n) != n)
|
||||
if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf)
|
||||
return -1;
|
||||
n = 0;
|
||||
bbuf = APK_BLOB_BUF(buf);
|
||||
}
|
||||
if (n != 0 && os->write(os, buf, n) != n)
|
||||
if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf)
|
||||
return -1;
|
||||
n = 0;
|
||||
bbuf = APK_BLOB_BUF(buf);
|
||||
}
|
||||
os->write(os, "\n", 1);
|
||||
}
|
||||
|
@ -943,9 +943,12 @@ static void apk_db_cache_get_name(char *buf, size_t bufsz,
|
|||
const char *file, int temp)
|
||||
{
|
||||
char csumstr[sizeof(csum_t)*2+1];
|
||||
apk_blob_t bbuf = APK_BLOB_BUF(csumstr);
|
||||
|
||||
apk_blob_push_hexdump(&bbuf,
|
||||
APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t)));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(""));
|
||||
|
||||
apk_hexdump_format(sizeof(csumstr), csumstr,
|
||||
APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t)));
|
||||
snprintf(buf, bufsz, "%s/%s/%s.%s%s",
|
||||
db->root, db->cache_dir, csumstr, file, temp ? ".new" : "");
|
||||
}
|
||||
|
|
|
@ -290,17 +290,19 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
|
|||
apk_deps_parse(db, &pkg->depends, value);
|
||||
break;
|
||||
case 'C':
|
||||
apk_hexdump_parse(APK_BLOB_BUF(pkg->csum), value);
|
||||
apk_blob_pull_hexdump(&value, APK_BLOB_BUF(pkg->csum));
|
||||
break;
|
||||
case 'S':
|
||||
pkg->size = apk_blob_parse_uint(&value, 10);
|
||||
pkg->size = apk_blob_pull_uint(&value, 10);
|
||||
break;
|
||||
case 'I':
|
||||
pkg->installed_size = apk_blob_parse_uint(&value, 10);
|
||||
pkg->installed_size = apk_blob_pull_uint(&value, 10);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (APK_BLOB_IS_NULL(value))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -643,22 +645,29 @@ int apk_pkg_write_index_entry(struct apk_package *info,
|
|||
struct apk_ostream *os)
|
||||
{
|
||||
char buf[512];
|
||||
int n, r, t = 0;
|
||||
apk_blob_t bbuf = APK_BLOB_BUF(buf);
|
||||
int r;
|
||||
|
||||
n = snprintf(buf, sizeof(buf),
|
||||
"P:%s\n"
|
||||
"V:%s\n"
|
||||
"S:%zu\n"
|
||||
"I:%zu\n"
|
||||
"T:%s\n"
|
||||
"U:%s\n"
|
||||
"L:%s\n",
|
||||
info->name->name, info->version,
|
||||
info->size, info->installed_size,
|
||||
info->description, info->url, info->license);
|
||||
if (os->write(os, buf, n) != n)
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("C:"));
|
||||
apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(info->csum));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nP:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->name->name));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nV:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->version));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nS:"));
|
||||
apk_blob_push_uint(&bbuf, info->size, 10);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nI:"));
|
||||
apk_blob_push_uint(&bbuf, info->installed_size, 10);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nT:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->description));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nU:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->url));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nL:"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->license));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
|
||||
|
||||
if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf)
|
||||
return -1;
|
||||
t += n;
|
||||
|
||||
if (info->depends != NULL) {
|
||||
if (os->write(os, "D:", 2) != 2)
|
||||
|
@ -668,18 +677,9 @@ int apk_pkg_write_index_entry(struct apk_package *info,
|
|||
return r;
|
||||
if (os->write(os, "\n", 1) != 1)
|
||||
return -1;
|
||||
t += r + 3;
|
||||
}
|
||||
|
||||
n = snprintf(buf, sizeof(buf), "C:");
|
||||
n += apk_hexdump_format(sizeof(buf)-n, &buf[n], APK_BLOB_BUF(info->csum));
|
||||
n += snprintf(&buf[n], sizeof(buf)-n, "\n");
|
||||
|
||||
if (os->write(os, buf, n) != n)
|
||||
return -1;
|
||||
t += n;
|
||||
|
||||
return n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b)
|
||||
|
|
Loading…
Reference in New Issue