diff --git a/doc/site/modules/core/list.markdown b/doc/site/modules/core/list.markdown index b5d17ac2f..cc710dd83 100644 --- a/doc/site/modules/core/list.markdown +++ b/doc/site/modules/core/list.markdown @@ -36,6 +36,10 @@ System.print(list) //> [0, 1, 2, 3, 4, 5, 6] Returns the added items. +### **capacity** + +The number of elements that can fit in the underlying container before it needs to be resized. + ### **clear**() Removes all elements from the list. @@ -136,6 +140,10 @@ System.print(["a", "b", "c"].removeAt(1)) //> b It is a runtime error if the index is not an integer or is out of bounds. +### **reserve**(capacity) + +Resize the underlying container size to `capacity` if it is greater than its current size. + ### **sort**(), **sort**(comparer) Sorts the elements of a list in-place; altering the list. The default sort is implemented using the quicksort algorithm. diff --git a/src/vm/wren_core.c b/src/vm/wren_core.c index d0a121f8c..2091c4496 100644 --- a/src/vm/wren_core.c +++ b/src/vm/wren_core.c @@ -336,6 +336,11 @@ DEF_PRIMITIVE(list_addCore) RETURN_VAL(args[0]); } +DEF_PRIMITIVE(list_capacity) +{ + RETURN_NUM(AS_LIST(args[0])->elements.capacity); +} + DEF_PRIMITIVE(list_clear) { wrenValueBufferClear(vm, &AS_LIST(args[0])->elements); @@ -406,6 +411,15 @@ DEF_PRIMITIVE(list_removeValue) { RETURN_VAL(wrenListRemoveAt(vm, list, index)); } +DEF_PRIMITIVE(list_reserve) +{ + ObjList* list = AS_LIST(args[0]); + if (!validateInt(vm, args[1], "New capacity")) return false; + double newCapacity = AS_NUM(args[1]); + wrenValueBufferReserve(vm, &list->elements, newCapacity); + RETURN_NULL; +} + DEF_PRIMITIVE(list_indexOf) { ObjList* list = AS_LIST(args[0]); @@ -1434,6 +1448,7 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->listClass, "[_]=(_)", list_subscriptSetter); PRIMITIVE(vm->listClass, "add(_)", list_add); PRIMITIVE(vm->listClass, "addCore_(_)", list_addCore); + PRIMITIVE(vm->listClass, "capacity", list_capacity); PRIMITIVE(vm->listClass, "clear()", list_clear); PRIMITIVE(vm->listClass, "count", list_count); PRIMITIVE(vm->listClass, "insert(_,_)", list_insert); @@ -1441,6 +1456,7 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->listClass, "iteratorValue(_)", list_iteratorValue); PRIMITIVE(vm->listClass, "removeAt(_)", list_removeAt); PRIMITIVE(vm->listClass, "remove(_)", list_removeValue); + PRIMITIVE(vm->listClass, "reserve(_)", list_reserve); PRIMITIVE(vm->listClass, "indexOf(_)", list_indexOf); PRIMITIVE(vm->listClass, "swap(_,_)", list_swap); diff --git a/src/vm/wren_utils.h b/src/vm/wren_utils.h index c2a6e4a36..9a103f621 100644 --- a/src/vm/wren_utils.h +++ b/src/vm/wren_utils.h @@ -24,6 +24,8 @@ typedef struct sObjString ObjString; void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer); \ void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \ int count); \ + void wren##name##BufferReserve(WrenVM* vm, name##Buffer* buffer, \ + int newCapacity); \ void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data) // This should be used once for each type instantiation, somewhere in a .c file. @@ -44,13 +46,7 @@ typedef struct sObjString ObjString; void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \ int count) \ { \ - if (buffer->capacity < buffer->count + count) \ - { \ - int capacity = wrenPowerOf2Ceil(buffer->count + count); \ - buffer->data = (type*)wrenReallocate(vm, buffer->data, \ - buffer->capacity * sizeof(type), capacity * sizeof(type)); \ - buffer->capacity = capacity; \ - } \ + wren##name##BufferReserve(vm, buffer, buffer->count + count); \ \ for (int i = 0; i < count; i++) \ { \ @@ -58,6 +54,18 @@ typedef struct sObjString ObjString; } \ } \ \ + void wren##name##BufferReserve(WrenVM* vm, name##Buffer* buffer, \ + int newCapacity) \ + { \ + if (buffer->capacity < newCapacity) \ + { \ + newCapacity = wrenPowerOf2Ceil(newCapacity); \ + buffer->data = (type*)wrenReallocate(vm, buffer->data, \ + buffer->capacity * sizeof(type), newCapacity * sizeof(type)); \ + buffer->capacity = newCapacity; \ + } \ + } \ + \ void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data) \ { \ wren##name##BufferFill(vm, buffer, data, 1); \