Optimized _asn1_append_sequence_set() by caching the tail of the element to append on.
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 4 Jun 2014 15:21:15 +0000 (17:21 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 4 Jun 2014 15:21:15 +0000 (17:21 +0200)
lib/decoding.c
lib/element.c
lib/element.h

index c79a5c4..199580c 100644 (file)
@@ -899,6 +899,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
   asn1_node node, p, p2, p3;
   char temp[128];
   int counter, len2, len3, len4, move, ris, tlen;
+  asn1_node ptail = NULL;
   unsigned char class;
   unsigned long tag;
   int indefinite, result, total_len = ider_len;
@@ -1290,7 +1291,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                    {           /* indefinite length method */
                      if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
                        {
-                         _asn1_append_sequence_set (p);
+                         _asn1_append_sequence_set (p, &ptail);
                          p = p->down;
                          while (p->right)
                            p = p->right;
@@ -1299,6 +1300,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                        }
 
                      p->tmp_ival = 0;
+                     ptail = NULL; /* finished decoding this structure */
                      DECR_LEN(ider_len, 2);
                      counter += 2;
                    }
@@ -1306,7 +1308,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                    {           /* definite length method */
                      if (len2 > counter)
                        {
-                         _asn1_append_sequence_set (p);
+                         _asn1_append_sequence_set (p, &ptail);
                          p = p->down;
                          while (p->right)
                            p = p->right;
@@ -1315,6 +1317,8 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                        }
 
                      p->tmp_ival = 0;
+                     ptail = NULL; /* finished decoding this structure */
+
                      if (len2 != counter)
                        {
                          result = ASN1_DER_ERROR;
@@ -1351,7 +1355,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                             || (type_field (p2->type) == ASN1_ETYPE_SIZE))
                        p2 = p2->right;
                      if (p2->right == NULL)
-                       _asn1_append_sequence_set (p);
+                       _asn1_append_sequence_set (p, &ptail);
                      p = p2;
                    }
                }
index b45c3ec..66bd8fa 100644 (file)
@@ -130,7 +130,7 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
 
 
 int
-_asn1_append_sequence_set (asn1_node node)
+_asn1_append_sequence_set (asn1_node node, asn1_node *ptail)
 {
   asn1_node p, p2;
   char temp[LTOSTR_MAX_SIZE];
@@ -144,9 +144,19 @@ _asn1_append_sequence_set (asn1_node node)
         || (type_field (p->type) == ASN1_ETYPE_SIZE))
     p = p->right;
   p2 = _asn1_copy_structure3 (p);
-  while (p->right)
-    p = p->right;
+
+  if (ptail == NULL || *ptail == NULL || (*ptail)->up != p->up)
+    while (p->right) {
+      p = p->right;
+    }
+  else
+    {
+      p = *ptail;
+    }
+
   _asn1_set_right (p, p2);
+  if (ptail)
+    *ptail = p2;
 
   if (p->name[0] == 0)
     _asn1_str_cpy (temp, sizeof (temp), "?1");
@@ -608,7 +618,7 @@ asn1_write_value (asn1_node node_root, const char *name,
     case ASN1_ETYPE_SET_OF:
       if (_asn1_strcmp (value, "NEW"))
        return ASN1_VALUE_NOT_VALID;
-      _asn1_append_sequence_set (node);
+      _asn1_append_sequence_set (node, NULL);
       break;
     default:
       return ASN1_ELEMENT_NOT_FOUND;
index fdecafb..65a4845 100644 (file)
@@ -23,7 +23,7 @@
 #define _ELEMENT_H
 
 
-int _asn1_append_sequence_set (asn1_node node);
+int _asn1_append_sequence_set (asn1_node node, asn1_node *pcached);
 
 int _asn1_convert_integer (const unsigned char *value,
                           unsigned char *value_out,