Adding KeyValues read/write, work in progress

This commit is contained in:
samcake 2017-03-06 18:26:31 -08:00
parent 8782fe1d93
commit c267b5cd09
4 changed files with 111 additions and 40 deletions

View file

@ -71,6 +71,35 @@ size_t Header::evalImageSize(uint32_t level) const {
}
KeyValue::KeyValue(const std::string& key, uint32_t valueByteSize, const Byte* value) :
_byteSize((uint32_t) key.size() + valueByteSize),
_key(key),
_value(valueByteSize)
{
if (_value.size() && value) {
memcpy(_value.data(), value, valueByteSize);
}
}
KeyValue::KeyValue(const std::string& key, const std::string& value) :
KeyValue(key, (uint32_t) value.size(), (const Byte*) value.data())
{
}
uint32_t KeyValue::serializedByteSize() const {
return (uint32_t) (sizeof(uint32_t) + _byteSize + Header::evalPadding(_byteSize));
}
uint32_t KeyValue::serializedKeyValuesByteSize(const KeyValues& keyValues) {
size_t keyValuesSize = 0;
for (auto& keyval : keyValues) {
keyValuesSize += keyval.serializedByteSize();
}
return (keyValuesSize + Header::evalPadding(keyValuesSize));
}
KTX::KTX() {
}

View file

@ -17,6 +17,7 @@
#include <vector>
#include <cstdint>
#include <cstring>
#include <string>
#include <memory>
#include <shared/Storage.h>
@ -385,9 +386,27 @@ namespace ktx {
};
// Key Values
using KeyValue = std::pair<std::string, std::string>;
using KeyValues = std::list<KeyValue>;
struct KeyValue {
uint32_t _byteSize { 0 };
std::string _key;
std::vector<Byte> _value;
KeyValue(const std::string& key, uint32_t valueByteSize, const Byte* value);
KeyValue(const std::string& key, const std::string& value);
uint32_t serializedByteSize() const;
static KeyValue parseKeyAndValue(uint32_t keyAndValueByteSize, const Byte* bytes);
static KeyValue parseSerializedKeyAndValue(uint32_t byteSizeAhead, const Byte* bytes);
using KeyValues = std::list<KeyValue>;
static uint32_t serializedKeyValuesByteSize(const KeyValues& keyValues);
};
using KeyValues = KeyValue::KeyValues;
struct Image {
using FaceBytes = std::vector<const Byte*>;
@ -445,12 +464,14 @@ namespace ktx {
// This is exactly what is done in the create function
static size_t evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues = KeyValues());
static size_t write(Byte* destBytes, size_t destByteSize, const Header& header, const Images& images, const KeyValues& keyValues = KeyValues());
static size_t writeKeyValues(Byte* destBytes, size_t destByteSize, const KeyValues& keyValues);
static Images writeImages(Byte* destBytes, size_t destByteSize, const Images& images);
// Parse a block of memory and create a KTX object from it
static std::unique_ptr<KTX> create(const StoragePointer& src);
static bool checkHeaderFromStorage(size_t srcSize, const Byte* srcBytes);
static KeyValues parseKeyValues(size_t srcSize, const Byte* srcBytes);
static Images parseImages(const Header& header, size_t srcSize, const Byte* srcBytes);
// Access raw pointers to the main sections of the KTX

View file

@ -56,38 +56,52 @@ namespace ktx {
return true;
}
KeyValues getKeyValues(size_t length, const Byte* src) {
KeyValues keyValues;
size_t offset = 0;
while (offset < length) {
// determine byte size
uint32_t keyValueByteSize;
memcpy(&keyValueByteSize, src, sizeof(uint32_t));
if (keyValueByteSize > length - offset) {
throw ReaderException("invalid key-value size");
KeyValue KeyValue::parseKeyAndValue(uint32_t keyAndValueByteSize, const Byte* bytes) {
// find the first null character \0
uint32_t keyLength = 0;
while (reinterpret_cast<const char*>(bytes[++keyLength]) != '\0') {
if (keyLength == keyAndValueByteSize) {
// key must be null-terminated, and there must be space for the value
throw ReaderException("invalid key-value " + std::string(reinterpret_cast<const char*>(bytes), keyLength));
}
// find the first null character \0
uint32_t keyLength = 0;
while (reinterpret_cast<const char*>(src[++keyLength]) != '\0') {
if (keyLength == keyValueByteSize) {
// key must be null-terminated, and there must be space for the value
throw ReaderException("invalid key-value " + std::string(reinterpret_cast<const char*>(src), keyLength));
}
}
// populate the key-value
keyValues.emplace_back(
std::move(std::string(reinterpret_cast<const char*>(src), keyLength)),
std::move(std::string(reinterpret_cast<const char*>(src + keyLength), keyValueByteSize - keyLength)));
// advance offset/src
uint32_t keyValuePadding = 3 - ((keyValueByteSize + 3) % PACKING_SIZE);
offset += keyValueByteSize + keyValuePadding;
src += keyValueByteSize + keyValuePadding;
}
return KeyValue(std::string(reinterpret_cast<const char*>(bytes), keyLength), keyAndValueByteSize - keyLength, bytes + keyLength);
}
static KeyValue parseSerializedKeyAndValue(uint32_t byteSizeAhead, const Byte* bytes) {
uint32_t keyValueByteSize;
memcpy(&keyValueByteSize, bytes, sizeof(uint32_t));
if (keyValueByteSize > byteSizeAhead) {
throw ReaderException("invalid key-value size");
}
auto keyValueBytes = bytes + sizeof(uint32_t);
// parse the key-value
return KeyValue::parseKeyAndValue(keyValueByteSize, keyValueBytes);
}
static KeyValues parseKeyValues(size_t srcSize, const Byte* srcBytes);
KeyValues KTX::parseKeyValues(size_t srcSize, const Byte* src) {
KeyValues keyValues;
try {
uint32_t length = (uint32_t) srcSize;
uint32_t offset = 0;
while (offset < length) {
auto keyValue = parseSerializedKeyAndValue(length - offset, src);
keyValues.emplace_back(keyValue);
// advance offset/src
offset += keyValue.serializedByteSize();
src += keyValue.serializedByteSize();
}
}
catch (const ReaderException& e) {
qWarning() << e.what();
}
return keyValues;
}
@ -176,7 +190,7 @@ namespace ktx {
result->resetStorage(src);
// read metadata
// result->_keyValues = getKeyValues(result->getHeader()->bytesOfKeyValueData, result->getKeyValueData());
result->_keyValues = parseKeyValues(result->getHeader()->bytesOfKeyValueData, result->getKeyValueData());
// populate image table
result->_images = parseImages(*result->getHeader(), result->getTexelsDataSize(), result->getTexelsData());

View file

@ -29,9 +29,9 @@ namespace ktx {
std::unique_ptr<KTX> KTX::create(const Header& header, const Images& images, const KeyValues& keyValues) {
StoragePointer storagePointer;
{
auto storageSize = ktx::KTX::evalStorageSize(header, images);
auto storageSize = ktx::KTX::evalStorageSize(header, images, keyValues);
auto memoryStorage = new storage::MemoryStorage(storageSize);
ktx::KTX::write(memoryStorage->data(), memoryStorage->size(), header, images);
ktx::KTX::write(memoryStorage->data(), memoryStorage->size(), header, images, keyValues);
storagePointer.reset(memoryStorage);
}
return create(storagePointer);
@ -40,8 +40,9 @@ namespace ktx {
size_t KTX::evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues) {
size_t storageSize = sizeof(Header);
if (header.bytesOfKeyValueData && !keyValues.empty()) {
if (!keyValues.empty()) {
size_t keyValuesSize = KeyValue::serializedKeyValuesByteSize(keyValues);
storageSize += keyValuesSize;
}
auto numMips = header.getNumberOfLevels();
@ -68,11 +69,12 @@ namespace ktx {
currentDestPtr += sizeof(Header);
// KeyValues
// Skip for now
if (header.bytesOfKeyValueData && !keyValues.empty()) {
if (!keyValues.empty()) {
destHeader->bytesOfKeyValueData = writeKeyValues(currentDestPtr, destByteSize - sizeof(Header), keyValues);
} else {
// Make sure the header contains the right bytesOfKeyValueData size
destHeader->bytesOfKeyValueData = 0;
}
destHeader->bytesOfKeyValueData = 0;
currentDestPtr += destHeader->bytesOfKeyValueData;
// Images
@ -82,6 +84,11 @@ namespace ktx {
return destByteSize;
}
static size_t writeKeyValues(Byte* destBytes, size_t destByteSize, const KeyValues& keyValues) {
}
Images KTX::writeImages(Byte* destBytes, size_t destByteSize, const Images& srcImages) {
Images destImages;
auto imagesDataPtr = destBytes;