📄 persimpl.c
字号:
#ifdef __cplusplus
extern "C"
{
#endif
/*
***********************************************************************************
NOTICE:
This document contains information that is proprietary to RADVISION LTD..
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVISION LTD..
RADVISION LTD. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.
***********************************************************************************
*/
/*
perSimple.c
Encoding Rules are ASN.1 PER BASIC - ALIGNED.
Encoding/Decoding of ASN simple types.
Integer, length, null, boolean, octet string.
Note: Open type fields are encoded into a separate bit buffer and then added
to the complete encoding as an octet string with unconstrained length.
Note: Bit order should be: Most Significant Bit(MSB) first.
Byte order ...
Encoding: Add to tail of buffer.
Decoding: Decode from position in buffer. Returns the number of bits being decoded.
Does not change the buffer.
Uses user allocated memory for integers and strings(sra).
Parameters:
n: number.
lb: lower bound. -1 if no constraint.
ub: upper bound. -1 if no constraint.
from: position in bit buffer from which to decode.
decoded: number of bits successfully decoded from buffer.
bbH: bit buffer handler.
*/
#include "rvstdio.h"
#include "perintr.h"
#include "persimpl.h"
#define K64 65536lu /* 64K */
#define BIT24 16777216lu /* 2^24 */
#define BIT32 4294967295lu /* 2^32 - 1 */
#define nprn(s) ((s)?(s):"(null)")
int
perEncodeSemiConstInt(IN RvUint32 n, /* the number */
IN RvInt32 lb,
OUT HBB bbH,
OUT RvUint32 *length); /* in octets */
int
perDecodeSemiConstInt(IN RvUint32 *n,
IN RvInt32 lb,
IN RvInt32 length, /* in octets */
IN HPER hPer,
IN RvUint32 from,
OUT RvUint32 *dec);
/* Description: Returns the exact number of bits for a constrained
integer with defined range.
Inupt: range- ub - lb + 1
Returns: The number of bits for the integer. or -1 if range too
large to conclude the size;
*/
static RvUint8
perIntBits(RvUint32 range)
{
static const char lut[]=
{
0,
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
};
if (range <= 256)
return lut[range];
if (range <= K64)
return 2*8;
if (range <= BIT24)
return 3*8;
return 4*8;
}
/*___________________________________________________________________________*/
/*________________________Constraigned_whole_Integer_________________________*/
/*___________________________________________________________________________*/
/*
Desc: Encodes an integer and puts it in TAIL of bit buffer.
Returns: Failure if cannnot encode n.
*/
int
perEncodeInt(IN RvUint32 n,
IN RvUint32 lb,
IN RvUint32 ub,
IN RvBool isFromAbsent,
IN RvBool isToAbsent,
IN RvBool isExtension,
OUT HBB bbH) /* Should be initialized with sufficient size.
It has to have at least 4 bytes size. */
{
RvBool isExtended = RV_FALSE;
RvUint32 num = n - lb;
RvUint32 tmpNum;
RvUint32 range = ub - lb + 1;
unsigned char ch; /* for case 10.5.7.1 */
unsigned char numOct[MAX_INT_SIZE]; /*num converted to array in BIG ENDIAN*/
int bits;
if (lb == 0 && ub == BIT32)
range = (RvUint32)BIT32;
if (!bbH || bbFreeBytes(bbH) < MAX_INT_SIZE)
{
RvLogExcep(&rvPerErrLogSource, (&rvPerErrLogSource,
"per:EncodeInt: Buffer allocation error"))
return RV_ERROR_UNKNOWN; /* Buffer allocation error */
}
if (isExtension)
{
if (((!isFromAbsent) && n<lb) ||((!isToAbsent) && ub < n))
{
isExtended = RV_TRUE;
perEncodeBool(RV_TRUE, bbH); /* adding extension bit. Sergey M. */
}
else
perEncodeBool(RV_FALSE, bbH);
}
/* Unconstrained or Semiconstrained INTEGER. Sergey M. */
if (isToAbsent != RV_FALSE || isExtended)
{
if (n == 0)
bits = 1;
else
bits = perIntBits(n + 1);
if (isFromAbsent != RV_FALSE && (bits==8 || (bits==16 && (n&0x8000)) || (bits==24 && (n&0x800000))))
bits++;
ch =(unsigned char)bbSetByte(bits);
perEncodeLen(perLenTypeUNCONSTRAINED, (RvUint32)ch, 0, 0, bbH);
if (isFromAbsent != RV_FALSE || isExtended) /* Unconstrained INTEGER. Sergey M. */
{
/* Convert the number to 4 bytes in BIG ENDIAN order */
tmpNum = n; /* 4 bytes integer */
numOct[0] =(unsigned char)(tmpNum >> 24); /* n / 2^24 */
tmpNum -= numOct[0] << 24;
numOct[1] =(unsigned char)(tmpNum >> 16); /* n / 2^16 */
tmpNum -= numOct[1] << 16;
numOct[2] =(unsigned char)(tmpNum >> 8); /* n / 2^8 */
tmpNum -= numOct[2] << 8;
numOct[3] =(unsigned char)tmpNum;
return bbAddTail(bbH, (RvUint8 *)(numOct + (MAX_INT_SIZE - ch)), ch*8, RV_TRUE);
}
else
{
if (n < lb)
{
RvLogError(&rvPerErrLogSource, (&rvPerErrLogSource,
"per:EncodeInt: Integer out of range [%d <= %d ", lb, n));
return RV_ERROR_UNKNOWN; /* Range Error */
}
return perEncodeSemiConstInt(n, (RvInt32)lb, bbH, NULL);
}
} /* End of unconstrained or semiconstrained INTEGER. Sergey M. */
if (ub == lb)
return RV_TRUE; /* no encoding needed */
/* Irina * changes for negative numbers */
if (/*lb > ub || n < lb || n > ub */ n-lb > ub-lb)
{
if ((int)ub>(int)lb)
{
RvLogError(&rvPerErrLogSource, (&rvPerErrLogSource,
"per:EncodeInt: Integer out of range [%d <= %d <= %d]", lb, n, ub));
}
else
{
RvLogError(&rvPerErrLogSource, (&rvPerErrLogSource,
"per:EncodeInt: Integer out of range [%u <= %u <= %u]", lb, n, ub));
return RV_ERROR_UNKNOWN; /* Range Error */
}
}
bits = perIntBits(range);
/* range <= 255: 10.5.7.1 */
if (range <= 255)
{
ch =(unsigned char)num;
ch =(unsigned char)(ch <<(8 - bits));
return bbAddTail(bbH, (RvUint8 *)&ch, bits, RV_FALSE);
}
/* range = 256: 10.5.7.2 */
if (range == 256)
{
ch =(unsigned char)num;
return bbAddTail(bbH, (RvUint8 *)&ch, 8, RV_TRUE);
}
/* Convert the number to 4 bytes in BIG ENDIAN order */
tmpNum = num; /* 4 bytes integer */
numOct[0] =(unsigned char)(tmpNum >> 24); /* n / 2^24 */
tmpNum -= numOct[0] << 24;
numOct[1] =(unsigned char)(tmpNum >> 16); /* n / 2^16 */
tmpNum -= numOct[1] << 16;
numOct[2] =(unsigned char)(tmpNum >> 8); /* n / 2^8 */
tmpNum -= numOct[2] << 8;
numOct[3] =(unsigned char)tmpNum;
/* range <=K64: 10.5.7.3; 2 octets aligned */
if (range <= K64)
{
/* 256 < num <= 65536 */
if (bits/8 < 0 || bits/8 > MAX_INT_SIZE)
return RV_ERROR_UNKNOWN;
return bbAddTail(bbH, (RvUint8 *)(numOct + (MAX_INT_SIZE - bits/8)), bits, RV_TRUE);
}
/* range > K64: 10.5.7.4: indefinite length case */
/* These cases require additional length field */
/* The length shall be encoded according to clause 10.9.3.6 and be treated
as an octet - aligned - bit - field. The length is <= 127. */
bits = perIntBits(num);
ch =(unsigned char)bbSetByte(bits);
if (ch == 0)
ch = 1; /* at least 1 octet */
/* length: 12.2.6a */
perEncodeLen(perLenTypeCONSTRAINED, (RvUint32)ch, 1, bbSetByte(perIntBits(ub)), bbH);
return bbAddTail(bbH, (RvUint8 *)(numOct + (MAX_INT_SIZE - ch)), ch*8, RV_TRUE); /* number */
}
int /* RV_TRUE or negative value on failure */
perDecodeInt(
/* Decodes an integer from a bit buffer. */
OUT RvUint32 *n, /* decoded number */
IN RvUint32 lb,
IN RvUint32 ub,
IN RvBool isFromAbsent,
IN RvBool isToAbsent,
IN RvBool isExtension,
IN HPER hPer,
IN RvUint32 from, /* position in buffer */
OUT RvUint32 *decoded,
IN char* desc /* short description(optional) */
)
{
RvBool isExtended = RV_FALSE;
perStruct *per =(perStruct *)hPer;
RvUint32 num;
RvUint32 extract, bits, bytes;
RvUint32 range = ub - lb + 1;
RvUint8 numOct[MAX_INT_SIZE]; /*num converted to array in BIG ENDIAN*/
RvUint32 myFrom = from;
RV_UNUSED_ARG(desc);
memset((char *)numOct, 0, MAX_INT_SIZE);
if (lb == 0 && ub == BIT32)
range = (RvUint32)BIT32;
if (!n || !decoded)
{
RvLogError(&rvPerErrLogSource, (&rvPerErrLogSource,
"per:DecodeInt:%s: parameters (n,del) not allocated.", nprn(desc)));
return RV_ERROR_UNKNOWN;
}
*n = 0;
*decoded = 0;
if (!(per->hBB))
{
RvLogError(&rvPerErrLogSource, (&rvPerErrLogSource,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -