aboutsummaryrefslogtreecommitdiffstats
path: root/g13/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'g13/utils.c')
-rw-r--r--g13/utils.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/g13/utils.c b/g13/utils.c
index 15b4426ef..ef0c572a6 100644
--- a/g13/utils.c
+++ b/g13/utils.c
@@ -28,6 +28,17 @@
#include "utils.h"
+/* Definition of the tuple descriptor object. */
+struct tupledesc_s
+{
+ unsigned char *data; /* The tuple data. */
+ size_t datalen; /* The length of the data. */
+ size_t pos; /* The current position as used by next_tuple. */
+ int refcount; /* Number of references hold. */
+};
+
+
+
/* Append the TAG and the VALUE to the MEMBUF. There is no error
checking here; this is instead done while getting the value back
from the membuf. */
@@ -49,3 +60,121 @@ append_tuple (membuf_t *membuf, int tag, const void *value, size_t length)
put_membuf (membuf, value, length);
}
+
+/* Create a tuple object by moving the ownership of (DATA,DATALEN) to
+ a new object. Returns 0 on success and stores the new object at
+ R_TUPLEHD. The return object must be released using
+ destroy_tuples(). */
+gpg_error_t
+create_tupledesc (tupledesc_t *r_desc, void *data, size_t datalen)
+{
+ if (datalen < 5 || memcmp (data, "\x00\x00\x00\x01\x01", 5))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ *r_desc = xtrymalloc (sizeof **r_desc);
+ if (!*r_desc)
+ return gpg_error_from_syserror ();
+ (*r_desc)->data = data;
+ (*r_desc)->datalen = datalen;
+ (*r_desc)->pos = 0;
+ (*r_desc)->refcount++;
+ return 0;
+}
+
+/* Unref a tuple descriptor and if the refcount is down to 0 release
+ its allocated storage. */
+void
+destroy_tupledesc (tupledesc_t tupledesc)
+{
+ if (!tupledesc)
+ return;
+
+ if (!--tupledesc->refcount)
+ {
+ xfree (tupledesc->data);
+ xfree (tupledesc);
+ }
+}
+
+
+tupledesc_t
+ref_tupledesc (tupledesc_t tupledesc)
+{
+ if (tupledesc)
+ tupledesc->refcount++;
+ return tupledesc;
+}
+
+
+/* Find the first tuple with tag TAG. On success return a pointer to
+ its value and store the length of the value at R_LENGTH. If no
+ tuple was return NULL. For future use by next_tupe, the last
+ position is stored in the descriptor. */
+const void *
+find_tuple (tupledesc_t tupledesc, unsigned int tag, size_t *r_length)
+{
+ const unsigned char *s;
+ const unsigned char *s_end; /* Points right behind the data. */
+ unsigned int t;
+ size_t n;
+
+ s = tupledesc->data;
+ if (!s)
+ return NULL;
+ s_end = s + tupledesc->datalen;
+ while (s < s_end)
+ {
+ if (s+3 >= s_end || s + 3 < s)
+ break;
+ t = s[0] << 8;
+ t |= s[1];
+ n = s[2] << 8;
+ n |= s[3];
+ s += 4;
+ if (s + n > s_end || s + n < s)
+ break;
+ if (t == tag)
+ {
+ tupledesc->pos = (s + n) - tupledesc->data;
+ *r_length = n;
+ return s;
+ }
+ s += n;
+ }
+ return NULL;
+}
+
+
+const void *
+next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length)
+{
+ const unsigned char *s;
+ const unsigned char *s_end; /* Points right behind the data. */
+ unsigned int t;
+ size_t n;
+
+ s = tupledesc->data;
+ if (!s)
+ return NULL;
+ s_end = s + tupledesc->datalen;
+ s += tupledesc->pos;
+ if (s < s_end
+ && !(s+3 >= s_end || s + 3 < s))
+ {
+ t = s[0] << 8;
+ t |= s[1];
+ n = s[2] << 8;
+ n |= s[3];
+ s += 4;
+ if (!(s + n > s_end || s + n < s))
+ {
+ tupledesc->pos = (s + n) - tupledesc->data;
+ *r_tag = t;
+ *r_length = n;
+ return s;
+ }
+ }
+
+ return NULL;
+}
+