Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/base/StarMemoryAssetSource.cpp
blob: 5dec1236d80f307b9073c7aa72809fbb0fc4a543 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "StarMemoryAssetSource.hpp"
#include "StarDataStreamDevices.hpp"
#include "StarDataStreamExtra.hpp"
#include "StarImage.hpp"

namespace Star {

MemoryAssetSource::MemoryAssetSource(String const& name, JsonObject metadata) : m_name(name), m_metadata(metadata) {}

String MemoryAssetSource::name() const {
  return m_name;
}

JsonObject MemoryAssetSource::metadata() const {
  return m_metadata;
}

StringList MemoryAssetSource::assetPaths() const {
  return m_files.keys();
}

IODevicePtr MemoryAssetSource::open(String const& path) {
  struct AssetReader : public IODevice {
    AssetReader(char* assetData, size_t assetSize, String name) {
      this->assetData = assetData;
      this->assetSize = assetSize;
      this->name = std::move(name);
      setMode(IOMode::Read);
    }

    size_t read(char* data, size_t len) override {
      len = min<StreamOffset>(len, StreamOffset(assetSize) - assetPos);
      memcpy(data, assetData + assetPos, len);
      assetPos += len;
      return len;
    }

    size_t write(char const*, size_t) override {
      throw IOException("Assets IODevices are read-only");
    }

    StreamOffset size() override { return assetSize; }
    StreamOffset pos() override { return assetPos; }

    String deviceName() const override { return name; }

    bool atEnd() override {
      return assetPos >= (StreamOffset)assetSize;
    }

    void seek(StreamOffset p, IOSeek mode) override {
      if (mode == IOSeek::Absolute)
        assetPos = p;
      else if (mode == IOSeek::Relative)
        assetPos = clamp<StreamOffset>(assetPos + p, 0, assetSize);
      else
        assetPos = clamp<StreamOffset>(assetPos - p, 0, assetSize);
    }

    IODevicePtr clone() override {
      auto cloned = make_shared<AssetReader>(assetData, assetSize, name);
      cloned->assetPos = assetPos;
      return cloned;
    }

    char* assetData;
    size_t assetSize;
    StreamOffset assetPos = 0;
    String name;
  };

  auto p = m_files.ptr(path);
  if (!p)
    throw AssetSourceException::format("Requested file '{}' does not exist in memory", path);
  else if (auto byteArray = p->ptr<ByteArray>())
    return make_shared<AssetReader>(byteArray->ptr(), byteArray->size(), path);
  else {
    auto image = p->get<ImagePtr>().get();
    return make_shared<AssetReader>((char*)image->data(), image->width() * image->height() * image->bytesPerPixel(), path);
  }
}

bool MemoryAssetSource::empty() const {
  return m_files.empty();
}

bool MemoryAssetSource::contains(String const& path) const {
  return m_files.contains(path);
}

bool MemoryAssetSource::erase(String const& path) {
  return m_files.erase(path) != 0;
}

void MemoryAssetSource::set(String const& path, ByteArray data) {
  m_files[path] = std::move(data);
}

void MemoryAssetSource::set(String const& path, Image const& image) {
  m_files[path] = make_shared<Image>(image);
}

void MemoryAssetSource::set(String const& path, Image&& image) {
  m_files[path] = make_shared<Image>(std::move(image));
}

ByteArray MemoryAssetSource::read(String const& path) {
  auto p = m_files.ptr(path);
  if (!p)
    throw AssetSourceException::format("Requested file '{}' does not exist in memory", path);
  else if (auto bytes = p->ptr<ByteArray>())
    return *bytes;
  else {
    Image const* image = p->get<ImagePtr>().get();
    return ByteArray((char const*)image->data(), image->width() * image->height() * image->bytesPerPixel());
  }
}

ImageConstPtr MemoryAssetSource::image(String const& path) {
  auto p = m_files.ptr(path);
  if (!p)
    throw AssetSourceException::format("Requested file '{}' does not exist in memory", path);
  else if (auto imagePtr = p->ptr<ImagePtr>())
    return *imagePtr;
  else
    return nullptr;
}

}