Blender V5.0
DNA_array_utils.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13#pragma once
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_function_ref.hh"
18#include "BLI_index_range.hh"
19#include "BLI_utildefines.h"
20
22
26template<typename T>
27inline void remove_index(
28 T **items, int *items_num, int *active_index, const int index, void (*destruct_item)(T *))
29{
30 static_assert(std::is_trivial_v<T>);
31 BLI_assert(index >= 0);
32 BLI_assert(index < *items_num);
33
34 const int old_items_num = *items_num;
35 const int new_items_num = old_items_num - 1;
36
37 T *old_items = *items;
38 T *new_items = MEM_calloc_arrayN<T>(new_items_num, __func__);
39
40 std::copy_n(old_items, index, new_items);
41 std::copy_n(old_items + index + 1, old_items_num - index - 1, new_items + index);
42
43 destruct_item(&old_items[index]);
44 MEM_freeN(old_items);
45
46 *items = new_items;
47 *items_num = new_items_num;
48
49 if (active_index) {
50 const int old_active_index = active_index ? *active_index : 0;
51 const int new_active_index = std::max(
52 0, old_active_index == new_items_num ? new_items_num - 1 : old_active_index);
53 *active_index = new_active_index;
54 }
55}
56
61template<typename T>
62inline void remove_if(T **items,
63 int *items_num,
64 FunctionRef<bool(const T &)> predicate,
65 void (*destruct_item)(T *))
66{
67 static_assert(std::is_trivial_v<T>);
68 /* This sorts the items-to-remove to the back. */
69 const int remaining = std::stable_partition(*items,
70 *items + *items_num,
71 [&](const T &value) { return !predicate(value); }) -
72 *items;
73 for (const int i : IndexRange::from_begin_end(remaining, *items_num)) {
74 destruct_item(&(*items)[i]);
75 }
76 *items_num = remaining;
77}
78
82template<typename T>
83inline void clear(T **items, int *items_num, int *active_index, void (*destruct_item)(T *))
84{
85 static_assert(std::is_trivial_v<T>);
86 for (const int i : IndexRange(*items_num)) {
87 destruct_item(&(*items)[i]);
88 }
89 MEM_SAFE_FREE(*items);
90 *items_num = 0;
91 if (active_index) {
92 *active_index = 0;
93 }
94}
95
99template<typename T>
100inline void move_index(T *items, const int items_num, const int from_index, const int to_index)
101{
102 static_assert(std::is_trivial_v<T>);
103 BLI_assert(from_index >= 0);
104 BLI_assert(from_index < items_num);
105 BLI_assert(to_index >= 0);
106 BLI_assert(to_index < items_num);
107 UNUSED_VARS_NDEBUG(items_num);
108
109 if (from_index == to_index) {
110 return;
111 }
112
113 if (from_index < to_index) {
114 const T tmp = items[from_index];
115 for (int i = from_index; i < to_index; i++) {
116 items[i] = items[i + 1];
117 }
118 items[to_index] = tmp;
119 }
120 else if (from_index > to_index) {
121 const T tmp = items[from_index];
122 for (int i = from_index; i > to_index; i--) {
123 items[i] = items[i - 1];
124 }
125 items[to_index] = tmp;
126 }
127}
128
129} // namespace blender::dna::array
#define BLI_assert(a)
Definition BLI_assert.h:46
#define UNUSED_VARS_NDEBUG(...)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define T
void remove_if(T **items, int *items_num, FunctionRef< bool(const T &)> predicate, void(*destruct_item)(T *))
void remove_index(T **items, int *items_num, int *active_index, const int index, void(*destruct_item)(T *))
void clear(T **items, int *items_num, int *active_index, void(*destruct_item)(T *))
void move_index(T *items, const int items_num, const int from_index, const int to_index)
i
Definition text_draw.cc:230