diff options
Diffstat (limited to 'crypto/src/asn1/DerEnumerated.cs')
-rw-r--r-- | crypto/src/asn1/DerEnumerated.cs | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs index 1344926bd..8654a3bfd 100644 --- a/crypto/src/asn1/DerEnumerated.cs +++ b/crypto/src/asn1/DerEnumerated.cs @@ -9,6 +9,7 @@ namespace Org.BouncyCastle.Asn1 : Asn1Object { private readonly byte[] bytes; + private readonly int start; /** * return an integer from the passed in object @@ -54,7 +55,17 @@ namespace Org.BouncyCastle.Asn1 if (val < 0) throw new ArgumentException("enumerated must be non-negative", "val"); - bytes = BigInteger.ValueOf(val).ToByteArray(); + this.bytes = BigInteger.ValueOf(val).ToByteArray(); + this.start = 0; + } + + public DerEnumerated(long val) + { + if (val < 0L) + throw new ArgumentException("enumerated must be non-negative", "val"); + + this.bytes = BigInteger.ValueOf(val).ToByteArray(); + this.start = 0; } public DerEnumerated(BigInteger val) @@ -62,7 +73,8 @@ namespace Org.BouncyCastle.Asn1 if (val.SignValue < 0) throw new ArgumentException("enumerated must be non-negative", "val"); - bytes = val.ToByteArray(); + this.bytes = val.ToByteArray(); + this.start = 0; } public DerEnumerated(byte[] bytes) @@ -73,6 +85,7 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("enumerated must be non-negative", "bytes"); this.bytes = Arrays.Clone(bytes); + this.start = DerInteger.SignBytesToSkip(bytes); } public BigInteger Value @@ -80,17 +93,34 @@ namespace Org.BouncyCastle.Asn1 get { return new BigInteger(bytes); } } - internal override void Encode( - DerOutputStream derOut) + public bool HasValue(BigInteger x) + { + return null != x + // Fast check to avoid allocation + && DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned) == x.IntValue + && Value.Equals(x); + } + + public int IntValueExact + { + get + { + int count = bytes.Length - start; + if (count > 4) + throw new ArithmeticException("ASN.1 Enumerated out of int range"); + + return DerInteger.IntValue(bytes, start, DerInteger.SignExtSigned); + } + } + + internal override void Encode(DerOutputStream derOut) { derOut.WriteEncoded(Asn1Tags.Enumerated, bytes); } - protected override bool Asn1Equals( - Asn1Object asn1Object) + protected override bool Asn1Equals(Asn1Object asn1Object) { DerEnumerated other = asn1Object as DerEnumerated; - if (other == null) return false; @@ -106,27 +136,21 @@ namespace Org.BouncyCastle.Asn1 internal static DerEnumerated FromOctetString(byte[] enc) { + if (enc.Length > 1) + return new DerEnumerated(enc); if (enc.Length == 0) - { throw new ArgumentException("ENUMERATED has zero length", "enc"); - } - if (enc.Length == 1) + int value = enc[0]; + if (value >= cache.Length) + return new DerEnumerated(enc); + + DerEnumerated possibleMatch = cache[value]; + if (possibleMatch == null) { - int value = enc[0]; - if (value < cache.Length) - { - DerEnumerated cached = cache[value]; - if (cached != null) - { - return cached; - } - - return cache[value] = new DerEnumerated(Arrays.Clone(enc)); - } + cache[value] = possibleMatch = new DerEnumerated(enc); } - - return new DerEnumerated(Arrays.Clone(enc)); + return possibleMatch; } } } |