Skip to content

Commit b171d12

Browse files
Add Enumeration::index_of API (#5482)
Add `Enumeration::index_of` API which returns an `std::optional<uint64_t>` containing the internal index of a value in an Enumeration if it exists. User code who needs to extend an enumeration given a list of values need to recreate the internal hash map structure to efficiently find which values are missing from the enumeration. Also remapping the indexes from a subset of values to the values the enumeration holds also requires the creation of the values hash map. Providing access to the internal hash map of the enumeration eliminates the need to recreate the map which might me an expensive step. --- TYPE: FEATURE DESC: Add `Enumeration::index_of` API
1 parent 089153d commit b171d12

File tree

5 files changed

+232
-0
lines changed

5 files changed

+232
-0
lines changed

test/src/unit-cppapi-enumerations.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,46 @@ TEST_CASE_METHOD(
282282
REQUIRE_THROWS_WITH(enmr.extend(add_values), matcher);
283283
}
284284

285+
TEST_CASE_METHOD(
286+
CPPEnumerationFx,
287+
"CPP: Enumeration API - Var Size index_of",
288+
"[enumeration][index_of]") {
289+
std::vector<std::string> init_values = {"fred", "wilma"};
290+
auto enmr = Enumeration::create(ctx_, enmr_name, init_values, true);
291+
292+
std::string_view val = "wilma";
293+
294+
REQUIRE(enmr.index_of(val).has_value() == true);
295+
REQUIRE(enmr.index_of(val).value() == 1);
296+
}
297+
298+
TEST_CASE_METHOD(
299+
CPPEnumerationFx,
300+
"CPP: Enumeration API - Fix Size Int64 index_of",
301+
"[enumeration][index_of]") {
302+
std::vector<int64_t> init_values = {1, 5, 6};
303+
auto enmr =
304+
Enumeration::create(ctx_, enmr_name, init_values, true, TILEDB_INT64);
305+
std::string_view val = "wilma";
306+
REQUIRE(enmr.index_of(val).has_value() == false);
307+
308+
REQUIRE(enmr.index_of<int32_t>(1).has_value() == false);
309+
REQUIRE(enmr.index_of<int64_t>(1).has_value() == true);
310+
}
311+
312+
TEST_CASE_METHOD(
313+
CPPEnumerationFx,
314+
"CPP: Enumeration API - Fix Size Float32 index_of",
315+
"[enumeration][index_of]") {
316+
std::vector<float_t> init_values = {1, 5, 6, -4};
317+
auto enmr = Enumeration::create(ctx_, enmr_name, init_values, true);
318+
319+
REQUIRE(enmr.index_of<int32_t>(-4).has_value() == false);
320+
REQUIRE(enmr.index_of<float_t>(-4).has_value() == true);
321+
REQUIRE(enmr.index_of<float_t>(-4).value() == 3);
322+
REQUIRE(enmr.index_of<double_t>(-4).has_value() == false);
323+
}
324+
285325
TEST_CASE_METHOD(
286326
CPPEnumerationFx,
287327
"CPP: Enumeration API - Dump Basic",

tiledb/api/c_api/enumeration/enumeration_api.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,22 @@ capi_return_t tiledb_enumeration_get_name(
125125
return TILEDB_OK;
126126
}
127127

128+
capi_return_t tiledb_enumeration_get_value_index(
129+
tiledb_enumeration_t* enumeration,
130+
const void* value,
131+
uint64_t value_size,
132+
int* exist,
133+
uint64_t* index) {
134+
ensure_enumeration_is_valid(enumeration);
135+
ensure_output_pointer_is_valid(exist);
136+
ensure_output_pointer_is_valid(index);
137+
138+
*index = enumeration->enumeration()->index_of(value, value_size);
139+
*exist = *index != sm::constants::enumeration_missing_value ? 1 : 0;
140+
141+
return TILEDB_OK;
142+
}
143+
128144
capi_return_t tiledb_enumeration_get_type(
129145
tiledb_enumeration_t* enumeration, tiledb_datatype_t* type) {
130146
ensure_enumeration_is_valid(enumeration);
@@ -269,6 +285,18 @@ CAPI_INTERFACE(
269285
ctx, enumeration, name);
270286
}
271287

288+
CAPI_INTERFACE(
289+
enumeration_get_value_index,
290+
tiledb_ctx_t* ctx,
291+
tiledb_enumeration_t* enumeration,
292+
const void* value,
293+
uint64_t value_size,
294+
int* exist,
295+
uint64_t* index) {
296+
return api_entry_context<tiledb::api::tiledb_enumeration_get_value_index>(
297+
ctx, enumeration, value, value_size, exist, index);
298+
}
299+
272300
CAPI_INTERFACE(
273301
enumeration_get_type,
274302
tiledb_ctx_t* ctx,

tiledb/api/c_api/enumeration/enumeration_api_experimental.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,37 @@ TILEDB_EXPORT capi_return_t tiledb_enumeration_get_offsets(
293293
const void** offsets,
294294
uint64_t* offsets_size) TILEDB_NOEXCEPT;
295295

296+
/**
297+
* Return the index of the given value in the enumeration
298+
*
299+
* **Example:**
300+
*
301+
* @code{.c}
302+
* int32_t value = 10;
303+
* int exist;
304+
* uint64_t index;
305+
* tiledb_enumeration_get_value_index(ctx, enumeration, &value, sizeof(int32_t),
306+
* &exist, &index);
307+
* @endcode
308+
*
309+
* @param ctx The TileDB context.
310+
* @param enumeration The enumeration.
311+
* @param value A pointer to the enumeration value data to check if is
312+
* contained.
313+
* @param value_size The length of the value buffer provided.
314+
* @param exist The return pointer storing whether the value exists.
315+
* @param index The return pointer storing the index of the value in the
316+
* enumration if it exists.
317+
* @return `TILEDB_OK` or `TILEDB_ERR`.
318+
*/
319+
TILEDB_EXPORT capi_return_t tiledb_enumeration_get_value_index(
320+
tiledb_ctx_t* ctx,
321+
tiledb_enumeration_t* enumeration,
322+
const void* value,
323+
uint64_t value_size,
324+
int* exist,
325+
uint64_t* index) TILEDB_NOEXCEPT;
326+
296327
#ifndef TILEDB_REMOVE_DEPRECATIONS
297328
/**
298329
* Dumps the contents of an Enumeration in ASCII form to some output (e.g.,

tiledb/api/c_api/enumeration/test/unit_capi_enumeration.cc

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,107 @@ TEST_CASE(
585585
REQUIRE(rc == TILEDB_ERR);
586586
}
587587
}
588+
589+
TEST_CASE(
590+
"C API: tiledb_enumeration_get_value_index argument validation",
591+
"[capi][enumeration]") {
592+
FixedSizeEnumeration fe;
593+
VarSizeEnumeration ve;
594+
NotAllEmptyStringEnumeration ne;
595+
AllEmptyStringEnumeration ae;
596+
int exist;
597+
uint64_t index;
598+
599+
SECTION("found") {
600+
uint32_t uint32_t_value = 3;
601+
auto rc = tiledb_enumeration_get_value_index(
602+
fe.ctx_.context,
603+
fe.enumeration_,
604+
&uint32_t_value,
605+
sizeof(uint32_t),
606+
&exist,
607+
&index);
608+
REQUIRE(rc == TILEDB_OK);
609+
REQUIRE(exist == 1);
610+
REQUIRE(index == 2);
611+
612+
std::string string_value = "bar";
613+
rc = tiledb_enumeration_get_value_index(
614+
ve.ctx_.context,
615+
ve.enumeration_,
616+
string_value.data(),
617+
string_value.size(),
618+
&exist,
619+
&index);
620+
REQUIRE(rc == TILEDB_OK);
621+
REQUIRE(exist == 1);
622+
REQUIRE(index == 1);
623+
624+
std::string empty_string_value = "";
625+
rc = tiledb_enumeration_get_value_index(
626+
ne.ctx_.context,
627+
ne.enumeration_,
628+
empty_string_value.data(),
629+
empty_string_value.size(),
630+
&exist,
631+
&index);
632+
REQUIRE(rc == TILEDB_OK);
633+
REQUIRE(exist == 1);
634+
REQUIRE(index == 1);
635+
636+
rc = tiledb_enumeration_get_value_index(
637+
ae.ctx_.context,
638+
ae.enumeration_,
639+
empty_string_value.data(),
640+
empty_string_value.size(),
641+
&exist,
642+
&index);
643+
REQUIRE(rc == TILEDB_OK);
644+
REQUIRE(exist == 1);
645+
REQUIRE(index == 0);
646+
}
647+
648+
SECTION("not found") {
649+
uint32_t uint32_t_value = 10;
650+
auto rc = tiledb_enumeration_get_value_index(
651+
fe.ctx_.context,
652+
fe.enumeration_,
653+
&uint32_t_value,
654+
sizeof(uint32_t),
655+
&exist,
656+
&index);
657+
REQUIRE(rc == TILEDB_OK);
658+
REQUIRE(exist == 0);
659+
660+
std::string string_value = "fun";
661+
rc = tiledb_enumeration_get_value_index(
662+
ve.ctx_.context,
663+
ve.enumeration_,
664+
string_value.data(),
665+
string_value.size(),
666+
&exist,
667+
&index);
668+
REQUIRE(rc == TILEDB_OK);
669+
REQUIRE(exist == 0);
670+
671+
rc = tiledb_enumeration_get_value_index(
672+
ne.ctx_.context,
673+
ne.enumeration_,
674+
string_value.data(),
675+
string_value.size(),
676+
&exist,
677+
&index);
678+
REQUIRE(rc == TILEDB_OK);
679+
REQUIRE(exist == 0);
680+
681+
rc = tiledb_enumeration_get_value_index(
682+
ae.ctx_.context,
683+
ae.enumeration_,
684+
string_value.data(),
685+
string_value.size(),
686+
&exist,
687+
&index);
688+
REQUIRE(rc == TILEDB_OK);
689+
REQUIRE(exist == 0);
690+
}
691+
}

tiledb/sm/cpp_api/enumeration_experimental.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#include "tiledb.h"
3838
#include "tiledb_experimental.h"
3939

40+
#include <optional>
41+
4042
namespace tiledb {
4143

4244
class Enumeration {
@@ -198,6 +200,33 @@ class Enumeration {
198200
return ret;
199201
}
200202

203+
template <typename T, impl::enable_trivial<T>* = nullptr>
204+
std::optional<uint64_t> index_of(T value) {
205+
int exist = 0;
206+
uint64_t index;
207+
tiledb_ctx_t* c_ctx = ctx_.get().ptr().get();
208+
ctx_.get().handle_error(tiledb_enumeration_get_value_index(
209+
c_ctx, enumeration_.get(), &value, sizeof(T), &exist, &index));
210+
211+
return exist == 1 ? std::make_optional(index) : std::nullopt;
212+
}
213+
214+
template <typename T, impl::enable_trivial<T>* = nullptr>
215+
std::optional<uint64_t> index_of(std::basic_string_view<T> value) {
216+
int exist = 0;
217+
uint64_t index;
218+
tiledb_ctx_t* c_ctx = ctx_.get().ptr().get();
219+
ctx_.get().handle_error(tiledb_enumeration_get_value_index(
220+
c_ctx,
221+
enumeration_.get(),
222+
value.data(),
223+
value.size() * sizeof(T),
224+
&exist,
225+
&index));
226+
227+
return exist == 1 ? std::make_optional(index) : std::nullopt;
228+
}
229+
201230
/**
202231
* Get the context of the enumeration
203232
* @return Context The context of the enumeration.

0 commit comments

Comments
 (0)