Use special function for common usage of _asn1_extract_tag_der().
[platform/upstream/libtasn1.git] / lib / decoding.c
index eb83d89..26e5041 100644 (file)
@@ -376,6 +376,7 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
   return ASN1_SUCCESS;
 }
 
+
 static int
 _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
                       int *ret_len)
@@ -549,6 +550,29 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
 }
 
 static int
+extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len,
+                      int *ret_len)
+{
+asn1_node p;
+int ris;
+
+  if (type_field (node->type) == ASN1_ETYPE_CHOICE)
+    {
+      p = node->down;
+      while (p)
+        {
+          ris = _asn1_extract_tag_der (p, der, der_len, ret_len);
+          if (ris == ASN1_SUCCESS)
+            break;
+          p = p->right;
+       }
+      return ris;
+    }
+  else
+    return _asn1_extract_tag_der (node, der, der_len, ret_len);
+}
+
+static int
 _asn1_delete_not_used (asn1_node node)
 {
   asn1_node p, p2;
@@ -782,6 +806,14 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len)
 
 }
 
+static void delete_unneeded_choice_fields(asn1_node p)
+{
+  if (p->right)
+    {
+      asn1_delete_structure (&p->right);
+    }
+}
+
 /**
  * asn1_der_decoding:
  * @element: pointer to an ASN1 structure.
@@ -865,23 +897,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                {
                  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
                    {
-                     if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
-                       ris =
-                         _asn1_extract_tag_der (p2, der + counter,
+                     ris =
+                         extract_tag_der_recursive (p2, der + counter,
                                                 len - counter, &len2);
-                     else
-                       {
-                         p3 = p2->down;
-                         while (p3)
-                           {
-                             ris =
-                               _asn1_extract_tag_der (p3, der + counter,
-                                                      len - counter, &len2);
-                             if (ris == ASN1_SUCCESS)
-                               break;
-                             p3 = p3->right;
-                           }
-                       }
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;
@@ -926,17 +944,13 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                {
                  if (counter < len)
                    ris =
-                     _asn1_extract_tag_der (p->down, der + counter,
+                     extract_tag_der_recursive (p->down, der + counter,
                                             len - counter, &len2);
                  else
                    ris = ASN1_DER_ERROR;
                  if (ris == ASN1_SUCCESS)
                    {
-                     while (p->down->right)
-                       {
-                         p2 = p->down->right;
-                         asn1_delete_structure (&p2);
-                       }
+                     delete_unneeded_choice_fields(p->down);
                      break;
                    }
                  else if (ris == ASN1_ERROR_TYPE_ANY)
@@ -1473,23 +1487,9 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
                {
                  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
                    {
-                     if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
-                       ris =
-                         _asn1_extract_tag_der (p2, der + counter,
+                     ris =
+                         extract_tag_der_recursive (p2, der + counter,
                                                 len - counter, &len2);
-                     else
-                       {
-                         p3 = p2->down;
-                         while (p3)
-                           {
-                             ris =
-                               _asn1_extract_tag_der (p3, der + counter,
-                                                      len - counter, &len2);
-                             if (ris == ASN1_SUCCESS)
-                               break;
-                             p3 = p3->right;
-                           }
-                       }
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;
@@ -1540,11 +1540,7 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
                    ris = ASN1_DER_ERROR;
                  if (ris == ASN1_SUCCESS)
                    {
-                     while (p->down->right)
-                       {
-                         p2 = p->down->right;
-                         asn1_delete_structure (&p2);
-                       }
+                     delete_unneeded_choice_fields(p->down);
                      break;
                    }
                  else if (ris == ASN1_ERROR_TYPE_ANY)
@@ -2256,20 +2252,9 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
                {
                  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
                    {           /* CONTROLLARE */
-                     if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
-                       ris =
-                         _asn1_extract_tag_der (p2, der + counter,
+                     ris =
+                         extract_tag_der_recursive (p2, der + counter,
                                                 len - counter, &len2);
-                     else
-                       {
-                         p3 = p2->down;
-                         if (p3 == NULL)
-                           return ASN1_DER_ERROR;
-
-                         ris =
-                           _asn1_extract_tag_der (p3, der + counter,
-                                                  len - counter, &len2);
-                       }
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;