windows-nt/Source/XPSP1/NT/enduser/msasn1/bit.c
2020-09-26 16:20:57 +08:00

422 lines
11 KiB
C

/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
static const ASN1uint8_t
c_aBitMask[] = {
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
};
static const ASN1uint8_t
c_aBitMask2[] = {
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
};
static const ASN1uint8_t
c_aBitMask4[] = {
0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00
};
static const ASN1int32_t
c_aBitMask5[] = {
(ASN1int32_t)0xffffffff, (ASN1int32_t)0xfffffffe,
(ASN1int32_t)0xfffffffc, (ASN1int32_t)0xfffffff8,
(ASN1int32_t)0xfffffff0, (ASN1int32_t)0xffffffe0,
(ASN1int32_t)0xffffffc0, (ASN1int32_t)0xffffff80,
(ASN1int32_t)0xffffff00, (ASN1int32_t)0xfffffe00,
(ASN1int32_t)0xfffffc00, (ASN1int32_t)0xfffff800,
(ASN1int32_t)0xfffff000, (ASN1int32_t)0xffffe000,
(ASN1int32_t)0xffffc000, (ASN1int32_t)0xffff8000,
(ASN1int32_t)0xffff0000, (ASN1int32_t)0xfffe0000,
(ASN1int32_t)0xfffc0000, (ASN1int32_t)0xfff80000,
(ASN1int32_t)0xfff00000, (ASN1int32_t)0xffe00000,
(ASN1int32_t)0xffc00000, (ASN1int32_t)0xff800000,
(ASN1int32_t)0xff000000, (ASN1int32_t)0xfe000000,
(ASN1int32_t)0xfc000000, (ASN1int32_t)0xf8000000,
(ASN1int32_t)0xf0000000, (ASN1int32_t)0xe0000000,
(ASN1int32_t)0xc0000000, (ASN1int32_t)0x80000000,
(ASN1int32_t)0x00000000
};
static const ASN1uint8_t
c_aBitCount[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
/* copy nbits bits from src/srcbit into dst/dstbit;
src points to first octet containing bits to be copied
srcbit names the first bit within the first octet to be copied (0=msb, 7=lsb)
dst points to first octet to copy into
dstbit names the first bit within the first octet to copy into (0=msb, 7=lsb)
nbits is the number of bits to copy;
assumes that bits of broken octet at dst/dstbit are cleared;
bits of last octet behind dst/dstbit+nbits-1 will be cleared
*/
void ASN1bitcpy(ASN1octet_t *dst, ASN1uint32_t dstbit, ASN1octet_t *src, ASN1uint32_t srcbit, ASN1uint32_t nbits)
{
ASN1uint32_t xsrcbit, xdstbit;
if (!nbits)
return;
if (dstbit >= 8) {
dst += dstbit / 8;
dstbit &= 7;
}
if (srcbit >= 8) {
src += srcbit / 8;
srcbit &= 7;
}
/* check if we have to fill broken first octet */
if (dstbit) {
xdstbit = 8 - dstbit;
/* enough bits to fill up broken octet? */
if (nbits >= xdstbit) {
if (srcbit < dstbit) {
*dst++ |= (*src >> (dstbit - srcbit)) & c_aBitMask[xdstbit];
nbits -= xdstbit;
srcbit += xdstbit;
dstbit = 0;
} else if (srcbit == dstbit) {
*dst++ |= *src++ & c_aBitMask[xdstbit];
nbits -= xdstbit;
srcbit = 0;
dstbit = 0;
} else {
*dst++ |= ((*src & c_aBitMask[8 - srcbit]) << (srcbit - dstbit)) |
(src[1] >> (8 - (srcbit - dstbit)));
nbits -= xdstbit;
src++;
srcbit -= dstbit;
dstbit = 0;
}
/* less bits to fill than needed to fill up the broken octet */
} else {
if (srcbit <= dstbit) {
*dst |= ((*src >> (8 - srcbit - nbits)) & c_aBitMask[nbits]) <<
(xdstbit - nbits);
} else {
*dst++ |= ((*src & c_aBitMask[8 - srcbit]) << (srcbit - dstbit)) |
((src[1] >> (16 - srcbit - nbits)) << (xdstbit - nbits));
}
return;
}
}
/* fill up complete octets */
if (nbits >= 8) {
if (!srcbit) {
CopyMemory(dst, src, nbits / 8);
dst += nbits / 8;
src += nbits / 8;
nbits &= 7;
} else {
xsrcbit = 8 - srcbit;
do {
*dst++ = (*src << srcbit) | (src[1] >> (xsrcbit));
src++;
nbits -= 8;
} while (nbits >= 8);
}
}
/* fill bits into last octet */
if (nbits)
{
*dst = (*src << srcbit) & c_aBitMask2[nbits];
// lonchanc: made the following fix for the case that
// src bits across byte boundary.
if (srcbit + nbits > 8)
{
xsrcbit = nbits - (8 - srcbit);
src++;
*dst |= ((*src & c_aBitMask2[xsrcbit]) >> (8 - srcbit));
}
}
}
/* clear nbits bits at dst/dstbit;
bits of last octet behind dst/dstbit+nbits-1 will be cleared
*/
void ASN1bitclr(ASN1octet_t *dst, ASN1uint32_t dstbit, ASN1uint32_t nbits)
{
ASN1uint32_t xdstbit;
if (!nbits)
return;
if (dstbit >= 8) {
dst += dstbit / 8;
dstbit &= 7;
}
/* clear broken ASN1octet first */
if (dstbit) {
xdstbit = 8 - dstbit;
*dst &= c_aBitMask2[xdstbit];
if (xdstbit < nbits) {
dst++;
nbits -= xdstbit;
} else {
return;
}
}
/* clear remaining bits */
ZeroMemory(dst, (nbits + 7) / 8);
}
/* clear nbits bits at dst/dstbit;
bits of last octet behind dst/dstbit+nbits-1 will be cleared
*/
void ASN1bitset(ASN1octet_t *dst, ASN1uint32_t dstbit, ASN1uint32_t nbits)
{
ASN1uint32_t xdstbit;
if (!nbits)
return;
if (dstbit >= 8) {
dst += dstbit / 8;
dstbit &= 7;
}
/* set broken ASN1octet first */
if (dstbit) {
xdstbit = 8 - dstbit;
if (xdstbit < nbits) {
*dst |= c_aBitMask4[xdstbit];
dst++;
nbits -= xdstbit;
} else {
*dst |= c_aBitMask4[nbits] << (xdstbit - nbits);
return;
}
}
/* set complete octets */
if (nbits >= 8) {
memset(dst, 0xff, nbits / 8);
dst += nbits / 8;
nbits &= 7;
}
/* set remaining bits */
if (nbits)
*dst |= c_aBitMask4[nbits] << (8 - nbits);
}
/* write nbits bits of val at dst/dstbit;
assumes that bits of broken octet at dst/dstbit are cleared;
bits of last octet behind dst/dstbit+nbits-1 will be cleared
*/
void ASN1bitput(ASN1octet_t *dst, ASN1uint32_t dstbit, ASN1uint32_t val, ASN1uint32_t nbits)
{
ASN1uint32_t xdstbit;
if (!nbits)
return;
if (dstbit >= 8) {
dst += dstbit / 8;
dstbit &= 7;
}
xdstbit = 8 - dstbit;
/* fill up broken octet first */
if (dstbit) {
if (xdstbit <= nbits) {
*dst++ |= val >> (nbits -= xdstbit);
} else {
*dst |= (val & c_aBitMask[nbits]) << (xdstbit - nbits);
return;
}
}
/* copy complete octets */
while (nbits >= 8)
*dst++ = (ASN1octet_t) (val >> (nbits -= 8));
/* copy left bits */
if (nbits)
*dst = (ASN1octet_t) ((val & c_aBitMask[nbits]) << (8 - nbits));
}
/* read nbits bits of val at src/srcbit */
// lonchanc: the return value is independent of big or little endian
// because we use shift left within a long integer.
ASN1uint32_t ASN1bitgetu(ASN1octet_t *src, ASN1uint32_t srcbit, ASN1uint32_t nbits)
{
ASN1uint32_t xsrcbit;
ASN1uint32_t ret;
if (!nbits)
return 0;
if (srcbit >= 8) {
src += srcbit / 8;
srcbit &= 7;
}
xsrcbit = 8 - srcbit;
ret = 0;
/* get bits from broken octet first */
if (srcbit) {
if (xsrcbit <= nbits) {
ret = (*src++ & c_aBitMask[xsrcbit]) << (nbits -= xsrcbit);
} else {
return (*src >> (xsrcbit - nbits)) & c_aBitMask[nbits];
}
}
/* get complete octets */
while (nbits >= 8)
ret |= *src++ << (nbits -= 8);
/* get left bits */
if (nbits)
ret |= ((*src) >> (8 - nbits)) & c_aBitMask[nbits];
return ret;
}
/* read nbits bits of val at src/srcbit */
ASN1int32_t ASN1bitget(ASN1octet_t *src, ASN1uint32_t srcbit, ASN1uint32_t nbits)
{
ASN1uint32_t xsrcbit;
ASN1int32_t ret;
if (!nbits)
return 0;
if (srcbit >= 8) {
src += srcbit / 8;
srcbit &= 7;
}
xsrcbit = 8 - srcbit;
if (*src & (0x80 >> srcbit))
ret = c_aBitMask5[nbits];
else
ret = 0;
/* get bits from broken octet first */
if (srcbit) {
if (xsrcbit <= nbits) {
ret = *src++ << (nbits -= xsrcbit);
} else {
return (*src >> (xsrcbit - nbits)) & c_aBitMask[nbits];
}
}
/* get complete octets */
while (nbits >= 8)
ret |= *src++ << (nbits -= 8);
/* get left bits */
if (nbits)
ret |= ((*src) >> (8 - nbits)) & c_aBitMask[nbits];
return ret;
}
/* get number of set bits in nbits bits at src/srcbit */
ASN1uint32_t ASN1bitcount(ASN1octet_t *src, ASN1uint32_t srcbit, ASN1uint32_t nbits)
{
ASN1uint32_t xsrcbit;
ASN1uint32_t ret;
if (!nbits)
return 0;
if (srcbit >= 8) {
src += srcbit / 8;
srcbit &= 7;
}
xsrcbit = 8 - srcbit;
/* count bits from broken octet first */
if (srcbit) {
if (xsrcbit <= nbits) {
ret = c_aBitCount[*src++ & c_aBitMask4[srcbit]];
nbits -= xsrcbit;
} else {
return c_aBitCount[(*src >> (xsrcbit - nbits)) & c_aBitMask[nbits]];
}
} else {
ret = 0;
}
/* count bits in complete octets */
while (nbits >= 8)
{
ret += c_aBitCount[*src++];
nbits -= 8;
}
/* count left bits */
if (nbits)
ret += c_aBitCount[(*src) & c_aBitMask2[nbits]];
return ret;
}
/* write noctets of val at dst */
void ASN1octetput(ASN1octet_t *dst, ASN1uint32_t val, ASN1uint32_t noctets)
{
switch (noctets) {
case 4:
*dst++ = (ASN1octet_t)(val >> 24);
/*FALLTHROUGH*/
case 3:
*dst++ = (ASN1octet_t)(val >> 16);
/*FALLTHROUGH*/
case 2:
*dst++ = (ASN1octet_t)(val >> 8);
/*FALLTHROUGH*/
case 1:
*dst++ = (ASN1octet_t)(val);
break;
default:
break;
MyAssert(0);
/*NOTREACHED*/
}
}
/* read noctets of val at dst */
ASN1uint32_t ASN1octetget(ASN1octet_t *src, ASN1uint32_t noctets)
{
switch (noctets) {
case 4:
return (*src << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
case 3:
return (*src << 16) | (src[1] << 8) | src[2];
case 2:
return (*src << 8) | src[1];
case 1:
return *src;
default:
MyAssert(0);
return(0);
/*NOTREACHED*/
}
}