Commit 8d1eeb58 authored by Timo Teräs's avatar Timo Teräs

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.
parent ab37bd0b
......@@ -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 {
......
......@@ -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)
{
unsigned int val;
int ch;
val = 0;
while (blob->len && blob->ptr[0] != 0) {
ch = dx(blob->ptr[0]);
if (ch < 0 || ch >= base)
break;
val *= base;
val += ch;
if (APK_BLOB_IS_NULL(*to))
return;
blob->ptr++;
blob->len--;
if (to->len < literal.len) {
*to = APK_BLOB_NULL;
return;
}
return val;
memcpy(to->ptr, literal.ptr, literal.len);
to->ptr += literal.len;
to->len -= literal.len;
}
int apk_blob_parse_char(apk_blob_t *blob)
static const char *xd = "0123456789abcdefghijklmnopqrstuvwxyz";
void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix)
{
int r;
char buf[64];
char *ptr = &buf[sizeof(buf)-1];
if (blob->len == 0 || blob->ptr == NULL)
return -1;
r = blob->ptr[0];
blob->ptr++;
blob->len--;
if (value == 0) {
apk_blob_push_blob(to, APK_BLOB_STR("0"));
return;
}
while (value != 0) {
*(ptr--) = xd[value % radix];
value /= radix;
}
return r;
apk_blob_push_blob(to, APK_BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1]));
}
int apk_hexdump_parse(apk_blob_t to, apk_blob_t from)
void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary)
{
char *d;
int i;
if (to.len * 2 != from.len)
return -1;
if (APK_BLOB_IS_NULL(*to))
return;
for (i = 0; i < from.len / 2; i++)
to.ptr[i] = (dx(from.ptr[i*2]) << 4) + dx(from.ptr[i*2+1]);
if (to->len < binary.len * 2) {
*to = APK_BLOB_NULL;
return;
}
return 0;
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;
}
int apk_hexdump_format(int tolen, char *to, apk_blob_t from)
void apk_blob_pull_char(apk_blob_t *b, int expected)
{
static const char *xd = "0123456789abcdef";
int i;
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 (b->len && b->ptr[0] != 0) {
ch = dx(b->ptr[0]);
if (ch < 0 || ch >= radix)
break;
val *= radix;
val += ch;
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];
b->ptr++;
b->len--;
}
to[i*2] = 0;
return i*2;
return val;
}
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to)
{
char *s, *d;
int i, r1, r2;
if (APK_BLOB_IS_NULL(*b))
return;
if (to.len > b->len * 2)
goto err;
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;
}
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;
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_t bbuf = APK_BLOB_BUF(buf);
int r;
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment