#ifndef RAY_CELL_GROWTH_H
#define RAY_CELL_GROWTH_H
#include "mem/heap.h"
static inline size_t ray_cell_growth_limit(void) {
size_t limit = SIZE_MAX;
if ((uint64_t)limit > (uint64_t)INT64_MAX) limit = (size_t)INT64_MAX;
return (limit & ~(size_t)4095) - RAY_DIRECT_HDR - 32;
}
static inline bool ray_cell_growth_bytes(int64_t len, int64_t count,
size_t width, size_t* required) {
if (len < 0 || count < 0 || width == 0 || count > INT64_MAX - len)
return false;
uint64_t n = (uint64_t)(len + count);
if (n > (uint64_t)SIZE_MAX) return false;
size_t bytes;
if (__builtin_mul_overflow((size_t)n, width, &bytes) ||
bytes > ray_cell_growth_limit()) return false;
*required = bytes;
return true;
}
static inline bool ray_cell_growth_request(size_t room, size_t required,
size_t* request) {
size_t limit = ray_cell_growth_limit();
if (required > limit || room > limit) return false;
size_t bytes = required;
if (ray_order_for_size(required) >= RAY_HEAP_POOL_ORDER) {
size_t doubled = room > limit / 2 ? limit : room * 2;
if (doubled > bytes) bytes = doubled;
}
*request = bytes;
return true;
}
static __attribute__((cold, noinline, unused))
ray_t* ray_cell_grow_one(ray_t* value, size_t width) {
size_t required, request;
if (!ray_cell_growth_bytes(value->len, 1, width, &required) ||
!ray_cell_growth_request(ray_block_data_bytes(value), required, &request))
return NULL;
return ray_scratch_realloc(value, request);
}
#endif