mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 17:54:00 +02:00
Adding abstracted storage for in-memory or file backed data
This commit is contained in:
parent
b4745657e0
commit
d1b91cb436
4 changed files with 258 additions and 0 deletions
86
libraries/shared/src/shared/Storage.cpp
Normal file
86
libraries/shared/src/shared/Storage.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/02/17
|
||||
// Copyright 2013-2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Storage.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
using namespace storage;
|
||||
|
||||
MemoryStoragePointer Storage::toMemoryStorage() const {
|
||||
return std::make_unique<MemoryStorage>(size(), data());
|
||||
}
|
||||
|
||||
FileStoragePointer Storage::toFileStorage(const QString& filename) const {
|
||||
return FileStorage::create(filename, size(), data());
|
||||
}
|
||||
|
||||
MemoryStorage::MemoryStorage(size_t size, const uint8_t* data) {
|
||||
_data.resize(size);
|
||||
memcpy(_data.data(), data, size);
|
||||
}
|
||||
|
||||
const uint8_t* MemoryStorage::data() const {
|
||||
return _data.data();
|
||||
}
|
||||
|
||||
size_t MemoryStorage::size() const {
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
FileStoragePointer FileStorage::create(const QString& filename, size_t size, const uint8_t* data) {
|
||||
QFile file(filename);
|
||||
if (!file.open(QFile::ReadWrite | QIODevice::Truncate)) {
|
||||
throw std::runtime_error("Unable to open file for writing");
|
||||
}
|
||||
if (!file.resize(size)) {
|
||||
throw std::runtime_error("Unable to resize file");
|
||||
}
|
||||
{
|
||||
auto mapped = file.map(0, size);
|
||||
if (!mapped) {
|
||||
throw std::runtime_error("Unable to map file");
|
||||
}
|
||||
memcpy(mapped, data, size);
|
||||
if (!file.unmap(mapped)) {
|
||||
throw std::runtime_error("Unable to unmap file");
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
return std::make_unique<FileStorage>(filename);
|
||||
}
|
||||
|
||||
FileStorage::FileStorage(const QString& filename) : _file(filename) {
|
||||
if (!_file.open(QFile::ReadOnly)) {
|
||||
throw std::runtime_error("Unable to open file");
|
||||
}
|
||||
_mapped = _file.map(0, _file.size());
|
||||
if (!_mapped) {
|
||||
throw std::runtime_error("Unable to map file");
|
||||
}
|
||||
}
|
||||
|
||||
FileStorage::~FileStorage() {
|
||||
if (_mapped) {
|
||||
if (!_file.unmap(_mapped)) {
|
||||
throw std::runtime_error("Unable to unmap file");
|
||||
}
|
||||
}
|
||||
if (_file.isOpen()) {
|
||||
_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const uint8_t* FileStorage::data() const {
|
||||
return _mapped;
|
||||
}
|
||||
|
||||
size_t FileStorage::size() const {
|
||||
return _file.size();
|
||||
}
|
65
libraries/shared/src/shared/Storage.h
Normal file
65
libraries/shared/src/shared/Storage.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/02/17
|
||||
// Copyright 2013-2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Storage_h
|
||||
#define hifi_Storage_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
|
||||
namespace storage {
|
||||
class Storage;
|
||||
using StoragePointer = std::unique_ptr<Storage>;
|
||||
class MemoryStorage;
|
||||
using MemoryStoragePointer = std::unique_ptr<MemoryStorage>;
|
||||
class FileStorage;
|
||||
using FileStoragePointer = std::unique_ptr<FileStorage>;
|
||||
|
||||
class Storage {
|
||||
public:
|
||||
virtual ~Storage() {}
|
||||
virtual const uint8_t* data() const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
FileStoragePointer toFileStorage(const QString& filename) const;
|
||||
MemoryStoragePointer toMemoryStorage() const;
|
||||
};
|
||||
|
||||
class MemoryStorage : public Storage {
|
||||
public:
|
||||
MemoryStorage(size_t size, const uint8_t* data);
|
||||
const uint8_t* data() const override;
|
||||
size_t size() const override;
|
||||
private:
|
||||
std::vector<uint8_t> _data;
|
||||
};
|
||||
|
||||
class FileStorage : public Storage {
|
||||
public:
|
||||
static FileStoragePointer create(const QString& filename, size_t size, const uint8_t* data);
|
||||
FileStorage(const QString& filename);
|
||||
~FileStorage();
|
||||
// Prevent copying
|
||||
FileStorage(const FileStorage& other) = delete;
|
||||
FileStorage& operator=(const FileStorage& other) = delete;
|
||||
|
||||
const uint8_t* data() const override;
|
||||
size_t size() const override;
|
||||
private:
|
||||
QFile _file;
|
||||
uint8_t* _mapped { nullptr };
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // hifi_Storage_h
|
75
tests/shared/src/StorageTests.cpp
Normal file
75
tests/shared/src/StorageTests.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/02/17
|
||||
// Copyright 2013-2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "StorageTests.h"
|
||||
|
||||
QTEST_MAIN(StorageTests)
|
||||
|
||||
using namespace storage;
|
||||
|
||||
StorageTests::StorageTests() {
|
||||
for (size_t i = 0; i < _testData.size(); ++i) {
|
||||
_testData[i] = (uint8_t)rand();
|
||||
}
|
||||
_testFile = QDir::tempPath() + "/" + QUuid::createUuid().toString();
|
||||
}
|
||||
|
||||
StorageTests::~StorageTests() {
|
||||
QFileInfo fileInfo(_testFile);
|
||||
if (fileInfo.exists()) {
|
||||
QFile(_testFile).remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StorageTests::testConversion() {
|
||||
{
|
||||
QFileInfo fileInfo(_testFile);
|
||||
QCOMPARE(fileInfo.exists(), false);
|
||||
}
|
||||
StoragePointer storagePointer = std::make_unique<MemoryStorage>(_testData.size(), _testData.data());
|
||||
QCOMPARE(storagePointer->size(), (quint64)_testData.size());
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
|
||||
// Convert to a file
|
||||
storagePointer = storagePointer->toFileStorage(_testFile);
|
||||
{
|
||||
QFileInfo fileInfo(_testFile);
|
||||
QCOMPARE(fileInfo.exists(), true);
|
||||
QCOMPARE(fileInfo.size(), (qint64)_testData.size());
|
||||
}
|
||||
QCOMPARE(storagePointer->size(), (quint64)_testData.size());
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
|
||||
|
||||
// Convert to memory
|
||||
storagePointer = storagePointer->toMemoryStorage();
|
||||
QCOMPARE(storagePointer->size(), (quint64)_testData.size());
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
|
||||
{
|
||||
// ensure the file is unaffected
|
||||
QFileInfo fileInfo(_testFile);
|
||||
QCOMPARE(fileInfo.exists(), true);
|
||||
QCOMPARE(fileInfo.size(), (qint64)_testData.size());
|
||||
}
|
||||
|
||||
// truncate the data as a new memory object
|
||||
auto newSize = _testData.size() / 2;
|
||||
storagePointer = std::make_unique<MemoryStorage>(newSize, storagePointer->data());
|
||||
QCOMPARE(storagePointer->size(), (quint64)newSize);
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0);
|
||||
|
||||
// Convert back to file
|
||||
storagePointer = storagePointer->toFileStorage(_testFile);
|
||||
QCOMPARE(storagePointer->size(), (quint64)newSize);
|
||||
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0);
|
||||
{
|
||||
// ensure the file is truncated
|
||||
QFileInfo fileInfo(_testFile);
|
||||
QCOMPARE(fileInfo.exists(), true);
|
||||
QCOMPARE(fileInfo.size(), (qint64)newSize);
|
||||
}
|
||||
}
|
32
tests/shared/src/StorageTests.h
Normal file
32
tests/shared/src/StorageTests.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/02/17
|
||||
// Copyright 2013-2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_StorageTests_h
|
||||
#define hifi_StorageTests_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <shared/Storage.h>
|
||||
#include <array>
|
||||
|
||||
class StorageTests : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StorageTests();
|
||||
~StorageTests();
|
||||
|
||||
private slots:
|
||||
void testConversion();
|
||||
|
||||
private:
|
||||
std::array<uint8_t, 1025> _testData;
|
||||
QString _testFile;
|
||||
};
|
||||
|
||||
#endif // hifi_StorageTests_h
|
Loading…
Reference in a new issue