<ply-base.h>namespace plyArrays
<ply-base.h>namespace plyArrays are sequences of items of the same type stored contiguously in memory. Plywood provides three class templates for working with arrays:
Array<Item>is a dynamically resizable array that owns its contents.ArrayView<Item>is a non-owning view into another array.FixedArray<Item, NumItems>is a fixed-size array that owns its contents.
All classes perform runtime bounds checking when assertions are enabled.
These classes all use 32-bit integers for indexing, which means they can store a maximum of roughly 4 billion items.
When a reference to an array is const, all of its items effectively become const, making the array read-only.
These classes aren't thread-safe. Functions that read from the same array can be called concurrently from separate threads, but functions that modify the same array must not be called concurrently.
Common Array Methods
The following member functions are implemented for all array classes:
| Accessing Items | |
Item* | items() |
const Item* | items() const |
u32 | num_items() const |
Item& | operator[](u32 index) & |
Item&& | operator[](u32 index) && |
const Item& | operator[](u32 index) const & |
Item& | back(s32 offset) & |
Item&& | back(s32 offset) && |
const Item& | back(s32 offset) const & |
bool | is_empty() const |
explicit | operator bool() const |
ArrayView<Item> | subview(u32 start) |
ArrayView<const Item> | subview(u32 start) const |
ArrayView<Item> | subview(u32 start, u32 num_items) |
ArrayView<const Item> | subview(u32 start, u32 num_items) const |
Item* | begin() |
const Item* | begin() const |
Item* | end() |
const Item* | end() const |
| Casting to Other Types | |
ArrayView<Item> | view() |
ArrayView<const Item> | view() const |
| operator ArrayView<const Item>() const |
StringView | string_view() const |
MutStringView | mut_string_view() |
Accessing Items
Item* items()
const Item* items() constReturns a raw pointer to the first item in the array, or
nullptrif the array is empty. Avoid calling this function since it bypasses the bounds checking normally performed by other methods. Mainly used to pass array contents to legacy functions that expect a raw pointer.u32 num_items() constReturns the number of items in the array.
Item& operator[](u32 index) &
Item&& operator[](u32 index) &&
const Item& operator[](u32 index) const &Subscript operator with runtime bounds checking. Returns a reference to the item at the specified
index. Will assert ifindexis out of bounds.Array<u32> array = {4, 5, 6}; array[0]; // Returns 4 array[10]; // AssertsItem& back(s32 offset) &
Item&& back(s32 offset) &&
const Item& back(s32 offset) const &Returns a reference to the last item if no argument is provided; otherwise returns a reference to the item at the specified
offsetrelative to the end of the array. Anoffsetof-1returns the last item,-2returns the second-to-last item, and so on. Will assert ifoffsetis out of bounds.Array<u32> array = {4, 5, 6}; array.back(); // Returns 6 array.back(-2); // Returns 5 array.back(-10); // Assertsbool is_empty() constReturns
trueif the array is empty.explicit operator bool() constReturns
trueif the array is non-empty. Allows array objects to be used inifandwhileconditions.Array<u32> array = {4, 5, 6}; if (array) { // array is not empty }ArrayView<Item> subview(u32 start)
ArrayView<const Item> subview(u32 start) const
ArrayView<Item> subview(u32 start, u32 num_items)
ArrayView<const Item> subview(u32 start, u32 num_items) constReturns a view of a portion of the array. If only one argument is provided, returns a view from
startto the end of the array. If two arguments are provided, returns a view of at mostnum_items. These functions don't assert if their arguments are out of range; instead they return an empty or truncated view.Array<u32> array = {4, 5, 6}; array.subview(1); // Returns {5, 6} array.subview(0, 2); // Returns {4, 5} array.subview(2, 3); // Returns {6} array.subview(10); // Returns an empty viewItem* begin()
const Item* begin() const
Item* end()
const Item* end() constLets you use arrays in range-based for loops.
Array<u32> array = {4, 5, 6};
for (u32 item : array) {
get_stdout().format("{}\n", item);
}
4 5 6
Casting to Other Types
ArrayView<Item> view()
ArrayView<const Item> view() constExplicitly creates an
ArrayViewof the entire array. If the array isconst, a read-only view is created.operator ArrayView<Item>()
operator ArrayView<const Item>() constMakes the array implicitly convertible to
ArrayView. The second form allows arrays to be passed to functions that accept only read-onlyArrayViewarguments.// A function that accepts a read-only ArrayView. void use_read_only_view(ArrayView<const u32> array); void test() { Array<u32> array = {4, 5, 6}; use_read_only_view(array); // Implicit conversion to ArrayView<const u32> }StringView string_view() constInterprets the array's bytes as a string and returns a
StringView.MutStringView mut_string_view()Interprets the array's bytes as a mutable string.
Item* release()Releases ownership of the internal buffer and returns a pointer to it. The array becomes empty and the caller is responsible for freeing the memory.
Array
An Array instance is a dynamically resizable array that owns all its items, similar to std::vector from the C++ Standard Library.
template <typename Item> class Array;
In addition to the common array methods listed in the previous section, Array provides the following member functions:
| Additional Constructors | |
template <typename T> | |
| Array(T&& other_array) |
| Array(std::initializer_list<Item> init_list) |
static Array<Item> | adopt(Item* items, u32 num_items) |
| Additional Assignment Operators | |
template <typename T> | |
Array<Item>& | operator=(T&& other_array) |
Array<Item>& | operator=(std::initializer_list init_list) |
| Modifying Array Contents | |
void | resize(u32 num_items) |
void | clear() |
Item& | append(const Item& item) |
Item& | append(Item&& item) |
template <typename... Args> | |
Item& | append(Args&& args) |
Array<Item>& | operator+=(Array<Item>&& other_array) |
template <typename T> | |
Array<Item>& | operator+=(T&& other_array) |
Array<Item>& | operator+=(std::initializer_list init_list) |
Item& | insert(u32 pos, u32 count) |
void | erase(u32 pos, u32 count) |
void | erase_quick(u32 pos, u32 count) |
void | pop(u32 count) |
void | reserve(u32 num_items) |
void | compact() |
Item* | release() |
Be careful not to resize the array while holding a pointer or reference to an item.
It automatically allocates memory to hold the elements from the heap.When an Array object is destroyed, all of its items are destructed and the memory containing them is freed. the ,
, similar to std::vector.
const.
It's movable and copyable. Be careful to avoid unwanted copies.
Internally, it's represented as:
Item* | items |
u32 | num_items |
u32 | population |
The items are allocated from the Plywood heap. There are some gotchas to watch out for. The allocattion strategy is simple. It allocates memory by powers of 2 but you can trim it by calling compact().
You don't need to define the type before declaring an Array member variable. But you do need it if instantiating a variable.
struct Foo; // Forward declaration
struct Bar {
Array<Foo> array; // OK to declare member variable before defining Foo
};
void test() {
Array<Foo> array; // error: Foo should be defined at this point
}
Additional Constructors
The Array class template supports default and move constructors as well as move assignment. It supports copy construction and copy assignment as long as the underlying item type is copyable. Be careful to avoid unwanted copies such as when assigning to auto or passing by value. In addition, it also supports the following constructors and assignment operators:
template <typename T> Array(T&& other_array)Constructs from any compatible array.
other_arraycan be anArray,ArrayView,FixedArrayor a fixed-size C-style array of any type convertible toItem. Ifother_arrayis an rvalue reference, the items are constructed using move semantics if possible.String temp[] = {"apple", "banana", "cherry"}; // Fixed-size C-style array of Strings. Array<String> array{std::move(temp)}; // String items are moved.Array(std::initializer_list<Item> init_list)Constructs an array directly from a C++11-style braced initializer list.
Array<int> array = {3, 4, 5};static Array<Item> adopt(Item* items, u32 num_items)Explicitly create an
Arrayobject from the provided arguments. No memory is allocated and no constructors are called; the returned array simply adopts the provideditems, which must be allocated from the Plywood heap. This memory will be freed when theArrayis destructed.
Additional Assignment Operators
template <typename T> Array<Item>& operator=(T&& other_array)Assigns from any compatible array.
other_arraycan be anArray,ArrayView,FixedArrayor a fixed-size C-style array of any type convertible toItem. Ifother_arrayis an rvalue reference, the items are assigned using move semantics if possible.Array<Item>& operator=(std::initializer_list init_list)Assigns directly from a C++11-style braced initializer list.
Modifying Array Contents
void resize(u32 num_items)Resizes the array.
void clear()Clears the array.
Item& append(const Item& item)
Item& append(Item&& item)Adds an item to the end of the array and returns a reference to it. The array is resized if necessary.
template <typename... Args> Item& append(Args&& args)Constructs a new item in place at the end of the array using the provided arguments, and returns a reference to it.
Array<Item>& operator+=(Array<Item>&& other_array)Move extend.
template <typename T> Array<Item>& operator+=(T&& other_array)Extend from any compatible array.
Array<Item>& operator+=(std::initializer_list init_list)Extend from initializer list.
Item& insert(u32 pos, u32 count)Inserts
countdefault-constructed items at positionpos. Existing items at and afterposare shifted. Returns a reference to the first inserted item.void erase(u32 pos, u32 count)Removes
countitems starting atpos. Items after the erased range are shifted down to fill the gap.void erase_quick(u32 pos, u32 count)Removes
countitems starting atposby moving the last items of the array into the gap. This is faster thanerasebut does not preserve order.void pop(u32 count)Removes
countitems from the end of the array.void reserve(u32 num_items)Ensures the array has capacity for at least
num_itemswithout reallocation. Does not change the current size.void compact()Releases any excess capacity, shrinking the buffer to match the current number of items.
ArrayView
An ArrayView is a non-owning view into another array.
Supports default, move and copy construction and move and copy assignment. Implements the following member functions in addition to the common string methods:
By convention, Plywood usually passes ArrayView objects to functions by value instead of by reference, since copying an ArrayView doesn't copy the underlying items.
| Additional Constructors | |
| ArrayView(Item* items, u32 num_items) |
| ArrayView(Item) |
| ArrayView(std::initializer_list<Item> init) |
It's implicitly convertible to ArrayView<const Item>.
Additional Constructors
ArrayView(Item* items, u32 num_items)Constructs a view over an existing buffer of
num_itemsitems starting atitems.ArrayView(Item)Constructs a view from a static array. The size is automatically inferred.
ArrayView(std::initializer_list<Item> init)Constructs a view from an initializer list. Be careful: the initializer list's storage is temporary.
FixedArray
A FixedArray is a fixed-size array that owns its contents.
template <typename Item, u32 Size> class FixedArray;
No additional heap allocations are performed. All the array items are stored directly in the FixedArray object. It's equivalent to a C-style array, but with runtime bounds checking.
The default constructor default-constructs all items.
| Additional Constructors | |
| FixedArray(std::initializer_list<Item> args) |
| FixedArray(Args&& args) |
Additional Constructors
FixedArray(std::initializer_list<Item> args)Constructs the array from an initializer list. The list must have exactly
Sizeelements.FixedArray(Args&& args)Constructs the array from the provided arguments. Each argument is used to construct one item.