diff --git a/res/layouts/code_editor.xml.lua b/res/layouts/code_editor.xml.lua
index 4e6c68d4..733fa903 100644
--- a/res/layouts/code_editor.xml.lua
+++ b/res/layouts/code_editor.xml.lua
@@ -110,7 +110,7 @@ function unlock_access()
end
local function reload_model(filename, name)
- assets.parse_model("xml", document.editor.text, name)
+ assets.parse_model(file.ext(filename), document.editor.text, name)
end
function run_current_file()
diff --git a/res/layouts/console.xml b/res/layouts/console.xml
index 756459de..3772d240 100644
--- a/res/layouts/console.xml
+++ b/res/layouts/console.xml
@@ -33,5 +33,4 @@
onup="on_history_up()"
ondown="on_history_down()">
-
diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp
index 88dd66bd..d865cc1a 100644
--- a/src/assets/assetload_funcs.cpp
+++ b/src/assets/assetload_funcs.cpp
@@ -381,7 +381,8 @@ assetload::postfunc assetload::model(
auto text = io::read_string(path);
try {
- auto model = vcm::parse(path.string(), text).release();
+ auto model = vcm::parse(path.string(), text, path.extension() == ".xml")
+ .release();
return [=](Assets* assets) {
request_textures(loader, *model);
assets->store(std::unique_ptr(model), name);
diff --git a/src/coders/vcm.cpp b/src/coders/vcm.cpp
index 9b564787..337d721f 100644
--- a/src/coders/vcm.cpp
+++ b/src/coders/vcm.cpp
@@ -163,11 +163,11 @@ static std::unique_ptr load_model(const xmlelement& root) {
}
std::unique_ptr vcm::parse(
- std::string_view file, std::string_view src
+ std::string_view file, std::string_view src, bool usexml
) {
try {
- auto doc = io::path(std::string(file)).extension() == ".xml"
- ? xml::parse(file, src) : xml::parse_vcm(file, src, "model");
+ auto doc =
+ usexml ? xml::parse(file, src) : xml::parse_vcm(file, src, "model");
const auto& root = *doc->getRoot();
if (root.getTag() != "model") {
throw std::runtime_error(
diff --git a/src/coders/vcm.hpp b/src/coders/vcm.hpp
index 6f239604..e0629de1 100644
--- a/src/coders/vcm.hpp
+++ b/src/coders/vcm.hpp
@@ -8,5 +8,7 @@ namespace model {
}
namespace vcm {
- std::unique_ptr parse(std::string_view file, std::string_view src);
+ std::unique_ptr parse(
+ std::string_view file, std::string_view src, bool usexml
+ );
}
diff --git a/src/logic/scripting/lua/libs/libassets.cpp b/src/logic/scripting/lua/libs/libassets.cpp
index 3f9ab456..9924069a 100644
--- a/src/logic/scripting/lua/libs/libassets.cpp
+++ b/src/logic/scripting/lua/libs/libassets.cpp
@@ -55,7 +55,9 @@ static int l_parse_model(lua::State* L) {
auto name = lua::require_string(L, 3);
if (format == "xml" || format == "vcm") {
- engine->getAssets()->store(vcm::parse(name, string), name);
+ engine->getAssets()->store(
+ vcm::parse(name, string, format == "xml"), name
+ );
} else {
throw std::runtime_error("unknown format " + util::quote(std::string(format)));
}
diff --git a/src/util/stack_vector.hpp b/src/util/stack_vector.hpp
index a167d1d7..32902d86 100644
--- a/src/util/stack_vector.hpp
+++ b/src/util/stack_vector.hpp
@@ -5,20 +5,30 @@
namespace util {
template
class stack_vector {
+ struct buffer {
+ alignas(alignof(T)) char* data[sizeof(T) * capacity];
+
+ T* ptr() {
+ return reinterpret_cast(data);
+ }
+ const T* ptr() const {
+ return reinterpret_cast(data);
+ }
+ };
public:
stack_vector() : size_(0) {}
stack_vector(const stack_vector& other)
: size_(other.size_) {
for (int i = 0; i < size_; ++i) {
- new (&data_[i]) T(other.data_[i]);
+ new (&data_.ptr()[i]) T(other.data_.ptr()[i]);
}
}
stack_vector(stack_vector&& other) noexcept
: size_(other.size_) {
for (int i = 0; i < size_; ++i) {
- new (&data_[i]) T(std::move(other.data_[i]));
+ new (&data_.ptr()[i]) T(std::move(other.data_.ptr()[i]));
}
other.size_ = 0;
}
@@ -29,17 +39,25 @@ namespace util {
"initializer list exceeds stack vector capacity"
);
for (const auto& value : init) {
- new (&data_[size_++]) T(value);
+ new (&data_.ptr()[size_++]) T(value);
}
}
- ~stack_vector() {
- clear();
- }
+ ~stack_vector() = default;
void push_back(const T& value) {
if (size_ < capacity) {
- data_[size_++] = value;
+ auto data = reinterpret_cast(data_.ptr() + (size_++));
+ new (data) T(value);
+ } else {
+ throw std::overflow_error("stack vector capacity exceeded");
+ }
+ }
+
+ void push_back(T&& value) {
+ if (size_ < capacity) {
+ auto data = reinterpret_cast(data_.ptr() + (size_++));
+ new (data) T(std::move(value));
} else {
throw std::overflow_error("stack vector capacity exceeded");
}
@@ -47,7 +65,7 @@ namespace util {
void pop_back() {
if (size_ > 0) {
- data_[size_ - 1].~T();
+ data_.ptr()[size_ - 1].~T();
--size_;
} else {
throw std::underflow_error("stack vector is empty");
@@ -56,31 +74,31 @@ namespace util {
void clear() {
for (int i = 0; i < size_; ++i) {
- data_[i].~T();
+ data_.ptr()[i].~T();
}
size_ = 0;
}
T& operator[](int index) {
- return data_[index];
+ return data_.ptr()[index];
}
const T& operator[](int index) const {
- return data_[index];
+ return data_.ptr()[index];
}
T& at(int index) {
if (index < 0 || index >= size_) {
throw std::out_of_range("index out of range");
}
- return data_[index];
+ return data_.ptr()[index];
}
const T& at(int index) const {
if (index < 0 || index >= size_) {
throw std::out_of_range("index out of range");
}
- return data_[index];
+ return data_.ptr()[index];
}
int size() const {
@@ -96,22 +114,22 @@ namespace util {
}
auto begin() {
- return data_;
+ return data_.ptr();
}
auto end() {
- return data_ + size_;
+ return data_.ptr() + size_;
}
auto begin() const {
- return data_;
+ return data_.ptr();
}
auto end() const {
- return data_ + size_;
+ return data_.ptr() + size_;
}
private:
- T data_[capacity];
+ buffer data_;
int size_;
};
}
diff --git a/test/util/stack_vector.cpp b/test/util/stack_vector.cpp
new file mode 100644
index 00000000..ec3edc89
--- /dev/null
+++ b/test/util/stack_vector.cpp
@@ -0,0 +1,20 @@
+#include
+#include
+
+#include "util/stack_vector.hpp"
+
+using namespace util;
+
+TEST(util, stack_vector) {
+ stack_vector vec;
+ vec.push_back("hello");
+ vec.push_back("world");
+ vec.push_back("?");
+ ASSERT_EQ(3, vec.size());
+ vec.pop_back();
+ ASSERT_EQ(2, vec.size());
+ vec.clear();
+ ASSERT_EQ(0, vec.size());
+ ASSERT_TRUE(vec.empty());
+ vec.push_back("test");
+}