#include "asn-config.h"
#include "asn-len.h"
#include "asn-tag.h"
#include "asn-type.h"
#include "asn-bits.h"
#include "str-stk.h"
#ifndef __APPLE__
extern StrStk strStkG;
unsigned short int strStkUnusedBitsG;
#endif
const
char numToHexCharTblG[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
AsnBits::~AsnBits()
{
delete bits;
}
AsnType *AsnBits::Clone() const
{
return new AsnBits;
}
AsnType *AsnBits::Copy() const
{
return new AsnBits (*this);
}
void AsnBits::Set (size_t numBits)
{
bitLen = numBits;
size_t octetLen = (bitLen+7)/8;
#ifndef _IBM_ENC_
bits = Asn1Alloc (octetLen);
#else
bits = (char *) mem_mgr_ptr->Get (octetLen); #endif
memzero (bits, octetLen); }
void AsnBits::Set (const char *bitOcts, size_t numBits)
{
if (bitOcts != bits)
{
bitLen = numBits;
size_t octetLen = (bitLen+7)/8;
#ifndef _IBM_ENC_
bits = new char[octetLen];
#else
bits = (char *) mem_mgr_ptr->Get (octetLen); #endif
memcpy (bits, bitOcts, octetLen);
}
}
void AsnBits::Set (const AsnBits &b)
{
if (&b != this)
{
bitLen = b.bitLen;
size_t octetLen = (bitLen+7)/8;
#ifndef _IBM_ENC_
bits = new char[octetLen];
#else
bits = (char *) mem_mgr_ptr->Get (octetLen); #endif
memcpy (bits, b.bits, octetLen);
}
}
void AsnBits::ReSet (size_t numBits)
{
#ifndef _IBM_ENC_
delete bits;
Set (numBits);
#else
mem_mgr_ptr->Put ((void *) bits); Set (numBits);
#endif
}
void AsnBits::ReSet (const char *bitOcts, size_t numBits)
{
if (bitOcts != bits)
{
#ifndef _IBM_ENC_
delete bits;
Set (bitOcts, numBits);
#else
mem_mgr_ptr->Put ((void *) bits); Set (bitOcts, numBits);
#endif
}
}
void AsnBits::ReSet (const AsnBits &b)
{
if (&b != this) {
#ifndef _IBM_ENC_
delete bits;
Set (b);
#else
mem_mgr_ptr->Put ((void *) bits); Set (b);
#endif
}
}
bool AsnBits::BitsEquiv (const AsnBits &ab) const
{
size_t octetsLessOne = (bitLen-1)/8;
size_t octetBits = 7 - (bitLen % 8);
if (!bitLen && !ab.bitLen)
return true;
return bitLen == ab.bitLen
&& !memcmpeq (bits, ab.bits, octetsLessOne)
&& (bits[octetsLessOne] & (0xFF << octetBits)) == (ab.bits[octetsLessOne] & (0xFF << octetBits));
}
void AsnBits::SetBit (size_t bit)
{
if (bit < bitLen)
{
size_t octet = bit/8;
size_t octetsBit = 7 - (bit % 8); bits[octet] |= 1 << octetsBit;
}
#ifdef DEBUG
else
Asn1Errror << "AsnBits::SetBit: ERROR - bit larger than bit string" << endl;
#endif
}
void AsnBits::ClrBit (size_t bit)
{
if (bit < bitLen)
{
size_t octet = bit/8;
size_t octetsBit = 7 - (bit % 8); bits[octet] &= ~(1 << octetsBit);
}
#ifdef DEBUG
else
Asn1Errror << "AsnBits::ClrBit: ERROR - bit larger than bit string" << endl;
#endif
}
bool AsnBits::GetBit (size_t bit) const
{
if (bit < bitLen)
{
size_t octet = bit/8;
size_t octetsBit = 7 - (bit % 8); return !!(bits[octet] & (1 << octetsBit));
}
#ifdef DEBUG
else
Asn1Errror << "AsnBits::GetBit: ERROR - bit larger than bit string" << endl;
#endif
return false;
}
AsnLen AsnBits::BEncContent (BUF_TYPE b)
{
size_t byteLen = (bitLen+7)/8;
b.PutSegRvs (bits, byteLen);
size_t unusedBits = (bitLen % 8);
if (unusedBits != 0)
unusedBits = 8 - unusedBits;
b.PutByteRvs (unusedBits);
return byteLen + 1;
}
void AsnBits::BDecContent (BUF_TYPE b, AsnTag tagId, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env)
{
if (tagId & 0x20000000)
BDecConsBits (b, elmtLen, bytesDecoded, env);
else
{
bytesDecoded += elmtLen;
elmtLen--;
bitLen = (elmtLen * 8) - (unsigned int)b.GetByte();
#ifndef _IBM_ENC_
bits = Asn1Alloc (elmtLen);
#else
bits = (char *) mem_mgr_ptr->Get (elmtLen); #endif
b.CopyOut (bits, elmtLen);
if (b.ReadError())
{
Asn1Error << "BDecBitString: ERROR - decoded past end of data" << endl;
#if SNACC_EXCEPTION_ENABLE
SnaccExcep::throwMe(-1);
#else
longjmp (env, -1);
#endif
}
}
}
AsnLen AsnBits::BEnc (BUF_TYPE b)
{
AsnLen l;
l = BEncContent (b);
l += BEncDefLen (b, l);
l += BEncTag1 (b, UNIV, PRIM, BITSTRING_TAG_CODE);
return l;
}
void AsnBits::BDec (BUF_TYPE b, AsnLen &bytesDecoded, ENV_TYPE env)
{
AsnLen elmtLen;
AsnTag tag;
tag = BDecTag (b, bytesDecoded, env);
if ((tag != MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE))
&& (tag != MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE)))
{
Asn1Error << "AsnBits::BDec: ERROR tag on BIT STRING is wrong." << endl;
#if SNACC_EXCEPTION_ENABLE
SnaccExcep::throwMe(-50);
#else
longjmp (env,-50);
#endif
}
elmtLen = BDecLen (b, bytesDecoded, env);
BDecContent (b, tag, elmtLen, bytesDecoded, env);
}
#ifdef __APPLE__
void AsnBits::FillBitStringStk (BUF_TYPE b, AsnLen elmtLen0,
AsnLen &bytesDecoded, ENV_TYPE env,
StrStk &strStkG,
unsigned short int &strStkUnusedBitsG)
#else
void AsnBits::FillBitStringStk (BUF_TYPE b, AsnLen elmtLen0,
AsnLen &bytesDecoded, ENV_TYPE env)
#endif
{
size_t refdLen;
size_t totalRefdLen;
char *strPtr;
AsnLen totalElmtsLen1 = 0;
unsigned long int tagId1;
AsnLen elmtLen1;
size_t lenToRef;
for (; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); )
{
tagId1 = BDecTag (b, totalElmtsLen1, env);
if ((tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN))
{
BDEC_2ND_EOC_OCTET (b, totalElmtsLen1, env);
break;
}
elmtLen1 = BDecLen (b, totalElmtsLen1, env);
if (tagId1 == MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE))
{
if (strStkUnusedBitsG != 0)
{
Asn1Error << "BDecConsBitString: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits" << endl;
#if SNACC_EXCEPTION_ENABLE
SnaccExcep::throwMe(-2);
#else
longjmp (env, -2);
#endif
}
if (elmtLen1 != 0)
strStkUnusedBitsG = b.GetByte();
totalRefdLen = 0;
lenToRef =elmtLen1-1;
refdLen = lenToRef;
while (1)
{
strPtr = b.GetSeg (&refdLen);
strStkG.Push (strPtr, refdLen);
totalRefdLen += refdLen;
if (totalRefdLen == lenToRef)
break;
if (refdLen == 0)
{
Asn1Error << "BDecConsOctetString: ERROR - expecting more data" << endl;
#if SNACC_EXCEPTION_ENABLE
SnaccExcep::throwMe(-3);
#else
longjmp (env, -3);
#endif
}
refdLen = lenToRef - totalRefdLen;
}
totalElmtsLen1 += elmtLen1;
}
else if (tagId1 == MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE))
{
FillBitStringStk (b, elmtLen1, totalElmtsLen1, env
#ifdef __APPLE__
, strStkG, strStkUnusedBitsG
#endif
);
}
else
{
Asn1Error << "BDecConsBitString: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING" << endl;
#if SNACC_EXCEPTION_ENABLE
SnaccExcep::throwMe(-4);
#else
longjmp (env, -4);
#endif
}
}
bytesDecoded += totalElmtsLen1;
}
void AsnBits::BDecConsBits (BUF_TYPE b, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env)
{
#ifdef __APPLE__
StrStk strStkG(128, 64);
unsigned short int strStkUnusedBitsG;
#endif
strStkG.Reset();
strStkUnusedBitsG = 0;
FillBitStringStk (b, elmtLen, bytesDecoded, env, strStkG,
strStkUnusedBitsG);
bitLen = strStkG.totalByteLen*8 - strStkUnusedBitsG;
#ifndef _IBM_ENC_
bits = Asn1Alloc (strStkG.totalByteLen);
#else
bits = (char *) mem_mgr_ptr->Get (strStkG.totalByteLen); #endif
strStkG.CopyOut (bits);
}
void AsnBits::Print (ostream &os) const
{
#ifndef NDEBUG
size_t octetLen = (bitLen+7)/8;
os << "'";
for (unsigned i = 0; i < octetLen; i++)
os << TO_HEX (bits[i] >> 4) << (TO_HEX (bits[i]));
os << "'H -- BIT STRING bitlen = " << bitLen << " --";
#endif
}
#if META
const AsnBitsTypeDesc AsnBits::_desc (NULL, NULL, false, AsnTypeDesc::BIT_STRING, NULL, NULL);
const AsnTypeDesc *AsnBits::_getdesc() const
{
return &_desc;
}
#if TCL
int AsnBits::TclGetVal (Tcl_Interp *interp) const
{
Tcl_ResetResult(interp);
for (int i=0; i<bitLen; i++)
Tcl_AppendResult(interp,GetBit (i) ? "1" : "0",NULL);
return TCL_OK;
}
int AsnBits::TclSetVal (Tcl_Interp *interp, const char *valstr)
{
int i;
const char *p;
for (i=0, p=valstr; *p; i++, p++)
switch (*p)
{
case '0':
case '1':
break;
default:
const char c[2] = { *p, '\0' };
Tcl_AppendResult (interp, "illegal character '", c, "' for bit in type ", _getdesc()->getmodule()->name, ".", _getdesc()->getname(), NULL);
Tcl_SetErrorCode (interp, "SNACC", "ILLBIT", NULL);
return TCL_ERROR;
}
ReSet (i);
for (i=0, p=valstr; i<bitLen; i++, p++)
*p == '0' ? ClrBit(i) : SetBit(i);
return TCL_OK;
}
#endif
#endif