Add const-converter and Container support to Span
diff --git a/include/rive/assets/file_asset_contents.hpp b/include/rive/assets/file_asset_contents.hpp
index 10546d2..917bbb0 100644
--- a/include/rive/assets/file_asset_contents.hpp
+++ b/include/rive/assets/file_asset_contents.hpp
@@ -9,11 +9,11 @@
std::vector<uint8_t> m_Bytes;
public:
- const Span<const uint8_t> bytes() const;
+ Span<const uint8_t> bytes() const;
StatusCode import(ImportStack& importStack) override;
void decodeBytes(Span<const uint8_t> value) override;
void copyBytes(const FileAssetContentsBase& object) override;
};
} // namespace rive
-#endif
\ No newline at end of file
+#endif
diff --git a/include/rive/span.hpp b/include/rive/span.hpp
index 9aa8319..abfae67 100644
--- a/include/rive/span.hpp
+++ b/include/rive/span.hpp
@@ -6,7 +6,6 @@
#define _RIVE_SPAN_HPP_
#include "rive/rive_types.hpp"
-#include <vector>
/*
* Span : cheap impl of std::span (which is C++20)
@@ -26,9 +25,11 @@
assert(ptr <= ptr + size);
}
- // We don't modify vec, but we don't want to say const, since that would
- // change .data() to return const T*, and we don't want to change it.
- Span(std::vector<T>& vec) : Span(vec.data(), vec.size()) {}
+ // Handle Span<foo> --> Span<const foo>
+ template <typename U,
+ typename = typename std::enable_if<std::is_same<const U, T>::value>::type>
+ constexpr Span(const Span<U>& that) : Span(that.data(), that.size()) {}
+ constexpr Span(const Span&) = default;
constexpr T& operator[](size_t index) const {
assert(index < m_Size);
@@ -61,6 +62,12 @@
}
};
+template <typename Container>
+inline auto toSpan(Container& c)
+ -> Span<typename std::remove_reference<decltype(*(c.data()))>::type> {
+ return {c.data(), c.size()};
+}
+
} // namespace rive
#endif
diff --git a/src/assets/file_asset_contents.cpp b/src/assets/file_asset_contents.cpp
index e12c804..d4c0340 100644
--- a/src/assets/file_asset_contents.cpp
+++ b/src/assets/file_asset_contents.cpp
@@ -24,6 +24,6 @@
assert(false);
}
-const Span<const uint8_t> FileAssetContents::bytes() const {
- return Span<const uint8_t>(&m_Bytes[0], m_Bytes.size());
-}
\ No newline at end of file
+Span<const uint8_t> FileAssetContents::bytes() const {
+ return toSpan(m_Bytes);
+}
diff --git a/src/core/binary_reader.cpp b/src/core/binary_reader.cpp
index b115e65..1a735ee 100644
--- a/src/core/binary_reader.cpp
+++ b/src/core/binary_reader.cpp
@@ -62,7 +62,7 @@
const uint8_t* start = m_Position;
m_Position += length;
- return Span<const uint8_t>(start, length);
+ return {start, length};
}
double BinaryReader::readFloat64() {
diff --git a/src/importers/file_asset_importer.cpp b/src/importers/file_asset_importer.cpp
index d8488fe..9c69728 100644
--- a/src/importers/file_asset_importer.cpp
+++ b/src/importers/file_asset_importer.cpp
@@ -12,7 +12,7 @@
m_FileAsset(fileAsset), m_FileAssetResolver(assetResolver) {}
void FileAssetImporter::loadContents(const FileAssetContents& contents) {
- Span<const uint8_t> data = contents.bytes();
+ auto data = contents.bytes();
if (m_FileAsset->decode(data.begin(), data.size())) {
m_LoadedContents = true;
}
@@ -27,4 +27,4 @@
// Note that it's ok for an asset to not resolve (or to resolve async).
return StatusCode::Ok;
-}
\ No newline at end of file
+}
diff --git a/src/shapes/mesh.cpp b/src/shapes/mesh.cpp
index a51114c..ded4edc 100644
--- a/src/shapes/mesh.cpp
+++ b/src/shapes/mesh.cpp
@@ -90,16 +90,14 @@
uv[index++] = vertex->u();
uv[index++] = vertex->v();
}
- m_UVRenderBuffer = makeBufferF32(Span<const float>(uv.data(), uv.size()));
- m_IndexRenderBuffer = makeBufferU16(
- Span((const uint16_t*)m_IndexBuffer->data(), m_IndexBuffer->size()));
+ m_UVRenderBuffer = makeBufferF32(toSpan(uv));
+ m_IndexRenderBuffer = makeBufferU16(toSpan(*m_IndexBuffer));
}
void Mesh::update(ComponentDirt value) {
if (hasDirt(value, ComponentDirt::Vertices)) {
if (skin() != nullptr) {
- skin()->deform(
- Span((Vertex**)m_Vertices.data(), m_Vertices.size()));
+ skin()->deform({(Vertex**)m_Vertices.data(), m_Vertices.size()});
}
m_VertexRenderBuffer = nullptr;
}
@@ -112,15 +110,14 @@
float opacity) {
if (m_VertexRenderBuffer == nullptr) {
- std::vector<float> vertices = std::vector<float>(m_Vertices.size() * 2);
+ std::vector<float> vertices(m_Vertices.size() * 2);
std::size_t index = 0;
for (auto vertex : m_Vertices) {
auto translation = vertex->renderTranslation();
vertices[index++] = translation[0];
vertices[index++] = translation[1];
}
- m_VertexRenderBuffer =
- makeBufferF32(Span((const float*)vertices.data(), vertices.size()));
+ m_VertexRenderBuffer = makeBufferF32(toSpan(vertices));
}
if (skin() == nullptr) {
@@ -133,4 +130,4 @@
m_IndexRenderBuffer,
blendMode,
opacity);
-}
\ No newline at end of file
+}
diff --git a/test/span_test.cpp b/test/span_test.cpp
index c59c532..661415b 100644
--- a/test/span_test.cpp
+++ b/test/span_test.cpp
@@ -8,15 +8,6 @@
using namespace rive;
-namespace {
- class baseclass {};
- class subclass : public baseclass {};
-} // namespace
-
-static void function(Span<int> span) {}
-static void function(Span<baseclass*> span) {}
-static void function(Span<subclass*> span) {}
-
TEST_CASE("basics", "[span]") {
Span<int> span;
REQUIRE(span.empty());
@@ -52,12 +43,21 @@
REQUIRE(sub.size() == 0);
}
-TEST_CASE("vector-integration", "[span]") {
- std::vector<int> vi;
- std::vector<baseclass*> vb;
- std::vector<subclass*> vs;
+static void funca(Span<int> span) {}
+static void funcb(Span<const int> span) {}
- function(vi);
- function(vb);
- function(vs);
+TEST_CASE("const-and-containers", "[span]") {
+ const int carray[] = {1, 2, 3, 4};
+ funcb({carray, 4});
+
+ int array[] = {1, 2, 3, 4};
+ funca({array, 4});
+ funcb({array, 4});
+
+ std::vector<const int> cv;
+ funcb(ToSpan(cv));
+
+ std::vector<int> v;
+ funca(ToSpan(v));
+ funcb(ToSpan(v));
}