diff --git a/xo-object2/include/xo/object2/DArray.hpp b/xo-object2/include/xo/object2/DArray.hpp index 2de3b312..f07941cb 100644 --- a/xo-object2/include/xo/object2/DArray.hpp +++ b/xo-object2/include/xo/object2/DArray.hpp @@ -64,6 +64,10 @@ namespace xo { bool is_empty() const noexcept { return size_ == 0; } /** only support finite arrays :-) **/ bool is_finite() const noexcept { return true; } + /** array capacity **/ + size_type capacity() const noexcept { return capacity_; } + /** current array size (number of elements) **/ + size_type size() const noexcept { return size_; } /** return element @p index of this array (0-based) **/ obj at(size_type index) const; ///@} diff --git a/xo-object2/include/xo/object2/DString.hpp b/xo-object2/include/xo/object2/DString.hpp index a029da3f..6f3fa4ec 100644 --- a/xo-object2/include/xo/object2/DString.hpp +++ b/xo-object2/include/xo/object2/DString.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +//#include namespace xo { namespace scm { @@ -34,6 +34,7 @@ namespace xo { using traits_type = std::char_traits; /** type of each character in this DString **/ using value_type = char; + /** type for string index / size **/ using size_type = std::uint32_t; /** representation for a read/write iterator **/ using iterator = char *; @@ -57,7 +58,7 @@ namespace xo { **/ DString(const DString &) = delete; - /** create empty string with space for @cap chars + /** create empty string with space for @p cap chars * (including null terminator). * Use memory from allocator @p mm **/ diff --git a/xo-object2/src/object2/DArray.cpp b/xo-object2/src/object2/DArray.cpp index 1039427e..676086d4 100644 --- a/xo-object2/src/object2/DArray.cpp +++ b/xo-object2/src/object2/DArray.cpp @@ -4,6 +4,8 @@ **/ #include "DArray.hpp" +#include +#include namespace xo { using xo::mm::AGCObject; @@ -33,6 +35,19 @@ namespace xo { return result; } + obj + DArray::at(size_type ix) const + { + if (ix < size_) { + return elts_[ix]; + } else { + throw std::runtime_error(tostr("DArray::at: out-of-range index where [0..z) expected", + xtag("index", ix), + xtag("z", this->size()))); + return obj(); + } + } + bool DArray::push_back(obj elt) noexcept { if (size_ >= capacity_) { diff --git a/xo-object2/src/object2/DString.cpp b/xo-object2/src/object2/DString.cpp index 517f3f97..8787f687 100644 --- a/xo-object2/src/object2/DString.cpp +++ b/xo-object2/src/object2/DString.cpp @@ -26,6 +26,9 @@ namespace xo { sizeof(DString) + cap); result = new (mem) DString(); + + assert(result); + result->capacity_ = cap; result->size_ = 0; if (cap > 0) { diff --git a/xo-object2/utest/DArray.test.cpp b/xo-object2/utest/DArray.test.cpp index 14282f8c..aa718d44 100644 --- a/xo-object2/utest/DArray.test.cpp +++ b/xo-object2/utest/DArray.test.cpp @@ -5,11 +5,13 @@ #include #include +#include #include #include #include namespace xo { + using xo::scm::ListOps; using xo::scm::DArray; using xo::scm::DInteger; using xo::mm::AAllocator; @@ -20,6 +22,18 @@ namespace xo { using xo::facet::obj; namespace ut { + TEST_CASE("DArray-nullctor", "[object2][DArray]") + { + DArray arr; + + REQUIRE(arr.size() == 0); + REQUIRE(arr.capacity() == 0); + + REQUIRE(arr.is_empty());; + + REQUIRE(arr.push_back(ListOps::nil()) == false); + } + TEST_CASE("DArray-empty", "[object2][DArray]") { ArenaConfig cfg { .name_ = "testarena", @@ -30,7 +44,10 @@ namespace xo { DArray * arr = DArray::empty(alloc, 16); REQUIRE(arr != nullptr); + REQUIRE(arr->capacity() == 16); + REQUIRE(arr->is_empty() == true); + REQUIRE(arr->size() == 0); REQUIRE(arr->is_finite() == true); } @@ -43,6 +60,8 @@ namespace xo { DArray * arr = DArray::empty(alloc, 16); REQUIRE(arr != nullptr); + REQUIRE(arr->capacity() == 16); + REQUIRE(arr->size() == 0); obj elt = DInteger::box(alloc, 42); @@ -50,6 +69,8 @@ namespace xo { REQUIRE(ok == true); REQUIRE(arr->is_empty() == false); + REQUIRE(arr->size() == 1); + REQUIRE(arr->capacity() == 16); } TEST_CASE("DArray-push_back-multiple", "[object2][DArray]") @@ -61,14 +82,21 @@ namespace xo { DArray * arr = DArray::empty(alloc, 4); REQUIRE(arr != nullptr); + REQUIRE(arr->capacity() == 4); + REQUIRE(arr->size() == 0); for (int i = 0; i < 4; ++i) { + REQUIRE(arr->capacity() == 4); + REQUIRE(arr->size() == i); + obj elt = DInteger::box(alloc, 100 + i); bool ok = arr->push_back(elt); REQUIRE(ok == true); - } - REQUIRE(arr->is_empty() == false); + REQUIRE(arr->capacity() == 4); + REQUIRE(arr->is_empty() == false); + REQUIRE(arr->size() == i+1); + } } TEST_CASE("DArray-push_back-overflow", "[object2][DArray]") @@ -79,15 +107,50 @@ namespace xo { auto alloc = with_facet::mkobj(&arena); DArray * arr = DArray::empty(alloc, 2); + REQUIRE(arr != nullptr); + REQUIRE(arr->capacity() == 2); + REQUIRE(arr->size() == 0); obj e1 = DInteger::box(alloc, 1); obj e2 = DInteger::box(alloc, 2); obj e3 = DInteger::box(alloc, 3); REQUIRE(arr->push_back(e1) == true); + REQUIRE(arr->size() == 1); REQUIRE(arr->push_back(e2) == true); + REQUIRE(arr->size() == 2); REQUIRE(arr->push_back(e3) == false); + REQUIRE(arr->size() == 2); + REQUIRE(arr->capacity() == 2); + } + + TEST_CASE("DArray-at", "[object2][DArray]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DArray * arr = DArray::empty(alloc, 4); + + REQUIRE(arr != nullptr); + REQUIRE(arr->size() == 0); + REQUIRE(arr->capacity() == 4); + + obj e0 = DInteger::box(alloc, 100); + obj e1 = DInteger::box(alloc, 200); + obj e2 = DInteger::box(alloc, 300); + + arr->push_back(e0); + arr->push_back(e1); + arr->push_back(e2); + + REQUIRE(arr->size() == 3); + + REQUIRE(arr->at(0).data() == e0.data()); + REQUIRE(arr->at(1).data() == e1.data()); + REQUIRE(arr->at(2).data() == e2.data()); } } /*namespace ut*/