148 lines
4.2 KiB
C
148 lines
4.2 KiB
C
/*
|
|
* Macro support functions for reading/writing raw data.
|
|
*
|
|
* These are done using memcpy to ensure they're valid even for unaligned
|
|
* reads/writes on platforms where alignment counts. On x86 at least gcc
|
|
* is able to compile these into a bswap+mov. "Always inline" is used to
|
|
* ensure these macros compile to minimal code.
|
|
*/
|
|
|
|
#include "duk_internal.h"
|
|
|
|
union duk__u16_union {
|
|
duk_uint8_t b[2];
|
|
duk_uint16_t x;
|
|
};
|
|
typedef union duk__u16_union duk__u16_union;
|
|
|
|
union duk__u32_union {
|
|
duk_uint8_t b[4];
|
|
duk_uint32_t x;
|
|
};
|
|
typedef union duk__u32_union duk__u32_union;
|
|
|
|
#if defined(DUK_USE_64BIT_OPS)
|
|
union duk__u64_union {
|
|
duk_uint8_t b[8];
|
|
duk_uint64_t x;
|
|
};
|
|
typedef union duk__u64_union duk__u64_union;
|
|
#endif
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
|
|
duk__u16_union u;
|
|
duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
|
|
u.x = DUK_NTOH16(u.x);
|
|
return u.x;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
|
|
duk__u32_union u;
|
|
duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
|
|
u.x = DUK_NTOH32(u.x);
|
|
return u.x;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_read_float_be(const duk_uint8_t *p) {
|
|
duk_float_union fu;
|
|
duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
|
|
duk_fltunion_big_to_host(&fu);
|
|
return fu.f;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(const duk_uint8_t *p) {
|
|
duk_double_union du;
|
|
duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
|
|
duk_dblunion_big_to_host(&du);
|
|
return du.d;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
|
|
duk_uint16_t res = duk_raw_read_u16_be(*p);
|
|
*p += 2;
|
|
return res;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
|
|
duk_uint32_t res = duk_raw_read_u32_be(*p);
|
|
*p += 4;
|
|
return res;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p) {
|
|
duk_float_t res = duk_raw_read_float_be(*p);
|
|
*p += 4;
|
|
return res;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p) {
|
|
duk_double_t res = duk_raw_read_double_be(*p);
|
|
*p += 8;
|
|
return res;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
|
|
duk__u16_union u;
|
|
u.x = DUK_HTON16(val);
|
|
duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
|
|
duk__u32_union u;
|
|
u.x = DUK_HTON32(val);
|
|
duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val) {
|
|
duk_float_union fu;
|
|
fu.f = val;
|
|
duk_fltunion_host_to_big(&fu);
|
|
duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val) {
|
|
duk_double_union du;
|
|
du.d = val;
|
|
duk_dblunion_host_to_big(&du);
|
|
duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
|
|
}
|
|
|
|
DUK_INTERNAL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val) {
|
|
duk_small_int_t len = duk_unicode_encode_xutf8(val, p);
|
|
return len;
|
|
}
|
|
|
|
DUK_INTERNAL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val) {
|
|
duk_small_int_t len = duk_unicode_encode_cesu8(val, p);
|
|
return len;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
|
|
duk_raw_write_u16_be(*p, val);
|
|
*p += 2;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
|
|
duk_raw_write_u32_be(*p, val);
|
|
*p += 4;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val) {
|
|
duk_raw_write_float_be(*p, val);
|
|
*p += 4;
|
|
}
|
|
|
|
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val) {
|
|
duk_raw_write_double_be(*p, val);
|
|
*p += 8;
|
|
}
|
|
|
|
DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
|
|
duk_small_int_t len = duk_unicode_encode_xutf8(val, *p);
|
|
*p += len;
|
|
}
|
|
|
|
DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
|
|
duk_small_int_t len = duk_unicode_encode_cesu8(val, *p);
|
|
*p += len;
|
|
}
|