Coverage Report

Created: 2025-01-28 06:45

/src/tarantool/third_party/luajit/src/lj_wbuf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** Low-level writer for LuaJIT.
3
**
4
** Major portions taken verbatim or adapted from the LuaVela.
5
** Copyright (C) 2015-2019 IPONWEB Ltd.
6
*/
7
8
#define lj_wbuf_c
9
#define LUA_CORE
10
11
#include <errno.h>
12
13
#include "lj_obj.h"
14
#include "lj_wbuf.h"
15
#include "lj_utils.h"
16
17
static LJ_AINLINE void wbuf_set_flag(struct lj_wbuf *buf, uint8_t flag)
18
0
{
19
0
  buf->flags |= flag;
20
0
}
21
22
static LJ_AINLINE void wbuf_save_errno(struct lj_wbuf *buf)
23
0
{
24
0
  buf->saved_errno = errno;
25
0
}
26
27
static LJ_AINLINE size_t wbuf_len(const struct lj_wbuf *buf)
28
0
{
29
0
  return (size_t)(buf->pos - buf->buf);
30
0
}
31
32
static LJ_AINLINE size_t wbuf_left(const struct lj_wbuf *buf)
33
0
{
34
0
  return buf->size - wbuf_len(buf);
35
0
}
36
37
void lj_wbuf_init(struct lj_wbuf *buf, lj_wbuf_writer writer,
38
      void *ctx, uint8_t *mem, size_t size)
39
0
{
40
0
  buf->ctx = ctx;
41
0
  buf->writer = writer;
42
0
  buf->buf = mem;
43
0
  buf->pos = mem;
44
0
  buf->size = size;
45
0
  buf->flags = 0;
46
0
  buf->saved_errno = 0;
47
0
}
48
49
void LJ_FASTCALL lj_wbuf_terminate(struct lj_wbuf *buf)
50
0
{
51
0
  lj_wbuf_init(buf, NULL, NULL, NULL, 0);
52
0
}
53
54
static LJ_AINLINE void wbuf_reserve(struct lj_wbuf *buf, size_t n)
55
0
{
56
0
  lj_assertX(n <= buf->size, "wbuf overflow");
57
0
  if (LJ_UNLIKELY(wbuf_left(buf) < n))
58
0
    lj_wbuf_flush(buf);
59
0
}
60
61
/* Writes a byte to the output buffer. */
62
void LJ_FASTCALL lj_wbuf_addbyte(struct lj_wbuf *buf, uint8_t b)
63
0
{
64
0
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
65
0
    return;
66
0
  wbuf_reserve(buf, sizeof(b));
67
0
  *buf->pos++ = b;
68
0
}
69
70
/* Writes an unsigned integer which is at most 64 bits long to the output. */
71
void LJ_FASTCALL lj_wbuf_addu64(struct lj_wbuf *buf, uint64_t n)
72
0
{
73
0
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
74
0
    return;
75
0
  wbuf_reserve(buf, LEB128_U64_MAXSIZE);
76
0
  buf->pos += (ptrdiff_t)lj_utils_write_uleb128(buf->pos, n);
77
0
}
78
79
/* Writes n bytes from an arbitrary buffer src to the buffer. */
80
void lj_wbuf_addn(struct lj_wbuf *buf, const void *src, size_t n)
81
0
{
82
0
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
83
0
    return;
84
  /*
85
  ** Very unlikely: We are told to write a large buffer at once.
86
  ** Buffer doesn't belong to us so we must to pump data
87
  ** through the buffer.
88
  */
89
0
  while (LJ_UNLIKELY(n > buf->size)) {
90
0
    const size_t left = wbuf_left(buf);
91
0
    memcpy(buf->pos, src, left);
92
0
    buf->pos += (ptrdiff_t)left;
93
0
    lj_wbuf_flush(buf);
94
0
    src = (uint8_t *)src + (ptrdiff_t)left;
95
0
    n -= left;
96
0
  }
97
98
0
  wbuf_reserve(buf, n);
99
0
  memcpy(buf->pos, src, n);
100
0
  buf->pos += (ptrdiff_t)n;
101
0
}
102
103
/* Writes a \0-terminated C string to the output buffer. */
104
void LJ_FASTCALL lj_wbuf_addstring(struct lj_wbuf *buf, const char *s)
105
0
{
106
0
  const size_t l = strlen(s);
107
108
  /* Check that profiling is still active is made in the callee's scope. */
109
0
  lj_wbuf_addu64(buf, (uint64_t)l);
110
0
  lj_wbuf_addn(buf, s, l);
111
0
}
112
113
void LJ_FASTCALL lj_wbuf_flush(struct lj_wbuf *buf)
114
0
{
115
0
  const size_t len = wbuf_len(buf);
116
0
  size_t written;
117
118
0
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
119
0
    return;
120
121
0
  written = buf->writer((const void **)&buf->buf, len, buf->ctx);
122
123
0
  if (LJ_UNLIKELY(written < len)) {
124
0
    wbuf_set_flag(buf, STREAM_ERRIO);
125
0
    wbuf_save_errno(buf);
126
0
  }
127
0
  if (LJ_UNLIKELY(buf->buf == NULL)) {
128
0
    wbuf_set_flag(buf, STREAM_STOP);
129
0
    wbuf_save_errno(buf);
130
0
  }
131
0
  buf->pos = buf->buf;
132
0
}
133
134
int LJ_FASTCALL lj_wbuf_test_flag(const struct lj_wbuf *buf, uint8_t flag)
135
0
{
136
0
  return buf->flags & flag;
137
0
}
138
139
int LJ_FASTCALL lj_wbuf_errno(const struct lj_wbuf *buf)
140
0
{
141
0
  return buf->saved_errno;
142
0
}