cosmopolitan/third_party/duktape/duk_util_memrw.c

149 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 "third_party/duktape/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;
}