generic primitive codec added

diff --git a/skeletons/ber_codec_prim.c b/skeletons/ber_codec_prim.c
new file mode 100644
index 0000000..6bb3613
--- /dev/null
+++ b/skeletons/ber_codec_prim.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <ber_codec_prim.h>
+#include <assert.h>
+#include <errno.h>
+
+/*
+ * Decode an always-primitive type.
+ */
+ber_dec_rval_t
+ber_decode_primitive(asn1_TYPE_descriptor_t *td,
+	void **sptr, void *buf_ptr, size_t size, int tag_mode) {
+	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
+	ber_dec_rval_t rval;
+	ber_tlv_len_t length;
+
+	/*
+	 * If the structure is not there, allocate it.
+	 */
+	if(st == NULL) {
+		(void *)st = *sptr = CALLOC(1, sizeof(*st));
+		if(st == NULL) {
+			rval.code = RC_FAIL;
+			rval.consumed = 0;
+			return rval;
+		}
+	}
+
+	ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
+		td->name, tag_mode);
+
+	/*
+	 * Check tags and extract value length.
+	 */
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, 0, &length, 0);
+	if(rval.code != RC_OK)
+		return rval;
+
+	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
+
+	/*
+	 * Make sure we have this length.
+	 */
+	buf_ptr = ((char *)buf_ptr) + rval.consumed;
+	size -= rval.consumed;
+	if(length > (ber_tlv_len_t)size) {
+		rval.code = RC_WMORE;
+		rval.consumed = 0;
+		return rval;
+	}
+
+	st->buf = (uint8_t *)MALLOC(length + 1);
+	if(st->buf) {
+		st->size = length;
+	} else {
+		rval.code = RC_FAIL;
+		rval.consumed = 0;
+		return rval;
+	}
+
+	memcpy(st->buf, buf_ptr, length);
+	st->buf[length] = '\0';		/* Just in case */
+
+	rval.code = RC_OK;
+	rval.consumed += length;
+
+	ASN_DEBUG("Took %ld/%ld bytes to encode %s",
+		(long)rval.consumed,
+		(long)length, td->name);
+
+	return rval;
+}
+
+/*
+ * Encode an always-primitive type using DER.
+ */
+asn_enc_rval_t
+der_encode_primitive(asn1_TYPE_descriptor_t *td, void *sptr,
+	int tag_mode, ber_tlv_tag_t tag,
+	asn_app_consume_bytes_f *cb, void *app_key) {
+	asn_enc_rval_t erval;
+	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
+
+	ASN_DEBUG("%s %s as a primitive type (tm=%d)",
+		cb?"Encoding":"Estimating", td->name, tag_mode);
+
+	erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
+		cb, app_key);
+	ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
+	if(erval.encoded == -1) {
+		erval.failed_type = td;
+		erval.structure_ptr = sptr;
+		return erval;
+	}
+
+	if(cb && st->buf) {
+		if(cb(st->buf, st->size, app_key) < 0) {
+			erval.encoded = -1;
+			erval.failed_type = td;
+			erval.structure_ptr = sptr;
+			return erval;
+		}
+	} else {
+		assert(st->buf || st->size == 0);
+	}
+
+	erval.encoded += st->size;
+
+	return erval;
+}
+
+void
+ASN__PRIMITIVE_TYPE_free(asn1_TYPE_descriptor_t *td, void *sptr,
+		int contents_only) {
+	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
+
+	if(!td || !sptr)
+		return;
+
+	ASN_DEBUG("Freeing %s as a primitive type", td->name);
+
+	if(st->buf)
+		FREEMEM(st->buf);
+
+	if(!contents_only)
+		FREEMEM(st);
+}
+