blob: optimize digit and base64 decoding
parent
ac1a8ac712
commit
4aa80564f9
151
src/blob.c
151
src/blob.c
|
@ -159,15 +159,44 @@ int apk_blob_for_each_segment(apk_blob_t blob, const char *split,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dx(int c)
|
static unsigned char digitdecode[] = {
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
|
||||||
|
0xff, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int dx(unsigned char c)
|
||||||
{
|
{
|
||||||
if (likely(c >= '0' && c <= '9'))
|
return digitdecode[c];
|
||||||
return c - '0';
|
|
||||||
if (likely(c >= 'a' && c <= 'f'))
|
|
||||||
return c - 'a' + 0xa;
|
|
||||||
if (c >= 'A' && c <= 'F')
|
|
||||||
return c - 'A' + 0xa;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal)
|
void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal)
|
||||||
|
@ -298,7 +327,7 @@ unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix)
|
||||||
val = 0;
|
val = 0;
|
||||||
while (b->len && b->ptr[0] != 0) {
|
while (b->len && b->ptr[0] != 0) {
|
||||||
ch = dx(b->ptr[0]);
|
ch = dx(b->ptr[0]);
|
||||||
if (ch < 0 || ch >= radix)
|
if (ch >= radix)
|
||||||
break;
|
break;
|
||||||
val *= radix;
|
val *= radix;
|
||||||
val += ch;
|
val += ch;
|
||||||
|
@ -322,7 +351,7 @@ void apk_blob_pull_csum(apk_blob_t *b, struct apk_checksum *csum)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dx(b->ptr[0]) != -1) {
|
if (dx(b->ptr[0]) != 0xff) {
|
||||||
/* Assume MD5 for backwards compatibility */
|
/* Assume MD5 for backwards compatibility */
|
||||||
csum->type = APK_CHECKSUM_MD5;
|
csum->type = APK_CHECKSUM_MD5;
|
||||||
apk_blob_pull_hexdump(b, APK_BLOB_CSUM(*csum));
|
apk_blob_pull_hexdump(b, APK_BLOB_CSUM(*csum));
|
||||||
|
@ -357,7 +386,7 @@ void apk_blob_pull_csum(apk_blob_t *b, struct apk_checksum *csum)
|
||||||
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to)
|
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to)
|
||||||
{
|
{
|
||||||
char *s, *d;
|
char *s, *d;
|
||||||
int i, r1, r2;
|
int i, r, r1, r2;
|
||||||
|
|
||||||
if (unlikely(APK_BLOB_IS_NULL(*b)))
|
if (unlikely(APK_BLOB_IS_NULL(*b)))
|
||||||
return;
|
return;
|
||||||
|
@ -365,15 +394,14 @@ void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to)
|
||||||
if (unlikely(to.len > b->len * 2))
|
if (unlikely(to.len > b->len * 2))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
r = 0;
|
||||||
for (i = 0, s = b->ptr, d = to.ptr; i < to.len; i++) {
|
for (i = 0, s = b->ptr, d = to.ptr; i < to.len; i++) {
|
||||||
r1 = dx(*(s++));
|
r |= r1 = dx(*(s++));
|
||||||
if (unlikely(r1 < 0))
|
r |= r2 = dx(*(s++));
|
||||||
goto err;
|
|
||||||
r2 = dx(*(s++));
|
|
||||||
if (unlikely(r2 < 0))
|
|
||||||
goto err;
|
|
||||||
*(d++) = (r1 << 4) + r2;
|
*(d++) = (r1 << 4) + r2;
|
||||||
}
|
}
|
||||||
|
if (unlikely(r == 0xff))
|
||||||
|
goto err;
|
||||||
b->ptr = s;
|
b->ptr = s;
|
||||||
b->len -= to.len * 2;
|
b->len -= to.len * 2;
|
||||||
return;
|
return;
|
||||||
|
@ -382,31 +410,53 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char b64decode[] = {
|
static unsigned char b64decode[] = {
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
|
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||||
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0x3c, 0x3d, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
|
||||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
|
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||||
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||||
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
|
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||||
|
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||||
|
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||||
|
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int pull_b64_chunk(unsigned char *to, const unsigned char *from, int len)
|
static inline __attribute__((always_inline))
|
||||||
|
int pull_b64_chunk(unsigned char *to, const unsigned char *from, int len)
|
||||||
{
|
{
|
||||||
unsigned char tmp[4];
|
unsigned char tmp[4];
|
||||||
int i;
|
int i, r = 0;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (unlikely(from[i] >= 0x80))
|
|
||||||
return -1;
|
|
||||||
tmp[i] = b64decode[from[i]];
|
tmp[i] = b64decode[from[i]];
|
||||||
if (unlikely(tmp[i] == 0xff))
|
r |= tmp[i];
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
if (unlikely(r == 0xff))
|
||||||
|
return -1;
|
||||||
|
|
||||||
to[0] = (tmp[0] << 2 | tmp[1] >> 4);
|
to[0] = (tmp[0] << 2 | tmp[1] >> 4);
|
||||||
if (len > 1)
|
if (len > 1)
|
||||||
|
@ -422,9 +472,10 @@ static inline int pull_b64_chunk(unsigned char *to, const unsigned char *from, i
|
||||||
|
|
||||||
void apk_blob_pull_base64(apk_blob_t *b, apk_blob_t to)
|
void apk_blob_pull_base64(apk_blob_t *b, apk_blob_t to)
|
||||||
{
|
{
|
||||||
|
unsigned char tmp[4];
|
||||||
unsigned char *src = (unsigned char *) b->ptr;
|
unsigned char *src = (unsigned char *) b->ptr;
|
||||||
unsigned char *dst = (unsigned char *) to.ptr;
|
unsigned char *dst = (unsigned char *) to.ptr;
|
||||||
int i, needed;
|
int i, r, needed;
|
||||||
|
|
||||||
if (unlikely(APK_BLOB_IS_NULL(*b)))
|
if (unlikely(APK_BLOB_IS_NULL(*b)))
|
||||||
return;
|
return;
|
||||||
|
@ -435,11 +486,29 @@ void apk_blob_pull_base64(apk_blob_t *b, apk_blob_t to)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < to.len / 3; i++, src += 4, dst += 3)
|
r = 0;
|
||||||
pull_b64_chunk(dst, src, 4);
|
for (i = 0; i < to.len / 3; i++, src += 4, dst += 3) {
|
||||||
|
r |= tmp[0] = b64decode[src[0]];
|
||||||
|
r |= tmp[1] = b64decode[src[1]];
|
||||||
|
r |= tmp[2] = b64decode[src[2]];
|
||||||
|
r |= tmp[3] = b64decode[src[3]];
|
||||||
|
dst[0] = (tmp[0] << 2 | tmp[1] >> 4);
|
||||||
|
dst[1] = (tmp[1] << 4 | tmp[2] >> 2);
|
||||||
|
dst[2] = (((tmp[2] << 6) & 0xc0) | tmp[3]);
|
||||||
|
}
|
||||||
|
if (unlikely(r == 0xff)) {
|
||||||
|
*b = APK_BLOB_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
i = to.len % 3;
|
i = to.len % 3;
|
||||||
if (i != 0)
|
if (i != 0) {
|
||||||
pull_b64_chunk(dst, src, i);
|
if (pull_b64_chunk(dst, src, i) != 0) {
|
||||||
|
*b = APK_BLOB_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b->ptr += needed;
|
b->ptr += needed;
|
||||||
b->len -= needed;
|
b->len -= needed;
|
||||||
}
|
}
|
||||||
|
@ -461,7 +530,7 @@ static apk_blob_t null_blob = {0,0};
|
||||||
|
|
||||||
void apk_atom_init(void)
|
void apk_atom_init(void)
|
||||||
{
|
{
|
||||||
apk_hash_init(&atom_hash, &atom_ops, 2048);
|
apk_hash_init(&atom_hash, &atom_ops, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
apk_blob_t *apk_blob_atomize(apk_blob_t blob)
|
apk_blob_t *apk_blob_atomize(apk_blob_t blob)
|
||||||
|
|
Loading…
Reference in New Issue