summary refs log tree commit diff
path: root/crypto/src/asn1/DerEnumerated.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/asn1/DerEnumerated.cs')
-rw-r--r--crypto/src/asn1/DerEnumerated.cs70
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;
         }
     }
 }