/*
* Copyright (c) 2007, Novell Inc.
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
*/
/* pack/unpack functions for key data */
#ifndef LIBSOLV_REPOPACK_H
#define LIBSOLV_REPOPACK_H
static inline unsigned char *
data_read_id(unsigned char *dp, Id *idp)
{
Id x;
unsigned char c;
if (!(dp[0] & 0x80))
{
*idp = dp[0];
return dp + 1;
}
if (!(dp[1] & 0x80))
{
*idp = dp[0] << 7 ^ dp[1] ^ 0x4000;
return dp + 2;
}
if (!(dp[2] & 0x80))
{
*idp = dp[0] << 14 ^ dp[1] << 7 ^ dp[2] ^ 0x204000;
return dp + 3;
}
if (!(dp[3] & 0x80))
{
*idp = dp[0] << 21 ^ dp[1] << 14 ^ dp[2] << 7 ^ dp[3] ^ 0x10204000;
return dp + 4;
}
x = dp[0] << 28 ^ dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204000;
if (!(dp[4] & 0x80))
{
*idp = x;
return dp + 5;
}
x ^= 80;
dp += 5;
for (;;)
{
c = *dp++;
if (!(c & 0x80))
{
*idp = (x << 7) ^ c;
return dp;
}
x = (x << 7) ^ (c ^ 128);
}
}
static inline unsigned char *
data_read_num64(unsigned char *dp, unsigned int *low, unsigned int *high)
{
unsigned long long int x;
unsigned char c;
*high = 0;
if (!(dp[0] & 0x80))
{
*low = dp[0];
return dp + 1;
}
if (!(dp[1] & 0x80))
{
*low = dp[0] << 7 ^ dp[1] ^ 0x4000;
return dp + 2;
}
if (!(dp[2] & 0x80))
{
*low = dp[0] << 14 ^ dp[1] << 7 ^ dp[2] ^ 0x204000;
return dp + 3;
}
if (!(dp[3] & 0x80))
{
*low = dp[0] << 21 ^ dp[1] << 14 ^ dp[2] << 7 ^ dp[3] ^ 0x10204000;
return dp + 4;
}
if (!(dp[4] & 0x80))
{
*low = dp[0] << 28 ^ dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204000;
*high = (dp[0] ^ 0x80) >> 4;
return dp + 5;
}
x = (unsigned long long)(dp[0] ^ 0x80) << 28 ^ (unsigned int)(dp[1] << 21 ^ dp[2] << 14 ^ dp[3] << 7 ^ dp[4] ^ 0x10204080);
dp += 5;
for (;;)
{
c = *dp++;
if (!(c & 0x80))
{
x = (x << 7) ^ c;
*low = x;
*high = x >> 32;
return dp;
}
x = (x << 7) ^ (c ^ 128);
}
}
static inline unsigned char *
data_read_ideof(unsigned char *dp, Id *idp, int *eof)
{
Id x = 0;
unsigned char c;
for (;;)
{
c = *dp++;
if (!(c & 0x80))
{
if (c & 0x40)
{
c ^= 0x40;
*eof = 0;
}
else
*eof = 1;
*idp = (x << 6) ^ c;
return dp;
}
x = (x << 7) ^ c ^ 128;
}
}
static inline unsigned char *
data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
{
kv->eof = 1;
if (!dp)
return 0;
switch (key->type)
{
case REPOKEY_TYPE_VOID:
case REPOKEY_TYPE_DELETED:
return dp;
case REPOKEY_TYPE_CONSTANT:
kv->num2 = 0;
kv->num = key->size;
return dp;
case REPOKEY_TYPE_CONSTANTID:
kv->id = key->size;
return dp;
case REPOKEY_TYPE_STR:
kv->str = (const char *)dp;
return dp + strlen(kv->str) + 1;
case REPOKEY_TYPE_ID:
case REPOKEY_TYPE_DIR:
return data_read_id(dp, &kv->id);
case REPOKEY_TYPE_NUM:
return data_read_num64(dp, &kv->num, &kv->num2);
case REPOKEY_TYPE_MD5:
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + SIZEOF_MD5;
case REPOKEY_TYPE_SHA1:
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + SIZEOF_SHA1;
case REPOKEY_TYPE_SHA224:
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + SIZEOF_SHA224;
case REPOKEY_TYPE_SHA256:
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + SIZEOF_SHA256;
case REPOKEY_TYPE_SHA384:
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + SIZEOF_SHA384;
case REPOKEY_TYPE_SHA512:
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + SIZEOF_SHA512;
case REPOKEY_TYPE_BINARY:
dp = data_read_id(dp, (Id *)&kv->num);
kv->str = (const char *)dp;
return dp + kv->num;
case REPOKEY_TYPE_IDARRAY:
return data_read_ideof(dp, &kv->id, &kv->eof);
case REPOKEY_TYPE_DIRSTRARRAY:
dp = data_read_ideof(dp, &kv->id, &kv->eof);
kv->num = 0; /* not stringified yet */
kv->str = (const char *)dp;
return dp + strlen(kv->str) + 1;
case REPOKEY_TYPE_DIRNUMNUMARRAY:
dp = data_read_id(dp, &kv->id);
dp = data_read_id(dp, (Id *)&kv->num);
return data_read_ideof(dp, (Id *)&kv->num2, &kv->eof);
case REPOKEY_TYPE_FIXARRAY:
case REPOKEY_TYPE_FLEXARRAY:
if (!kv->entry)
{
dp = data_read_id(dp, (Id *)&kv->num); /* number of elements */
if (!kv->num)
return 0; /* illegal */
}
if (!kv->entry || key->type == REPOKEY_TYPE_FLEXARRAY)
dp = data_read_id(dp, &kv->id); /* schema */
kv->str = (const char *)dp;
return dp;
default:
return 0;
}
}
static inline unsigned char *
data_skip(unsigned char *dp, int type)
{
unsigned char x;
switch (type)
{
case REPOKEY_TYPE_VOID:
case REPOKEY_TYPE_CONSTANT:
case REPOKEY_TYPE_CONSTANTID:
case REPOKEY_TYPE_DELETED:
return dp;
case REPOKEY_TYPE_ID:
case REPOKEY_TYPE_NUM:
case REPOKEY_TYPE_DIR:
while ((*dp & 0x80) != 0)
dp++;
return dp + 1;
case REPOKEY_TYPE_MD5:
return dp + SIZEOF_MD5;
case REPOKEY_TYPE_SHA1:
return dp + SIZEOF_SHA1;
case REPOKEY_TYPE_SHA224:
return dp + SIZEOF_SHA224;
case REPOKEY_TYPE_SHA256:
return dp + SIZEOF_SHA256;
case REPOKEY_TYPE_SHA384:
return dp + SIZEOF_SHA384;
case REPOKEY_TYPE_SHA512:
return dp + SIZEOF_SHA512;
case REPOKEY_TYPE_IDARRAY:
case REPOKEY_TYPE_REL_IDARRAY:
while ((*dp & 0xc0) != 0)
dp++;
return dp + 1;
case REPOKEY_TYPE_STR:
while ((*dp) != 0)
dp++;
return dp + 1;
case REPOKEY_TYPE_BINARY:
{
unsigned int len;
dp = data_read_id(dp, (Id *)&len);
return dp + len;
}
case REPOKEY_TYPE_DIRSTRARRAY:
for (;;)
{
while ((*dp & 0x80) != 0)
dp++;
x = *dp++;
while ((*dp) != 0)
dp++;
dp++;
if (!(x & 0x40))
return dp;
}
case REPOKEY_TYPE_DIRNUMNUMARRAY:
for (;;)
{
while ((*dp & 0x80) != 0)
dp++;
dp++;
while ((*dp & 0x80) != 0)
dp++;
dp++;
while ((*dp & 0x80) != 0)
dp++;
if (!(*dp & 0x40))
return dp + 1;
dp++;
}
default:
return 0;
}
}
#endif /* LIBSOLV_REPOPACK */