Skip to content

Commit afb3299

Browse files
elliotttJakeChampion
authored andcommitted
Delay reallocation to the end of http_req_header_names_get
1 parent a829a7b commit afb3299

File tree

1 file changed

+62
-40
lines changed

1 file changed

+62
-40
lines changed

c-dependencies/js-compute-runtime/xqd-world/xqd_world_adapter.cpp

Lines changed: 62 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
#include <algorithm>
2+
#include <string_view>
3+
#include <vector>
4+
5+
#pragma clang diagnostic push
6+
#pragma clang diagnostic ignored "-Winvalid-offsetof"
7+
#include "js/Utility.h"
8+
#pragma clang diagnostic pop
9+
110
#include "xqd_world_adapter.h"
211

312
#ifndef COMPONENT
@@ -176,50 +185,63 @@ bool xqd_fastly_http_req_new(fastly_request_handle_t *ret, fastly_error_t *err)
176185

177186
bool xqd_fastly_http_req_header_names_get(fastly_request_handle_t h, fastly_list_string_t *ret,
178187
fastly_error_t *err) {
179-
size_t str_max = LIST_ALLOC_SIZE;
180-
181-
xqd_world_string_t *strs =
182-
static_cast<xqd_world_string_t *>(cabi_malloc(str_max * sizeof(xqd_world_string_t), 1));
183-
size_t str_cnt = 0;
184-
size_t nwritten;
185-
char *buf = static_cast<char *>(cabi_malloc(HOSTCALL_BUFFER_LEN, 1));
186-
uint32_t cursor = 0;
187-
int64_t next_cursor = 0;
188-
while (true) {
189-
if (!convert_result(
190-
xqd_req_header_names_get(h, buf, HEADER_MAX_LEN, cursor, &next_cursor, &nwritten),
191-
err)) {
192-
cabi_free(strs);
193-
cabi_free(buf);
194-
return false;
188+
struct Chunk {
189+
JS::UniqueChars buffer;
190+
size_t length;
191+
192+
static Chunk make(std::string_view data) {
193+
Chunk res{JS::UniqueChars{static_cast<char *>(cabi_malloc(data.size(), 1))}, data.size()};
194+
std::copy(data.begin(), data.end(), res.buffer.get());
195+
return res;
195196
}
196-
if (nwritten == 0)
197-
break;
198-
uint32_t offset = 0;
199-
for (size_t i = 0; i < nwritten; i++) {
200-
if (buf[i] != '\0')
201-
continue;
202-
if (str_cnt == str_max) {
203-
strs = static_cast<xqd_world_string_t *>(
204-
cabi_realloc(strs, str_max * sizeof(xqd_world_string_t), 1,
205-
(str_max + LIST_ALLOC_SIZE) * sizeof(xqd_world_string_t)));
206-
str_max += LIST_ALLOC_SIZE;
197+
};
198+
199+
std::vector<Chunk> chunks;
200+
{
201+
JS::UniqueChars buf{static_cast<char *>(cabi_malloc(HOSTCALL_BUFFER_LEN, 1))};
202+
uint32_t cursor = 0;
203+
while (true) {
204+
size_t length = 0;
205+
int64_t ending_cursor = 0;
206+
auto res =
207+
xqd_req_header_names_get(h, buf.get(), HEADER_MAX_LEN, cursor, &ending_cursor, &length);
208+
if (!convert_result(res, err)) {
209+
return false;
207210
}
208-
strs[str_cnt].ptr = static_cast<char *>(cabi_malloc(i - offset + 1, 1));
209-
strs[str_cnt].len = i - offset;
210-
memcpy(strs[str_cnt].ptr, buf + offset, i - offset + 1);
211-
offset = i + 1;
212-
str_cnt++;
211+
212+
if (length == 0) {
213+
break;
214+
}
215+
216+
std::string_view result{buf.get(), length};
217+
while (!result.empty()) {
218+
auto end = result.find('\0');
219+
chunks.emplace_back(Chunk::make(result.substr(0, end)));
220+
if (end == result.npos) {
221+
break;
222+
}
223+
224+
result = result.substr(end + 1);
225+
}
226+
227+
if (ending_cursor < 0) {
228+
break;
229+
}
230+
231+
cursor = ending_cursor;
213232
}
214-
if (next_cursor < 0)
215-
break;
216-
cursor = (uint32_t)next_cursor;
217233
}
218-
cabi_free(buf);
219-
strs = static_cast<xqd_world_string_t *>(cabi_realloc(strs, str_max * sizeof(xqd_world_string_t),
220-
1, str_cnt * sizeof(xqd_world_string_t)));
221-
ret->ptr = strs;
222-
ret->len = str_cnt;
234+
235+
ret->len = chunks.size();
236+
ret->ptr =
237+
static_cast<xqd_world_string_t *>(cabi_malloc(chunks.size() * sizeof(xqd_world_string_t), 1));
238+
auto *next = ret->ptr;
239+
for (auto &chunk : chunks) {
240+
next->len = chunk.length;
241+
next->ptr = chunk.buffer.release();
242+
++next;
243+
}
244+
223245
return true;
224246
}
225247

0 commit comments

Comments
 (0)