[ox/ptrarith] Fix NodeBuffer to properly handle removing only node

This commit is contained in:
Gary Talent 2019-06-25 00:32:53 -05:00
parent 6571129686
commit 3adf0df9c7
5 changed files with 113 additions and 14 deletions

View File

@ -5,3 +5,5 @@ install(
DESTINATION
include/ox/ptrarith
)
add_subdirectory(test)

View File

@ -19,7 +19,7 @@ class __attribute__((packed)) NodeBuffer {
public:
struct __attribute__((packed)) Header {
ox::LittleEndian<size_t> size = sizeof(Header);
ox::LittleEndian<size_t> size = sizeof(Header); // capacity
ox::LittleEndian<size_t> bytesUsed = sizeof(Header);
ox::LittleEndian<size_t> firstItem = 0;
};
@ -67,7 +67,7 @@ class __attribute__((packed)) NodeBuffer {
return m_current;
}
bool valid() const noexcept {
[[nodiscard]] bool valid() const noexcept {
return m_current.valid();
}
@ -113,22 +113,29 @@ class __attribute__((packed)) NodeBuffer {
template<typename T>
Ptr<T, size_t, sizeof(Item)> dataOf(ItemPtr);
ItemPtr prev(Item *item);
[[nodiscard]] ItemPtr prev(Item *item);
ItemPtr next(Item *item);
[[nodiscard]] ItemPtr next(Item *item);
ItemPtr ptr(size_t offset);
[[nodiscard]] ItemPtr ptr(size_t offset);
ItemPtr ptr(void *item);
[[nodiscard]] ItemPtr ptr(void *item);
ItemPtr malloc(size_t size);
[[nodiscard]] ItemPtr malloc(size_t size);
Error free(ItemPtr item);
[[nodiscard]] ox::Error free(ItemPtr item);
bool valid(size_t maxSize);
[[nodiscard]] bool valid(size_t maxSize);
Error setSize(size_t size);
/**
* Set size, capacity.
*/
[[nodiscard]] ox::Error setSize(size_t size);
/**
* Get size, capacity.
* @return capacity
*/
size_t size();
/**
@ -278,16 +285,26 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
auto prev = this->prev(item);
auto next = this->next(item);
if (prev.valid() && next.valid()) {
prev->next = next.offset();
next->prev = prev.offset();
if (next != item) {
prev->next = next.offset();
next->prev = prev.offset();
if (item.offset() == m_header.firstItem) {
m_header.firstItem = next;
}
} else {
// only one item, null out first
oxTrace("ox::ptrarith::NodeBuffer::free") << "Nulling out firstItem.";
m_header.firstItem = 0;
}
} else {
if (!prev.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid prev element pointer:" << prev.offset();
return OxError(1);
}
if (!next.valid()) {
oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid next element pointer:" << next.offset();
return OxError(1);
}
return OxError(1);
}
m_header.bytesUsed -= item.size();
return OxError(0);

View File

@ -31,7 +31,7 @@ class Ptr {
inline Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize = sizeof(T), size_t itemTypeSize = sizeof(T));
inline bool valid() const;
[[nodiscard]] inline bool valid() const;
inline size_t size() const;

View File

@ -0,0 +1,11 @@
add_executable(
PtrArithTests
tests.cpp
)
target_link_libraries(
PtrArithTests
OxStd
)
add_test("Test\\ PtrArith::setSize" PtrArithTests PtrArith::setSize)

69
deps/ox/src/ox/ptrarith/test/tests.cpp vendored Normal file
View File

@ -0,0 +1,69 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// make sure asserts are enabled for the test file
#undef NDEBUG
#include <iostream>
#include <assert.h>
#include <array>
#include <map>
#include <vector>
#include <string>
#include <ox/ptrarith/nodebuffer.hpp>
#include <ox/fs/fs.hpp>
#include <ox/std/std.hpp>
#include <ox/fs/filestore/filestoretemplate.hpp>
#include <ox/fs/filesystem/filesystem.hpp>
using namespace std;
using namespace ox;
template<typename T>
struct __attribute__((packed)) NodeType: public ox::ptrarith::Item<T> {
public:
int i = 0;
size_t fullSize() const {
return this->size() + sizeof(*this);
}
};
map<string, int(*)(string)> tests = {
{
{
"PtrArith::setSize",
[](string) {
using BuffPtr_t = uint32_t;
std::vector<char> buff(5 * ox::units::MB);
auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size());
auto a1 = buffer->malloc(50);
auto a2 = buffer->malloc(50);
oxAssert(buffer->free(a1), "Free failed.");
oxAssert(buffer->free(a2), "Free failed.");
oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed.");
return 0;
}
},
},
};
int main(int argc, const char **args) {
int retval = -1;
if (argc > 1) {
auto testName = args[1];
string testArg = "";
if (args[2]) {
testArg = args[2];
}
if (tests.find(testName) != tests.end()) {
retval = tests[testName](testArg);
}
}
return retval;
}