aboutsummaryrefslogtreecommitdiffstats
path: root/skeletons/per_encoder.c
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2006-08-18 01:34:18 +0000
committerLev Walkin <vlm@lionet.info>2006-08-18 01:34:18 +0000
commit523de9eba2d6963b2e0620bc93a3edc50e038c67 (patch)
tree14ca9b70265a116636cc10677d92af9a0f630e01 /skeletons/per_encoder.c
parent1dc85299236b3264bc9eb6d7f2177153ffe0ce55 (diff)
per support
Diffstat (limited to 'skeletons/per_encoder.c')
-rw-r--r--skeletons/per_encoder.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/skeletons/per_encoder.c b/skeletons/per_encoder.c
new file mode 100644
index 00000000..6ba28e53
--- /dev/null
+++ b/skeletons/per_encoder.c
@@ -0,0 +1,89 @@
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <per_encoder.h>
+
+/* Flush partially filled buffer */
+static int _uper_encode_flush_outp(asn_per_outp_t *po);
+
+asn_enc_rval_t
+uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_per_outp_t po;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->uper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ po.buffer = po.tmpspace;
+ po.nboff = 0;
+ po.nbits = 8 * sizeof(po.tmpspace);
+ po.outper = cb;
+ po.op_key = app_key;
+
+ er = td->uper_encoder(td, 0, sptr, &po);
+ if(er.encoded != -1 && _uper_encode_flush_outp(&po))
+ _ASN_ENCODE_FAILED;
+
+ return er;
+}
+
+/*
+ * Argument type and callback necessary for uper_encode_to_buffer().
+ */
+typedef struct enc_to_buf_arg {
+ void *buffer;
+ size_t left;
+} enc_to_buf_arg;
+static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
+ enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
+
+ if(arg->left < size)
+ return -1; /* Data exceeds the available buffer size */
+
+ memcpy(arg->buffer, buffer, size);
+ arg->buffer = ((char *)arg->buffer) + size;
+ arg->left -= size;
+
+ return 0;
+}
+
+asn_enc_rval_t
+uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
+ enc_to_buf_arg key;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->uper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ key.buffer = buffer;
+ key.left = buffer_size;
+
+ ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
+
+ er = uper_encode(td, sptr, encode_to_buffer_cb, &key);
+ if(er.encoded != -1)
+ er.encoded = buffer_size - key.left;
+ return er;
+}
+
+static int
+_uper_encode_flush_outp(asn_per_outp_t *po) {
+ uint8_t *buf;
+
+ if(po->nboff == 0 && po->buffer == po->tmpspace)
+ return 0;
+
+ buf = po->buffer + (po->nboff >> 3);
+ /* Make sure we account for the last, partially filled */
+ if(po->nboff & 0x07) {
+ buf[0] &= 0xff << (8 - (po->nboff & 0x07));
+ buf++;
+ }
+
+ return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
+}