add OER binary32 and binary64 IEEE-754 formats for native REAL type
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 419e7d1..da3d328 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -78,40 +78,12 @@
 	0	/* No specifics */
 };
 
-static double
-NativeReal__get_double(const asn_TYPE_descriptor_t *td, const void *ptr) {
-    const asn_NativeReal_specifics_t *specs =
-        (const asn_NativeReal_specifics_t *)td->specifics;
-    size_t float_size = specs ? specs->float_size : sizeof(double);
-    if(float_size == sizeof(float)) {
-        return *(const float *)ptr;
-    } else {
-        return *(const double *)ptr;
-    }
-}
-
-static ssize_t  /* Returns -1 or float size. */
-NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr, double d) {
-    const asn_NativeReal_specifics_t *specs =
-        (const asn_NativeReal_specifics_t *)td->specifics;
-    size_t float_size = specs ? specs->float_size : sizeof(double);
-    void *native;
-
-    if(!(native = *sptr)) {
-        native = (*sptr = CALLOC(1, float_size));
-        if(!native) {
-            return -1;
-        }
-    }
-
-    if(float_size == sizeof(float)) {
-        *(float *)native = d;
-    } else {
-        *(double *)native = d;
-    }
-
-    return float_size;
-}
+static double NativeReal__get_double(const asn_TYPE_descriptor_t *td,
+                                     const void *ptr);
+static ssize_t NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr,
+                               double d);
+static void NativeReal__network_swap(size_t float_size, const void *srcp,
+                                     uint8_t *dst);
 
 /*
  * Decode REAL type.
@@ -302,30 +274,61 @@
 NativeReal_encode_oer(asn_TYPE_descriptor_t *td,
                    const asn_oer_constraints_t *constraints, void *sptr,
                    asn_app_consume_bytes_f *cb, void *app_key) {
-    double d = NativeReal__get_double(td, sptr);
-    asn_enc_rval_t er = { 0, 0, 0 };
-    ssize_t len_len;
-    REAL_t tmp;
+    asn_enc_rval_t er = {0, 0, 0};
 
-	/* Prepare a temporary clean structure */
-	memset(&tmp, 0, sizeof(tmp));
+    if(!constraints) constraints = td->encoding_constraints.oer_constraints;
+    if(constraints && constraints->value.width != 0) {
+        /* X.696 IEEE 754 binary32 and binary64 encoding */
+        uint8_t scratch[sizeof(double)];
+        const asn_NativeReal_specifics_t *specs =
+            (const asn_NativeReal_specifics_t *)td->specifics;
+        size_t wire_size = constraints->value.width;
 
-    (void)td;
-    (void)constraints;  /* Constraints are unused in OER */
+        if(specs ? (wire_size == specs->float_size)
+                 : (wire_size == sizeof(double))) {
+            /*
+             * Our representation matches the wire, modulo endianness.
+             * That was the whole point of compact encoding!
+             */
+        } else {
+            assert(wire_size == sizeof(double)
+                   || specs && specs->float_size == wire_size);
+            ASN__ENCODE_FAILED;
+        }
 
-    if(asn_double2REAL(&tmp, d)) {
-        ASN__ENCODE_FAILED;
-	}
-
-    /* Encode a fake REAL */
-    len_len = oer_serialize_length(tmp.size, cb, app_key);
-    if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
-        ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
-        ASN__ENCODE_FAILED;
+        /*
+         * The X.696 standard doesn't specify endianness, neither is IEEE 754.
+         * So we assume the network format is big endian.
+         */
+        NativeReal__network_swap(wire_size, sptr, scratch);
+        if(cb(scratch, wire_size, app_key) < 0) {
+            ASN__ENCODE_FAILED;
+        } else {
+            er.encoded = wire_size;
+            ASN__ENCODED_OK(er);
+        }
     } else {
-        er.encoded = len_len + tmp.size;
-        ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
-        ASN__ENCODED_OK(er);
+        double d = NativeReal__get_double(td, sptr);
+        ssize_t len_len;
+        REAL_t tmp;
+
+        /* Prepare a temporary clean structure */
+        memset(&tmp, 0, sizeof(tmp));
+
+        if(asn_double2REAL(&tmp, d)) {
+            ASN__ENCODE_FAILED;
+        }
+
+        /* Encode a fake REAL */
+        len_len = oer_serialize_length(tmp.size, cb, app_key);
+        if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
+            ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+            ASN__ENCODE_FAILED;
+        } else {
+            er.encoded = len_len + tmp.size;
+            ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+            ASN__ENCODED_OK(er);
+        }
     }
 }
 
@@ -340,7 +343,38 @@
     size_t real_body_len;
 
     (void)opt_codec_ctx;
-    (void)constraints; /* Constraints are unused in OER */
+
+    if(!constraints) constraints = td->encoding_constraints.oer_constraints;
+    if(constraints && constraints->value.width != 0) {
+        /* X.696 IEEE 754 binary32 and binary64 encoding */
+        uint8_t scratch[sizeof(double)];
+        size_t wire_size = constraints->value.width;
+
+        if(size < wire_size)
+            ASN__DECODE_STARVED;
+
+        /*
+         * The X.696 standard doesn't specify endianness, neither is IEEE 754.
+         * So we assume the network format is big endian.
+         */
+        NativeReal__network_swap(wire_size, ptr, scratch);
+
+        switch(wire_size) {
+        case sizeof(double):
+            if(NativeReal__set(td, sptr, *(const double *)scratch) < 0)
+                ASN__DECODE_FAILED;
+            break;
+        case sizeof(float):
+            if(NativeReal__set(td, sptr, *(const float *)scratch) < 0)
+                ASN__DECODE_FAILED;
+            break;
+        default:
+            ASN__DECODE_FAILED;
+        }
+
+        ok.consumed = wire_size;
+        return ok;
+    }
 
     len_len = oer_fetch_length(ptr, size, &real_body_len);
     if(len_len < 0) ASN__DECODE_FAILED;
@@ -541,3 +575,99 @@
     result_ok.length = float_set_size;
     return result_ok;
 }
+
+
+/*
+ * Local helper functions.
+ */
+
+static double
+NativeReal__get_double(const asn_TYPE_descriptor_t *td, const void *ptr) {
+    const asn_NativeReal_specifics_t *specs =
+        (const asn_NativeReal_specifics_t *)td->specifics;
+    size_t float_size = specs ? specs->float_size : sizeof(double);
+    if(float_size == sizeof(float)) {
+        return *(const float *)ptr;
+    } else {
+        return *(const double *)ptr;
+    }
+}
+
+static ssize_t  /* Returns -1 or float size. */
+NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr, double d) {
+    const asn_NativeReal_specifics_t *specs =
+        (const asn_NativeReal_specifics_t *)td->specifics;
+    size_t float_size = specs ? specs->float_size : sizeof(double);
+    void *native;
+
+    if(!(native = *sptr)) {
+        native = (*sptr = CALLOC(1, float_size));
+        if(!native) {
+            return -1;
+        }
+    }
+
+    if(float_size == sizeof(float)) {
+        *(float *)native = d;
+    } else {
+        *(double *)native = d;
+    }
+
+    return float_size;
+}
+
+/*
+ * Swap bytes from/to network, if local is little-endian.
+ * Unused endianness sections are likely removed at compile phase.
+ */
+static void
+NativeReal__network_swap(size_t float_size, const void *srcp, uint8_t *dst) {
+    const uint8_t *src = srcp;
+    double test = -0.0;
+    int float_big_endian = *(const char *)&test != 0;
+    /* In lieu of static_assert(sizeof(double) == 8) */
+    static const char sizeof_double_is_8_a[sizeof(double)-7] CC_NOTUSED;
+    static const char sizeof_double_is_8_b[9-sizeof(double)] CC_NOTUSED;
+    /* In lieu of static_assert(sizeof(sizeof) == 4) */
+    static const char sizeof_float_is_4_a[sizeof(float)-3] CC_NOTUSED;
+    static const char sizeof_float_is_4_b[5-sizeof(float)] CC_NOTUSED;
+
+    switch(float_size) {
+    case sizeof(double):
+        assert(sizeof(double) == 8);
+        if(float_big_endian) {
+            dst[0] = src[0];
+            dst[1] = src[1];
+            dst[2] = src[2];
+            dst[3] = src[3];
+            dst[4] = src[4];
+            dst[5] = src[5];
+            dst[6] = src[6];
+            dst[7] = src[7];
+        } else {
+            dst[0] = src[7];
+            dst[1] = src[6];
+            dst[2] = src[5];
+            dst[3] = src[4];
+            dst[4] = src[3];
+            dst[5] = src[2];
+            dst[6] = src[1];
+            dst[7] = src[0];
+        }
+        return;
+    case sizeof(float):
+        assert(sizeof(float) == 4);
+        if(float_big_endian) {
+            dst[0] = src[0];
+            dst[1] = src[1];
+            dst[2] = src[2];
+            dst[3] = src[3];
+        } else {
+            dst[0] = src[3];
+            dst[1] = src[2];
+            dst[2] = src[1];
+            dst[3] = src[0];
+        }
+        return;
+    }
+}