📄 asn_obj.cpp
字号:
/*****************************************************************************
File: asn_obj.C
Contents: Member functions for library
System: ASN development.
Created:
Author: Charles W. Gardiner <gardiner@bbn.com>
Remarks:
COPYRIGHT 1995 BBN Systems and Technologies, A Division of BBN Inc.
150 CambridgePark Drive
Cambridge, Ma. 02140
617-873-4000
*****************************************************************************/
#ifndef lint
const char asn_obj_rcsid[]="$Header: /nfs/sub-rosa/u2/IOS_Project/ASN/Dev/rcs/lib/asn_obj/asn_obj.C,v 1.23 1995/09/25 22:15:27 gardiner Exp $";
const char asn_obj_sfcsid[] = "@(#)asn_obj.C 282P";
#endif
#include "includes.h"
#include "asn_obj.h"
UcharArray::UcharArray(int sz)
{
siz = sz;
ua = new uchar[siz];
memset(ua, 0, sz);
}
UcharArray::UcharArray(const uchar *val, int sz)
{
siz = sz;
ua = new uchar[siz];
memcpy(ua, val, sz);
}
int UcharArray::append(const uchar *addendum, int lth)
{
uchar *tmp = new uchar[siz + lth];
memcpy(tmp, ua, siz);
memcpy(&tmp[siz], addendum, lth);
if (ua) delete ua;
ua = tmp;
return siz += lth;
}
void UcharArray::copy(AsnObj *objp) const
{
objp->_valp = new UcharArray(ua, siz);
}
int UcharArray::diff(const AsnObj *objp) const
{
uchar *b, *c, *e;
if (siz != objp->_valp->siz) return 1;
for (b = ua, c = objp->_valp->ua, e = &b[siz]; b < e && *b == *c++; b++);
return (b < e);
}
int UcharArray::diff(const char *c) const
{
uchar *b, *e;
if (siz != strlen(c)) return 1;
for (b = ua, e = &b[siz]; b < e && *b == *c++; b++);
return (b < e);
}
AsnObj::AsnObj()
{
_tag = _type = 0;
_next = _sub = _supra = (AsnObj *)0;
_valp = (UcharArray *)0;
_flags = _mask = 0;
_min = _max = 0;
}
AsnObj::~AsnObj()
{
/**
Function: Deletes any _valp
**/
if (_valp)
{
delete _valp;
_valp = (UcharArray *)0;
}
}
const AsnObj *AsnObj::check_choice() const
{
/**
Function: Goes down through any pointers, choices and defined-bys to find the
proper object to encode
Returns: pointer to proper object
Procedure:
1. WHILE (at a pointer object which points to something) OR
(at a defined-by) OR
(at a filled in choice)
IF it's a pointer, go to what it points to
ELSE IF it's a defined-by
Find the chosen member
IF none AND it's not optional, return error
IF the chosen is also a defined-by (a split definee), return the
chosen item (it looks like a filled-in choice, but we mustn't
go farther)
Go to the chosen member
ELSE IF it's a filled-in choice, go to the filled-in member
Return the answer
**/
const AsnObj *tobjp, *objp = this;
while (((objp->_flags & ASN_POINTER_FLAG) && ((AsnPtr *)objp)->_ptr) ||
(objp->_flags & ASN_DEFINED_FLAG) ||
(objp->_type == ASN_CHOICE && (objp->_flags & ASN_FILLED_FLAG)))
{
if ((objp->_flags & ASN_POINTER_FLAG) && ((AsnPtr *)objp)->_ptr)
objp = ((AsnPtr *)objp)->_ptr;
else if ((objp->_flags & ASN_DEFINED_FLAG))
{
for (tobjp = objp->_sub; tobjp && !(tobjp->_flags & ASN_CHOSEN_FLAG);
tobjp = tobjp->_next);
if (!tobjp)
{
if (!(_flags & ASN_OPTIONAL_FLAG)) asn_obj_err(ASN_NO_DEF_ERR);
return tobjp;
}
if ((tobjp->_flags & (ASN_CHOSEN_FLAG | ASN_DEFINED_FLAG)) ==
(ASN_CHOSEN_FLAG | ASN_DEFINED_FLAG)) return tobjp;
objp = tobjp;
}
else if (objp->_type == ASN_CHOICE && (objp->_flags & ASN_FILLED_FLAG))
{
for (tobjp = objp->_sub; tobjp && !(tobjp->_flags & ASN_FILLED_FLAG);
tobjp = tobjp->_next);
if (!tobjp) return objp->_sub; // any unfilled choice will do
objp = tobjp;
}
}
return objp;
}
int AsnObj::check_efilled() const
{
int i;
if ((i = check_filled()) < -1) i = 1;
return i;
}
int AsnObj::check_vfilled() const
{
int i;
if ((i = check_filled()) < -1) i = 0;
return i;
}
int AsnObj::check_filled() const
{
/**
Function: Checks for filled state of *this
Returns: IF filled, 1
ELSE IF it's a CHOICE that's empty AND OPTIONAL, 0
ELSE IF it's a non-chosen member of a choice OR is optional OR
is a chosen member of an optional OR
is the end of an OF OR is a mandatory absent, 0
ELSE IF it's an empty set/sequence OF that can be empty, -2
ELSE -1 with error message
**/
if ((_flags & ASN_FILLED_FLAG) || _type == ASN_NULL) return 1;
if (_type == ASN_CHOICE &&
(_flags & (ASN_FILLED_FLAG | ASN_OPTIONAL_FLAG)) == ASN_OPTIONAL_FLAG)
return 0;
if ((_supra && _supra->_type == ASN_CHOICE &&
(_supra->_flags & ASN_FILLED_FLAG) &&
!(_flags & ASN_FILLED_FLAG)) || (_flags & ASN_OPTIONAL_FLAG) ||
(_supra && (_supra->_flags & ASN_OF_FLAG) && !_next) || _type == ASN_NONE)
return 0;
if ((_flags & ASN_OF_FLAG) && !_min) return -2;
if ((_type & ASN_CONSTRUCTED))
{
AsnObj *tobjp;
for(tobjp = _sub; tobjp && (tobjp->_flags & ASN_OPTIONAL_FLAG);
tobjp = tobjp->_next);
if(!tobjp) return 0;
}
return -1;
}
void AsnObj::clear()
{
/**
Function: Calls _clear to clear all data arrays in this and subordinate items
NOTE: This uses a simplified form of asn_map_string in case it dies at a lower
level. This is purely for diagnostic purposes
**/
_clear(0);
*asn_map_string = 0;
}
void AsnObj::_clear(int level)
{
/**
Function: Clears all data arrays in this and subordinate items, including
through pointers
Procedure:
1. IF it's a pointer item
IF the object to which it points was duped, delete that
Clear the pointer (even if it wasn't duped -- prevents loops when doing
a decode that runs into a 'real' pointer which was previously
connected for any reason)
2. IF it is a constructed item (don't do all those with subs because we don't
want to clear a table and don't have to clear an ENUM or BITSTRING,
since they have no _valp)
IF it's an OF item, delete each subordinate except the last
3. ELSE
FOR each subordinate, clear it
IF it's a SET, clear its relink chain
4. IF this has a valp, delete it
Clear the filled flag
**/
AsnObj *subp;
char *c = &asn_map_string[level];
/* step 1 */
if ((_flags & ASN_POINTER_FLAG))
{
AsnPtr *ptrp = (AsnPtr *)this;
if (ptrp->_ptr && (ptrp->_ptr->_flags & ASN_DUPED_FLAG)) delete ptrp->_ptr;
ptrp->_ptr = (AsnObj *)0;
}
/* step 2 */
if ((_tag & ASN_CONSTRUCTED))
{
if (level >= 0)
{
*c = '1';
c[1] = 0;
level++;
}
if ((_flags & ASN_OF_FLAG) && _sub)
{
for (subp = _sub; subp->_next; _sub = subp)
{
subp = subp->_next;
_sub->_next = _sub->_supra = (AsnObj *)0;
delete _sub;
}
}
/* step 3 */
else
{
for(AsnObj *subp = _sub; subp; subp = subp->_next)
{
subp->_clear(level);
if (level >= 0) (*c)++;
}
if (_type == ASN_SET)
{
AsnSet *setp = (AsnSet *)this;
if (setp->_relinksp)
{
delete setp->_relinksp;
setp->_relinksp = 0;
}
}
}
}
if (_valp) /* step 4 */
{
delete _valp;
_valp = (UcharArray *)0;
}
if ((_flags & ASN_TABLE_FLAG)) ((AsnTableObj *)this)->set_definees(-1);
_flags &= ~(ASN_FILLED_FLAG | ASN_INDEF_LTH_FLAG | ASN_SUB_INDEF_FLAG);
}
int AsnObj::copy(AsnObj *objp) const
{
int ansr, siz;
uchar *c = (uchar *)0;
AsnObj *superp;
if (!objp) return asn_obj_err(ASN_NULL_PTR);
for(superp = objp; superp; superp = superp->_supra)
{
if (superp->_supra && (superp->_supra->_flags & ASN_OF_FLAG) &&
!superp->_next) return asn_obj_err(ASN_OF_BOUNDS_ERR);
}
if ((siz = vsize()) < 0) return asn_obj_err(ASN_EMPTY_ERR);
if (!(c = (uchar *)calloc(siz, 1))) return -1;
if ((ansr = read(c)) > 0 || _type == ASN_NULL) ansr = objp->write(c, siz);
if (c) free(c);
return ansr;
}
int AsnObj::diff(const AsnObj *objp) const
{
int siz, tosiz;
uchar *b, *c;
if (!objp) return asn_obj_err(ASN_NULL_PTR);
if (!(_flags & ASN_FILLED_FLAG) || !(objp->_flags & ASN_FILLED_FLAG))
return -1;
if (_type == ASN_UTCTIME || _type == ASN_GENTIME)
{
if (objp->_type != ASN_UTCTIME && objp->_type != ASN_GENTIME) return -1;
long bb, cc;
if (read(&bb) < 0 || objp->read(&cc) < 0) return -1;
if (bb == cc) siz = 0;
else siz = 1;
}
else
{
b = c = (uchar *)0;
if ((siz = vsize()) < 0 || !(c = (uchar *)calloc(siz, 1)) ||
(tosiz = objp->vsize()) < 0 || !(b = (uchar *)calloc(tosiz, 1)))
return asn_obj_err(ASN_MEM_ERR);
if (siz != tosiz) siz = -1;
else if (re_read(c) < 0 || objp->re_read(b) < 0) siz = -1;
else if ((siz = memcmp((char *)b, (char *)c, siz)) < 0) siz = 1;
if (c) free(c);
if (b) free(b);
}
return siz;
}
int AsnObj::encode_lth(uchar *to, ulong lth) const
{
uchar *c = to;
ulong tmp = 0;
if (lth < 128) *to = (uchar)lth;
else
{
for (tmp = lth; tmp; tmp >>= 8, c++);
for (*to = ASN_INDEF_LTH + (tmp = (c - to)); c > to ; *c-- = (lth & 0xFF),
lth >>= 8);
}
return tmp + 1;
}
int AsnObj::encode_tag(uchar *to, ulong tag) const
{
ulong tmp;
uchar *c = to;
*c++ = (uchar)tag;
if ((tag & ASN_XT_TAG) == ASN_XT_TAG)
{
for(tmp = tag >> 8; (tmp & ASN_INDEF_LTH); *c++ = (uchar)tmp,
tmp >>= 8);
*c++ = (uchar)tmp;
}
return (c - to);
}
void AsnObj::fill_upward(int filled)
{
/**
Function: Marks this and higher objects filled in and clears de-chosen ones
Input: IF filling, ASN_FILLED_FLAG
ELSE zero (just clearing unused choices)
Procedure:
1. Search all higher objects until a filled one is found
Mark object as filled as this is
IF it is a CHOICE
Clear all its subordinates except this one
IF parent is a SET, put this item in the right place in the relinks
list
**/
AsnObj *superp, *subp;
_flags |= filled;
this->_flags |= filled;
for(subp = this, superp = _supra; superp && !(superp->_flags & ASN_FILLED_FLAG);
subp = superp, superp = superp->_supra)
{
superp->_flags |= filled;
if ((superp->_type == ASN_CHOICE))
{
if ((superp->_flags & ASN_DEFINED_FLAG) &&
!(subp->_flags & ASN_CHOSEN_FLAG)) asn_obj_err(ASN_NO_DEF_ERR);
else for(AsnObj *tobjp = superp->_sub; tobjp; tobjp = tobjp->_next)
{
if (tobjp != subp) tobjp->_clear(-1);
}
}
if (superp->_type == ASN_SET && !(superp->_flags & ASN_OF_FLAG))
{
AsnSet *setp = (AsnSet *)superp;
if (!setp->_relinksp)
{
setp->_relinksp = new AsnLink;
setp->_relinksp->objp = subp;
}
else
{
AsnLink *relinkp;
for (relinkp = setp->_relinksp; relinkp->_next &&
relinkp->objp != subp; relinkp = relinkp->_next);
if (relinkp->objp != subp)
{
relinkp->_next = new AsnLink;
relinkp->_next->objp = subp;
}
}
}
}
}
int AsnObj::is_default() const
{
AsnObj *subp;
long tmp;
uchar *c;
if (!(_flags & ASN_DEFAULT_FLAG) || _type == ASN_NONE) return 0;
if (!(_flags & ASN_FILLED_FLAG)) return 1;
if ((_type & ASN_CONSTRUCTED)) return (!(_readsize(c, 0))? 1: 0);
if (_type == ASN_ANY) return ((_tag == ASN_NULL)? 1: 0);
if (_type == ASN_BOOLEAN)
return (((*_valp)[0] == ((AsnBoolean *)this)->_default)? 1: 0);
if (_type == ASN_ENUMERATED || _type == ASN_INTEGER)
{
for (subp = _sub; subp && !(subp->_flags & ASN_DEFAULT_FLAG);
subp = subp->_next);
if (!subp || read(&tmp) < 0) return -1;
return ((tmp == subp->_tag)? 1: 0);
}
if (_type == ASN_BITSTRING) return ((_valp->size() <= 1)? 1: 0);
return 0;
}
int AsnObj::read_empty(int i, int mode) const
{
if (i < 0)
{
if ((mode & ASN_READING)) i = asn_obj_err(ASN_MANDATORY_ERR);
else
{
i = 0;
asn_errno = ASN_MANDATORY_ERR;
}
}
return i;
}
int AsnObj::set_asn_lth(uchar *from, uchar *to, int mode) const
{
uchar *b, *c;
ulong lth, tmp;
int bwd;
if ((*from++ & ASN_XT_TAG) == ASN_XT_TAG)
{
while ((*from & ASN_INDEF)) from++;
from++;
}
if ((bwd = (int)*from++) & ASN_INDEF)
{
bwd &= ~ASN_INDEF;
if ((mode & ASN_READING)) for (b = from, c = &b[bwd]; c < to; *b++ = *c++);
to -= bwd;
}
else bwd = 0;
if ((lth = to - from) >= 128 && (mode & ASN_READING))
{
for (c = to, tmp = lth; tmp; tmp >>= 8, to++);
while (c > from) *(--to) = *(--c);
}
return this->encode_lth(--from, lth) - 1 - bwd;
}
AsnTableObj::AsnTableObj()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -