Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / der_encoder.c
diff --git a/asn1c_defs/all-defs/der_encoder.c b/asn1c_defs/all-defs/der_encoder.c
new file mode 100755 (executable)
index 0000000..8d9e82c
--- /dev/null
@@ -0,0 +1,194 @@
+/*-\r
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
+ * Redistribution and modifications are permitted subject to BSD license.\r
+ */\r
+#include <asn_internal.h>\r
+#include <errno.h>\r
+\r
+static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,\r
+       asn_app_consume_bytes_f *cb, void *app_key, int constructed);\r
+\r
+/*\r
+ * The DER encoder of any type.\r
+ */\r
+asn_enc_rval_t\r
+der_encode(const asn_TYPE_descriptor_t *type_descriptor, const void *struct_ptr,\r
+           asn_app_consume_bytes_f *consume_bytes, void *app_key) {\r
+    ASN_DEBUG("DER encoder invoked for %s",\r
+               type_descriptor->name);\r
+\r
+       /*\r
+        * Invoke type-specific encoder.\r
+        */\r
+    return type_descriptor->op->der_encoder(\r
+        type_descriptor, struct_ptr, /* Pointer to the destination structure */\r
+        0, 0, consume_bytes, app_key);\r
+}\r
+\r
+/*\r
+ * Argument type and callback necessary for der_encode_to_buffer().\r
+ */\r
+typedef struct enc_to_buf_arg {\r
+       void *buffer;\r
+       size_t left;\r
+} enc_to_buf_arg;\r
+static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {\r
+       enc_to_buf_arg *arg = (enc_to_buf_arg *)key;\r
+\r
+       if(arg->left < size)\r
+               return -1;      /* Data exceeds the available buffer size */\r
+\r
+       memcpy(arg->buffer, buffer, size);\r
+       arg->buffer = ((char *)arg->buffer) + size;\r
+       arg->left -= size;\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * A variant of the der_encode() which encodes the data into the provided buffer\r
+ */\r
+asn_enc_rval_t\r
+der_encode_to_buffer(const asn_TYPE_descriptor_t *type_descriptor,\r
+                     const void *struct_ptr, void *buffer, size_t buffer_size) {\r
+    enc_to_buf_arg arg;\r
+       asn_enc_rval_t ec;\r
+\r
+       arg.buffer = buffer;\r
+       arg.left = buffer_size;\r
+\r
+       ec = type_descriptor->op->der_encoder(type_descriptor,\r
+               struct_ptr,     /* Pointer to the destination structure */\r
+               0, 0, encode_to_buffer_cb, &arg);\r
+       if(ec.encoded != -1) {\r
+               assert(ec.encoded == (ssize_t)(buffer_size - arg.left));\r
+               /* Return the encoded contents size */\r
+       }\r
+       return ec;\r
+}\r
+\r
+\r
+/*\r
+ * Write out leading TL[v] sequence according to the type definition.\r
+ */\r
+ssize_t\r
+der_write_tags(const asn_TYPE_descriptor_t *sd, size_t struct_length,\r
+               int tag_mode, int last_tag_form,\r
+               ber_tlv_tag_t tag, /* EXPLICIT or IMPLICIT tag */\r
+               asn_app_consume_bytes_f *cb, void *app_key) {\r
+#define ASN1_DER_MAX_TAGS_COUNT 4\r
+    ber_tlv_tag_t\r
+        tags_buf_scratch[ASN1_DER_MAX_TAGS_COUNT * sizeof(ber_tlv_tag_t)];\r
+    ssize_t lens[ASN1_DER_MAX_TAGS_COUNT * sizeof(ssize_t)];\r
+    const ber_tlv_tag_t *tags; /* Copy of tags stream */\r
+    int tags_count;            /* Number of tags */\r
+    size_t overall_length;\r
+    int i;\r
+\r
+    ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)",\r
+               sd->name, tag_mode, sd->tags_count,\r
+               ber_tlv_tag_string(tag),\r
+               tag_mode\r
+                       ?(sd->tags_count+1\r
+                               -((tag_mode == -1) && sd->tags_count))\r
+                       :sd->tags_count\r
+       );\r
+\r
+    if(sd->tags_count + 1 > ASN1_DER_MAX_TAGS_COUNT) {\r
+        ASN_DEBUG("System limit %d on tags count", ASN1_DER_MAX_TAGS_COUNT);\r
+        return -1;\r
+    }\r
+\r
+       if(tag_mode) {\r
+               /*\r
+                * Instead of doing shaman dance like we do in ber_check_tags(),\r
+                * allocate a small array on the stack\r
+                * and initialize it appropriately.\r
+                */\r
+               int stag_offset;\r
+               ber_tlv_tag_t *tags_buf = tags_buf_scratch;\r
+               tags_count = sd->tags_count\r
+                       + 1     /* EXPLICIT or IMPLICIT tag is given */\r
+                       - ((tag_mode == -1) && sd->tags_count);\r
+               /* Copy tags over */\r
+               tags_buf[0] = tag;\r
+               stag_offset = -1 + ((tag_mode == -1) && sd->tags_count);\r
+               for(i = 1; i < tags_count; i++)\r
+                       tags_buf[i] = sd->tags[i + stag_offset];\r
+               tags = tags_buf;\r
+       } else {\r
+               tags = sd->tags;\r
+               tags_count = sd->tags_count;\r
+       }\r
+\r
+       /* No tags to write */\r
+       if(tags_count == 0)\r
+               return 0;\r
+\r
+       /*\r
+        * Array of tags is initialized.\r
+        * Now, compute the size of the TLV pairs, from right to left.\r
+        */\r
+       overall_length = struct_length;\r
+       for(i = tags_count - 1; i >= 0; --i) {\r
+               lens[i] = der_write_TL(tags[i], overall_length, 0, 0, 0);\r
+               if(lens[i] == -1) return -1;\r
+               overall_length += lens[i];\r
+               lens[i] = overall_length - lens[i];\r
+       }\r
+\r
+       if(!cb) return overall_length - struct_length;\r
+\r
+       ASN_DEBUG("Encoding %s TL sequence (%d elements)", sd->name,\r
+                  tags_count);\r
+\r
+       /*\r
+        * Encode the TL sequence for real.\r
+        */\r
+       for(i = 0; i < tags_count; i++) {\r
+               ssize_t len;\r
+               int _constr;\r
+\r
+               /* Check if this tag happens to be constructed */\r
+               _constr = (last_tag_form || i < (tags_count - 1));\r
+\r
+               len = der_write_TL(tags[i], lens[i], cb, app_key, _constr);\r
+               if(len == -1) return -1;\r
+       }\r
+\r
+       return overall_length - struct_length;\r
+}\r
+\r
+static ssize_t\r
+der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,\r
+               asn_app_consume_bytes_f *cb, void *app_key,\r
+               int constructed) {\r
+       uint8_t buf[32];\r
+       size_t size = 0;\r
+       int buf_size = cb?sizeof(buf):0;\r
+       ssize_t tmp;\r
+\r
+       /* Serialize tag (T from TLV) into possibly zero-length buffer */\r
+       tmp = ber_tlv_tag_serialize(tag, buf, buf_size);\r
+       if(tmp == -1 || tmp > (ssize_t)sizeof(buf)) return -1;\r
+       size += tmp;\r
+\r
+       /* Serialize length (L from TLV) into possibly zero-length buffer */\r
+       tmp = der_tlv_length_serialize(len, buf+size, buf_size?buf_size-size:0);\r
+       if(tmp == -1) return -1;\r
+       size += tmp;\r
+\r
+       if(size > sizeof(buf))\r
+               return -1;\r
+\r
+       /*\r
+        * If callback is specified, invoke it, and check its return value.\r
+        */\r
+       if(cb) {\r
+               if(constructed) *buf |= 0x20;\r
+               if(cb(buf, size, app_key) < 0)\r
+                       return -1;\r
+       }\r
+\r
+       return size;\r
+}\r