• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kos-lang / kos / 6443252132

07 Oct 2023 08:12PM UTC coverage: 96.469% (-0.06%) from 96.528%
6443252132

push

github

Chris Dragan
tools: update tmbundle for Sublime Text

24345 of 25236 relevant lines covered (96.47%)

1023563.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.24
/core/kos_buffer.c
1
/* SPDX-License-Identifier: MIT
2
 * Copyright (c) 2014-2023 Chris Dragan
3
 */
4

5
#include "../inc/kos_buffer.h"
6
#include "../inc/kos_error.h"
7
#include "../inc/kos_utils.h"
8
#include "kos_heap.h"
9
#include "kos_math.h"
10
#include "kos_misc.h"
11
#include "kos_object_internal.h"
12
#include <string.h>
13

14
KOS_DECLARE_STATIC_CONST_STRING(str_err_empty,            "cannot modify empty buffer");
15
KOS_DECLARE_STATIC_CONST_STRING(str_err_external_storage, "buffer with external storage has fixed capacity");
16
KOS_DECLARE_STATIC_CONST_STRING(str_err_make_room_size,   "buffer size limit exceeded");
17
KOS_DECLARE_STATIC_CONST_STRING(str_err_not_buffer,       "object is not a buffer");
18
KOS_DECLARE_STATIC_CONST_STRING(str_err_read_only,        "buffer is read-only");
19

20
#define KOS_buffer_alloc_size(cap) (sizeof(KOS_BUFFER_STORAGE) + ((cap) - 1U))
21

22
static KOS_BUFFER_STORAGE *alloc_buffer(KOS_CONTEXT ctx, unsigned capacity)
2,648✔
23
{
24
    KOS_BUFFER_STORAGE *const data = (KOS_BUFFER_STORAGE *)
25
            kos_alloc_object(ctx,
2,648✔
26
                             KOS_ALLOC_MOVABLE,
27
                             OBJ_BUFFER_STORAGE,
28
                             KOS_buffer_alloc_size(capacity));
29

30
#ifndef NDEBUG
31
    /*
32
     * The caller is supposed to fill it out completely and reliably.
33
     * Therefore in debug builds, we fill it with random data to trigger
34
     * any bugs more easily.
35
     */
36
    if (data && capacity) {
2,648✔
37
        static struct KOS_RNG rng;
38
        static int            init = 0;
39
        uint64_t             *buf = (uint64_t *)&data->buf[0];
2,600✔
40
        uint64_t             *end = (uint64_t *)((intptr_t)buf + capacity);
2,600✔
41

42
        assert(kos_get_object_type(data->header) == OBJ_BUFFER_STORAGE);
2,600✔
43

44
        if ( ! init) {
2,600✔
45
            kos_rng_init(&rng);
234✔
46
            init = 1;
234✔
47
        }
48

49
        /* Cheat, reuse ctx_mutex to ensure the RNG is not banged from
50
         * multiple threads. */
51
        kos_lock_mutex(ctx->inst->threads.ctx_mutex);
2,600✔
52

53
        while (((intptr_t)buf & 7) && buf < end) {
2,600✔
54
            *(uint8_t *)buf = (uint8_t)kos_rng_random(&rng);
×
55
            buf = (uint64_t *)((intptr_t)buf + 1);
×
56
        }
57

58
        while (buf + 1 <= end)
15,456,200✔
59
            *(buf++) = kos_rng_random(&rng);
15,453,600✔
60

61
        kos_unlock_mutex(ctx->inst->threads.ctx_mutex);
2,600✔
62
    }
63
#endif
64

65
    if (data) {
2,648✔
66
        data->ptr   = &data->buf[0];
2,600✔
67
        data->flags = 0;
2,600✔
68
        KOS_atomic_write_release_u32(data->capacity, capacity);
2,600✔
69
    }
70

71
    return data;
2,648✔
72
}
73

74
KOS_OBJ_ID KOS_new_buffer(KOS_CONTEXT ctx,
1,801✔
75
                          unsigned    size)
76
{
77
    const unsigned capacity = (size + (KOS_BUFFER_CAPACITY_ALIGN-1)) & ~(KOS_BUFFER_CAPACITY_ALIGN-1);
1,801✔
78
    KOS_LOCAL      obj;
79

80
    KOS_init_local_with(ctx, &obj, OBJID(BUFFER, (KOS_BUFFER *)
1,801✔
81
                kos_alloc_object(ctx,
82
                                 KOS_ALLOC_MOVABLE,
83
                                 OBJ_BUFFER,
84
                                 sizeof(KOS_BUFFER))));
85
    if ( ! IS_BAD_PTR(obj.o)) {
1,801✔
86

87
        OBJPTR(BUFFER, obj.o)->size  = size;
1,799✔
88
        OBJPTR(BUFFER, obj.o)->flags = 0;
1,799✔
89
        OBJPTR(BUFFER, obj.o)->data  = KOS_BADPTR;
1,799✔
90

91
        if (capacity) {
1,799✔
92

93
            KOS_BUFFER_STORAGE *data;
94

95
            data = alloc_buffer(ctx, capacity);
184✔
96

97
            if (data)
184✔
98
                KOS_atomic_write_release_ptr(OBJPTR(BUFFER, obj.o)->data,
184✔
99
                                             OBJID(BUFFER_STORAGE, data));
100
            else
101
                obj.o = KOS_BADPTR;
×
102
        }
103
    }
104

105
    return KOS_destroy_top_local(ctx, &obj);
1,801✔
106
}
107

108
KOS_OBJ_ID KOS_new_external_buffer(KOS_CONTEXT  ctx,
1✔
109
                                   void        *ptr,
110
                                   unsigned     size,
111
                                   void        *priv,
112
                                   KOS_FINALIZE finalize)
113
{
114
    KOS_LOCAL obj;
115

116
    KOS_init_local(ctx, &obj);
1✔
117

118
    obj.o = OBJID(BUFFER, (KOS_BUFFER *)kos_alloc_object(ctx,
1✔
119
                                                         KOS_ALLOC_MOVABLE,
120
                                                         OBJ_BUFFER,
121
                                                         sizeof(KOS_BUFFER)));
122
    if ( ! IS_BAD_PTR(obj.o)) {
1✔
123

124
        KOS_BUFFER_EXTERNAL_STORAGE *data;
125

126
        OBJPTR(BUFFER, obj.o)->size  = size;
1✔
127
        OBJPTR(BUFFER, obj.o)->flags = KOS_EXTERNAL_STORAGE;
1✔
128
        OBJPTR(BUFFER, obj.o)->data  = KOS_BADPTR;
1✔
129

130
        data = (KOS_BUFFER_EXTERNAL_STORAGE *)alloc_buffer(ctx,
1✔
131
                (unsigned)(sizeof(KOS_BUFFER_EXTERNAL_STORAGE) - sizeof(KOS_BUFFER_STORAGE)));
132

133
        if (data) {
1✔
134
            KOS_atomic_write_release_ptr(OBJPTR(BUFFER, obj.o)->data,
1✔
135
                                         OBJID(BUFFER_STORAGE, (KOS_BUFFER_STORAGE *)data));
136
            data->ptr      = (uint8_t *)ptr;
1✔
137
            data->flags    = KOS_EXTERNAL_STORAGE;
1✔
138
            data->capacity = size;
1✔
139
            data->priv     = priv;
1✔
140
            data->finalize = finalize;
1✔
141
        }
142
        else
143
            obj.o = KOS_BADPTR;
×
144
    }
145

146
    return KOS_destroy_top_local(ctx, &obj);
1✔
147
}
148

149
static KOS_BUFFER_STORAGE *get_data(KOS_OBJ_ID obj_id)
6,664✔
150
{
151
    const KOS_OBJ_ID buf_obj = KOS_atomic_read_acquire_obj(OBJPTR(BUFFER, obj_id)->data);
6,664✔
152
    return IS_BAD_PTR(buf_obj) ? KOS_NULL : OBJPTR(BUFFER_STORAGE, buf_obj);
6,664✔
153
}
154

155
static KOS_OBJ_ID get_storage(KOS_OBJ_ID obj_id)
7,778✔
156
{
157
    const KOS_OBJ_ID storage_obj = KOS_atomic_read_acquire_obj(OBJPTR(BUFFER, obj_id)->data);
7,778✔
158
    return storage_obj;
7,778✔
159
}
160

161
int KOS_buffer_reserve(KOS_CONTEXT ctx,
2,472✔
162
                       KOS_OBJ_ID  obj_id,
163
                       unsigned    new_capacity)
164
{
165
    KOS_LOCAL obj;
166
    KOS_LOCAL old_buf;
167
    int       error = KOS_ERROR_EXCEPTION;
2,472✔
168

169
    assert( ! IS_BAD_PTR(obj_id));
2,472✔
170

171
    KOS_init_local_with(ctx, &obj, obj_id);
2,472✔
172
    KOS_init_local(ctx, &old_buf);
2,472✔
173

174
    new_capacity = (new_capacity + (KOS_BUFFER_CAPACITY_ALIGN-1)) & ~(KOS_BUFFER_CAPACITY_ALIGN-1);
2,472✔
175

176
    if (GET_OBJ_TYPE(obj.o) != OBJ_BUFFER)
2,472✔
177
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
2✔
178
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj.o)->flags) & KOS_READ_ONLY)
2,470✔
179
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
5✔
180
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj.o)->flags) & KOS_EXTERNAL_STORAGE)
2,465✔
181
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_external_storage));
×
182
    else {
183
        for (;;) {
86✔
184
            uint32_t capacity;
185

186
            old_buf.o = get_storage(obj.o);
2,551✔
187
            capacity  = IS_BAD_PTR(old_buf.o) ? 0
5,102✔
188
                      : KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER_STORAGE, old_buf.o)->capacity);
2,551✔
189

190
            if (new_capacity > capacity) {
2,551✔
191

192
                uint32_t                  size;
193
                KOS_BUFFER_STORAGE *const buf = alloc_buffer(ctx, new_capacity);
2,463✔
194
                if ( ! buf)
2,463✔
195
                    break;
48✔
196

197
                size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj.o)->size);
2,415✔
198

199
                if (size > capacity)
2,415✔
200
                    continue;
86✔
201

202
                if (size)
2,329✔
203
                    memcpy(buf->ptr, OBJPTR(BUFFER_STORAGE, old_buf.o)->ptr, size);
818✔
204

205
                (void)KOS_atomic_cas_strong_ptr(OBJPTR(BUFFER, obj.o)->data,
2,329✔
206
                                                old_buf.o,
207
                                                OBJID(BUFFER_STORAGE, buf));
208
            }
209

210
            error = KOS_SUCCESS;
2,417✔
211
            break;
2,417✔
212
        }
213
    }
214

215
    KOS_destroy_top_locals(ctx, &old_buf, &obj);
2,472✔
216

217
    return error;
2,472✔
218
}
219

220
int KOS_buffer_resize(KOS_CONTEXT ctx,
1,852✔
221
                      KOS_OBJ_ID  obj_id,
222
                      unsigned    size)
223
{
224
    int error = KOS_ERROR_EXCEPTION;
1,852✔
225

226
    assert( ! IS_BAD_PTR(obj_id));
1,852✔
227

228
    if (GET_OBJ_TYPE(obj_id) != OBJ_BUFFER)
1,852✔
229
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
2✔
230
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->flags) & KOS_READ_ONLY)
1,850✔
231
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
5✔
232
    else {
233
        const uint32_t old_size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->size);
1,845✔
234

235
        error = KOS_SUCCESS;
1,845✔
236

237
        if (size > old_size) {
1,845✔
238

239
            KOS_BUFFER_STORAGE *const data = get_data(obj_id);
1,618✔
240
            const uint32_t capacity = data ? KOS_atomic_read_relaxed_u32(data->capacity) : 0;
1,618✔
241

242
            if (size > capacity) {
1,618✔
243
                KOS_LOCAL      obj;
244
                const uint32_t new_capacity = size > capacity * 2 ? size : capacity * 2;
1,531✔
245

246
                KOS_init_local_with(ctx, &obj, obj_id);
1,531✔
247

248
                error = KOS_buffer_reserve(ctx, obj.o, new_capacity);
1,531✔
249

250
                obj_id = KOS_destroy_top_local(ctx, &obj);
1,531✔
251
            }
252
        }
253

254
        if ( ! error)
1,845✔
255
            KOS_atomic_swap_u32(OBJPTR(BUFFER, obj_id)->size, size);
1,797✔
256
    }
257

258
    return error;
1,852✔
259
}
260

261
uint8_t *KOS_buffer_data(KOS_CONTEXT ctx,
119✔
262
                         KOS_OBJ_ID  obj_id)
263
{
264
    uint8_t *ret = KOS_NULL;
119✔
265

266
    assert( ! IS_BAD_PTR(obj_id));
119✔
267

268
    if (GET_OBJ_TYPE(obj_id) != OBJ_BUFFER)
119✔
269
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
×
270
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->flags) & KOS_READ_ONLY)
119✔
271
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
2✔
272
    else {
273

274
        KOS_OBJ_ID buf_id = get_storage(obj_id);
117✔
275

276
        if (IS_BAD_PTR(buf_id) || kos_is_heap_object(buf_id)) {
117✔
277

278
            KOS_LOCAL obj;
279
            int       error;
280

281
            KOS_init_local_with(ctx, &obj, obj_id);
20✔
282

283
            error = KOS_buffer_reserve(ctx, obj.o, KOS_MAX_HEAP_OBJ_SIZE * 2U);
20✔
284

285
            obj_id = KOS_destroy_top_local(ctx, &obj);
20✔
286

287
            if (error)
20✔
288
                goto cleanup;
×
289

290
            buf_id = get_storage(obj_id);
20✔
291
        }
292

293
        assert(kos_is_tracked_object(buf_id) && ! kos_is_heap_object(buf_id));
117✔
294

295
        ret = OBJPTR(BUFFER_STORAGE, buf_id)->ptr;
117✔
296
    }
297

298
cleanup:
119✔
299
    return ret;
119✔
300
}
301

302
uint8_t *KOS_buffer_data_volatile(KOS_CONTEXT ctx,
10,021✔
303
                                  KOS_OBJ_ID  obj_id)
304
{
305
    uint8_t *ret = KOS_NULL;
10,021✔
306

307
    assert( ! IS_BAD_PTR(obj_id));
10,021✔
308

309
    if (GET_OBJ_TYPE(obj_id) != OBJ_BUFFER)
10,021✔
310
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
×
311
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->flags) & KOS_READ_ONLY)
10,021✔
312
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
2✔
313
    else {
314
        const KOS_OBJ_ID buf_obj = KOS_atomic_read_relaxed_obj(OBJPTR(BUFFER, obj_id)->data);
10,019✔
315

316
        if (IS_BAD_PTR(buf_obj))
10,019✔
317
            KOS_raise_exception(ctx, KOS_CONST_ID(str_err_empty));
×
318
        else {
319
            KOS_BUFFER_STORAGE *data = OBJPTR(BUFFER_STORAGE, buf_obj);
10,019✔
320

321
            ret = data->ptr;
10,019✔
322
        }
323
    }
324

325
    return ret;
10,018✔
326
}
327

328
uint8_t *KOS_buffer_make_room(KOS_CONTEXT ctx,
5,008✔
329
                              KOS_OBJ_ID  obj_id,
330
                              unsigned    size_delta)
331
{
332
    uint8_t *ret = KOS_NULL;
5,008✔
333

334
    assert( ! IS_BAD_PTR(obj_id));
5,008✔
335

336
    if (GET_OBJ_TYPE(obj_id) != OBJ_BUFFER)
5,008✔
337
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
2✔
338
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->flags) & KOS_READ_ONLY)
5,006✔
339
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
4✔
340
    else {
341
        for (;;) {
89✔
342
            const uint32_t   old_size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->size);
5,091✔
343
            const uint32_t   new_size = old_size + size_delta;
5,091✔
344
            const KOS_OBJ_ID data_id  = get_storage(obj_id);
5,091✔
345
            const uint32_t   capacity = IS_BAD_PTR(data_id) ? 0 :
5,090✔
346
                    KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER_STORAGE, data_id)->capacity);
5,052✔
347

348
            /* Ensure that the new buffer is allocated off heap */
349
            const uint32_t off_heap_size = KOS_max(new_size, KOS_MAX_HEAP_OBJ_SIZE * 2U);
5,090✔
350

351
            if (size_delta > 0xFFFFFFFFU - old_size) {
5,090✔
352
                KOS_raise_exception(ctx, KOS_CONST_ID(str_err_make_room_size));
1✔
353
                break;
1✔
354
            }
355

356
            if (off_heap_size > capacity) {
5,089✔
357
                KOS_LOCAL      obj;
358
                const uint32_t new_capacity = new_size > capacity * 2 ? new_size : capacity * 2;
906✔
359
                int            error;
360

361
                KOS_init_local_with(ctx, &obj, obj_id);
906✔
362

363
                error = KOS_buffer_reserve(ctx, obj.o, new_capacity);
906✔
364

365
                obj_id = KOS_destroy_top_local(ctx, &obj);
906✔
366

367
                if (error)
906✔
368
                    break;
×
369
            }
370

371
            if (KOS_atomic_cas_strong_u32(OBJPTR(BUFFER, obj_id)->size, old_size, new_size)) {
5,089✔
372
                ret = KOS_buffer_data_volatile(ctx, obj_id);
5,001✔
373
                if (ret)
5,000✔
374
                    ret += old_size;
5,000✔
375
                break;
5,000✔
376
            }
377
        }
378
    }
379

380
    return ret;
5,007✔
381
}
382

383
int KOS_buffer_fill(KOS_CONTEXT ctx,
1,654✔
384
                    KOS_OBJ_ID  obj_id,
385
                    int64_t     begin,
386
                    int64_t     end,
387
                    uint8_t     value)
388
{
389
    int error = KOS_ERROR_EXCEPTION;
1,654✔
390

391
    assert( ! IS_BAD_PTR(obj_id));
1,654✔
392

393
    if (GET_OBJ_TYPE(obj_id) != OBJ_BUFFER)
1,654✔
394
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
2✔
395
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->flags) & KOS_READ_ONLY)
1,652✔
396
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
2✔
397
    else {
398
        uint32_t size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj_id)->size);
1,650✔
399
        KOS_BUFFER_STORAGE *const data = get_data(obj_id);
1,650✔
400

401
        begin = KOS_fix_index(begin, size);
1,650✔
402
        end   = KOS_fix_index(end,   size);
1,650✔
403

404
        if (begin < end)
1,650✔
405
            memset(&data->ptr[begin], (int)value, (size_t)(end - begin));
1,648✔
406

407
        error = KOS_SUCCESS;
1,650✔
408
    }
409

410
    return error;
1,654✔
411
}
412

413
int KOS_buffer_copy(KOS_CONTEXT ctx,
1,666✔
414
                    KOS_OBJ_ID  destptr,
415
                    int64_t     dest_begin,
416
                    KOS_OBJ_ID  srcptr,
417
                    int64_t     src_begin,
418
                    int64_t     src_end)
419
{
420
    int error = KOS_ERROR_EXCEPTION;
1,666✔
421

422
    assert( ! IS_BAD_PTR(srcptr));
1,666✔
423
    assert( ! IS_BAD_PTR(destptr));
1,666✔
424

425
    if (GET_OBJ_TYPE(destptr) != OBJ_BUFFER ||
1,666✔
426
        GET_OBJ_TYPE(srcptr)  != OBJ_BUFFER)
1,664✔
427

428
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
4✔
429
    else if (KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, destptr)->flags) & KOS_READ_ONLY)
1,662✔
430
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_read_only));
×
431
    else {
432
        uint32_t dest_size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, destptr)->size);
1,662✔
433
        KOS_BUFFER_STORAGE *const dest_data = get_data(destptr);
1,662✔
434

435
        uint32_t src_size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, srcptr)->size);
1,662✔
436
        KOS_BUFFER_STORAGE *const src_data = get_data(srcptr);
1,662✔
437

438
        dest_begin = KOS_fix_index(dest_begin, dest_size);
1,662✔
439
        src_begin  = KOS_fix_index(src_begin, src_size);
1,662✔
440
        src_end    = KOS_fix_index(src_end,   src_size);
1,662✔
441

442
        if (src_begin < src_end && dest_begin < dest_size) {
1,662✔
443
            const size_t size = (size_t)KOS_min(src_end - src_begin, dest_size - dest_begin);
1,661✔
444
            uint8_t     *dest = &dest_data->ptr[dest_begin];
1,661✔
445
            uint8_t     *src  = &src_data->ptr[src_begin];
1,661✔
446

447
            if (src >= dest + size || src + size <= dest)
1,661✔
448
                memcpy(dest, src, size);
1,658✔
449
            else
450
                memmove(dest, src, size);
3✔
451
        }
452

453
        error = KOS_SUCCESS;
1,662✔
454
    }
455

456
    return error;
1,666✔
457
}
458

459
KOS_OBJ_ID KOS_buffer_slice(KOS_CONTEXT ctx,
41✔
460
                            KOS_OBJ_ID  obj_id,
461
                            int64_t     begin,
462
                            int64_t     end)
463
{
464
    KOS_LOCAL  obj;
465
    KOS_OBJ_ID ret = KOS_BADPTR;
41✔
466

467
    assert( ! IS_BAD_PTR(obj_id));
41✔
468

469
    KOS_init_local_with(ctx, &obj, obj_id);
41✔
470

471
    if (GET_OBJ_TYPE(obj.o) != OBJ_BUFFER)
41✔
472
        KOS_raise_exception(ctx, KOS_CONST_ID(str_err_not_buffer));
2✔
473
    else {
474
        const uint32_t src_size = KOS_atomic_read_relaxed_u32(OBJPTR(BUFFER, obj.o)->size);
39✔
475

476
        if (src_size) {
39✔
477

478
            uint32_t new_size;
479
            int64_t  new_size_64;
480

481
            begin = KOS_fix_index(begin, src_size);
38✔
482
            end   = KOS_fix_index(end,   src_size);
38✔
483

484
            if (end < begin)
38✔
485
                end = begin;
1✔
486

487
            new_size_64 = end - begin;
38✔
488
            assert(new_size_64 <= 0xFFFFFFFF);
38✔
489
            new_size = (uint32_t)new_size_64;
38✔
490

491
            ret = KOS_new_buffer(ctx, new_size);
38✔
492

493
            if (new_size && ! IS_BAD_PTR(ret)) {
38✔
494
                KOS_BUFFER_STORAGE *const dst_data = get_data(ret);
36✔
495
                memcpy(dst_data->ptr, &get_data(obj.o)->ptr[begin], new_size);
36✔
496
            }
497
        }
498
        else
499
            ret = KOS_new_buffer(ctx, 0);
1✔
500
    }
501

502
    KOS_destroy_top_local(ctx, &obj);
41✔
503

504
    return ret;
41✔
505
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc