diff options
Diffstat (limited to 'src/lj_buf.h')
-rw-r--r-- | src/lj_buf.h | 100 |
1 files changed, 87 insertions, 13 deletions
diff --git a/src/lj_buf.h b/src/lj_buf.h index 268fce5e..1fb70146 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h | |||
@@ -10,13 +10,53 @@ | |||
10 | #include "lj_gc.h" | 10 | #include "lj_gc.h" |
11 | #include "lj_str.h" | 11 | #include "lj_str.h" |
12 | 12 | ||
13 | /* Resizable string buffers. SBuf struct definition in lj_obj.h. */ | 13 | /* Resizable string buffers. */ |
14 | #define sbufsz(sb) ((MSize)((sb)->e - (sb)->b)) | ||
15 | #define sbuflen(sb) ((MSize)((sb)->w - (sb)->b)) | ||
16 | #define sbufleft(sb) ((MSize)((sb)->e - (sb)->w)) | ||
17 | 14 | ||
18 | #define sbufL(sb) (mref((sb)->L, lua_State)) | 15 | /* The SBuf struct definition is in lj_obj.h: |
19 | #define setsbufL(sb, l) (setmref((sb)->L, (l))) | 16 | ** char *w; Write pointer. |
17 | ** char *e; End pointer. | ||
18 | ** char *b; Base pointer. | ||
19 | ** MRef L; lua_State, used for buffer resizing. Extension bits in 3 LSB. | ||
20 | */ | ||
21 | |||
22 | /* Extended string buffer. */ | ||
23 | typedef struct SBufExt { | ||
24 | SBufHeader; | ||
25 | union { | ||
26 | GCRef cowref; /* Copy-on-write object reference. */ | ||
27 | MRef bsb; /* Borrowed string buffer. */ | ||
28 | }; | ||
29 | char *r; /* Read pointer. */ | ||
30 | int depth; /* Remaining recursion depth. */ | ||
31 | } SBufExt; | ||
32 | |||
33 | #define sbufsz(sb) ((MSize)((sb)->e - (sb)->b)) | ||
34 | #define sbuflen(sb) ((MSize)((sb)->w - (sb)->b)) | ||
35 | #define sbufleft(sb) ((MSize)((sb)->e - (sb)->w)) | ||
36 | #define sbufxlen(sbx) ((MSize)((sbx)->w - (sbx)->r)) | ||
37 | #define sbufxslack(sbx) ((MSize)((sbx)->r - (sbx)->b)) | ||
38 | |||
39 | #define SBUF_MASK_FLAG (7) | ||
40 | #define SBUF_MASK_L (~(GCSize)SBUF_MASK_FLAG) | ||
41 | #define SBUF_FLAG_EXT 1 /* Extended string buffer. */ | ||
42 | #define SBUF_FLAG_COW 2 /* Copy-on-write buffer. */ | ||
43 | #define SBUF_FLAG_BORROW 4 /* Borrowed string buffer. */ | ||
44 | |||
45 | #define sbufL(sb) \ | ||
46 | ((lua_State *)(void *)(uintptr_t)(mrefu((sb)->L) & SBUF_MASK_L)) | ||
47 | #define setsbufL(sb, l) (setmref((sb)->L, (l))) | ||
48 | #define setsbufXL(sb, l, flag) \ | ||
49 | (setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) + (flag))) | ||
50 | #define setsbufXL_(sb, l) \ | ||
51 | (setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) | (mrefu((sb)->L) & SBUF_MASK_FLAG))) | ||
52 | |||
53 | #define sbufflag(sb) (mrefu((sb)->L)) | ||
54 | #define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT) | ||
55 | #define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW) | ||
56 | #define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW) | ||
57 | #define sbufX(sb) \ | ||
58 | (lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb)) | ||
59 | #define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag))) | ||
20 | 60 | ||
21 | /* Buffer management */ | 61 | /* Buffer management */ |
22 | LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz); | 62 | 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) | |||
45 | 85 | ||
46 | static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb) | 86 | static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb) |
47 | { | 87 | { |
88 | lj_assertG(!sbufisext(sb), "bad free of SBufExt"); | ||
48 | lj_mem_free(g, sb->b, sbufsz(sb)); | 89 | lj_mem_free(g, sb->b, sbufsz(sb)); |
49 | } | 90 | } |
50 | 91 | ||
@@ -62,6 +103,46 @@ static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz) | |||
62 | return sb->w; | 103 | return sb->w; |
63 | } | 104 | } |
64 | 105 | ||
106 | /* Extended buffer management */ | ||
107 | static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx) | ||
108 | { | ||
109 | memset(sbx, 0, sizeof(SBufExt)); | ||
110 | setsbufXL(sbx, L, SBUF_FLAG_EXT); | ||
111 | } | ||
112 | |||
113 | static LJ_AINLINE void lj_bufx_init_borrow(lua_State *L, SBufExt *sbx, SBuf *sb) | ||
114 | { | ||
115 | memset(sbx, 0, sizeof(SBufExt)); | ||
116 | setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW); | ||
117 | setmref(sbx->bsb, sb); | ||
118 | sbx->r = sbx->w = sbx->b = sb->b; | ||
119 | sbx->e = sb->e; | ||
120 | } | ||
121 | |||
122 | static LJ_AINLINE void lj_bufx_init_cow(lua_State *L, SBufExt *sbx, | ||
123 | const char *p, MSize len) | ||
124 | { | ||
125 | memset(sbx, 0, sizeof(SBufExt)); | ||
126 | setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW); | ||
127 | sbx->r = sbx->b = (char *)p; | ||
128 | sbx->w = sbx->e = (char *)p + len; | ||
129 | } | ||
130 | |||
131 | static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx) | ||
132 | { | ||
133 | if (sbufiscow(sbx)) { | ||
134 | setmrefu(sbx->L, (mrefu(sbx->L) & ~(GCSize)SBUF_FLAG_COW)); | ||
135 | setgcrefnull(sbx->cowref); | ||
136 | sbx->b = sbx->e = NULL; | ||
137 | } | ||
138 | sbx->r = sbx->w = sbx->b; | ||
139 | } | ||
140 | |||
141 | static LJ_AINLINE void lj_bufx_free(global_State *g, SBufExt *sbx) | ||
142 | { | ||
143 | if (!sbufiscow(sbx)) lj_mem_free(g, sbx->b, sbufsz(sbx)); | ||
144 | } | ||
145 | |||
65 | /* Low-level buffer put operations */ | 146 | /* Low-level buffer put operations */ |
66 | LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); | 147 | LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); |
67 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); | 148 | 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) | |||
97 | return lj_str_new(L, sb->b, sbuflen(sb)); | 178 | return lj_str_new(L, sb->b, sbuflen(sb)); |
98 | } | 179 | } |
99 | 180 | ||
100 | /* Interim user-accessible string buffer. */ | ||
101 | typedef struct StrBuf { | ||
102 | SBuf *sb; /* Pointer to system buffer. */ | ||
103 | char *r; /* String buffer read pointer. */ | ||
104 | int depth; /* Remaining recursion depth. */ | ||
105 | } StrBuf; | ||
106 | |||
107 | #endif | 181 | #endif |