public Asn1Object ReadObject()
{
int tag = ReadByte();
if (tag <= 0)
{
if (tag == 0)
throw new IOException("unexpected end-of-contents marker");
return null;
}
//
// calculate tag number
//
int tagNo = ReadTagNumber(this.s, tag);
bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
//
// calculate length
//
int length = ReadLength(this.s, limit);
if (length < 0) // indefinite length method
{
if (!isConstructed)
throw new IOException("indefinite length primitive encoding encountered");
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
if ((tag & Asn1Tags.Application) != 0)
{
return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object();
}
if ((tag & Asn1Tags.Tagged) != 0)
{
return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object();
}
// TODO There are other tags that may be constructed (e.g. BitString)
switch (tagNo)
{
case Asn1Tags.OctetString:
return new BerOctetStringParser(sp).ToAsn1Object();
case Asn1Tags.Sequence:
return new BerSequenceParser(sp).ToAsn1Object();
case Asn1Tags.Set:
return new BerSetParser(sp).ToAsn1Object();
case Asn1Tags.External:
return new DerExternalParser(sp).ToAsn1Object();
default:
throw new IOException("unknown BER object encountered");
}
}
else
{
try
{
return BuildObject(tag, tagNo, length);
}
catch (ArgumentException e)
{
throw new Asn1Exception("corrupted stream detected", e);
}
}
}