mirror of https://github.com/rusefi/bldc.git
Merge pull request #698 from laxsjo/master
add option for buf-resize to create a copy of the given array
This commit is contained in:
commit
36ed818e97
|
@ -4552,7 +4552,7 @@ The last byte in `seq` will be ignored as that is the null-terminator if `seq` i
|
||||||
| ESC, Express | 6.05+ |
|
| ESC, Express | 6.05+ |
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
(buf-resize arr delta-size opt-absolute-size)
|
(buf-resize arr delta-size opt-absolute-size opt-copy-symbol)
|
||||||
```
|
```
|
||||||
|
|
||||||
Change the length of array `arr` in bytes. A reference to `arr` is returned.
|
Change the length of array `arr` in bytes. A reference to `arr` is returned.
|
||||||
|
@ -4567,6 +4567,14 @@ This extension can be used in two modes:
|
||||||
Passing `nil` to `delta-size` while not passing any value for
|
Passing `nil` to `delta-size` while not passing any value for
|
||||||
`opt-absolute-size` will result in an `eval_error`.
|
`opt-absolute-size` will result in an `eval_error`.
|
||||||
|
|
||||||
|
You can optionally pass the symbol `'copy` to `opt-copy-symbol` to specify that
|
||||||
|
`arr` should be left unchanged and that a copy should instead be made. Don't
|
||||||
|
worry about the exact position of the argument, the only important part is that
|
||||||
|
`opt-copy-symbol` is last. So you can give a value for `opt-copy-symbol` even
|
||||||
|
when `opt-absolute-size` isn't passed. You can also for completeness pass the
|
||||||
|
symbol `'mut` to specify that the standard behaviour of modifying `arr` in place
|
||||||
|
should remain in effect.
|
||||||
|
|
||||||
When growing the length of the array a new range will be allocated and the old
|
When growing the length of the array a new range will be allocated and the old
|
||||||
data copied over. The new bytes will be initialised to zero. If the new length
|
data copied over. The new bytes will be initialised to zero. If the new length
|
||||||
of the array is smaller than the previous the allocated range will simply be
|
of the array is smaller than the previous the allocated range will simply be
|
||||||
|
@ -4576,7 +4584,7 @@ It is possible to shrink an array to a length of zero.
|
||||||
|
|
||||||
**Note**
|
**Note**
|
||||||
The array will be resized in place. The returned reference to `arr` is just for
|
The array will be resized in place. The returned reference to `arr` is just for
|
||||||
convenience.
|
convenience. (Unless `opt-copy-symbol` is `'copy` of course.)
|
||||||
|
|
||||||
Example where we remove the terminating null byte from a string buffer:
|
Example where we remove the terminating null byte from a string buffer:
|
||||||
```clj
|
```clj
|
||||||
|
@ -4593,6 +4601,18 @@ Example where we increase the length of `buf` to 5:
|
||||||
> [1 2 3 4 5]
|
> [1 2 3 4 5]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example where we create a copy of `name` with the terminating null byte
|
||||||
|
removed.
|
||||||
|
```clj
|
||||||
|
(def name "name")
|
||||||
|
(def name-array (buf-resize name -1 'copy))
|
||||||
|
|
||||||
|
(print name)
|
||||||
|
> "name"
|
||||||
|
(print name-array)
|
||||||
|
> [110 97 109 101]
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Import Files
|
## Import Files
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 Rasmus Söderhielm rasmus.soderhielm@gmail.com
|
||||||
|
|
||||||
|
This file is part of the VESC firmware.
|
||||||
|
|
||||||
|
The VESC firmware is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The VESC firmware is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "symrepr.h"
|
||||||
|
#include "lbm_defines.h"
|
||||||
|
#include "lbm_types.h"
|
||||||
|
#include "heap.h"
|
||||||
|
#include "eval_cps.h"
|
||||||
|
#include "lbm_flat_value.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
|
#include "lbm_vesc_utils.h"
|
||||||
|
|
||||||
|
bool lbm_add_symbol_const_if_new(char *name, lbm_uint *id) {
|
||||||
|
if (!lbm_get_symbol_by_name(name, id) && !lbm_add_symbol_const(name, id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_array_header_t *lbm_dec_array_header(lbm_value value) {
|
||||||
|
if (!lbm_is_array_r(value)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (lbm_array_header_t *)lbm_car(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *lbm_dec_array_data(lbm_value value) {
|
||||||
|
if (!lbm_is_array_r(value)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_array_header_t *header = lbm_dec_array_header(value);
|
||||||
|
if (!header->data) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return header->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_value lbm_allocate_empty_list(lbm_uint len) {
|
||||||
|
lbm_value res = ENC_SYM_NIL;
|
||||||
|
for (lbm_uint i = 0; i < len; i++) {
|
||||||
|
res = lbm_cons(ENC_SYM_NIL, res);
|
||||||
|
if (res == ENC_SYM_MERROR) {
|
||||||
|
return ENC_SYM_MERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_value lbm_allocate_empty_list_grid(lbm_uint height, lbm_uint width) {
|
||||||
|
lbm_value outer = ENC_SYM_NIL;
|
||||||
|
for (lbm_uint i = 0; i < height; i++) {
|
||||||
|
lbm_value inner = ENC_SYM_NIL;
|
||||||
|
for (lbm_uint j = 0; j < width; j++) {
|
||||||
|
inner = lbm_cons(ENC_SYM_NIL, inner);
|
||||||
|
if (inner == ENC_SYM_MERROR) {
|
||||||
|
return ENC_SYM_MERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outer = lbm_cons(inner, outer);
|
||||||
|
if (outer == ENC_SYM_MERROR) {
|
||||||
|
return ENC_SYM_MERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lbm_memory_shrink_bytes(void *array, lbm_uint size_bytes) {
|
||||||
|
lbm_uint size_words = size_bytes / LBM_WORD_SIZE;
|
||||||
|
if (size_bytes % LBM_WORD_SIZE != 0) {
|
||||||
|
size_words += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lbm_memory_shrink((lbm_uint *)array, size_words) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lbm_array_shrink(lbm_value array, lbm_uint new_size) {
|
||||||
|
if (!lbm_is_array_rw(array)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_array_header_t *header = (lbm_array_header_t *)lbm_car(array);
|
||||||
|
|
||||||
|
if (!lbm_memory_shrink_bytes(header->data, new_size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
header->size = new_size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char *lbm_error_str_num_args;
|
||||||
|
bool lbm_check_argn_range(lbm_uint argn, lbm_uint n_min, lbm_uint n_max) {
|
||||||
|
if (!(n_min <= argn && argn <= n_max)) {
|
||||||
|
lbm_set_error_reason((char *)lbm_error_str_num_args);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lbm_check_argn_least(lbm_uint argn, lbm_uint n_min) {
|
||||||
|
if (!(n_min <= argn)) {
|
||||||
|
lbm_set_error_reason((char *)lbm_error_str_num_args);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f_pack_array(lbm_flat_value_t *result, void *data, size_t size) {
|
||||||
|
if (!lbm_start_flatten(result, 5 + size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!f_lbm_array(result, size, data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lbm_finish_flatten(result)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 Rasmus Söderhielm rasmus.soderhielm@gmail.com
|
||||||
|
|
||||||
|
This file is part of the VESC firmware.
|
||||||
|
|
||||||
|
The VESC firmware is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
The VESC firmware is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "lbm_types.h"
|
||||||
|
#include "lbm_defines.h"
|
||||||
|
#include "heap.h"
|
||||||
|
#include "lbm_flat_value.h"
|
||||||
|
|
||||||
|
// Is this the right place to define this?
|
||||||
|
/**
|
||||||
|
* Bytes per word in the LBM memory.
|
||||||
|
*/
|
||||||
|
#define LBM_WORD_SIZE 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the array header struct from a lbm value array.
|
||||||
|
*
|
||||||
|
* The type of the value is checked to be at least be a readable array (doesn't
|
||||||
|
* have to be writeable though).
|
||||||
|
*
|
||||||
|
* @param value The lbm value to convert to an array header struct.
|
||||||
|
* @return The extracted pointer to the array header struct if value was a
|
||||||
|
* readable array. Null is returned otherwise. (@note: Null is also returned if
|
||||||
|
* the lbm_value contained a null pointer, @todo: unsure exactly what layer that would
|
||||||
|
* be right now though...)
|
||||||
|
*/
|
||||||
|
lbm_array_header_t *lbm_dec_array_header(lbm_value value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around lbm_memory_shrink that takes number of bytes instead of number
|
||||||
|
* of words. Shrinks the size of an pointer allocated in LBM memory to the
|
||||||
|
* smallest possible size while still having capacity for the specified amount
|
||||||
|
* of bytes.
|
||||||
|
*
|
||||||
|
* @param ptr Pointer to the allocated segment in LBM memory. Should have been
|
||||||
|
* obtained through lbm_malloc or other similar way at some point.
|
||||||
|
* @param size_bytes The new capacity of the allocation in bytes. Must be
|
||||||
|
* smaller or equal to the previous capacity.
|
||||||
|
* @return If the operation succeeded. The return value of lbm_memory_shrink is
|
||||||
|
* directly passed through, that is: false is returned either if ptr didn't
|
||||||
|
* point into the LBM memory/didn't point to the start of an allocated segment
|
||||||
|
* or if the new size was larger than the previous (note that since this
|
||||||
|
* function converts bytes to words, a larger size in bytes might not cause it
|
||||||
|
* to fail, as the size in words could still be the same). Otherwise true is
|
||||||
|
* returned.
|
||||||
|
*/
|
||||||
|
bool lbm_memory_shrink_bytes(void *ptr, lbm_uint size_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shrink an lbm array to the new specified size.
|
||||||
|
*
|
||||||
|
* @param lbm_value The array to shrink. Should hold an LBM value that
|
||||||
|
* corresponds to an array.
|
||||||
|
* @param new_size The new smaller array size.
|
||||||
|
* @return Bool indicating if the array was successfully shrunk. False is
|
||||||
|
* returned if array didn't hold a byte array value, or if new_len was larger
|
||||||
|
* than the original size.
|
||||||
|
*/
|
||||||
|
bool lbm_array_shrink(lbm_value array, lbm_uint new_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the number of arguments is the specified range. Sets error-reason if
|
||||||
|
* result is false.
|
||||||
|
*
|
||||||
|
* The range specified is inclusive!
|
||||||
|
*
|
||||||
|
* @param argn Number of arguments.
|
||||||
|
* @param n_min Minimum number of arguments.
|
||||||
|
* @param n_max Maximum number of arguments.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool lbm_check_argn_range(lbm_uint argn, lbm_uint n_min, lbm_uint n_max);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the number of arguments is at large as long as specified. Sets
|
||||||
|
* error-reason if result is false.
|
||||||
|
*
|
||||||
|
* The (open) range specified is inclusive!
|
||||||
|
*
|
||||||
|
* @param argn Number of arguments.
|
||||||
|
* @param n_min Minimum number of arguments.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool lbm_check_argn_least(lbm_uint argn, lbm_uint n_min);
|
||||||
|
|
||||||
|
#define LBM_CHECK_ARGN_RANGE(min, max) \
|
||||||
|
if (!lbm_check_argn_range(argn, (min), (max))) { \
|
||||||
|
return ENC_SYM_EERROR; \
|
||||||
|
}
|
||||||
|
#define LBM_CHECK_ARGN_LEAST(min) \
|
||||||
|
if (!lbm_check_argn_least(argn, (min))) { \
|
||||||
|
return ENC_SYM_EERROR; \
|
||||||
|
}
|
|
@ -25,7 +25,8 @@ LISPBMSRC = $(LISPBM)/src/env.c \
|
||||||
lispBM/lispif.c \
|
lispBM/lispif.c \
|
||||||
lispBM/lispif_vesc_extensions.c \
|
lispBM/lispif_vesc_extensions.c \
|
||||||
lispBM/lispif_vesc_dynamic_loader.c \
|
lispBM/lispif_vesc_dynamic_loader.c \
|
||||||
lispBM/lispif_c_lib.c
|
lispBM/lispif_c_lib.c \
|
||||||
|
lispBM/lbm_vesc_utils.c
|
||||||
|
|
||||||
LISPBMINC = lispBM \
|
LISPBMINC = lispBM \
|
||||||
$(LISPBM) \
|
$(LISPBM) \
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "extensions/math_extensions.h"
|
#include "extensions/math_extensions.h"
|
||||||
#include "extensions/string_extensions.h"
|
#include "extensions/string_extensions.h"
|
||||||
#include "lbm_constants.h"
|
#include "lbm_constants.h"
|
||||||
|
#include "lbm_vesc_utils.h"
|
||||||
|
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "mc_interface.h"
|
#include "mc_interface.h"
|
||||||
|
@ -222,6 +223,10 @@ typedef struct {
|
||||||
lbm_uint rate_400k;
|
lbm_uint rate_400k;
|
||||||
lbm_uint rate_700k;
|
lbm_uint rate_700k;
|
||||||
|
|
||||||
|
// Arrays
|
||||||
|
lbm_uint copy;
|
||||||
|
lbm_uint mut;
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
lbm_uint half_duplex;
|
lbm_uint half_duplex;
|
||||||
} vesc_syms;
|
} vesc_syms;
|
||||||
|
@ -548,6 +553,12 @@ static bool compare_symbol(lbm_uint sym, lbm_uint *comp) {
|
||||||
get_add_symbol("rate-700k", comp);
|
get_add_symbol("rate-700k", comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (comp == &syms_vesc.copy) {
|
||||||
|
get_add_symbol("copy", comp);
|
||||||
|
} else if (comp == &syms_vesc.mut) {
|
||||||
|
get_add_symbol("mut", comp);
|
||||||
|
}
|
||||||
|
|
||||||
else if (comp == &syms_vesc.half_duplex) {
|
else if (comp == &syms_vesc.half_duplex) {
|
||||||
get_add_symbol("half-duplex", comp);
|
get_add_symbol("half-duplex", comp);
|
||||||
}
|
}
|
||||||
|
@ -564,33 +575,6 @@ static bool is_symbol_true_false(lbm_value v) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around lbm_memory_shrink that takes number of bytes instead of number
|
|
||||||
* of words. Shrinks the size of an pointer allocated in LBM memory to the
|
|
||||||
* smallest possible size while still having capacity for the specified amount
|
|
||||||
* of bytes.
|
|
||||||
*
|
|
||||||
* @param ptr Pointer to the allocated segment in LBM memory. Should have been
|
|
||||||
* obtained through lbm_malloc or other similar way at some point.
|
|
||||||
* @param size_bytes The new capacity of the allocation in bytes. Must be
|
|
||||||
* smaller or equal to the previous capacity.
|
|
||||||
* @return If the operation succeeded. The return value of lbm_memory_shrink is
|
|
||||||
* directly passed through, that is: false is returned either if ptr didn't
|
|
||||||
* point into the LBM memory/didn't point to the start of an allocated segment
|
|
||||||
* or if the new size was larger than the previous (note that since this
|
|
||||||
* function converts bytes to words, a larger size in bytes might not cause it
|
|
||||||
* to fail, as the size in words could still be the same). Otherwise true is
|
|
||||||
* returned.
|
|
||||||
*/
|
|
||||||
static bool lbm_memory_shrink_bytes(void *array, lbm_uint size_bytes) {
|
|
||||||
lbm_uint size_words = size_bytes / LBM_WORD_SIZE;
|
|
||||||
if (size_bytes % LBM_WORD_SIZE != 0) {
|
|
||||||
size_words += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lbm_memory_shrink((lbm_uint *)array, size_words) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Various commands
|
// Various commands
|
||||||
|
|
||||||
static lbm_value ext_print(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_print(lbm_value *args, lbm_uint argn) {
|
||||||
|
@ -4664,15 +4648,41 @@ static lbm_value ext_buf_find(lbm_value *args, lbm_uint argn) {
|
||||||
* reference only for convenience.
|
* reference only for convenience.
|
||||||
*/
|
*/
|
||||||
static lbm_value ext_buf_resize(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_buf_resize(lbm_value *args, lbm_uint argn) {
|
||||||
if ((argn != 2 && argn != 3) || !lbm_is_array_rw(args[0])
|
LBM_CHECK_ARGN_RANGE(2, 4);
|
||||||
|| (!lbm_is_number(args[1]) && !lbm_is_symbol_nil(args[1]))
|
|
||||||
|| (argn == 3 && !lbm_is_number(args[2]))) {
|
bool should_copy = false;
|
||||||
lbm_set_error_reason((char *)lbm_error_str_incorrect_arg);
|
if (argn > 2 && lbm_is_symbol(args[argn - 1])) {
|
||||||
return ENC_SYM_TERROR;
|
lbm_uint sym = lbm_dec_sym(args[argn - 1]);
|
||||||
|
if (compare_symbol(sym, &syms_vesc.copy)) {
|
||||||
|
should_copy = true;
|
||||||
|
} else if (compare_symbol(sym, &syms_vesc.mut)) {
|
||||||
|
should_copy = false;
|
||||||
|
} else {
|
||||||
|
lbm_set_error_suspect(args[argn - 1]);
|
||||||
|
return ENC_SYM_TERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!should_copy && !lbm_is_array_rw(args[0]))
|
||||||
|
|| (should_copy && !lbm_is_array_r(args[0]))) {
|
||||||
|
lbm_set_error_suspect(args[0]);
|
||||||
|
return ENC_SYM_TERROR;
|
||||||
|
}
|
||||||
|
|
||||||
bool delta_size_passed = !lbm_is_symbol_nil(args[1]);
|
bool delta_size_passed = !lbm_is_symbol_nil(args[1]);
|
||||||
bool new_size_passed = argn == 3;
|
bool new_size_passed = argn > 2 && lbm_is_number(args[2]);
|
||||||
|
|
||||||
|
if (delta_size_passed && !lbm_is_number(args[1])) {
|
||||||
|
lbm_set_error_suspect(args[1]);
|
||||||
|
return ENC_SYM_TERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argn == 4 && !lbm_is_number(args[2])) {
|
||||||
|
// The case where argn is 3 is covered by the first check.
|
||||||
|
lbm_set_error_suspect(args[2]);
|
||||||
|
return ENC_SYM_TERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (!delta_size_passed && !new_size_passed) {
|
if (!delta_size_passed && !new_size_passed) {
|
||||||
lbm_set_error_reason(
|
lbm_set_error_reason(
|
||||||
"delta-size (arg 2) was nil while new-size wasn't provided (arg 3)"
|
"delta-size (arg 2) was nil while new-size wasn't provided (arg 3)"
|
||||||
|
@ -4680,7 +4690,7 @@ static lbm_value ext_buf_resize(lbm_value *args, lbm_uint argn) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_array_header_t *header = (lbm_array_header_t *)lbm_car(args[0]);
|
lbm_array_header_t *header = lbm_dec_array_header(args[0]);
|
||||||
if (header == NULL) {
|
if (header == NULL) {
|
||||||
// Should be impossible, unless it contained null pointer to header.
|
// Should be impossible, unless it contained null pointer to header.
|
||||||
return ENC_SYM_FATAL_ERROR;
|
return ENC_SYM_FATAL_ERROR;
|
||||||
|
@ -4701,36 +4711,54 @@ static lbm_value ext_buf_resize(lbm_value *args, lbm_uint argn) {
|
||||||
}
|
}
|
||||||
new_size = (uint32_t)new_size_signed;
|
new_size = (uint32_t)new_size_signed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_size == header->size) {
|
|
||||||
return args[0];
|
|
||||||
} else if (new_size < header->size) {
|
|
||||||
uint32_t allocated_size = new_size;
|
|
||||||
if (new_size == 0) {
|
|
||||||
// arrays of size 0 still need some memory allocated for them.
|
|
||||||
allocated_size = 1;
|
|
||||||
}
|
|
||||||
// We sadly can't trust the return value, as it fails if the allocation
|
|
||||||
// was previously a single word long. So we just throw it away.
|
|
||||||
lbm_memory_shrink_bytes(header->data, allocated_size);
|
|
||||||
|
|
||||||
header->size = new_size;
|
if (should_copy) {
|
||||||
|
void *buffer = lbm_malloc(new_size);
|
||||||
return args[0];
|
if (!buffer) {
|
||||||
} else {
|
|
||||||
void *buffer = lbm_malloc_reserve(new_size);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return ENC_SYM_MERROR;
|
return ENC_SYM_MERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, header->data, MIN(header->size, new_size));
|
||||||
|
if (new_size > header->size) {
|
||||||
|
memset(buffer + header->size, 0, new_size - header->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_value result;
|
||||||
|
if (!lbm_lift_array(&result, buffer, new_size)) {
|
||||||
|
return ENC_SYM_MERROR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
if (new_size == header->size) {
|
||||||
|
return args[0];
|
||||||
|
} else if (new_size < header->size) {
|
||||||
|
uint32_t allocated_size = new_size;
|
||||||
|
if (new_size == 0) {
|
||||||
|
// arrays of size 0 still need some memory allocated for them.
|
||||||
|
allocated_size = 1;
|
||||||
|
}
|
||||||
|
// We sadly can't trust the return value, as it fails if the allocation
|
||||||
|
// was previously a single word long. So we just throw it away.
|
||||||
|
lbm_memory_shrink_bytes(header->data, allocated_size);
|
||||||
|
|
||||||
|
header->size = new_size;
|
||||||
|
|
||||||
memcpy(buffer, header->data, header->size);
|
return args[0];
|
||||||
memset(buffer + header->size, 0, new_size - header->size);
|
} else {
|
||||||
|
void *buffer = lbm_malloc(new_size);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return ENC_SYM_MERROR;
|
||||||
|
}
|
||||||
|
|
||||||
lbm_memory_free(header->data);
|
memcpy(buffer, header->data, header->size);
|
||||||
header->data = buffer;
|
memset(buffer + header->size, 0, new_size - header->size);
|
||||||
header->size = new_size;
|
|
||||||
|
|
||||||
return args[0];
|
lbm_memory_free(header->data);
|
||||||
|
header->data = buffer;
|
||||||
|
header->size = new_size;
|
||||||
|
|
||||||
|
return args[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue