diff --git a/cutils.c b/cutils.c index c038cf4..52ff164 100644 --- a/cutils.c +++ b/cutils.c @@ -100,15 +100,20 @@ void dbuf_init(DynBuf *s) dbuf_init2(s, NULL, NULL); } -/* return < 0 if error */ -int dbuf_realloc(DynBuf *s, size_t new_size) +/* Try to allocate 'len' more bytes. return < 0 if error */ +int dbuf_claim(DynBuf *s, size_t len) { - size_t size; + size_t new_size, size; uint8_t *new_buf; + new_size = s->size + len; + if (new_size < len) + return -1; /* overflow case */ if (new_size > s->allocated_size) { if (s->error) return -1; - size = s->allocated_size * 3 / 2; + size = s->allocated_size + (s->allocated_size / 2); + if (size < s->allocated_size) + return -1; /* overflow case */ if (size > new_size) new_size = size; new_buf = s->realloc_func(s->opaque, s->buf, new_size); @@ -122,22 +127,10 @@ int dbuf_realloc(DynBuf *s, size_t new_size) return 0; } -int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) -{ - size_t end; - end = offset + len; - if (dbuf_realloc(s, end)) - return -1; - memcpy(s->buf + offset, data, len); - if (end > s->size) - s->size = end; - return 0; -} - int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) { - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) + if (unlikely((s->allocated_size - s->size) < len)) { + if (dbuf_claim(s, len)) return -1; } memcpy_no_ub(s->buf + s->size, data, len); @@ -147,8 +140,8 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) int dbuf_put_self(DynBuf *s, size_t offset, size_t len) { - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) + if (unlikely((s->allocated_size - s->size) < len)) { + if (dbuf_claim(s, len)) return -1; } memcpy(s->buf + s->size, s->buf + offset, len); @@ -156,11 +149,26 @@ int dbuf_put_self(DynBuf *s, size_t offset, size_t len) return 0; } -int dbuf_putc(DynBuf *s, uint8_t c) +int __dbuf_putc(DynBuf *s, uint8_t c) { return dbuf_put(s, &c, 1); } +int __dbuf_put_u16(DynBuf *s, uint16_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 2); +} + +int __dbuf_put_u32(DynBuf *s, uint32_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 4); +} + +int __dbuf_put_u64(DynBuf *s, uint64_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 8); +} + int dbuf_putstr(DynBuf *s, const char *str) { return dbuf_put(s, (const uint8_t *)str, strlen(str)); @@ -182,7 +190,7 @@ int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, /* fast case */ return dbuf_put(s, (uint8_t *)buf, len); } else { - if (dbuf_realloc(s, s->size + len + 1)) + if (dbuf_claim(s, len + 1)) return -1; va_start(ap, fmt); vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, diff --git a/cutils.h b/cutils.h index 9fcb7a6..094a8f1 100644 --- a/cutils.h +++ b/cutils.h @@ -264,24 +264,58 @@ typedef struct DynBuf { void dbuf_init(DynBuf *s); void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); -int dbuf_realloc(DynBuf *s, size_t new_size); -int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); +int dbuf_claim(DynBuf *s, size_t len); int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); int dbuf_put_self(DynBuf *s, size_t offset, size_t len); -int dbuf_putc(DynBuf *s, uint8_t c); int dbuf_putstr(DynBuf *s, const char *str); +int __dbuf_putc(DynBuf *s, uint8_t c); +int __dbuf_put_u16(DynBuf *s, uint16_t val); +int __dbuf_put_u32(DynBuf *s, uint32_t val); +int __dbuf_put_u64(DynBuf *s, uint64_t val); + +static inline int dbuf_putc(DynBuf *s, uint8_t val) +{ + if (unlikely((s->allocated_size - s->size) < 1)) { + return __dbuf_putc(s, val); + } else { + s->buf[s->size++] = val; + return 0; + } +} + static inline int dbuf_put_u16(DynBuf *s, uint16_t val) { - return dbuf_put(s, (uint8_t *)&val, 2); + if (unlikely((s->allocated_size - s->size) < 2)) { + return __dbuf_put_u16(s, val); + } else { + put_u16(s->buf + s->size, val); + s->size += 2; + return 0; + } } + static inline int dbuf_put_u32(DynBuf *s, uint32_t val) { - return dbuf_put(s, (uint8_t *)&val, 4); + if (unlikely((s->allocated_size - s->size) < 4)) { + return __dbuf_put_u32(s, val); + } else { + put_u32(s->buf + s->size, val); + s->size += 4; + return 0; + } } + static inline int dbuf_put_u64(DynBuf *s, uint64_t val) { - return dbuf_put(s, (uint8_t *)&val, 8); + if (unlikely((s->allocated_size - s->size) < 8)) { + return __dbuf_put_u64(s, val); + } else { + put_u64(s->buf + s->size, val); + s->size += 8; + return 0; + } } + int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, const char *fmt, ...); void dbuf_free(DynBuf *s); diff --git a/libregexp.c b/libregexp.c index 0cf9a12..118d950 100644 --- a/libregexp.c +++ b/libregexp.c @@ -117,7 +117,7 @@ static inline int is_digit(int c) { /* insert 'len' bytes at position 'pos'. Return < 0 if error. */ static int dbuf_insert(DynBuf *s, int pos, int len) { - if (dbuf_realloc(s, s->size + len)) + if (dbuf_claim(s, len)) return -1; memmove(s->buf + pos + len, s->buf + pos, s->size - pos); s->size += len; @@ -2340,7 +2340,7 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir) speed is not really critical here) */ end = s->byte_code.size; term_size = end - term_start; - if (dbuf_realloc(&s->byte_code, end + term_size)) + if (dbuf_claim(&s->byte_code, term_size)) return -1; memmove(s->byte_code.buf + start + term_size, s->byte_code.buf + start, diff --git a/libunicode.c b/libunicode.c index 3791523..0c510cc 100644 --- a/libunicode.c +++ b/libunicode.c @@ -1179,7 +1179,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, is_compat = n_type >> 1; dbuf_init2(dbuf, opaque, realloc_func); - if (dbuf_realloc(dbuf, sizeof(int) * src_len)) + if (dbuf_claim(dbuf, sizeof(int) * src_len)) goto fail; /* common case: latin1 is unaffected by NFC */ diff --git a/quickjs.c b/quickjs.c index 908cf0d..d1c5ed8 100644 --- a/quickjs.c +++ b/quickjs.c @@ -22835,7 +22835,7 @@ static void emit_op(JSParseState *s, uint8_t val) static void emit_atom(JSParseState *s, JSAtom name) { DynBuf *bc = &s->cur_func->byte_code; - if (dbuf_realloc(bc, bc->size + 4)) + if (dbuf_claim(bc, 4)) return; /* not enough memory : don't duplicate the atom */ put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name)); bc->size += 4; @@ -27751,7 +27751,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, int chunk_size = pos_expr - pos_next; int offset = bc->size - pos_next; int i; - dbuf_realloc(bc, bc->size + chunk_size); + dbuf_claim(bc, chunk_size); dbuf_put(bc, bc->buf + pos_next, chunk_size); memset(bc->buf + pos_next, OP_nop, chunk_size); /* `next` part ends with a goto */ @@ -28157,7 +28157,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, int chunk_size = pos_body - pos_cont; int offset = bc->size - pos_cont; int i; - dbuf_realloc(bc, bc->size + chunk_size); + dbuf_claim(bc, chunk_size); dbuf_put(bc, bc->buf + pos_cont, chunk_size); memset(bc->buf + pos_cont, OP_nop, chunk_size); /* increment part ends with a goto */ @@ -37097,7 +37097,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s) /* XXX: could just append dbuf1 data, but it uses more memory if dbuf1 is larger than dbuf */ atoms_size = s->dbuf.size; - if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size)) + if (dbuf_claim(&dbuf1, atoms_size)) goto fail; memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size); memcpy(dbuf1.buf, s->dbuf.buf, atoms_size);