structure comparison functions
diff --git a/skeletons/ANY.c b/skeletons/ANY.c
index 3c82561..082f3df 100644
--- a/skeletons/ANY.c
+++ b/skeletons/ANY.c
@@ -16,6 +16,7 @@
 	"ANY",
 	OCTET_STRING_free,
 	OCTET_STRING_print,
+	OCTET_STRING_compare,
 	asn_generic_no_constraint,
 	OCTET_STRING_decode_ber,
 	OCTET_STRING_encode_der,
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index f247359..d87f0d4 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -22,6 +22,7 @@
 	"BIT_STRING",
 	OCTET_STRING_free,         /* Implemented in terms of OCTET STRING */
 	BIT_STRING_print,
+	BIT_STRING_compare,
 	BIT_STRING_constraint,
 	OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */
@@ -200,3 +201,46 @@
 	return 0;
 }
 
+/*
+ * Lexicographically compare the common prefix of both strings,
+ * and if it is the same return -1 for the smallest string.
+ */
+int
+BIT_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+                   const void *bptr) {
+    const BIT_STRING_t *a = aptr;
+    const BIT_STRING_t *b = bptr;
+
+    (void)td;
+
+    if(a && b) {
+        size_t common_prefix_size = a->size <= b->size ? a->size : b->size;
+        int ret = memcmp(a->buf, b->buf, common_prefix_size);
+        if(ret == 0) {
+            /* Figure out which string with equal prefixes is longer. */
+            if(a->size < b->size) {
+                return -1;
+            } else if(a->size > b->size) {
+                return 1;
+            } else {
+                /* Figure out how many unused bits */
+                if(a->bits_unused < b->bits_unused) {
+                    return -1;
+                } else if(a->bits_unused > b->bits_unused) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        } else {
+            return ret;
+        }
+    } else if(!a && !b) {
+        return 0;
+    } else if(!a) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
+
diff --git a/skeletons/BIT_STRING.h b/skeletons/BIT_STRING.h
index f74c433..d66c88e 100644
--- a/skeletons/BIT_STRING.h
+++ b/skeletons/BIT_STRING.h
@@ -24,6 +24,7 @@
 extern asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs;
 
 asn_struct_print_f BIT_STRING_print;	/* Human-readable output */
+asn_struct_compare_f BIT_STRING_compare;
 asn_constr_check_f BIT_STRING_constraint;
 xer_type_encoder_f BIT_STRING_encode_xer;
 
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index 26320b0..5fffc78 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -28,6 +28,7 @@
 	"BMPString",
 	OCTET_STRING_free,          /* Implemented in terms of OCTET STRING */
 	BMPString_print,
+	OCTET_STRING_compare,
 	asn_generic_no_constraint,  /* No constraint by default */
 	OCTET_STRING_decode_ber,
 	OCTET_STRING_encode_der,
diff --git a/skeletons/BMPString.h b/skeletons/BMPString.h
index 80b0854..a3c5ef6 100644
--- a/skeletons/BMPString.h
+++ b/skeletons/BMPString.h
@@ -20,13 +20,14 @@
 xer_type_decoder_f BMPString_decode_xer;
 xer_type_encoder_f BMPString_encode_xer;
 
-#define BMPString_free        OCTET_STRING_free
-#define BMPString_print       BMPString_print
-#define BMPString_constraint  asn_generic_no_constraint
-#define BMPString_decode_ber  OCTET_STRING_decode_ber
-#define BMPString_encode_der  OCTET_STRING_encode_der
-#define BMPString_decode_uper OCTET_STRING_decode_uper
-#define BMPString_encode_uper OCTET_STRING_encode_uper
+#define BMPString_free          OCTET_STRING_free
+#define BMPString_print         BMPString_print
+#define BMPString_compare       OCTET_STRING_compare
+#define BMPString_constraint    asn_generic_no_constraint
+#define BMPString_decode_ber    OCTET_STRING_decode_ber
+#define BMPString_encode_der    OCTET_STRING_encode_der
+#define BMPString_decode_uper   OCTET_STRING_decode_uper
+#define BMPString_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index 735a907..57e7c06 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -17,6 +17,7 @@
 	"BOOLEAN",
 	BOOLEAN_free,
 	BOOLEAN_print,
+	BOOLEAN_compare,
 	asn_generic_no_constraint,
 	BOOLEAN_decode_ber,
 	BOOLEAN_encode_der,
@@ -296,3 +297,27 @@
 
 	ASN__ENCODED_OK(er);
 }
+
+
+int
+BOOLEAN_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+                const void *bptr) {
+    const BOOLEAN_t *a = aptr;
+    const BOOLEAN_t *b = bptr;
+
+    (void)td;
+
+    if(a && b) {
+        if(*a == *b) {
+            return 0;
+        } else if(!*a) {
+            return -1;
+        } else {
+            return 1;
+        }
+    } else if(!a) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
diff --git a/skeletons/BOOLEAN.h b/skeletons/BOOLEAN.h
index 96e50a4..a35e799 100644
--- a/skeletons/BOOLEAN.h
+++ b/skeletons/BOOLEAN.h
@@ -22,6 +22,7 @@
 
 asn_struct_free_f BOOLEAN_free;
 asn_struct_print_f BOOLEAN_print;
+asn_struct_compare_f BOOLEAN_compare;
 ber_type_decoder_f BOOLEAN_decode_ber;
 der_type_encoder_f BOOLEAN_encode_der;
 xer_type_decoder_f BOOLEAN_decode_xer;
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index 34bb9bd..153ce15 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -19,6 +19,7 @@
 	"ENUMERATED",
 	ASN__PRIMITIVE_TYPE_free,
 	INTEGER_print,			/* Implemented in terms of INTEGER */
+	INTEGER_compare,		/* Implemented in terms of INTEGER */
 	asn_generic_no_constraint,
 	ber_decode_primitive,
 	INTEGER_encode_der,		/* Implemented in terms of INTEGER */
diff --git a/skeletons/ENUMERATED.h b/skeletons/ENUMERATED.h
index 8e77736..daa6211 100644
--- a/skeletons/ENUMERATED.h
+++ b/skeletons/ENUMERATED.h
@@ -20,6 +20,7 @@
 
 #define ENUMERATED_free       ASN__PRIMITIVE_TYPE_free
 #define ENUMERATED_print      INTEGER_print
+#define ENUMERATED_compare    INTEGER_compare
 #define ENUMERATED_constraint asn_generic_no_constraint
 #define ENUMERATED_decode_ber ber_decode_primitive
 #define ENUMERATED_encode_der INTEGER_encode_der
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index 0e87d12..805adcb 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -17,6 +17,7 @@
 	"GeneralString",
 	OCTET_STRING_free,
 	OCTET_STRING_print,         /* non-ascii string */
+	OCTET_STRING_compare,
 	asn_generic_unknown_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/GeneralString.h b/skeletons/GeneralString.h
index 508e224..bb56c1f 100644
--- a/skeletons/GeneralString.h
+++ b/skeletons/GeneralString.h
@@ -15,15 +15,16 @@
 
 extern asn_TYPE_descriptor_t asn_DEF_GeneralString;
 
-#define GeneralString_free         OCTET_STRING_free
-#define GeneralString_print        OCTET_STRING_print
-#define GeneralString_constraint   asn_generic_unknown_constraint
-#define GeneralString_decode_ber   OCTET_STRING_decode_ber
-#define GeneralString_encode_der   OCTET_STRING_encode_der
-#define GeneralString_decode_xer   OCTET_STRING_decode_xer_hex
-#define GeneralString_encode_xer   OCTET_STRING_encode_xer
-#define GeneralString_decode_uper  OCTET_STRING_decode_uper
-#define GeneralString_encode_uper  OCTET_STRING_encode_uper
+#define GeneralString_free          OCTET_STRING_free
+#define GeneralString_print         OCTET_STRING_print
+#define GeneralString_compare       OCTET_STRING_compare
+#define GeneralString_constraint    asn_generic_unknown_constraint
+#define GeneralString_decode_ber    OCTET_STRING_decode_ber
+#define GeneralString_encode_der    OCTET_STRING_encode_der
+#define GeneralString_decode_xer    OCTET_STRING_decode_xer_hex
+#define GeneralString_encode_xer    OCTET_STRING_encode_xer
+#define GeneralString_decode_uper   OCTET_STRING_decode_uper
+#define GeneralString_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 40a2f18..90be7cd 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -176,6 +176,7 @@
 	"GeneralizedTime",
 	OCTET_STRING_free,
 	GeneralizedTime_print,
+	OCTET_STRING_compare,   /* Does not normalize time zones! */
 	GeneralizedTime_constraint, /* Check validity of time */
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	GeneralizedTime_encode_der,
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index cb86412..4cd1718 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -17,6 +17,7 @@
 	"GraphicString",
 	OCTET_STRING_free,
 	OCTET_STRING_print,         /* non-ascii string */
+	OCTET_STRING_compare,
 	asn_generic_unknown_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/GraphicString.h b/skeletons/GraphicString.h
index 3f91b50..13da1e6 100644
--- a/skeletons/GraphicString.h
+++ b/skeletons/GraphicString.h
@@ -15,15 +15,16 @@
 
 extern asn_TYPE_descriptor_t asn_DEF_GraphicString;
 
-#define GraphicString_free         OCTET_STRING_free
-#define GraphicString_print        OCTET_STRING_print
-#define GraphicString_constraint   asn_generic_unknown_constraint
-#define GraphicString_decode_ber   OCTET_STRING_decode_ber
-#define GraphicString_encode_der   OCTET_STRING_encode_der
-#define GraphicString_decode_xer   OCTET_STRING_decode_xer_hex
-#define GraphicString_encode_xer   OCTET_STRING_encode_xer
-#define GraphicString_decode_uper  OCTET_STRING_decode_uper
-#define GraphicString_encode_uper  OCTET_STRING_encode_uper
+#define GraphicString_free          OCTET_STRING_free
+#define GraphicString_print         OCTET_STRING_print
+#define GraphicString_compare       OCTET_STRING_compare
+#define GraphicString_constraint    asn_generic_unknown_constraint
+#define GraphicString_decode_ber    OCTET_STRING_decode_ber
+#define GraphicString_encode_der    OCTET_STRING_encode_der
+#define GraphicString_decode_xer    OCTET_STRING_decode_xer_hex
+#define GraphicString_encode_xer    OCTET_STRING_encode_xer
+#define GraphicString_decode_uper   OCTET_STRING_decode_uper
+#define GraphicString_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index 9f51a8e..ec40d94 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -22,6 +22,7 @@
 	"IA5String",
 	OCTET_STRING_free,
 	OCTET_STRING_print_utf8,	/* ASCII subset */
+	OCTET_STRING_compare,
 	IA5String_constraint,       /* Constraint on the alphabet */
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/IA5String.h b/skeletons/IA5String.h
index 6f53dc8..0c6f018 100644
--- a/skeletons/IA5String.h
+++ b/skeletons/IA5String.h
@@ -20,14 +20,15 @@
 
 asn_constr_check_f IA5String_constraint;
 
-#define IA5String_free           OCTET_STRING_free
-#define IA5String_print          OCTET_STRING_print_utf8
-#define IA5String_decode_ber     OCTET_STRING_decode_ber
-#define IA5String_encode_der     OCTET_STRING_encode_der
-#define IA5String_decode_xer     OCTET_STRING_decode_xer_utf8
-#define IA5String_encode_xer     OCTET_STRING_encode_xer_utf8
-#define IA5String_decode_uper    OCTET_STRING_decode_uper
-#define IA5String_encode_uper    OCTET_STRING_encode_uper
+#define IA5String_free          OCTET_STRING_free
+#define IA5String_print         OCTET_STRING_print_utf8
+#define IA5String_compare       OCTET_STRING_compare
+#define IA5String_decode_ber    OCTET_STRING_decode_ber
+#define IA5String_encode_der    OCTET_STRING_encode_der
+#define IA5String_decode_xer    OCTET_STRING_decode_xer_utf8
+#define IA5String_encode_xer    OCTET_STRING_encode_xer_utf8
+#define IA5String_decode_uper   OCTET_STRING_decode_uper
+#define IA5String_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 4e085fb..1a00064 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -19,6 +19,7 @@
 	"INTEGER",
 	INTEGER_free,
 	INTEGER_print,
+    INTEGER_compare,
 	asn_generic_no_constraint,
 	ber_decode_primitive,
 	INTEGER_encode_der,
@@ -1084,3 +1085,46 @@
     return ASN_STRTOX_ERROR_INVAL;
 }
 
+int
+INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+                     const void *bptr) {
+    const INTEGER_t *a = aptr;
+    const INTEGER_t *b = bptr;
+
+    (void)td;
+
+    if(a && b) {
+        if(a->size && b->size) {
+            int sign_a = (a->buf[0] & 0x80) ? -1 : 1;
+            int sign_b = (b->buf[0] & 0x80) ? -1 : 1;
+
+            if(sign_a < sign_b) return -1;
+            if(sign_a > sign_b) return 1;
+
+            /* The shortest integer wins, unless comparing negatives */
+            if(a->size < b->size) {
+                return -1 * sign_a;
+            } else if(a->size > b->size) {
+                return 1 * sign_b;
+            }
+
+            return sign_a * memcmp(a->buf, b->buf, a->size);
+        } else if(a->size) {
+            int sign = (a->buf[0] & 0x80) ? -1 : 1;
+            return (1) * sign;
+        } else if(b->size) {
+            int sign = (a->buf[0] & 0x80) ? -1 : 1;
+            return (-1) * sign;
+        } else {
+            return 0;
+        }
+    } else if(!a && !b) {
+        return 0;
+    } else if(!a) {
+        return -1;
+    } else {
+        return 1;
+    }
+
+}
+
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index e8de019..9903362 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -36,6 +36,7 @@
 
 #define INTEGER_free    ASN__PRIMITIVE_TYPE_free
 asn_struct_print_f INTEGER_print;
+asn_struct_compare_f INTEGER_compare;
 ber_type_decoder_f INTEGER_decode_ber;
 der_type_encoder_f INTEGER_encode_der;
 xer_type_decoder_f INTEGER_decode_xer;
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index 55447f9..30a5459 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -22,6 +22,7 @@
 	"ISO646String",
 	OCTET_STRING_free,
 	OCTET_STRING_print_utf8,	/* ASCII subset */
+	OCTET_STRING_compare,
 	VisibleString_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/ISO646String.h b/skeletons/ISO646String.h
index 6478a2b..683ff0f 100644
--- a/skeletons/ISO646String.h
+++ b/skeletons/ISO646String.h
@@ -16,15 +16,16 @@
 
 extern asn_TYPE_descriptor_t asn_DEF_ISO646String;
 
-#define ISO646String_free         OCTET_STRING_free
-#define ISO646String_print        OCTET_STRING_print_utf8
-#define ISO646String_constraint   VisibleString_constraint
-#define ISO646String_decode_ber   OCTET_STRING_decode_ber
-#define ISO646String_encode_der   OCTET_STRING_encode_der
-#define ISO646String_decode_xer   OCTET_STRING_decode_xer_utf8
-#define ISO646String_encode_xer   OCTET_STRING_encode_xer_utf8
-#define ISO646String_decode_uper  OCTET_STRING_decode_uper
-#define ISO646String_encode_uper  OCTET_STRING_encode_uper
+#define ISO646String_free           OCTET_STRING_free
+#define ISO646String_print          OCTET_STRING_print_utf8
+#define ISO646String_compare        OCTET_STRING_compare
+#define ISO646String_constraint     VisibleString_constraint
+#define ISO646String_decode_ber     OCTET_STRING_decode_ber
+#define ISO646String_encode_der     OCTET_STRING_encode_der
+#define ISO646String_decode_xer     OCTET_STRING_decode_xer_utf8
+#define ISO646String_encode_xer     OCTET_STRING_encode_xer_utf8
+#define ISO646String_decode_uper    OCTET_STRING_decode_uper
+#define ISO646String_encode_uper    OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index 2a88e7e..b5991b8 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -18,6 +18,7 @@
 	"NULL",
 	BOOLEAN_free,
 	NULL_print,
+	NULL_compare,
 	asn_generic_no_constraint,
 	BOOLEAN_decode_ber,	/* Implemented in terms of BOOLEAN */
 	NULL_encode_der,	/* Special handling of DER encoding */
@@ -108,6 +109,14 @@
 }
 
 int
+NULL_compare(const asn_TYPE_descriptor_t *td, const void *a, const void *b) {
+    (void)td;
+    (void)a;
+    (void)b;
+    return 0;
+}
+
+int
 NULL_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	asn_app_consume_bytes_f *cb, void *app_key) {
 
diff --git a/skeletons/NULL.h b/skeletons/NULL.h
index 4c9104b..6b2537c 100644
--- a/skeletons/NULL.h
+++ b/skeletons/NULL.h
@@ -21,6 +21,7 @@
 extern asn_TYPE_descriptor_t asn_DEF_NULL;
 
 asn_struct_print_f NULL_print;
+asn_struct_compare_f NULL_compare;
 der_type_encoder_f NULL_encode_der;
 xer_type_decoder_f NULL_decode_xer;
 xer_type_encoder_f NULL_encode_xer;
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index 9de6dbf..0278657 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -23,6 +23,7 @@
 	"ENUMERATED",
 	NativeInteger_free,
 	NativeInteger_print,
+	NativeInteger_compare,
 	asn_generic_no_constraint,
 	NativeInteger_decode_ber,
 	NativeInteger_encode_der,
diff --git a/skeletons/NativeEnumerated.h b/skeletons/NativeEnumerated.h
index aa3019a..c89ac34 100644
--- a/skeletons/NativeEnumerated.h
+++ b/skeletons/NativeEnumerated.h
@@ -27,6 +27,7 @@
 
 #define NativeEnumerated_free       NativeInteger_free
 #define NativeEnumerated_print      NativeInteger_print
+#define NativeEnumerated_compare    NativeInteger_compare
 #define NativeEnumerated_constraint asn_generic_no_constraint
 #define NativeEnumerated_decode_ber NativeInteger_decode_ber
 #define NativeEnumerated_encode_der NativeInteger_encode_der
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index c49c6d2..38d6f5c 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -24,6 +24,7 @@
 	"INTEGER",
 	NativeInteger_free,
 	NativeInteger_print,
+	NativeInteger_compare,
 	asn_generic_no_constraint,
 	NativeInteger_decode_ber,
 	NativeInteger_encode_der,
@@ -348,3 +349,37 @@
 	}
 }
 
+int
+NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) {
+    (void)td;
+
+    if(aptr && bptr) {
+        const asn_INTEGER_specifics_t *specs =
+            (const asn_INTEGER_specifics_t *)td->specifics;
+        if(specs->field_unsigned)  {
+            const unsigned long *a = aptr;
+            const unsigned long *b = bptr;
+            if(*a < *b) {
+                return -1;
+            } else if(*a > *b) {
+                return 1;
+            } else {
+                return 1;
+            }
+        } else {
+            const long *a = aptr;
+            const long *b = bptr;
+            if(*a < *b) {
+                return -1;
+            } else if(*a > *b) {
+                return 1;
+            } else {
+                return 1;
+            }
+        }
+    } else if(!aptr) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
diff --git a/skeletons/NativeInteger.h b/skeletons/NativeInteger.h
index c57aad1..1816bd3 100644
--- a/skeletons/NativeInteger.h
+++ b/skeletons/NativeInteger.h
@@ -23,6 +23,7 @@
 
 asn_struct_free_f  NativeInteger_free;
 asn_struct_print_f NativeInteger_print;
+asn_struct_compare_f NativeInteger_compare;
 ber_type_decoder_f NativeInteger_decode_ber;
 der_type_encoder_f NativeInteger_encode_der;
 xer_type_decoder_f NativeInteger_decode_xer;
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 0278a92..d9eac63 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -13,6 +13,7 @@
 #include <NativeReal.h>
 #include <REAL.h>
 #include <OCTET_STRING.h>
+#include <math.h>
 
 /*
  * NativeReal basic type description.
@@ -25,6 +26,7 @@
 	"REAL",
 	NativeReal_free,
 	NativeReal_print,
+	NativeReal_compare,
 	asn_generic_no_constraint,
 	NativeReal_decode_ber,
 	NativeReal_encode_der,
@@ -341,6 +343,39 @@
 	return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0;
 }
 
+int
+NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+                   const void *bptr) {
+    const double *a = aptr;
+    const double *b = bptr;
+    (void)td;
+
+    if(a && b) {
+        /* NaN sorted above everything else */
+        if(isnan(*a)) {
+            if(isnan(*b)) {
+                return 0;
+            } else {
+                return -1;
+            }
+        } else if(isnan(*b)) {
+            return 1;
+        }
+        /* Value comparison. */
+        if(*a < *b) {
+            return -1;
+        } else if(*a > *b) {
+            return 1;
+        } else {
+            return 0;
+        }
+    } else if(!a) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
+
 void
 NativeReal_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 
diff --git a/skeletons/NativeReal.h b/skeletons/NativeReal.h
index 884ff69..a307722 100644
--- a/skeletons/NativeReal.h
+++ b/skeletons/NativeReal.h
@@ -21,6 +21,7 @@
 
 asn_struct_free_f  NativeReal_free;
 asn_struct_print_f NativeReal_print;
+asn_struct_compare_f NativeReal_compare;
 ber_type_decoder_f NativeReal_decode_ber;
 der_type_encoder_f NativeReal_encode_der;
 xer_type_decoder_f NativeReal_decode_xer;
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index b0eda2c..a314e51 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -42,6 +42,7 @@
 	"NumericString",
 	OCTET_STRING_free,
 	OCTET_STRING_print_utf8,   /* ASCII subset */
+	OCTET_STRING_compare,
 	NumericString_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/NumericString.h b/skeletons/NumericString.h
index aec4365..d805561 100644
--- a/skeletons/NumericString.h
+++ b/skeletons/NumericString.h
@@ -17,14 +17,15 @@
 
 asn_constr_check_f NumericString_constraint;
 
-#define NumericString_free           OCTET_STRING_free
-#define NumericString_print          OCTET_STRING_print_utf8
-#define NumericString_decode_ber     OCTET_STRING_decode_ber
-#define NumericString_encode_der     OCTET_STRING_encode_der
-#define NumericString_decode_xer     OCTET_STRING_decode_xer_utf8
-#define NumericString_encode_xer     OCTET_STRING_encode_xer_utf8
-#define NumericString_decode_uper    OCTET_STRING_decode_uper
-#define NumericString_encode_uper    OCTET_STRING_encode_uper
+#define NumericString_free          OCTET_STRING_free
+#define NumericString_print         OCTET_STRING_print_utf8
+#define NumericString_compare       OCTET_STRING_compare
+#define NumericString_decode_ber    OCTET_STRING_decode_ber
+#define NumericString_encode_der    OCTET_STRING_encode_der
+#define NumericString_decode_xer    OCTET_STRING_decode_xer_utf8
+#define NumericString_encode_xer    OCTET_STRING_encode_xer_utf8
+#define NumericString_decode_uper   OCTET_STRING_decode_uper
+#define NumericString_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index a3d9e72..18a23db 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -20,6 +20,7 @@
 	"OBJECT_IDENTIFIER",
 	ASN__PRIMITIVE_TYPE_free,
 	OBJECT_IDENTIFIER_print,
+	OCTET_STRING_compare,   /* Implemented in terms of a string comparison */
 	OBJECT_IDENTIFIER_constraint,
 	ber_decode_primitive,
 	der_encode_primitive,
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index c145631..62ad6c9 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -28,7 +28,8 @@
 	"OCTET STRING",		/* Canonical name */
 	"OCTET_STRING",		/* XML tag name */
 	OCTET_STRING_free,
-	OCTET_STRING_print,	/* non-ascii stuff, generally */
+	OCTET_STRING_print,	/* OCTET STRING generally means a non-ascii sequence */
+	OCTET_STRING_compare,
 	asn_generic_no_constraint,
 	OCTET_STRING_decode_ber,
 	OCTET_STRING_encode_der,
@@ -1820,3 +1821,40 @@
 	return st;
 }
 
+/*
+ * Lexicographically compare the common prefix of both strings,
+ * and if it is the same return -1 for the smallest string.
+ */
+int
+OCTET_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+                     const void *bptr) {
+    const OCTET_STRING_t *a = aptr;
+    const OCTET_STRING_t *b = bptr;
+
+    (void)td;
+
+    if(a && b) {
+        size_t common_prefix_size = a->size <= b->size ? a->size : b->size;
+        int ret = memcmp(a->buf, b->buf, common_prefix_size);
+        if(ret == 0) {
+            /* Figure out which string with equal prefixes is longer. */
+            if(a->size < b->size) {
+                return -1;
+            } else if(a->size > b->size) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else {
+            return ret;
+        }
+    } else if(!a && !b) {
+        return 0;
+    } else if(!a) {
+        return -1;
+    } else {
+        return 1;
+    }
+
+}
+
diff --git a/skeletons/OCTET_STRING.h b/skeletons/OCTET_STRING.h
index 63e7da8..fa40a0d 100644
--- a/skeletons/OCTET_STRING.h
+++ b/skeletons/OCTET_STRING.h
@@ -23,6 +23,7 @@
 asn_struct_free_f OCTET_STRING_free;
 asn_struct_print_f OCTET_STRING_print;
 asn_struct_print_f OCTET_STRING_print_utf8;
+asn_struct_compare_f OCTET_STRING_compare;
 ber_type_decoder_f OCTET_STRING_decode_ber;
 der_type_encoder_f OCTET_STRING_encode_der;
 xer_type_decoder_f OCTET_STRING_decode_xer_hex;		/* Hexadecimal */
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index ba539f8..b80b69e 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -17,6 +17,7 @@
 	"ObjectDescriptor",
 	OCTET_STRING_free,
 	OCTET_STRING_print_utf8,   /* Treat as ASCII subset (it's not) */
+	OCTET_STRING_compare,
 	asn_generic_unknown_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 4085aed..5e0e4b7 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -52,6 +52,7 @@
 	"PrintableString",
 	OCTET_STRING_free,
 	OCTET_STRING_print_utf8,	/* ASCII subset */
+	OCTET_STRING_compare,
 	PrintableString_constraint,
 	OCTET_STRING_decode_ber,      /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/PrintableString.h b/skeletons/PrintableString.h
index 19a6bbb..70f07b7 100644
--- a/skeletons/PrintableString.h
+++ b/skeletons/PrintableString.h
@@ -17,14 +17,15 @@
 
 asn_constr_check_f PrintableString_constraint;
 
-#define PrintableString_free           OCTET_STRING_free
-#define PrintableString_print          OCTET_STRING_print_utf8
-#define PrintableString_decode_ber     OCTET_STRING_decode_ber
-#define PrintableString_encode_der     OCTET_STRING_encode_der
-#define PrintableString_decode_xer     OCTET_STRING_decode_xer_utf8
-#define PrintableString_encode_xer     OCTET_STRING_encode_xer_utf8
-#define PrintableString_decode_uper    OCTET_STRING_decode_uper
-#define PrintableString_encode_uper    OCTET_STRING_encode_uper
+#define PrintableString_free            OCTET_STRING_free
+#define PrintableString_print           OCTET_STRING_print_utf8
+#define PrintableString_compare         OCTET_STRING_compare
+#define PrintableString_decode_ber      OCTET_STRING_decode_ber
+#define PrintableString_encode_der      OCTET_STRING_encode_der
+#define PrintableString_decode_xer      OCTET_STRING_decode_xer_utf8
+#define PrintableString_encode_xer      OCTET_STRING_encode_xer_utf8
+#define PrintableString_decode_uper     OCTET_STRING_decode_uper
+#define PrintableString_encode_uper     OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 4761b6d..ce03522 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -42,38 +42,40 @@
 	(ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
 };
 asn_TYPE_descriptor_t asn_DEF_REAL = {
-	"REAL",
-	"REAL",
-	ASN__PRIMITIVE_TYPE_free,
-	REAL_print,
-	asn_generic_no_constraint,
-	ber_decode_primitive,
-	der_encode_primitive,
-	REAL_decode_xer,
-	REAL_encode_xer,
+    "REAL",
+    "REAL",
+    ASN__PRIMITIVE_TYPE_free,
+    REAL_print,
+    REAL_compare,
+    asn_generic_no_constraint,
+    ber_decode_primitive,
+    der_encode_primitive,
+    REAL_decode_xer,
+    REAL_encode_xer,
 #ifdef	ASN_DISABLE_OER_SUPPORT
-	0,
-	0,
+    0,
+    0,
 #else
-	0,
-	0,
+    0,
+    0,
 #endif  /* ASN_DISABLE_OER_SUPPORT */
 #ifdef	ASN_DISABLE_PER_SUPPORT
-	0,
-	0,
+    0,
+    0,
 #else
-	REAL_decode_uper,
-	REAL_encode_uper,
+    REAL_decode_uper,
+    REAL_encode_uper,
 #endif	/* ASN_DISABLE_PER_SUPPORT */
-	0, /* Use generic outmost tag fetcher */
-	asn_DEF_REAL_tags,
-	sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
-	asn_DEF_REAL_tags,	/* Same as above */
-	sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
-	0,	/* No OER visible constraints */
-	0,	/* No PER visible constraints */
-	0, 0,	/* No members */
-	0	/* No specifics */
+    0,  /* Use generic outmost tag fetcher */
+    asn_DEF_REAL_tags,
+    sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
+    asn_DEF_REAL_tags, /* Same as above */
+    sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
+    0, /* No OER visible constraints */
+    0, /* No PER visible constraints */
+    0,
+    0, /* No members */
+    0  /* No specifics */
 };
 
 typedef enum specialRealValue {
@@ -292,6 +294,49 @@
 	return (ret < 0) ? -1 : 0;
 }
 
+int
+REAL_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+             const void *bptr) {
+    const REAL_t *a = aptr;
+    const REAL_t *b = bptr;
+
+    (void)td;
+
+    if(a && b) {
+        double adbl, bdbl;
+        int ra, rb;
+        ra = asn_REAL2double(a, &adbl);
+        rb = asn_REAL2double(b, &bdbl);
+        if(ra == 0 && rb == 0) {
+            if(isnan(adbl)) {
+                if(isnan(bdbl)) {
+                    return 0;
+                } else {
+                    return -1;
+                }
+            } else if(isnan(bdbl)) {
+                return 1;
+            }
+            /* Value comparison. */
+            if(adbl < bdbl) {
+                return -1;
+            } else if(adbl > bdbl) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if(ra) {
+            return -1;
+        } else {
+            return 1;
+        }
+    } else if(!a) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
+
 asn_enc_rval_t
 REAL_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
 	int ilevel, enum xer_encoder_flags_e flags,
diff --git a/skeletons/REAL.h b/skeletons/REAL.h
index 668f786..227c4b4 100644
--- a/skeletons/REAL.h
+++ b/skeletons/REAL.h
@@ -17,6 +17,7 @@
 extern asn_TYPE_descriptor_t asn_DEF_REAL;
 
 asn_struct_print_f REAL_print;
+asn_struct_compare_f REAL_compare;
 xer_type_decoder_f REAL_decode_xer;
 xer_type_encoder_f REAL_encode_xer;
 per_type_decoder_f REAL_decode_uper;
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 3d1d415..9efd90d 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -21,6 +21,7 @@
 	"RELATIVE_OID",
 	ASN__PRIMITIVE_TYPE_free,
 	RELATIVE_OID_print,
+	OCTET_STRING_compare,   /* Implemented in terms of opaque comparison */
 	asn_generic_no_constraint,
 	ber_decode_primitive,
 	der_encode_primitive,
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index afea666..694d2a0 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -17,6 +17,7 @@
 	"T61String",
 	OCTET_STRING_free,
 	OCTET_STRING_print,         /* non-ascii string */
+	OCTET_STRING_compare,
 	asn_generic_unknown_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/T61String.h b/skeletons/T61String.h
index 6a8b874..3c2d72f 100644
--- a/skeletons/T61String.h
+++ b/skeletons/T61String.h
@@ -15,15 +15,16 @@
 
 extern asn_TYPE_descriptor_t asn_DEF_T61String;
 
-#define T61String_free         OCTET_STRING_free
-#define T61String_print        OCTET_STRING_print
-#define T61String_constraint   asn_generic_unknown_constraint
-#define T61String_decode_ber   OCTET_STRING_decode_ber
-#define T61String_encode_der   OCTET_STRING_encode_der
-#define T61String_decode_xer   OCTET_STRING_decode_xer_hex
-#define T61String_encode_xer   OCTET_STRING_encode_xer
-#define T61String_decode_uper  OCTET_STRING_decode_uper
-#define T61String_encode_uper  OCTET_STRING_encode_uper
+#define T61String_free          OCTET_STRING_free
+#define T61String_print         OCTET_STRING_print
+#define T61String_compare       OCTET_STRING_compare
+#define T61String_constraint    asn_generic_unknown_constraint
+#define T61String_decode_ber    OCTET_STRING_decode_ber
+#define T61String_encode_der    OCTET_STRING_encode_der
+#define T61String_decode_xer    OCTET_STRING_decode_xer_hex
+#define T61String_encode_xer    OCTET_STRING_encode_xer
+#define T61String_decode_uper   OCTET_STRING_decode_uper
+#define T61String_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index d1b4070..15969b1 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -17,6 +17,7 @@
 	"TeletexString",
 	OCTET_STRING_free,
 	OCTET_STRING_print,         /* non-ascii string */
+	OCTET_STRING_compare,
 	asn_generic_unknown_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/TeletexString.h b/skeletons/TeletexString.h
index cec5548..5a756fb 100644
--- a/skeletons/TeletexString.h
+++ b/skeletons/TeletexString.h
@@ -15,15 +15,16 @@
 
 extern asn_TYPE_descriptor_t asn_DEF_TeletexString;
 
-#define TeletexString_free           OCTET_STRING_free
-#define TeletexString_print          OCTET_STRING_print
-#define TeletexString_constraint     asn_generic_unknown_constraint
-#define TeletexString_decode_ber     OCTET_STRING_decode_ber
-#define TeletexString_encode_der     OCTET_STRING_encode_der
-#define TeletexString_decode_xer     OCTET_STRING_decode_xer_hex
-#define TeletexString_encode_xer     OCTET_STRING_encode_xer
-#define TeletexString_decode_uper    OCTET_STRING_decode_uper
-#define TeletexString_encode_uper    OCTET_STRING_encode_uper
+#define TeletexString_free          OCTET_STRING_free
+#define TeletexString_print         OCTET_STRING_print
+#define TeletexString_compare       OCTET_STRING_compare
+#define TeletexString_constraint    asn_generic_unknown_constraint
+#define TeletexString_decode_ber    OCTET_STRING_decode_ber
+#define TeletexString_encode_der    OCTET_STRING_encode_der
+#define TeletexString_decode_xer    OCTET_STRING_decode_xer_hex
+#define TeletexString_encode_xer    OCTET_STRING_encode_xer
+#define TeletexString_decode_uper   OCTET_STRING_decode_uper
+#define TeletexString_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index bae698e..04776d7 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -33,6 +33,7 @@
 	"UTCTime",
 	OCTET_STRING_free,
 	UTCTime_print,
+	OCTET_STRING_compare,   /* Does not deal with time zones. */
 	UTCTime_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,    /* Implemented in terms of OCTET STRING */
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 330d968..de78c5e 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -18,6 +18,7 @@
 	"UTF8String",
 	OCTET_STRING_free,
 	UTF8String_print,
+	OCTET_STRING_compare,
 	UTF8String_constraint,      /* Check for invalid codes, etc. */
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/UTF8String.h b/skeletons/UTF8String.h
index 6713252..ca2f0e5 100644
--- a/skeletons/UTF8String.h
+++ b/skeletons/UTF8String.h
@@ -19,6 +19,7 @@
 asn_constr_check_f UTF8String_constraint;
 
 #define UTF8String_free         OCTET_STRING_free
+#define UTF8String_compare      OCTET_STRING_compare
 #define UTF8String_constraint   UTF8String_constraint
 #define UTF8String_decode_ber   OCTET_STRING_decode_ber
 #define UTF8String_encode_der   OCTET_STRING_encode_der
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index 59d8345..3f0344e 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -28,6 +28,7 @@
 	"UniversalString",
 	OCTET_STRING_free,
 	UniversalString_print,      /* Convert into UTF8 and print */
+	OCTET_STRING_compare,
 	asn_generic_no_constraint,
 	OCTET_STRING_decode_ber,
 	OCTET_STRING_encode_der,
diff --git a/skeletons/UniversalString.h b/skeletons/UniversalString.h
index 48eb49d..885e5ab 100644
--- a/skeletons/UniversalString.h
+++ b/skeletons/UniversalString.h
@@ -20,6 +20,13 @@
 xer_type_decoder_f UniversalString_decode_xer;
 xer_type_encoder_f UniversalString_encode_xer;
 
+#define UniversalString_free            OCTET_STRING_free
+#define UniversalString_compare         OCTET_STRING_compare
+#define UniversalString_decode_ber      OCTET_STRING_decode_ber
+#define UniversalString_encode_der      OCTET_STRING_encode_der
+#define UniversalString_decode_uper     OCTET_STRING_decode_uper
+#define UniversalString_encode_uper     OCTET_STRING_encode_uper
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index 46e127b..f377e2e 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -17,6 +17,7 @@
 	"VideotexString",
 	OCTET_STRING_free,
 	OCTET_STRING_print,         /* non-ascii string */
+	OCTET_STRING_compare,
 	asn_generic_unknown_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/VideotexString.h b/skeletons/VideotexString.h
index a1a6b81..f8befb7 100644
--- a/skeletons/VideotexString.h
+++ b/skeletons/VideotexString.h
@@ -17,6 +17,7 @@
 
 #define VideotexString_free         OCTET_STRING_free
 #define VideotexString_print        OCTET_STRING_print
+#define VideotexString_compare      OCTET_STRING_compare
 #define VideotexString_constraint   asn_generic_unknown_constraint
 #define VideotexString_decode_ber   OCTET_STRING_decode_ber
 #define VideotexString_encode_der   OCTET_STRING_encode_der
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index 2a09b8a..9a74a83 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -22,6 +22,7 @@
 	"VisibleString",
 	OCTET_STRING_free,
 	OCTET_STRING_print_utf8,   /* ASCII subset */
+	OCTET_STRING_compare,
 	VisibleString_constraint,
 	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
 	OCTET_STRING_encode_der,
diff --git a/skeletons/VisibleString.h b/skeletons/VisibleString.h
index 37080d8..e16ae49 100644
--- a/skeletons/VisibleString.h
+++ b/skeletons/VisibleString.h
@@ -17,15 +17,16 @@
 
 asn_constr_check_f VisibleString_constraint;
 
-#define VisibleString_free         OCTET_STRING_free
-#define VisibleString_print        OCTET_STRING_print
-#define VisibleString_constraint   VisibleString_constraint
-#define VisibleString_decode_ber   OCTET_STRING_decode_ber
-#define VisibleString_encode_der   OCTET_STRING_encode_der
-#define VisibleString_decode_xer   OCTET_STRING_decode_xer_hex
-#define VisibleString_encode_xer   OCTET_STRING_encode_xer
-#define VisibleString_decode_uper  OCTET_STRING_decode_uper
-#define VisibleString_encode_uper  OCTET_STRING_encode_uper
+#define VisibleString_free          OCTET_STRING_free
+#define VisibleString_print         OCTET_STRING_print
+#define VisibleString_compare       OCTET_STRING_compare
+#define VisibleString_constraint    VisibleString_constraint
+#define VisibleString_decode_ber    OCTET_STRING_decode_ber
+#define VisibleString_encode_der    OCTET_STRING_encode_der
+#define VisibleString_decode_xer    OCTET_STRING_decode_xer_hex
+#define VisibleString_encode_xer    OCTET_STRING_encode_xer
+#define VisibleString_decode_uper   OCTET_STRING_decode_uper
+#define VisibleString_encode_uper   OCTET_STRING_encode_uper
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 04cc4b7..e7adbf7 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -63,8 +63,11 @@
 /*
  * See the definitions.
  */
-static int _fetch_present_idx(const void *struct_ptr, int off, int size);
+static signed _fetch_present_idx(const void *struct_ptr, int off, int size);
 static void _set_present_idx(void *sptr, int offset, int size, int pres);
+static const void *_get_member_ptr(const asn_TYPE_descriptor_t *,
+                                   const void *sptr, asn_TYPE_member_t **elm,
+                                   signed *present);
 
 /*
  * Tags are canonically sorted in the tag to member table.
@@ -362,7 +365,7 @@
 	asn_enc_rval_t erval;
 	void *memb_ptr;
 	size_t computed_size = 0;
-	int present;
+	signed present;
 
 	if(!sptr) ASN__ENCODE_FAILED;
 
@@ -447,7 +450,7 @@
 ber_tlv_tag_t
 CHOICE_outmost_tag(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
 	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
-	int present;
+	signed present;
 
 	assert(tag_mode == 0); (void)tag_mode;
 	assert(tag == 0); (void)tag;
@@ -480,7 +483,7 @@
 CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
-	int present;
+	signed present;
 
 	if(!sptr) {
 		ASN__CTFAIL(app_key, td, sptr,
@@ -777,7 +780,7 @@
 		asn_app_consume_bytes_f *cb, void *app_key) {
 	asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics;
 	asn_enc_rval_t er;
-	int present;
+	signed present;
 
 	if(!sptr)
 		ASN__ENCODE_FAILED;
@@ -914,7 +917,7 @@
 	asn_TYPE_member_t *elm;	/* CHOICE's element */
 	const asn_per_constraint_t *ct;
 	void *memb_ptr;
-	int present;
+	signed present;
 	int present_enc;
 
 	if(!sptr) ASN__ENCODE_FAILED;
@@ -995,7 +998,7 @@
 CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 		asn_app_consume_bytes_f *cb, void *app_key) {
 	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
-	int present;
+	signed present;
 
 	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
@@ -1035,7 +1038,7 @@
 void
 CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
-	int present;
+	signed present;
 
 	if(!td || !ptr)
 		return;
@@ -1079,10 +1082,10 @@
  * is guaranteed to be aligned properly. ASN.1 compiler itself does not
  * produce packed code.
  */
-static int
+static signed
 _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
 	const void *present_ptr;
-	int present;
+	signed present;
 
 	present_ptr = ((const char *)struct_ptr) + pres_offset;
 
@@ -1113,3 +1116,69 @@
 		assert(pres_size != sizeof(int));
 	}
 }
+
+static const void *
+_get_member_ptr(const asn_TYPE_descriptor_t *td, const void *sptr,
+                asn_TYPE_member_t **elm_ptr, signed *present_out) {
+    asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+    signed present;
+
+    if(!sptr) {
+        *elm_ptr = NULL;
+        *present_out = 0;
+        return NULL;
+    }
+
+    /*
+	 * Figure out which CHOICE element is encoded.
+	 */
+	present = _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
+    *present_out = present;
+
+    /*
+     * The presence index is intentionally 1-based to avoid
+     * treating zeroed structure as a valid one.
+     */
+	if(present > 0 && (unsigned)present <= td->elements_count) {
+        asn_TYPE_member_t *const elm = &td->elements[present - 1];
+        const void *memb_ptr;
+
+		if(elm->flags & ATF_POINTER) {
+            memb_ptr =
+                *(const void *const *)((const char *)sptr + elm->memb_offset);
+        } else {
+            memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
+        }
+        *elm_ptr = elm;
+        return memb_ptr;
+    } else {
+        *elm_ptr = NULL;
+        return NULL;
+    }
+
+}
+
+int
+CHOICE_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) {
+    asn_TYPE_member_t *aelm;
+    asn_TYPE_member_t *belm;
+    signed apresent = 0;
+    signed bpresent = 0;
+    const void *amember = _get_member_ptr(td, aptr, &aelm, &apresent);
+    const void *bmember = _get_member_ptr(td, bptr, &belm, &apresent);
+
+    if(amember && bmember) {
+        if(apresent == bpresent) {
+            assert(aelm == belm);
+            return aelm->type->compare_struct(aelm->type, amember, bmember);
+        } else if(apresent < bpresent) {
+            return -1;
+        } else {
+            return 1;
+        }
+    } else if(!amember) {
+        return -1;
+    } else {
+        return 1;
+    }
+}
diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h
index 85b06ea..c30c181 100644
--- a/skeletons/constr_CHOICE.h
+++ b/skeletons/constr_CHOICE.h
@@ -41,6 +41,7 @@
  */
 asn_struct_free_f CHOICE_free;
 asn_struct_print_f CHOICE_print;
+asn_struct_compare_f CHOICE_compare;
 asn_constr_check_f CHOICE_constraint;
 ber_type_decoder_f CHOICE_decode_ber;
 der_type_encoder_f CHOICE_encode_der;
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 15c12e2..a64310d 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
  * All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
@@ -1427,3 +1427,37 @@
 	ASN__ENCODED_OK(er);
 }
 
+int
+SEQUENCE_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+                 const void *bptr) {
+    size_t edx;
+
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		const void *amemb;
+		const void *bmemb;
+        int ret;
+
+		if(elm->flags & ATF_POINTER) {
+            amemb =
+                *(const void *const *)((const char *)aptr + elm->memb_offset);
+            bmemb =
+                *(const void *const *)((const char *)bptr + elm->memb_offset);
+            if(!amemb) {
+                if(!bmemb) continue;
+                return -1;
+            } else if(!bmemb) {
+                return 1;
+            }
+		} else {
+            amemb = (const void *)((const char *)aptr + elm->memb_offset);
+            bmemb = (const void *)((const char *)bptr + elm->memb_offset);
+		}
+
+        ret = elm->type->compare_struct(elm->type, amemb, bmemb);
+        if(ret != 0) return ret;
+    }
+
+    return 0;
+}
+
diff --git a/skeletons/constr_SEQUENCE.h b/skeletons/constr_SEQUENCE.h
index a9890de..cae9c3c 100644
--- a/skeletons/constr_SEQUENCE.h
+++ b/skeletons/constr_SEQUENCE.h
@@ -45,6 +45,7 @@
  */
 asn_struct_free_f SEQUENCE_free;
 asn_struct_print_f SEQUENCE_print;
+asn_struct_compare_f SEQUENCE_compare;
 asn_constr_check_f SEQUENCE_constraint;
 ber_type_decoder_f SEQUENCE_decode_ber;
 der_type_encoder_f SEQUENCE_encode_der;
diff --git a/skeletons/constr_SEQUENCE_OF.h b/skeletons/constr_SEQUENCE_OF.h
index e2272f3..cc7f370 100644
--- a/skeletons/constr_SEQUENCE_OF.h
+++ b/skeletons/constr_SEQUENCE_OF.h
@@ -18,6 +18,7 @@
  */
 #define	SEQUENCE_OF_free	SET_OF_free
 #define	SEQUENCE_OF_print	SET_OF_print
+#define	SEQUENCE_OF_compare SET_OF_compare
 #define	SEQUENCE_OF_constraint	SET_OF_constraint
 #define	SEQUENCE_OF_decode_ber	SET_OF_decode_ber
 #define	SEQUENCE_OF_decode_xer	SET_OF_decode_xer
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index a4f276a..226bef3 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -987,3 +987,38 @@
 
 	return 0;
 }
+
+int
+SET_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+            const void *bptr) {
+    size_t edx;
+
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn_TYPE_member_t *elm = &td->elements[edx];
+		const void *amemb;
+		const void *bmemb;
+        int ret;
+
+		if(elm->flags & ATF_POINTER) {
+            amemb =
+                *(const void *const *)((const char *)aptr + elm->memb_offset);
+            bmemb =
+                *(const void *const *)((const char *)bptr + elm->memb_offset);
+            if(!amemb) {
+                if(!bmemb) continue;
+                return -1;
+            } else if(!bmemb) {
+                return 1;
+            }
+		} else {
+            amemb = (const void *)((const char *)aptr + elm->memb_offset);
+            bmemb = (const void *)((const char *)bptr + elm->memb_offset);
+		}
+
+        ret = elm->type->compare_struct(elm->type, amemb, bmemb);
+        if(ret != 0) return ret;
+    }
+
+    return 0;
+}
+
diff --git a/skeletons/constr_SET.h b/skeletons/constr_SET.h
index 702bc05..4bafffe 100644
--- a/skeletons/constr_SET.h
+++ b/skeletons/constr_SET.h
@@ -47,6 +47,7 @@
  */
 asn_struct_free_f SET_free;
 asn_struct_print_f SET_print;
+asn_struct_compare_f SET_compare;
 asn_constr_check_f SET_constraint;
 ber_type_decoder_f SET_decode_ber;
 der_type_encoder_f SET_encode_der;
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index 51291b8..62973ac 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -953,3 +953,12 @@
 	return rv;
 }
 
+int
+SET_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
+               const void *bptr) {
+    (void)td;
+    (void)aptr;
+    (void)bptr;
+    /* Not implemented yet. */
+    return 0;
+}
diff --git a/skeletons/constr_SET_OF.h b/skeletons/constr_SET_OF.h
index 75e18cf..a77931d 100644
--- a/skeletons/constr_SET_OF.h
+++ b/skeletons/constr_SET_OF.h
@@ -27,6 +27,7 @@
  */
 asn_struct_free_f SET_OF_free;
 asn_struct_print_f SET_OF_print;
+asn_struct_compare_f SET_OF_compare;
 asn_constr_check_f SET_OF_constraint;
 ber_type_decoder_f SET_OF_decode_ber;
 der_type_encoder_f SET_OF_encode_der;
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index 6fc618b..29961e3 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -69,6 +69,17 @@
 		asn_app_consume_bytes_f *callback, void *app_key);
 
 /*
+ * Compare two structs between each other.
+ * Returns <0 if struct_A is "smaller" than struct_B, >0 if "greater",
+ * and =0 if "equal to", for some type-specific, stable definition of
+ * "smaller", "greater" and "equal to".
+ */
+typedef int (asn_struct_compare_f)(
+		const struct asn_TYPE_descriptor_s *type_descriptor,
+		const void *struct_A,
+		const void *struct_B);
+
+/*
  * Return the outmost tag of the type.
  * If the type is untagged CHOICE, the dynamic operation is performed.
  * NOTE: This function pointer type is only useful internally.
@@ -94,6 +105,7 @@
 	 */
 	asn_struct_free_f  *free_struct;	/* Free the structure */
 	asn_struct_print_f *print_struct;	/* Human readable output */
+	asn_struct_compare_f *compare_struct;	/* Compare two structures */
 	asn_constr_check_f *check_constraints;	/* Constraints validator */
 	ber_type_decoder_f *ber_decoder;	/* Generic BER decoder */
 	der_type_encoder_f *der_encoder;	/* Canonical DER encoder */