String buffers, part 2b: Add extended string buffers. Use in serializer.

Sponsored by fmad.io.
This commit is contained in:
Mike Pall 2021-06-01 00:55:51 +02:00
parent 394fb6267a
commit 61990cef05
6 changed files with 210 additions and 98 deletions

View File

@ -22,15 +22,13 @@
#define LJLIB_MODULE_buffer
/* Note: this uses interim structs until the SBuf reorg. */
LJLIB_CF(buffer_encode)
{
cTValue *o = lj_lib_checkany(L, 1);
StrBuf sbuf;
sbuf.sb = lj_buf_tmp_(L);
lj_serialize_put(&sbuf, o);
setstrV(L, L->top++, lj_buf_str(L, sbuf.sb));
SBufExt sbx;
lj_bufx_init_borrow(L, &sbx, &G(L)->tmpbuf);
lj_serialize_put(&sbx, o);
setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx));
lj_gc_check(L);
return 1;
}
@ -38,16 +36,11 @@ LJLIB_CF(buffer_encode)
LJLIB_CF(buffer_decode)
{
GCstr *str = lj_lib_checkstr(L, 1);
char *p = (char *)strdata(str);
SBuf sb;
StrBuf sbuf;
setsbufL(&sb, L);
sb.b = p;
sb.w = sb.e = p + str->len;
sbuf.sb = &sb;
sbuf.r = p;
SBufExt sbx;
lj_bufx_init_cow(L, &sbx, strdata(str), str->len);
/* No need to set sbx.cowref here. */
setnilV(L->top++);
lj_serialize_get(&sbuf, L->top-1);
lj_serialize_get(&sbx, L->top-1);
lj_gc_check(L);
return 1;
}

View File

@ -20,12 +20,32 @@ static void buf_grow(SBuf *sb, MSize sz)
{
MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz;
char *b;
GCSize flag;
if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
while (nsz < sz) nsz += nsz;
b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz);
flag = sbufflag(sb);
if ((flag & SBUF_FLAG_COW)) { /* Copy-on-write semantics. */
lj_assertG_(G(sbufL(sb)), sb->w == sb->e, "bad SBuf COW");
b = (char *)lj_mem_new(sbufL(sb), nsz);
setsbufflag(sb, flag & ~(GCSize)SBUF_FLAG_COW);
setgcrefnull(sbufX(sb)->cowref);
memcpy(b, sb->b, osz);
} else {
b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz);
}
if ((flag & SBUF_FLAG_EXT)) {
sbufX(sb)->r = sbufX(sb)->r - sb->b + b; /* Adjust read pointer, too. */
}
/* Adjust buffer pointers. */
sb->b = b;
sb->w = b + len;
sb->e = b + nsz;
if ((flag & SBUF_FLAG_BORROW)) { /* Adjust borrowed buffer pointers. */
SBuf *bsb = mref(sbufX(sb)->bsb, SBuf);
bsb->b = b;
bsb->w = b + len;
bsb->e = b + nsz;
}
}
LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
@ -39,11 +59,31 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
{
MSize len = sbuflen(sb);
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
lj_err_mem(sbufL(sb));
buf_grow(sb, len + sz);
if (sbufisext(sb)) {
SBufExt *sbx = (SBufExt *)sb;
MSize len = sbufxlen(sbx);
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
lj_err_mem(sbufL(sbx));
if (len + sz > sbufsz(sbx)) { /* Must grow. */
buf_grow((SBuf *)sbx, len + sz);
} else if (sbufxslack(sbx) < (sbufsz(sbx) >> 3)) {
/* Also grow to avoid excessive compactions, if slack < size/8. */
buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */
return sbx->w;
}
if (sbx->r != sbx->b) { /* Compact by moving down. */
memmove(sbx->b, sbx->r, len);
sbx->r = sbx->b;
sbx->w = sbx->b + len;
lj_assertG_(G(sbufL(sbx)), len + sz <= sbufsz(sbx), "bad SBuf compact");
}
} else {
MSize len = sbuflen(sb);
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
lj_err_mem(sbufL(sb));
buf_grow(sb, len + sz);
}
return sb->w;
}
@ -58,6 +98,7 @@ void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
sb->w = b + n;
sb->e = b + (osz >> 1);
}
lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt");
}
char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)

View File

@ -10,13 +10,53 @@
#include "lj_gc.h"
#include "lj_str.h"
/* Resizable string buffers. SBuf struct definition in lj_obj.h. */
#define sbufsz(sb) ((MSize)((sb)->e - (sb)->b))
#define sbuflen(sb) ((MSize)((sb)->w - (sb)->b))
#define sbufleft(sb) ((MSize)((sb)->e - (sb)->w))
/* Resizable string buffers. */
#define sbufL(sb) (mref((sb)->L, lua_State))
#define setsbufL(sb, l) (setmref((sb)->L, (l)))
/* The SBuf struct definition is in lj_obj.h:
** char *w; Write pointer.
** char *e; End pointer.
** char *b; Base pointer.
** MRef L; lua_State, used for buffer resizing. Extension bits in 3 LSB.
*/
/* Extended string buffer. */
typedef struct SBufExt {
SBufHeader;
union {
GCRef cowref; /* Copy-on-write object reference. */
MRef bsb; /* Borrowed string buffer. */
};
char *r; /* Read pointer. */
int depth; /* Remaining recursion depth. */
} SBufExt;
#define sbufsz(sb) ((MSize)((sb)->e - (sb)->b))
#define sbuflen(sb) ((MSize)((sb)->w - (sb)->b))
#define sbufleft(sb) ((MSize)((sb)->e - (sb)->w))
#define sbufxlen(sbx) ((MSize)((sbx)->w - (sbx)->r))
#define sbufxslack(sbx) ((MSize)((sbx)->r - (sbx)->b))
#define SBUF_MASK_FLAG (7)
#define SBUF_MASK_L (~(GCSize)SBUF_MASK_FLAG)
#define SBUF_FLAG_EXT 1 /* Extended string buffer. */
#define SBUF_FLAG_COW 2 /* Copy-on-write buffer. */
#define SBUF_FLAG_BORROW 4 /* Borrowed string buffer. */
#define sbufL(sb) \
((lua_State *)(void *)(uintptr_t)(mrefu((sb)->L) & SBUF_MASK_L))
#define setsbufL(sb, l) (setmref((sb)->L, (l)))
#define setsbufXL(sb, l, flag) \
(setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) + (flag)))
#define setsbufXL_(sb, l) \
(setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) | (mrefu((sb)->L) & SBUF_MASK_FLAG)))
#define sbufflag(sb) (mrefu((sb)->L))
#define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT)
#define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW)
#define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW)
#define sbufX(sb) \
(lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb))
#define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag)))
/* Buffer management */
LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz);
@ -45,6 +85,7 @@ static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
{
lj_assertG(!sbufisext(sb), "bad free of SBufExt");
lj_mem_free(g, sb->b, sbufsz(sb));
}
@ -62,6 +103,46 @@ static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz)
return sb->w;
}
/* Extended buffer management */
static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx)
{
memset(sbx, 0, sizeof(SBufExt));
setsbufXL(sbx, L, SBUF_FLAG_EXT);
}
static LJ_AINLINE void lj_bufx_init_borrow(lua_State *L, SBufExt *sbx, SBuf *sb)
{
memset(sbx, 0, sizeof(SBufExt));
setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW);
setmref(sbx->bsb, sb);
sbx->r = sbx->w = sbx->b = sb->b;
sbx->e = sb->e;
}
static LJ_AINLINE void lj_bufx_init_cow(lua_State *L, SBufExt *sbx,
const char *p, MSize len)
{
memset(sbx, 0, sizeof(SBufExt));
setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW);
sbx->r = sbx->b = (char *)p;
sbx->w = sbx->e = (char *)p + len;
}
static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx)
{
if (sbufiscow(sbx)) {
setmrefu(sbx->L, (mrefu(sbx->L) & ~(GCSize)SBUF_FLAG_COW));
setgcrefnull(sbx->cowref);
sbx->b = sbx->e = NULL;
}
sbx->r = sbx->w = sbx->b;
}
static LJ_AINLINE void lj_bufx_free(global_State *g, SBufExt *sbx)
{
if (!sbufiscow(sbx)) lj_mem_free(g, sbx->b, sbufsz(sbx));
}
/* Low-level buffer put operations */
LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len);
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c);
@ -97,11 +178,4 @@ static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
return lj_str_new(L, sb->b, sbuflen(sb));
}
/* Interim user-accessible string buffer. */
typedef struct StrBuf {
SBuf *sb; /* Pointer to system buffer. */
char *r; /* String buffer read pointer. */
int depth; /* Remaining recursion depth. */
} StrBuf;
#endif

View File

@ -34,13 +34,17 @@ typedef struct MRef {
#if LJ_GC64
#define mref(r, t) ((t *)(void *)(r).ptr64)
#define mrefu(r) ((r).ptr64)
#define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p))
#define setmrefu(r, u) ((r).ptr64 = (uint64_t)(u))
#define setmrefr(r, v) ((r).ptr64 = (v).ptr64)
#else
#define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32)
#define mrefu(r) ((r).ptr32)
#define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p))
#define setmrefu(r, u) ((r).ptr32 = (uint32_t)(u))
#define setmrefr(r, v) ((r).ptr32 = (v).ptr32)
#endif

View File

@ -55,11 +55,11 @@ LJ_STATIC_ASSERT((SER_TAG_TAB & 7) == 0);
/* -- Helper functions ---------------------------------------------------- */
static LJ_AINLINE char *serialize_more(char *w, StrBuf *sbuf, MSize sz)
static LJ_AINLINE char *serialize_more(char *w, SBufExt *sbx, MSize sz)
{
if (LJ_UNLIKELY(sz > (MSize)(sbuf->sb->e - w))) {
sbuf->sb->w = w;
w = lj_buf_more2(sbuf->sb, sz);
if (LJ_UNLIKELY(sz > (MSize)(sbx->e - w))) {
sbx->w = w;
w = lj_buf_more2((SBuf *)sbx, sz);
}
return w;
}
@ -90,14 +90,14 @@ static LJ_AINLINE char *serialize_wu124(char *w, uint32_t v)
}
}
static LJ_NOINLINE char *serialize_ru124_(char *r, char *e, uint32_t *pv)
static LJ_NOINLINE char *serialize_ru124_(char *r, char *w, uint32_t *pv)
{
uint32_t v = *pv;
if (v != 0xff) {
if (r >= e) return NULL;
if (r >= w) return NULL;
v = ((v & 0x1f) << 8) + *(uint8_t *)r + 0xe0; r++;
} else {
if (r + 4 > e) return NULL;
if (r + 4 > w) return NULL;
v = lj_getu32(r); r += 4;
#if LJ_BE
v = lj_bswap(v);
@ -107,13 +107,13 @@ static LJ_NOINLINE char *serialize_ru124_(char *r, char *e, uint32_t *pv)
return r;
}
static LJ_AINLINE char *serialize_ru124(char *r, char *e, uint32_t *pv)
static LJ_AINLINE char *serialize_ru124(char *r, char *w, uint32_t *pv)
{
if (LJ_LIKELY(r < e)) {
if (LJ_LIKELY(r < w)) {
uint32_t v = *(uint8_t *)r; r++;
*pv = v;
if (LJ_UNLIKELY(v >= 0xe0)) {
r = serialize_ru124_(r, e, pv);
r = serialize_ru124_(r, w, pv);
}
return r;
}
@ -123,30 +123,30 @@ static LJ_AINLINE char *serialize_ru124(char *r, char *e, uint32_t *pv)
/* -- Internal serializer ------------------------------------------------- */
/* Put serialized object into buffer. */
static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o)
static char *serialize_put(char *w, SBufExt *sbx, cTValue *o)
{
if (LJ_LIKELY(tvisstr(o))) {
const GCstr *str = strV(o);
MSize len = str->len;
w = serialize_more(w, sbuf, 5+len);
w = serialize_more(w, sbx, 5+len);
w = serialize_wu124(w, SER_TAG_STR + len);
w = lj_buf_wmem(w, strdata(str), len);
} else if (tvisint(o)) {
uint32_t x = LJ_BE ? lj_bswap((uint32_t)intV(o)) : (uint32_t)intV(o);
w = serialize_more(w, sbuf, 1+4);
w = serialize_more(w, sbx, 1+4);
*w++ = SER_TAG_INT; memcpy(w, &x, 4); w += 4;
} else if (tvisnum(o)) {
uint64_t x = LJ_BE ? lj_bswap64(o->u64) : o->u64;
w = serialize_more(w, sbuf, 1+sizeof(lua_Number));
w = serialize_more(w, sbx, 1+sizeof(lua_Number));
*w++ = SER_TAG_NUM; memcpy(w, &x, 8); w += 8;
} else if (tvispri(o)) {
w = serialize_more(w, sbuf, 1);
w = serialize_more(w, sbx, 1);
*w++ = (char)(SER_TAG_NIL + ~itype(o));
} else if (tvistab(o)) {
const GCtab *t = tabV(o);
uint32_t narray = 0, nhash = 0, one = 2;
if (sbuf->depth <= 0) lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_DEPTH);
sbuf->depth--;
if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH);
sbx->depth--;
if (t->asize > 0) { /* Determine max. length of array part. */
ptrdiff_t i;
TValue *array = tvref(t->array);
@ -163,32 +163,32 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o)
nhash += !tvisnil(&node[i].val);
}
/* Write number of array slots and hash slots. */
w = serialize_more(w, sbuf, 1+2*5);
w = serialize_more(w, sbx, 1+2*5);
*w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0));
if (narray) w = serialize_wu124(w, narray);
if (nhash) w = serialize_wu124(w, nhash);
if (narray) { /* Write array entries. */
cTValue *oa = tvref(t->array) + (one >> 2);
cTValue *oe = tvref(t->array) + narray;
while (oa < oe) w = serialize_put(w, sbuf, oa++);
while (oa < oe) w = serialize_put(w, sbx, oa++);
}
if (nhash) { /* Write hash entries. */
const Node *node = noderef(t->node) + t->hmask;
for (;; node--)
if (!tvisnil(&node->val)) {
w = serialize_put(w, sbuf, &node->key);
w = serialize_put(w, sbuf, &node->val);
w = serialize_put(w, sbx, &node->key);
w = serialize_put(w, sbx, &node->val);
if (--nhash == 0) break;
}
}
sbuf->depth++;
sbx->depth++;
#if LJ_HASFFI
} else if (tviscdata(o)) {
CTState *cts = ctype_cts(sbufL(sbuf->sb));
CTState *cts = ctype_cts(sbufL(sbx));
CType *s = ctype_raw(cts, cdataV(o)->ctypeid);
uint8_t *sp = cdataptr(cdataV(o));
if (ctype_isinteger(s->info) && s->size == 8) {
w = serialize_more(w, sbuf, 1+8);
w = serialize_more(w, sbx, 1+8);
*w++ = (s->info & CTF_UNSIGNED) ? SER_TAG_UINT64 : SER_TAG_INT64;
#if LJ_BE
{ uint64_t u = lj_bswap64(*(uint64_t *)sp); memcpy(w, &u, 8); }
@ -197,7 +197,7 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o)
#endif
w += 8;
} else if (ctype_iscomplex(s->info) && s->size == 16) {
w = serialize_more(w, sbuf, 1+16);
w = serialize_more(w, sbx, 1+16);
*w++ = SER_TAG_COMPLEX;
#if LJ_BE
{ /* Only swap the doubles. The re/im order stays the same. */
@ -213,8 +213,8 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o)
}
#endif
} else if (tvislightud(o)) {
uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbuf->sb)), o);
w = serialize_more(w, sbuf, 1+sizeof(ud));
uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbx)), o);
w = serialize_more(w, sbx, 1+sizeof(ud));
if (ud == 0) {
*w++ = SER_TAG_NULL;
} else if (LJ_32 || checku32(ud)) {
@ -237,28 +237,28 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o)
#if LJ_HASFFI
badenc:
#endif
lj_err_callerv(sbufL(sbuf->sb), LJ_ERR_BUFFER_BADENC, lj_typename(o));
lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADENC, lj_typename(o));
}
return w;
}
/* Get serialized object from buffer. */
static char *serialize_get(char *r, StrBuf *sbuf, TValue *o)
static char *serialize_get(char *r, SBufExt *sbx, TValue *o)
{
char *e = sbuf->sb->e;
char *w = sbx->w;
uint32_t tp;
r = serialize_ru124(r, e, &tp); if (LJ_UNLIKELY(!r)) goto eob;
r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob;
if (LJ_LIKELY(tp >= SER_TAG_STR)) {
uint32_t len = tp - SER_TAG_STR;
if (LJ_UNLIKELY(len > (uint32_t)(e - r))) goto eob;
setstrV(sbufL(sbuf->sb), o, lj_str_new(sbufL(sbuf->sb), r, len));
if (LJ_UNLIKELY(len > (uint32_t)(w - r))) goto eob;
setstrV(sbufL(sbx), o, lj_str_new(sbufL(sbx), r, len));
r += len;
} else if (tp == SER_TAG_INT) {
if (LJ_UNLIKELY(r + 4 > e)) goto eob;
if (LJ_UNLIKELY(r + 4 > w)) goto eob;
setintV(o, (int32_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r)));
r += 4;
} else if (tp == SER_TAG_NUM) {
if (LJ_UNLIKELY(r + 8 > e)) goto eob;
if (LJ_UNLIKELY(r + 8 > w)) goto eob;
memcpy(o, r, 8); r += 8;
#if LJ_BE
o->u64 = lj_bswap64(o->u64);
@ -270,34 +270,34 @@ static char *serialize_get(char *r, StrBuf *sbuf, TValue *o)
uint32_t narray = 0, nhash = 0;
GCtab *t;
if (tp >= SER_TAG_TAB+2) {
r = serialize_ru124(r, e, &narray); if (LJ_UNLIKELY(!r)) goto eob;
r = serialize_ru124(r, w, &narray); if (LJ_UNLIKELY(!r)) goto eob;
}
if ((tp & 1)) {
r = serialize_ru124(r, e, &nhash); if (LJ_UNLIKELY(!r)) goto eob;
r = serialize_ru124(r, w, &nhash); if (LJ_UNLIKELY(!r)) goto eob;
}
t = lj_tab_new(sbufL(sbuf->sb), narray, hsize2hbits(nhash));
settabV(sbufL(sbuf->sb), o, t);
t = lj_tab_new(sbufL(sbx), narray, hsize2hbits(nhash));
settabV(sbufL(sbx), o, t);
if (narray) {
TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4);
TValue *oe = tvref(t->array) + narray;
while (oa < oe) r = serialize_get(r, sbuf, oa++);
while (oa < oe) r = serialize_get(r, sbx, oa++);
}
if (nhash) {
do {
TValue k, *v;
r = serialize_get(r, sbuf, &k);
v = lj_tab_set(sbufL(sbuf->sb), t, &k);
r = serialize_get(r, sbx, &k);
v = lj_tab_set(sbufL(sbx), t, &k);
if (LJ_UNLIKELY(!tvisnil(v)))
lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_DUPKEY);
r = serialize_get(r, sbuf, v);
lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DUPKEY);
r = serialize_get(r, sbx, v);
} while (--nhash);
}
#if LJ_HASFFI
} else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) {
uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8;
GCcdata *cd;
if (LJ_UNLIKELY(r + sz > e)) goto eob;
cd = lj_cdata_new_(sbufL(sbuf->sb),
if (LJ_UNLIKELY(r + sz > w)) goto eob;
cd = lj_cdata_new_(sbufL(sbx),
tp == SER_TAG_INT64 ? CTID_INT64 :
tp == SER_TAG_UINT64 ? CTID_UINT64 : CTID_COMPLEX_DOUBLE,
sz);
@ -307,50 +307,50 @@ static char *serialize_get(char *r, StrBuf *sbuf, TValue *o)
if (sz == 16)
((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]);
#endif
setcdataV(sbufL(sbuf->sb), o, cd);
setcdataV(sbufL(sbx), o, cd);
#endif
} else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) {
uintptr_t ud = 0;
if (tp == SER_TAG_LIGHTUD32) {
if (LJ_UNLIKELY(r + 4 > e)) goto eob;
if (LJ_UNLIKELY(r + 4 > w)) goto eob;
ud = (uintptr_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r));
r += 4;
}
#if LJ_64
else if (tp == SER_TAG_LIGHTUD64) {
if (LJ_UNLIKELY(r + 8 > e)) goto eob;
if (LJ_UNLIKELY(r + 8 > w)) goto eob;
memcpy(&ud, r, 8); r += 8;
#if LJ_BE
ud = lj_bswap64(ud);
#endif
}
setrawlightudV(o, lj_lightud_intern(sbufL(sbuf->sb), (void *)ud));
setrawlightudV(o, lj_lightud_intern(sbufL(sbx), (void *)ud));
#else
setrawlightudV(o, (void *)ud);
#endif
} else {
lj_err_callerv(sbufL(sbuf->sb), LJ_ERR_BUFFER_BADDEC, tp);
lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDEC, tp);
}
return r;
eob:
lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_EOB);
lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_EOB);
return NULL;
}
StrBuf * LJ_FASTCALL lj_serialize_put(StrBuf *sbuf, cTValue *o)
SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o)
{
sbuf->depth = LJ_SERIALIZE_DEPTH;
sbuf->sb->w = serialize_put(sbuf->sb->w, sbuf, o);
return sbuf;
sbx->depth = LJ_SERIALIZE_DEPTH;
sbx->w = serialize_put(sbx->w, sbx, o);
return sbx;
}
StrBuf * LJ_FASTCALL lj_serialize_get(StrBuf *sbuf, TValue *o)
SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o)
{
char *r = serialize_get(sbuf->r, sbuf, o);
if (r != sbuf->sb->w)
lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_LEFTOV);
sbuf->r = r;
return sbuf;
char *r = serialize_get(sbx->r, sbx, o);
if (r != sbx->w)
lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_LEFTOV);
sbx->r = r;
return sbx;
}
#endif

View File

@ -13,8 +13,8 @@
#define LJ_SERIALIZE_DEPTH 100 /* Default depth. */
LJ_FUNC StrBuf * LJ_FASTCALL lj_serialize_put(StrBuf *sb, cTValue *o);
LJ_FUNC StrBuf * LJ_FASTCALL lj_serialize_get(StrBuf *sb, TValue *o);
LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o);
LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o);
#endif