mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 14:00:43 +02:00
Adding KeyValues read/write, work in progress
This commit is contained in:
parent
8782fe1d93
commit
c267b5cd09
4 changed files with 111 additions and 40 deletions
|
@ -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() {
|
KTX::KTX() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <shared/Storage.h>
|
#include <shared/Storage.h>
|
||||||
|
@ -385,9 +386,27 @@ namespace ktx {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Key Values
|
// Key Values
|
||||||
using KeyValue = std::pair<std::string, std::string>;
|
struct KeyValue {
|
||||||
using KeyValues = std::list<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 {
|
struct Image {
|
||||||
using FaceBytes = std::vector<const Byte*>;
|
using FaceBytes = std::vector<const Byte*>;
|
||||||
|
@ -445,12 +464,14 @@ namespace ktx {
|
||||||
// This is exactly what is done in the create function
|
// 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 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 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);
|
static Images writeImages(Byte* destBytes, size_t destByteSize, const Images& images);
|
||||||
|
|
||||||
// Parse a block of memory and create a KTX object from it
|
// Parse a block of memory and create a KTX object from it
|
||||||
static std::unique_ptr<KTX> create(const StoragePointer& src);
|
static std::unique_ptr<KTX> create(const StoragePointer& src);
|
||||||
|
|
||||||
static bool checkHeaderFromStorage(size_t srcSize, const Byte* srcBytes);
|
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);
|
static Images parseImages(const Header& header, size_t srcSize, const Byte* srcBytes);
|
||||||
|
|
||||||
// Access raw pointers to the main sections of the KTX
|
// Access raw pointers to the main sections of the KTX
|
||||||
|
|
|
@ -56,38 +56,52 @@ namespace ktx {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyValues getKeyValues(size_t length, const Byte* src) {
|
|
||||||
KeyValues keyValues;
|
|
||||||
size_t offset = 0;
|
|
||||||
|
|
||||||
while (offset < length) {
|
KeyValue KeyValue::parseKeyAndValue(uint32_t keyAndValueByteSize, const Byte* bytes) {
|
||||||
// determine byte size
|
// find the first null character \0
|
||||||
uint32_t keyValueByteSize;
|
uint32_t keyLength = 0;
|
||||||
memcpy(&keyValueByteSize, src, sizeof(uint32_t));
|
while (reinterpret_cast<const char*>(bytes[++keyLength]) != '\0') {
|
||||||
if (keyValueByteSize > length - offset) {
|
if (keyLength == keyAndValueByteSize) {
|
||||||
throw ReaderException("invalid key-value size");
|
// 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;
|
return keyValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +190,7 @@ namespace ktx {
|
||||||
result->resetStorage(src);
|
result->resetStorage(src);
|
||||||
|
|
||||||
// read metadata
|
// read metadata
|
||||||
// result->_keyValues = getKeyValues(result->getHeader()->bytesOfKeyValueData, result->getKeyValueData());
|
result->_keyValues = parseKeyValues(result->getHeader()->bytesOfKeyValueData, result->getKeyValueData());
|
||||||
|
|
||||||
// populate image table
|
// populate image table
|
||||||
result->_images = parseImages(*result->getHeader(), result->getTexelsDataSize(), result->getTexelsData());
|
result->_images = parseImages(*result->getHeader(), result->getTexelsDataSize(), result->getTexelsData());
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace ktx {
|
||||||
std::unique_ptr<KTX> KTX::create(const Header& header, const Images& images, const KeyValues& keyValues) {
|
std::unique_ptr<KTX> KTX::create(const Header& header, const Images& images, const KeyValues& keyValues) {
|
||||||
StoragePointer storagePointer;
|
StoragePointer storagePointer;
|
||||||
{
|
{
|
||||||
auto storageSize = ktx::KTX::evalStorageSize(header, images);
|
auto storageSize = ktx::KTX::evalStorageSize(header, images, keyValues);
|
||||||
auto memoryStorage = new storage::MemoryStorage(storageSize);
|
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);
|
storagePointer.reset(memoryStorage);
|
||||||
}
|
}
|
||||||
return create(storagePointer);
|
return create(storagePointer);
|
||||||
|
@ -40,8 +40,9 @@ namespace ktx {
|
||||||
size_t KTX::evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues) {
|
size_t KTX::evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues) {
|
||||||
size_t storageSize = sizeof(Header);
|
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();
|
auto numMips = header.getNumberOfLevels();
|
||||||
|
@ -68,11 +69,12 @@ namespace ktx {
|
||||||
currentDestPtr += sizeof(Header);
|
currentDestPtr += sizeof(Header);
|
||||||
|
|
||||||
// KeyValues
|
// KeyValues
|
||||||
// Skip for now
|
if (!keyValues.empty()) {
|
||||||
if (header.bytesOfKeyValueData && !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;
|
currentDestPtr += destHeader->bytesOfKeyValueData;
|
||||||
|
|
||||||
// Images
|
// Images
|
||||||
|
@ -82,6 +84,11 @@ namespace ktx {
|
||||||
return destByteSize;
|
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 KTX::writeImages(Byte* destBytes, size_t destByteSize, const Images& srcImages) {
|
||||||
Images destImages;
|
Images destImages;
|
||||||
auto imagesDataPtr = destBytes;
|
auto imagesDataPtr = destBytes;
|
||||||
|
|
Loading…
Reference in a new issue