diff --git a/src/libexpr-c/nix_api_expr_internal.h b/src/libexpr-c/nix_api_expr_internal.h index 2b066ecff..b50a51347 100644 --- a/src/libexpr-c/nix_api_expr_internal.h +++ b/src/libexpr-c/nix_api_expr_internal.h @@ -5,32 +5,6 @@ #include "attr-set.hh" #include "nix_api_value.h" -class CListBuilder -{ -private: - std::vector values; - -public: - CListBuilder(size_t capacity) - { - values.reserve(capacity); - } - - void push_back(nix::Value * value) - { - values.push_back(value); - } - - Value * finish(nix::EvalState * state, nix::Value * list) - { - state->mkList(*list, values.size()); - for (size_t n = 0; n < list->listSize(); ++n) { - list->listElems()[n] = values[n]; - } - return list; - } -}; - struct EvalState { nix::EvalState state; @@ -43,7 +17,7 @@ struct BindingsBuilder struct ListBuilder { - CListBuilder builder; + nix::ListBuilder builder; }; struct nix_string_return diff --git a/src/libexpr-c/nix_api_value.cc b/src/libexpr-c/nix_api_value.cc index 1faf05611..26ae194d9 100644 --- a/src/libexpr-c/nix_api_value.cc +++ b/src/libexpr-c/nix_api_value.cc @@ -263,7 +263,8 @@ Value * nix_get_list_byidx(nix_c_context * context, const Value * value, EvalSta assert(v.type() == nix::nList); auto * p = v.listElems()[ix]; nix_gc_incref(nullptr, p); - state->state.forceValue(*p, nix::noPos); + if (p != nullptr) + state->state.forceValue(*p, nix::noPos); return (Value *) p; } NIXC_CATCH_ERRS_NULL @@ -417,7 +418,7 @@ ListBuilder * nix_make_list_builder(nix_c_context * context, EvalState * state, if (context) context->last_err_code = NIX_OK; try { - auto builder = CListBuilder(capacity); + auto builder = state->state.buildList(capacity); return new #if HAVE_BOEHMGC (NoGC) @@ -427,20 +428,21 @@ ListBuilder * nix_make_list_builder(nix_c_context * context, EvalState * state, NIXC_CATCH_ERRS_NULL } -nix_err nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, Value * value) +nix_err nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, unsigned int index, Value * value) { if (context) context->last_err_code = NIX_OK; try { - list_builder->builder.push_back((nix::Value *) value); + auto & e = check_value_not_null(value); + list_builder->builder[index] = &e; } NIXC_CATCH_ERRS } -void nix_list_builder_free(ListBuilder * bb) +void nix_list_builder_free(ListBuilder * list_builder) { #if HAVE_BOEHMGC - GC_FREE(bb); + GC_FREE(list_builder); #else delete bb; #endif @@ -452,7 +454,7 @@ nix_err nix_make_list(nix_c_context * context, EvalState * s, ListBuilder * list context->last_err_code = NIX_OK; try { auto & v = check_value_not_null(value); - list_builder->builder.finish(&(s->state), &v); + v.mkList(list_builder->builder); } NIXC_CATCH_ERRS } diff --git a/src/libexpr-c/nix_api_value.h b/src/libexpr-c/nix_api_value.h index b7115c27d..d80414fe8 100644 --- a/src/libexpr-c/nix_api_value.h +++ b/src/libexpr-c/nix_api_value.h @@ -360,17 +360,18 @@ ListBuilder * nix_make_list_builder(nix_c_context * context, EvalState * state, /** @brief Insert bindings into a builder * @param[out] context Optional, stores error information * @param[in] list_builder ListBuilder to insert into + * @param[in] index index to manipulate * @param[in] value value to insert * @return error code, NIX_OK on success. */ -nix_err nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, Value * value); +nix_err nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, unsigned int index, Value * value); /** @brief Free a list builder * * Does not fail. * @param[in] builder the builder to free */ -void nix_list_builder_free(ListBuilder * builder); +void nix_list_builder_free(ListBuilder * list_builder); /** @brief Create an attribute set from a bindings builder * @param[out] context Optional, stores error information diff --git a/tests/unit/libexpr/nix_api_value.cc b/tests/unit/libexpr/nix_api_value.cc index ac28526c8..fd7c91a7d 100644 --- a/tests/unit/libexpr/nix_api_value.cc +++ b/tests/unit/libexpr/nix_api_value.cc @@ -77,12 +77,13 @@ TEST_F(nix_api_expr_test, nix_build_and_init_list) Value * intValue = nix_alloc_value(nullptr, state); nix_init_int(nullptr, intValue, 42); - nix_list_builder_insert(nullptr, builder, intValue); + nix_list_builder_insert(nullptr, builder, 0, intValue); nix_make_list(nullptr, state, builder, value); nix_list_builder_free(builder); ASSERT_EQ(42, nix_get_int(nullptr, nix_get_list_byidx(nullptr, value, state, 0))); - ASSERT_EQ(1, nix_get_list_size(nullptr, value)); + ASSERT_EQ(nullptr, nix_get_list_byidx(nullptr, value, state, 1)); + ASSERT_EQ(10, nix_get_list_size(nullptr, value)); ASSERT_STREQ("a list", nix_get_typename(nullptr, value)); ASSERT_EQ(NIX_TYPE_LIST, nix_get_type(nullptr, value));