Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
8a721494b1 | |||
c993f8a38e | |||
e55390338a | |||
678624a75d | |||
65fee858dd |
48 changed files with 378 additions and 1269 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
tags
|
||||
compile_commands.json
|
||||
subprojects/wren/
|
||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -0,0 +1,3 @@
|
|||
[submodule "subprojects/wren/wren"]
|
||||
path = subprojects/wren/wren
|
||||
url = https://github.com/wren-lang/wren.git
|
27
README.md
27
README.md
|
@ -117,19 +117,6 @@ executable('my_project',
|
|||
)
|
||||
```
|
||||
|
||||
And the matching wrenpp.wrap file for your project (remember to update the
|
||||
revision SHA and the dependency name):
|
||||
|
||||
```
|
||||
[wrap-git]
|
||||
url = https://alarmpi.no-ip.org/gitan/King_DuckZ/wrenpp.git
|
||||
revision = ebca413c0a3e885ac1901bd555e127476c40b057
|
||||
|
||||
[provide]
|
||||
wrenpp = wrenpp_dep
|
||||
dependency_names = wrenpp-0.2.0
|
||||
```
|
||||
|
||||
This will make Wrenpp build as part of your project with Wren's optional random
|
||||
module enabled.
|
||||
|
||||
|
@ -143,6 +130,16 @@ wrenpp_dep = dependency('wrenpp', version: '>=0.1.0',
|
|||
)
|
||||
```
|
||||
|
||||
Note that when you use Wrenpp as a subproject, Wrenpp's subproject Wren will
|
||||
become a sub-subproject of your project. This is how Meson works and it simply
|
||||
means that in your top level source directory you will have to run this command
|
||||
before you will be able to compile (Meson should detect and print this as
|
||||
well):
|
||||
|
||||
```
|
||||
meson wrap promote subprojects/wrenpp/subprojects/wren
|
||||
```
|
||||
|
||||
### C++ ###
|
||||
|
||||
For working examples refer to the source files in the `examples/` directory.
|
||||
|
@ -164,8 +161,8 @@ at least. A description of all the relevant header files follows:
|
|||
* `def_configuration.hpp` The `DefConfiguration` struct extends the bare
|
||||
`Configuration` struct by providing an implementation for `write_fn`,
|
||||
`error_fn` and `reallocate_fn`. They are implemented in terms of `std::cout`,
|
||||
`std::cerr` and `std::realloc`/`std::free` respectively. You can safely ignore
|
||||
this header if this is not suitable for your project.
|
||||
`std::cerr` and `new[]`/`delete[]` respectively. You can safely ignore this
|
||||
header if this is not suitable for your project.
|
||||
|
||||
Other header files are intended for Wrenpp's use and you shouldn't need to use
|
||||
them. You are free to use them in your project if you think the code inside is
|
||||
|
|
|
@ -128,7 +128,7 @@ int main() {
|
|||
|
||||
vm.interpret("main", g_test_script);
|
||||
|
||||
Calendar* const cale = std::get<0>(wren::variables<Calendar>(vm, MN<"main", "cale">)).data();
|
||||
Calendar* const cale = std::get<0>(wren::variables<Calendar>(vm, MN<"main", "cale">));
|
||||
cale->print_appointments();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,219 +0,0 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wrenpp/vm_fun.hpp"
|
||||
#include "wrenpp/def_configuration.hpp"
|
||||
#include "wrenpp/callback_manager.hpp"
|
||||
#include "wrenpp/class_manager.hpp"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
constexpr char g_module_a[] =
|
||||
"foreign class ClassA {" R"script(
|
||||
construct new(msg) {
|
||||
System.print("Wren ClassA constructed")
|
||||
}
|
||||
|
||||
foreign say_hi()
|
||||
}
|
||||
)script";
|
||||
|
||||
constexpr char g_module_b[] = ""
|
||||
R"script(
|
||||
import "module_a" for ClassA
|
||||
|
||||
foreign class ClassB {
|
||||
construct new(nickname) {
|
||||
System.print("Wren ClassB constructed")
|
||||
}
|
||||
|
||||
do_action(obj_a, times) {
|
||||
System.print("Wren ClassB is doing its action %(times) times...")
|
||||
for (z in 1..times) {
|
||||
obj_a.say_hi()
|
||||
}
|
||||
greeting_message("John", "Doe", "\\(O.O)/")
|
||||
}
|
||||
|
||||
foreign greeting_message(first_name, family_name, emoji)
|
||||
foreign set_obj_c (obj)
|
||||
foreign get_obj_c()
|
||||
}
|
||||
)script";
|
||||
|
||||
constexpr char g_module_c[] =
|
||||
"foreign class ClassC {" R"script(
|
||||
construct new (msg) {}
|
||||
foreign print_message()
|
||||
}
|
||||
)script";
|
||||
|
||||
//This is several examples in one:
|
||||
//1. instantiate ClassA in Wren and pass it to do_action() which is a
|
||||
// non-foreign method in wren
|
||||
//2. instantiate ClassA in C++, have C++ invoke the non-foreign method
|
||||
// do_action() on the object obj_b from the previous execution and pass the
|
||||
// C++ instance of ClassA to it
|
||||
//3. instantiate ClassB in C++, have C++ invoke the non-foreign method
|
||||
// do_action() on it and pass the same ClassA instance from the previous
|
||||
// step to it
|
||||
//4. show how to return a pre-existing instance of ClassC from ClassB both in
|
||||
// C++ and Wren
|
||||
constexpr char g_script[] = ""
|
||||
R"script(
|
||||
import "module_a" for ClassA
|
||||
import "module_b" for ClassB
|
||||
import "module_c" for ClassC
|
||||
|
||||
var obj_b = ClassB.new("TheWren")
|
||||
obj_b.do_action(ClassA.new("instanciated from script"), 2)
|
||||
obj_b.greeting_message("Jane", "Doe", "ʕ·͡ᴥ·ʔ")
|
||||
|
||||
var obj_c = ClassC.new("Message of ClassC object instantiated in Wren")
|
||||
obj_b.set_obj_c(obj_c)
|
||||
obj_b.get_obj_c().print_message()
|
||||
)script";
|
||||
|
||||
class MyWrenConfig : public wren::DefConfiguration {
|
||||
public:
|
||||
char* load_module_fn (wren::VM* vm, std::string_view module_name) {
|
||||
if (module_name == "module_a")
|
||||
return copied(g_module_a, sizeof(g_module_a));
|
||||
else if (module_name == "module_b")
|
||||
return copied(g_module_b, sizeof(g_module_b));
|
||||
else if (module_name == "module_c")
|
||||
return copied(g_module_c, sizeof(g_module_c));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void load_module_complete_fn (wren::VM* vm, std::string_view module_name, char* buff) {
|
||||
static_cast<void>(vm);
|
||||
static_cast<void>(module_name);
|
||||
delete[] buff;
|
||||
}
|
||||
|
||||
private:
|
||||
char* copied (const char* source, std::size_t len) {
|
||||
char* const buff = new char[len];
|
||||
std::copy(source, source + len / sizeof(source[0]), buff);
|
||||
return buff;
|
||||
}
|
||||
};
|
||||
|
||||
struct ClassA {
|
||||
explicit ClassA (std::string msg) : m_message(msg) {
|
||||
std::cout << "C++ ClassA constructed\n";
|
||||
}
|
||||
ClassA (const ClassA&) = delete;
|
||||
ClassA (ClassA&&) = delete;
|
||||
|
||||
void say_hi() {
|
||||
std::cout << "C++ ClassA says \"" << m_message << "\"!\n";
|
||||
}
|
||||
|
||||
std::string m_message;
|
||||
};
|
||||
|
||||
class ClassC;
|
||||
|
||||
class ClassB {
|
||||
public:
|
||||
explicit ClassB (std::string nickname) : m_nickname(nickname) {
|
||||
std::cout << "C++ ClassB constructed\n";
|
||||
}
|
||||
|
||||
ClassB (const ClassB&) = delete;
|
||||
ClassB (ClassB&&) = delete;
|
||||
|
||||
void greeting_message (
|
||||
std::string_view first_name,
|
||||
const char* family_name,
|
||||
const std::string& emoji
|
||||
) {
|
||||
std::cout << "C++ ClassB says \"hello " << first_name << " '" <<
|
||||
m_nickname << "' " << family_name << "\" " << emoji << '\n';
|
||||
}
|
||||
|
||||
void set_obj_c (wren::ForeignObject<ClassC> obj) {
|
||||
m_obj_c = std::move(obj);
|
||||
}
|
||||
wren::ForeignObject<ClassC>* get_obj_c() { return &m_obj_c; }
|
||||
|
||||
private:
|
||||
std::string m_nickname;
|
||||
wren::ForeignObject<ClassC> m_obj_c;
|
||||
};
|
||||
|
||||
class ClassC {
|
||||
public:
|
||||
ClassC (std::string msg) : m_message(msg) {}
|
||||
void print_message() const { std::cout << m_message << '\n'; }
|
||||
|
||||
private:
|
||||
std::string m_message;
|
||||
};
|
||||
} //unnamed namespace
|
||||
|
||||
int main() {
|
||||
using wren::make_function_bindable;
|
||||
using wren::make_foreign_class;
|
||||
using wren::make_wren_object;
|
||||
|
||||
//We need a custom one to deal with custom module loading for
|
||||
//module_a and module_b
|
||||
MyWrenConfig config;
|
||||
wren::VM vm(&config, nullptr);
|
||||
|
||||
|
||||
vm.callback_manager()
|
||||
.add_callback(false, "module_a", "ClassA", "say_hi()", make_function_bindable<&ClassA::say_hi>)
|
||||
.add_callback(false, "module_b", "ClassB", "greeting_message(_,_,_)", make_function_bindable<&ClassB::greeting_message>)
|
||||
.add_callback(false, "module_b", "ClassB", "set_obj_c(_)", make_function_bindable<&ClassB::set_obj_c>)
|
||||
.add_callback(false, "module_b", "ClassB", "get_obj_c()", make_function_bindable<&ClassB::get_obj_c>)
|
||||
.add_callback(false, "module_c", "ClassC", "print_message()", make_function_bindable<&ClassC::print_message>)
|
||||
;
|
||||
vm.class_manager()
|
||||
.add_class_maker("module_b", "ClassB", make_foreign_class<ClassB, std::string>)
|
||||
.add_class_maker("module_a", "ClassA", make_foreign_class<ClassA, std::string>)
|
||||
.add_class_maker("module_c", "ClassC", make_foreign_class<ClassC, std::string>)
|
||||
;
|
||||
|
||||
//Example 1: invoke obj_b.do_action() from Wren passing an obj_a that's
|
||||
//also instantiated from within the Wren script
|
||||
vm.interpret("main", g_script);
|
||||
|
||||
//Example 2: invoke obj_b.do_action() from C++ passing a new obj_a which
|
||||
//is instantiated from C++
|
||||
wren::ForeignObject<ClassA> obj_a = make_wren_object<ClassA>(vm, wren::MN<"module_a", "ClassA">, "instantiated from c++");
|
||||
wren::call<void>(vm, wren::MN<"main", "obj_b">, "do_action", obj_a, 3);
|
||||
|
||||
//Example 3: invoke obj_b.do_action() from C++, where obj_b is also
|
||||
//instantiated from C++, and pass the C++ obj_a instance to it
|
||||
auto obj_b = make_wren_object<ClassB>(vm, wren::MN<"module_b", "ClassB">, "TheCpp");
|
||||
wren::call<void>(vm, obj_b, "do_action", obj_a, 4);
|
||||
|
||||
//Example 4: set obj_c on obj_c and query it back
|
||||
wren::ForeignObject<ClassC> obj_c = make_wren_object<ClassC>(vm, wren::MN<"module_c", "ClassC">, "Message of ClassC object instantiated in C++");
|
||||
obj_b.object().set_obj_c(std::move(obj_c));
|
||||
obj_b.object().get_obj_c()->object().print_message();
|
||||
|
||||
std::cout << "Quitting in 1 sec" << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
return 0;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
executable('cpp_calls',
|
||||
'main.cpp',
|
||||
dependencies: wrenpp_dep,
|
||||
install: false,
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -21,7 +21,6 @@
|
|||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
#if defined(__GNU_LIBRARY__) && ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) || __GLIBC__ > 2)
|
||||
# define HasSecureGetenv
|
||||
|
@ -63,6 +62,8 @@ void user_get_env (wren::VM& vm, wren::ModuleAndName) {
|
|||
} //unnamed namespace
|
||||
|
||||
int main() {
|
||||
//typedef wren::ModuleAndName MN;
|
||||
|
||||
wren::DefConfiguration config;
|
||||
wren::VM vm(&config, nullptr);
|
||||
vm.callback_manager().add_callback(true, "main", "User", "get_env(_)", [](){return &user_get_env;});
|
||||
|
|
|
@ -108,7 +108,6 @@ System.print("vec_base_x modified by scripting: <%(vec_base_x.x), %(vec_base_x.y
|
|||
int main() {
|
||||
using wren::make_function_bindable;
|
||||
using wren::make_foreign_class;
|
||||
using wren::ConstructorParameters;
|
||||
|
||||
MyConf conf;
|
||||
wren::VM vm(&conf, nullptr);
|
||||
|
@ -124,8 +123,8 @@ int main() {
|
|||
vm.class_manager()
|
||||
.add_class_maker("math_vector", "MathVector", make_foreign_class<Vector<double>,
|
||||
double, //single value constructor
|
||||
ConstructorParameters<double, double, double>, //x,y,z constructor
|
||||
ConstructorParameters<> //default constructor
|
||||
std::tuple<double, double, double>, //x,y,z constructor
|
||||
std::tuple<> //default constructor
|
||||
>);
|
||||
|
||||
vm.interpret("main", g_test_script);
|
||||
|
|
|
@ -2,4 +2,3 @@ subdir('dieroll')
|
|||
subdir('greet')
|
||||
subdir('calendar')
|
||||
subdir('math_vector')
|
||||
subdir('cpp_calls')
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "detail/strings_in_vector.hpp"
|
||||
#include "detail/construct_foreign_class.hpp"
|
||||
#include "detail/wren_class_name_from_type.hpp"
|
||||
#include "detail/type_id.hpp"
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
@ -80,28 +79,22 @@ namespace wren {
|
|||
std::size_t operator()(TempClassName value) const;
|
||||
};
|
||||
|
||||
class TypeIDHash {
|
||||
public:
|
||||
std::size_t operator()(TypeID tid) const;
|
||||
template <typename F>
|
||||
struct CppClassTypeHelper {
|
||||
static void register_ifp(ClassManager&, const ClassNameOwning* name);
|
||||
};
|
||||
|
||||
define_has_typedef(class_type, ClassType);
|
||||
template <typename T, typename... Args>
|
||||
struct CppClassTypeHelper<MakeForeignClass<T, Args...>> {
|
||||
static void register_ifp(ClassManager& classman, const ClassNameOwning* name);
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
//Customisation point - specialise for your own types if needed
|
||||
template <typename T>
|
||||
struct ClassMakerTraits {
|
||||
};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
struct ClassMakerTraits<detail::MakeForeignClass<T, Args...>> {
|
||||
typedef T class_type;
|
||||
};
|
||||
|
||||
class ClassManager {
|
||||
template <typename F> friend struct detail::CppClassTypeHelper;
|
||||
typedef std::function<foreign_class_t()> make_foreign_class_t;
|
||||
typedef std::unordered_map<detail::ClassNameOwning, make_foreign_class_t, detail::ClassNameHash, detail::ClassNameEqual> ClassMap;
|
||||
typedef std::unordered_map<TypeID, const detail::ClassNameOwning*, detail::TypeIDHash> TypeMap;
|
||||
typedef std::unordered_map<ClassManagerNameHashType, const detail::ClassNameOwning*> TypeMap;
|
||||
public:
|
||||
ClassManager();
|
||||
~ClassManager() noexcept;
|
||||
|
@ -109,7 +102,7 @@ namespace wren {
|
|||
template <typename F>
|
||||
ClassManager& add_class_maker (std::string module_name, std::string_view class_name, F&& maker);
|
||||
foreign_class_t make_class(std::string_view module_name, std::string_view class_name);
|
||||
ModuleAndName wren_class_name_from_hash(TypeID hash) const;
|
||||
ModuleAndName wren_class_name_from_hash(ClassManagerNameHashType hash) const;
|
||||
template <typename T>
|
||||
ModuleAndName wren_class_name_from_type() const;
|
||||
|
||||
|
@ -120,27 +113,33 @@ namespace wren {
|
|||
make_foreign_class_t
|
||||
);
|
||||
|
||||
void add_type (TypeID hash, const detail::ClassNameOwning* name);
|
||||
void add_type (ClassManagerNameHashType hash, const detail::ClassNameOwning* name);
|
||||
|
||||
ClassMap m_classes;
|
||||
TypeMap m_types; //refers to memory in m_classes
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
inline ClassManager& ClassManager::add_class_maker (std::string module_name, std::string_view class_name, F&& maker) {
|
||||
typedef ClassMakerTraits<std::decay_t<F>> MakerTraits;
|
||||
|
||||
auto it_new = this->add_class_maker_implem(module_name, class_name, std::forward<F>(maker));
|
||||
|
||||
//See if we can deduce the class type that maker is supposed to work
|
||||
//with. This is not guaranteed to be an existing piece of info because
|
||||
//user code can provide their own function that doesn't use any actual
|
||||
//c++ class, just normal functions.
|
||||
if constexpr (detail::HasClassTypeTypedef<MakerTraits>::value) {
|
||||
const auto& owning_name = it_new->first;
|
||||
this->add_type(type_id<typename MakerTraits::class_type>(), &owning_name);
|
||||
namespace detail {
|
||||
template <typename F>
|
||||
inline void CppClassTypeHelper<F>::register_ifp(ClassManager&, const ClassNameOwning*) {
|
||||
//Nothing to do
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline void CppClassTypeHelper<MakeForeignClass<T, Args...>>::register_ifp(
|
||||
ClassManager& classman,
|
||||
const ClassNameOwning* name
|
||||
) {
|
||||
const auto new_hash = type_hash<T>();
|
||||
classman.add_type(new_hash, name);
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
template <typename F>
|
||||
inline ClassManager& ClassManager::add_class_maker (std::string module_name, std::string_view class_name, F&& maker) {
|
||||
auto it_new = this->add_class_maker_implem(module_name, class_name, std::forward<F>(maker));
|
||||
const auto& owning_name = it_new->first;
|
||||
detail::CppClassTypeHelper<std::decay_t<F>>::register_ifp(*this, &owning_name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
148
include/wrenpp/detail/StringCRC32.hpp
Normal file
148
include/wrenpp/detail/StringCRC32.hpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
#ifndef id42C91D2875AE4E56BA61051619B58C03
|
||||
#define id42C91D2875AE4E56BA61051619B58C03
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace duckcore {
|
||||
class StringCRC32 {
|
||||
struct FnvHashBase {
|
||||
[[gnu::pure]] [[gnu::always_inline]]
|
||||
static uint32_t Calculate ( const char parChar, uint32_t parCrc );
|
||||
};
|
||||
|
||||
//Update step: crc_32_tab[(crc ^ ch) & 0xff] ^ (crc >> 8)
|
||||
template <uint32_t N, uint32_t I>
|
||||
struct FnvHash : private FnvHashBase {
|
||||
[[gnu::always_inline]]
|
||||
static uint32_t Calculate ( const char (&str)[N], uint32_t crc ) {
|
||||
const uint32_t prevcrc = FnvHash<N, I-1>::Calculate(str, crc);
|
||||
return FnvHashBase::Calculate(str[I-1], prevcrc);
|
||||
}
|
||||
};
|
||||
template <unsigned int N>
|
||||
struct FnvHash<N, 1> : private FnvHashBase {
|
||||
[[gnu::always_inline]]
|
||||
static uint32_t Calculate ( const char (&str)[N], uint32_t crc ) {
|
||||
return FnvHashBase::Calculate(str[0], crc);
|
||||
}
|
||||
};
|
||||
|
||||
class ConstCharWrapper {
|
||||
public:
|
||||
ConstCharWrapper ( const char* parStr ) : str(parStr) { }
|
||||
const char* const str;
|
||||
};
|
||||
public:
|
||||
|
||||
StringCRC32 ( ConstCharWrapper parStr );
|
||||
|
||||
template <unsigned int N>
|
||||
[[gnu::always_inline]]
|
||||
StringCRC32 ( const char (&str)[N] ) :
|
||||
m_hash(~FnvHash<N, N>::Calculate(str, 0xffffffff))
|
||||
{
|
||||
}
|
||||
|
||||
operator uint32_t ( void ) const { return m_hash; }
|
||||
|
||||
private:
|
||||
uint32_t m_hash;
|
||||
|
||||
private:
|
||||
//This is meant to represent a list of bits that are set to 1
|
||||
template <int N, typename T>
|
||||
struct BitArray {
|
||||
enum { value = N };
|
||||
typedef T Next;
|
||||
};
|
||||
//Polynomial from zlib: {0,1,2,4,5,7,8,10,11,12,16,22,23,26} or 0xedb88320UL
|
||||
// for (int poly = 0, n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
// poly |= (z_crc_t)1 << (31 - p[n]);
|
||||
typedef BitArray<0, BitArray<1, BitArray<2, BitArray<4, BitArray<5,
|
||||
BitArray<7, BitArray<8, BitArray<10, BitArray<11, BitArray<12,
|
||||
BitArray<16, BitArray<22, BitArray<23,
|
||||
BitArray<26, std::nullptr_t> > > > > > > > > > > > > > PolynomialBits;
|
||||
template <typename P, int M>
|
||||
struct MakePolynomial {
|
||||
enum { value = (1 << (M - P::value)) bitor MakePolynomial<typename P::Next, M>::value };
|
||||
};
|
||||
template <int M>
|
||||
struct MakePolynomial<std::nullptr_t, M> {
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
//CRC32 algorithm from zlib:
|
||||
// for (int n = 0; n < 256; n++) {
|
||||
// c = n;
|
||||
// for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
// crc_table[n] = c;
|
||||
// }
|
||||
template <int C, int S=8, uint32_t P=static_cast<uint32_t>(MakePolynomial<PolynomialBits, 31>::value)>
|
||||
struct TableLookup {
|
||||
static_assert(S > 1);
|
||||
enum {
|
||||
poly = P,
|
||||
value = TableLookup<TableLookup<C, S-1, poly>::value, 1, poly>::value
|
||||
};
|
||||
};
|
||||
template <int C, uint32_t P>
|
||||
struct TableLookup<C, 1, P> {
|
||||
enum {
|
||||
poly = P,
|
||||
value = ((C & 1) == 1 ? poly ^ (static_cast<uint32_t>(C) >> 1) : static_cast<uint32_t>(C) >> 1)
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inline uint32_t StringCRC32::FnvHashBase::Calculate (const char parChar, uint32_t parCrc) {
|
||||
static const uint32_t crc_32_tab[256] = { /* CRC polynomial 0xedb88320 */
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
return crc_32_tab[(parCrc ^ parChar) & 0xff] ^ (parCrc >> 8);
|
||||
}
|
||||
} //namespace duckcore
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -23,12 +23,11 @@
|
|||
# include "guess_class_name.hpp"
|
||||
#endif
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
namespace wren {
|
||||
template <typename... Args> struct ConstructorParameters { };
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename... Args, int... Indices>
|
||||
inline void construct_single (
|
||||
|
@ -47,13 +46,13 @@ namespace wren {
|
|||
template <typename T, typename... Args>
|
||||
struct ForeignClassHelper;
|
||||
|
||||
template <typename T, typename... PackArgs, typename... Args>
|
||||
struct ForeignClassHelper<T, ConstructorParameters<PackArgs...>, Args...> {
|
||||
template <typename T, template <typename...> class Pack, typename... PackArgs, typename... Args>
|
||||
struct ForeignClassHelper<T, Pack<PackArgs...>, Args...> {
|
||||
static ConstructResult construct (VM& vm, int cardinality, void* memory) {
|
||||
using std::make_integer_sequence;
|
||||
|
||||
//search by number of parameters.
|
||||
//once we find a ConstructorParameters that contains the right
|
||||
//once we find a tuple-like parameter that contains the right
|
||||
//number of types we invoke construct_single() with those types.
|
||||
constexpr int pack_size = static_cast<int>(sizeof...(PackArgs));
|
||||
if (pack_size == cardinality) {
|
||||
|
@ -76,12 +75,7 @@ namespace wren {
|
|||
return ConstructResult{1, true};
|
||||
}
|
||||
else {
|
||||
if constexpr (sizeof...(Args) > 0) {
|
||||
return ForeignClassHelper<T, Args...>::construct(vm, cardinality, memory);
|
||||
}
|
||||
else {
|
||||
return ConstructResult{0, false};
|
||||
}
|
||||
return ForeignClassHelper<T, Args...>::construct(vm, cardinality, memory);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -124,8 +118,7 @@ namespace wren {
|
|||
|
||||
template <typename... Args>
|
||||
constexpr void static_assert_all_packs_are_unique() {
|
||||
//If more than one arg (ctor overload) is given, check they are unique
|
||||
if constexpr (sizeof...(Args) > 1) {
|
||||
if constexpr (sizeof...(Args) > 0) {
|
||||
constexpr auto dummy = AssertIfDuplicateValues<ForeignParamHelper<Args>::argument_count...>::value;
|
||||
static_assert(dummy == 1); //always true
|
||||
}
|
||||
|
@ -150,14 +143,14 @@ namespace wren {
|
|||
|
||||
const auto result = detail::ForeignClassHelper<T, Args...>::construct(vm, vm.slot_count() - 1, mem);
|
||||
if (not result.success) {
|
||||
abort_fiber_with_error(vm, 1,
|
||||
std::string{"No registered c++ constructor "} +
|
||||
set(vm, 1, std::string{"No registered c++ constructor "} +
|
||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||
"for class " + guess_class_name<T>() + " " +
|
||||
"for class " + guess_class_name<T>() + " " +
|
||||
#endif
|
||||
"takes " + std::to_string(result.parameter_count) +
|
||||
" parameter" + (result.parameter_count == 1 ? "" : "s")
|
||||
"takes " + std::to_string(result.parameter_count) +
|
||||
" parameter" + (result.parameter_count == 1 ? "" : "s")
|
||||
);
|
||||
vm.abort_fiber(1);
|
||||
}
|
||||
};
|
||||
ret.finalize = [](void* mem) {
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace wren {
|
||||
namespace detail {
|
||||
[[gnu::const]]
|
||||
std::uint32_t runtime_crc32c (const char* data, std::size_t size, std::uint32_t crc);
|
||||
|
||||
constexpr std::uint32_t g_castagnoli_polynomial = 0x1EDC6F41;
|
||||
|
||||
[[gnu::const]]
|
||||
constexpr std::uint8_t reverse (std::uint8_t b) {
|
||||
//see https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits
|
||||
return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
|
||||
}
|
||||
|
||||
[[gnu::const]]
|
||||
constexpr std::uint32_t reverse (std::uint32_t val) {
|
||||
return (reverse(static_cast<std::uint8_t>(val & 0xff)) << 24) |
|
||||
(reverse(static_cast<std::uint8_t>(val >> 8 & 0xff)) << 16) |
|
||||
(reverse(static_cast<std::uint8_t>(val >> 16 & 0xff)) << 8) |
|
||||
reverse(static_cast<std::uint8_t>(val >> 24 & 0xff));
|
||||
}
|
||||
|
||||
consteval std::uint32_t calc_table_entry (std::uint32_t index, std::uint32_t polynomial) {
|
||||
polynomial = reverse(polynomial);
|
||||
auto c = static_cast<std::uint_fast32_t>(index);
|
||||
for (std::uint_fast32_t k = 0; k < 8; ++k) {
|
||||
c = (c >> 1) ^ ((c & 0x1u) ? polynomial : 0);
|
||||
}
|
||||
return static_cast<std::uint32_t>(c);
|
||||
}
|
||||
|
||||
template <std::uint32_t Polynomial, typename T>
|
||||
struct PolynomialTableBase;
|
||||
|
||||
template <std::uint32_t Polynomial, std::uint32_t... Indices>
|
||||
struct PolynomialTableBase<Polynomial, std::integer_sequence<std::uint32_t, Indices...>> {
|
||||
static constexpr std::size_t table_size = sizeof...(Indices);
|
||||
static constexpr std::uint32_t table[table_size] = {calc_table_entry(Indices, Polynomial)...};
|
||||
};
|
||||
|
||||
template <std::uint32_t Polynomial>
|
||||
struct PolynomialTable : public PolynomialTableBase<Polynomial, decltype(std::make_integer_sequence<std::uint32_t, 256>{})> {
|
||||
};
|
||||
|
||||
template <std::uint32_t Polynomial>
|
||||
constexpr inline auto g_polynomial_table = PolynomialTable<Polynomial>::table;
|
||||
|
||||
template <std::uint32_t Polynomial, std::uint32_t XorIn=0xffffffff, std::uint32_t XorOut=XorIn>
|
||||
constexpr std::uint32_t crc32 (const char* data, std::size_t len, std::uint32_t crc) noexcept {
|
||||
//static_assert(g_polynomial_table<Polynomial>[0b10000000] == Polynomial);
|
||||
crc ^= XorIn;
|
||||
for (std::size_t z = 0; z < len; ++z) {
|
||||
crc = g_polynomial_table<Polynomial>[(crc ^ static_cast<unsigned char>(data[z])) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
return crc ^ XorOut;
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
[[gnu::const]]
|
||||
constexpr std::uint32_t crc32c (const char* data, std::size_t size) {
|
||||
if (not std::is_constant_evaluated()) {
|
||||
return detail::runtime_crc32c(data, size, 0);
|
||||
}
|
||||
else {
|
||||
return detail::crc32<detail::g_castagnoli_polynomial>(data, size, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
[[gnu::const]]
|
||||
constexpr std::uint32_t crc32c (const T (&data)[N]) {
|
||||
return crc32c(static_cast<const char*>(data), N * sizeof(T));
|
||||
}
|
||||
} //namespace wren
|
|
@ -1,42 +0,0 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace wren::detail {
|
||||
|
||||
//Dereferences the given parameter if necessary, always returning an optionally
|
||||
//cv-qualified ref
|
||||
template <typename T>
|
||||
struct DerefIFN {
|
||||
static typename std::remove_reference<T>::type& deref (
|
||||
typename std::remove_reference<T>::type& param
|
||||
) {
|
||||
return param;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct DerefIFN<T*> {
|
||||
static T& deref (T* param) { return *param; }
|
||||
};
|
||||
|
||||
//Add specialisations for std::unique_ptr & co?
|
||||
|
||||
} //namespace wren::detail
|
|
@ -1,97 +0,0 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wrenpp/handle.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace wren {
|
||||
|
||||
class VM;
|
||||
|
||||
//This is meant to be a short lived object representing a still-in-a-slot
|
||||
//foreign object. Upon casting it to ForeignObject it will create a handle to
|
||||
//the data in given slot
|
||||
template <typename T>
|
||||
class TempForeignObject {
|
||||
public:
|
||||
TempForeignObject (VM* vm, T* object, int slot_num) :
|
||||
m_vm(vm),
|
||||
m_data(object),
|
||||
m_slot_num(slot_num)
|
||||
{ }
|
||||
|
||||
VM* vm() const { return m_vm; }
|
||||
T* data() const { return m_data; }
|
||||
int slot_num() const { return m_slot_num; }
|
||||
|
||||
private:
|
||||
VM* m_vm;
|
||||
T* m_data;
|
||||
int m_slot_num;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ForeignObject {
|
||||
public:
|
||||
ForeignObject() = default;
|
||||
ForeignObject (std::nullptr_t) : ForeignObject() {}
|
||||
ForeignObject (T* obj, Handle&& handle);
|
||||
ForeignObject (ForeignObject&&) = default;
|
||||
ForeignObject (const TempForeignObject<T>& temp_object);
|
||||
~ForeignObject() noexcept = default;
|
||||
|
||||
ForeignObject& operator= (ForeignObject&&) = default;
|
||||
bool operator!= (std::nullptr_t) const { return nullptr != m_object; }
|
||||
bool operator== (std::nullptr_t) const { return nullptr == m_object; }
|
||||
|
||||
void set_to_slot (int num);
|
||||
T& object() { return *m_object; }
|
||||
const T& object() const { return *m_object; }
|
||||
Handle& handle() { return m_handle; }
|
||||
const Handle& handle() const { return m_handle; }
|
||||
bool is_valid() const { return nullptr != m_object; }
|
||||
|
||||
operator T&() { return object(); }
|
||||
operator const T&() const { return object(); }
|
||||
operator Handle&() { return handle(); }
|
||||
operator const Handle&() const { return handle(); }
|
||||
|
||||
private:
|
||||
Handle m_handle;
|
||||
T* m_object{nullptr};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline ForeignObject<T>::ForeignObject (T* obj, Handle&& handle) :
|
||||
m_handle(std::move(handle)),
|
||||
m_object(obj)
|
||||
{ }
|
||||
|
||||
template <typename T>
|
||||
inline ForeignObject<T>::ForeignObject (const TempForeignObject<T>& temp_object) :
|
||||
m_handle(temp_object.vm(), temp_object.slot_num()),
|
||||
m_object(temp_object.data())
|
||||
{ }
|
||||
|
||||
template <typename T>
|
||||
inline void ForeignObject<T>::set_to_slot (int num) {
|
||||
m_handle.set_to_slot(num);
|
||||
}
|
||||
|
||||
} //namespace wren
|
|
@ -66,17 +66,5 @@
|
|||
}; \
|
||||
}
|
||||
|
||||
#define define_has_typedef(typedef_name,pretty_name) \
|
||||
template <typename T> \
|
||||
struct Has ## pretty_name ## Typedef { \
|
||||
private: \
|
||||
struct TrueType { int a[2]; }; \
|
||||
typedef int FalseType; \
|
||||
template <typename C> static TrueType has_typedef ( const typename C::typedef_name* ); \
|
||||
template <typename C> static FalseType has_typedef ( ... ); \
|
||||
public: \
|
||||
enum { value = sizeof(has_typedef<T>(nullptr)) == sizeof(TrueType) }; \
|
||||
}
|
||||
|
||||
namespace wren {
|
||||
} //namespace wren
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "deref_ifn.hpp"
|
||||
|
||||
namespace wren::detail {
|
||||
|
||||
template <typename T, typename TRaw>
|
||||
struct IsKindOfHandleHelper {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <typename TRaw>
|
||||
struct IsKindOfHandleHelper<Handle, TRaw> {
|
||||
static constexpr bool value = true;
|
||||
static void set_to_slot (int slot_num, TRaw obj) {DerefIFN<TRaw>::deref(obj).set_to_slot(slot_num);}
|
||||
};
|
||||
template <typename U, typename TRaw>
|
||||
struct IsKindOfHandleHelper<ForeignObject<U>, TRaw> {
|
||||
static constexpr bool value = true;
|
||||
static void set_to_slot (int slot_num, TRaw obj) {DerefIFN<TRaw>::deref(obj).set_to_slot(slot_num);}
|
||||
};
|
||||
template <typename T>
|
||||
using IsKindOfHandle = IsKindOfHandleHelper<typename std::remove_pointer<typename std::remove_cvref<T>::type>::type, T>;
|
||||
|
||||
} //namespace wren::detail
|
|
@ -1,14 +1,13 @@
|
|||
include_files = [
|
||||
'construct_foreign_class.hpp',
|
||||
'crc32.hpp',
|
||||
'error_type.hpp',
|
||||
'guess_class_name.hpp',
|
||||
'has_method.hpp',
|
||||
'module_and_name.hpp',
|
||||
'setters_getters.hpp',
|
||||
'string_bt.hpp',
|
||||
'StringCRC32.hpp',
|
||||
'strings_in_vector.hpp',
|
||||
'type_id.hpp',
|
||||
'wren_class_name_from_type.hpp',
|
||||
'wren_types.hpp',
|
||||
]
|
||||
|
|
|
@ -18,30 +18,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "string_bt.hpp"
|
||||
#include "crc32.hpp"
|
||||
#include <string_view>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
namespace wren {
|
||||
typedef decltype(crc32c(nullptr, 0)) ModuleAndNameHashType;
|
||||
class ModuleAndName;
|
||||
|
||||
namespace detail {
|
||||
template <dhandy::bt::string Str>
|
||||
template <dhandy::bt::string S>
|
||||
struct ModuleAndNameStaticStorage {
|
||||
static constexpr dhandy::bt::string value = Str;
|
||||
static constexpr const auto value = S;
|
||||
};
|
||||
|
||||
[[gnu::const]]
|
||||
bool deep_equal (const ModuleAndName& a, const ModuleAndName& b) noexcept;
|
||||
} //unnamed namespace
|
||||
|
||||
//Non-owning, lightweight class for storing a module name + generic name
|
||||
//pair. It holds a hash value too, which is currently only meaningful for
|
||||
//module name/class name pairs that are mapped to a c++ class.
|
||||
//Names are stored as consecutive strings within a single buffer with a
|
||||
//Non-owning, lightweight class for storing a module nome/class name pair.
|
||||
//They are stored as consecutive strings within a single buffer with a
|
||||
//null-char in-between and at the end so that each name is null-terminated
|
||||
//and can be used with C APIs.
|
||||
//Keep the size small, ideally within 2 registers size. Altering this might
|
||||
|
@ -51,16 +40,9 @@ namespace wren {
|
|||
//of this class get hardcoded in the dynamic functions that DynafuncMaker
|
||||
//spits out.
|
||||
class ModuleAndName {
|
||||
friend bool detail::deep_equal(const ModuleAndName&, const ModuleAndName&) noexcept;
|
||||
template <dhandy::bt::string S1, dhandy::bt::string S2>
|
||||
friend consteval ModuleAndName make_module_and_name() noexcept;
|
||||
public:
|
||||
constexpr ModuleAndName();
|
||||
constexpr ModuleAndName (const char* base, std::size_t mod_name_len, std::size_t class_name_len);
|
||||
|
||||
constexpr bool operator==(const ModuleAndName& other) const noexcept;
|
||||
constexpr bool operator!=(const ModuleAndName& other) const noexcept;
|
||||
constexpr bool deep_equal(const ModuleAndName& other) const noexcept;
|
||||
constexpr ModuleAndName (const char* base, std::uint32_t hash, std::size_t mod_name_len, std::size_t class_name_len);
|
||||
|
||||
constexpr const char* module_name_char() const noexcept { return m_base; }
|
||||
constexpr const char* class_name_char() const noexcept { return m_base + 1 + m_mod_name_len; }
|
||||
|
@ -71,19 +53,10 @@ namespace wren {
|
|||
constexpr const char* buffer_address() const noexcept { return m_base; }
|
||||
|
||||
private:
|
||||
constexpr ModuleAndName (const char* base, ModuleAndNameHashType hash, std::size_t mod_name_len, std::size_t class_name_len);
|
||||
|
||||
constexpr std::size_t raw_buffer_size() const noexcept;
|
||||
|
||||
const char* m_base;
|
||||
ModuleAndNameHashType m_hash;
|
||||
std::uint32_t m_hash;
|
||||
std::uint16_t m_mod_name_len;
|
||||
std::uint16_t m_class_name_len;
|
||||
|
||||
static_assert(
|
||||
sizeof(m_hash) <= sizeof(std::uint32_t),
|
||||
"Hash type is too large, review this struct or change it back to uint32_t"
|
||||
);
|
||||
};
|
||||
|
||||
union RawAccessModuleAndName {
|
||||
|
@ -105,59 +78,21 @@ namespace wren {
|
|||
ModuleAndName(nullptr, 0, 0, 0)
|
||||
{}
|
||||
|
||||
constexpr ModuleAndName::ModuleAndName (const char* base, std::size_t mod_name_len, std::size_t class_name_len) :
|
||||
ModuleAndName(base, crc32c(base, mod_name_len + class_name_len + 2), mod_name_len, class_name_len)
|
||||
{}
|
||||
|
||||
constexpr ModuleAndName::ModuleAndName (const char* base, ModuleAndNameHashType hash, std::size_t mod_name_len, std::size_t class_name_len) :
|
||||
constexpr ModuleAndName::ModuleAndName (const char* base, std::uint32_t hash, std::size_t mod_name_len, std::size_t class_name_len) :
|
||||
m_base(base),
|
||||
m_hash(hash),
|
||||
m_mod_name_len(mod_name_len),
|
||||
m_class_name_len(class_name_len)
|
||||
{}
|
||||
|
||||
constexpr bool ModuleAndName::operator==(const ModuleAndName& other) const noexcept {
|
||||
const bool retval = (this->m_hash == other.m_hash and deep_equal(other));
|
||||
return retval;
|
||||
}
|
||||
|
||||
constexpr bool ModuleAndName::operator!=(const ModuleAndName& other) const noexcept {
|
||||
return not this->operator==(other);
|
||||
}
|
||||
|
||||
constexpr bool ModuleAndName::deep_equal(const ModuleAndName& other) const noexcept {
|
||||
if (not std::is_constant_evaluated()) {
|
||||
return detail::deep_equal(*this, other);
|
||||
}
|
||||
else {
|
||||
if (this->raw_buffer_size() != other.raw_buffer_size())
|
||||
return false;
|
||||
for (std::size_t z = 0; z < raw_buffer_size(); ++z) {
|
||||
if (this->m_base[z] != other.m_base[z])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr std::size_t ModuleAndName::raw_buffer_size() const noexcept {
|
||||
return m_mod_name_len + m_class_name_len + 2;
|
||||
}
|
||||
|
||||
template <dhandy::bt::string S1, dhandy::bt::string S2>
|
||||
consteval ModuleAndName make_module_and_name() noexcept {
|
||||
constexpr ModuleAndName make_module_and_name() {
|
||||
using dhandy::bt::string;
|
||||
using detail::ModuleAndNameStaticStorage;
|
||||
constexpr string null_char{"\0"};
|
||||
using StaticStorage = ModuleAndNameStaticStorage<S1 + null_char + S2>;
|
||||
|
||||
constexpr const char* data = StaticStorage::value.data();
|
||||
constexpr const char* data = detail::ModuleAndNameStaticStorage<S1 + string("\0") + S2>::value.data();
|
||||
constexpr std::uint16_t s1_len = static_cast<std::uint16_t>(S1.size());
|
||||
constexpr std::uint16_t s2_len = static_cast<std::uint16_t>(S2.size());
|
||||
constexpr ModuleAndNameHashType hash = crc32c(
|
||||
StaticStorage::value.data(),
|
||||
StaticStorage::value.size()
|
||||
);
|
||||
constexpr std::uint32_t hash = 0; //not implemented yet
|
||||
|
||||
return ModuleAndName{data, hash, s1_len, s2_len};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -18,10 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../vm.hpp"
|
||||
#include "../handle.hpp"
|
||||
#include "foreign_object.hpp"
|
||||
#include "module_and_name.hpp"
|
||||
#include "is_kindof_handle.hpp"
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
@ -36,14 +33,8 @@ namespace wren {
|
|||
template<typename T>struct GetTypeToRetType{
|
||||
static_assert(not std::is_fundamental_v<T>, "User type expected");
|
||||
static_assert(not std::is_pointer_v<T>, "Unexpected pointer type");
|
||||
typedef TempForeignObject< std::remove_cv_t<T> > type;
|
||||
typedef std::remove_cv_t<T>* type;
|
||||
};
|
||||
template<typename T>struct GetTypeToRetType<ForeignObject<T>> {
|
||||
//This doesn't make much sense, essentially you're asking wrenpp to
|
||||
//give you a foreign object by vm/slot when you already have its
|
||||
//handle
|
||||
};
|
||||
template<typename T>struct GetTypeToRetType<TempForeignObject<T>> : TType<TempForeignObject<T>>{};
|
||||
template<>struct GetTypeToRetType<const char*> : TType<const char*>{};
|
||||
template<>struct GetTypeToRetType<double> : TType<double>{};
|
||||
template<>struct GetTypeToRetType<bool> : TType<bool>{};
|
||||
|
@ -96,8 +87,6 @@ namespace wren {
|
|||
void set (VM& vm, int slot_num, const char* beg, const char* end);
|
||||
void set (VM& vm, int slot_num, int value);
|
||||
void set (VM& vm, int slot_num, std::size_t value);
|
||||
void set (VM& vm, int slot_num, const Handle& handle);
|
||||
void set (VM& vm, int slot_num, const ModuleAndName& name);
|
||||
std::string_view slot_string_view (VM& vm, int slot_num);
|
||||
template <typename T> detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num);
|
||||
template <typename T> T* foreign (VM& vm, int slot_num);
|
||||
|
@ -149,14 +138,6 @@ namespace wren {
|
|||
vm.set_slot_double(slot_num, static_cast<double>(value));
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const Handle& handle) {
|
||||
vm.set_slot_handle(handle, slot_num);
|
||||
}
|
||||
|
||||
inline void set (VM& vm, int slot_num, const ModuleAndName& name) {
|
||||
vm.variable_or_throw(name.module_name_char(), name.class_name_char(), slot_num);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* foreign (VM& vm, int slot_num) {
|
||||
T* obj = static_cast<T*>(vm.slot_foreign(slot_num));
|
||||
|
@ -174,16 +155,16 @@ namespace wren {
|
|||
|
||||
template <typename T>
|
||||
inline detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num) {
|
||||
return {&vm, foreign<T>(vm, slot_num), slot_num};
|
||||
return foreign<T>(vm, slot_num);
|
||||
}
|
||||
|
||||
template<> const char* get<const char*> (VM& vm, int slot_num);
|
||||
template<> double get<double> (VM& vm, int slot_num);
|
||||
template<> bool get<bool> (VM& vm, int slot_num);
|
||||
template<> std::pair<const char*, int> get<std::pair<const char*,int>> (VM& vm, int slot_num);
|
||||
template <> double get<double> (VM& vm, int slot_num);
|
||||
template <> bool get<bool> (VM& vm, int slot_num);
|
||||
template <> std::pair<const char*, int> get<std::pair<const char*,int>> (VM& vm, int slot_num);
|
||||
template<> int get<int> (VM& vm, int slot_num);
|
||||
template<> std::size_t get<std::size_t> (VM& vm, int slot_num);
|
||||
template<> std::string get<std::string> (VM& vm, int slot_num);
|
||||
template<> std::string_view get<std::string_view> (VM& vm, int slot_num);
|
||||
template<> std::vector<char> get<std::vector<char>> (VM& vm, int slot_num);
|
||||
template <> std::string_view get<std::string_view> (VM& vm, int slot_num);
|
||||
template <> std::vector<char> get<std::vector<char>> (VM& vm, int slot_num);
|
||||
} //namespace wren
|
||||
|
|
|
@ -18,13 +18,9 @@
|
|||
#ifndef id170B0E6C34D14EBA9B92A35977BDBFB3
|
||||
#define id170B0E6C34D14EBA9B92A35977BDBFB3
|
||||
|
||||
//#define PRINTABLE_STRING_BT
|
||||
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#if defined(PRINTABLE_STRING_BT)
|
||||
# include <iostream>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace dhandy {
|
||||
|
@ -32,10 +28,8 @@ namespace dhandy {
|
|||
template <std::size_t S, typename Ch=char>
|
||||
class string;
|
||||
|
||||
#if defined(PRINTABLE_STRING_BT)
|
||||
template <std::size_t S, typename Ch>
|
||||
std::basic_ostream<Ch>& operator<< ( std::basic_ostream<Ch>& parStream, const string<S, Ch>& parString );
|
||||
#endif
|
||||
|
||||
namespace implem {
|
||||
template <std::size_t S, typename Ch> constexpr bool eq (const string<S, Ch>& l, const string<S, Ch>& r);
|
||||
|
@ -43,9 +37,7 @@ namespace dhandy {
|
|||
|
||||
template <std::size_t S, typename Ch>
|
||||
class string {
|
||||
#if defined(PRINTABLE_STRING_BT)
|
||||
friend std::ostream& operator<< <>( std::ostream& parStream, const string<S>& parString );
|
||||
#endif
|
||||
friend constexpr bool implem::eq<S, Ch> (const string<S, Ch>&, const string<S, Ch>&);
|
||||
public:
|
||||
using value_type = Ch;
|
||||
|
@ -130,13 +122,11 @@ namespace dhandy {
|
|||
return implem::concat(std::make_index_sequence<S + S2 - 1>(), string<S>(m_data), parOther);
|
||||
}
|
||||
|
||||
#if defined(PRINTABLE_STRING_BT)
|
||||
template <std::size_t S, typename Ch>
|
||||
inline std::ostream& operator<< (std::ostream& parStream, const string<S, Ch>& parString) {
|
||||
parStream << parString.m_data;
|
||||
return parStream;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::size_t S, typename Ch>
|
||||
constexpr bool string<S, Ch>::operator== (const string<S, Ch>& other) const {
|
||||
|
@ -146,7 +136,7 @@ namespace dhandy {
|
|||
template <std::size_t S, typename Ch>
|
||||
template <std::size_t Start, std::size_t Len>
|
||||
constexpr auto string<S, Ch>::substr() const {
|
||||
return string<std::min(S - 1 - std::min(Start, S - 1), Len) + 1, Ch>(m_data + std::min(Start, S - 1), 0) + string<1, Ch>({Ch{}});
|
||||
return string<std::min(S - 1 - std::min(Start, S - 1), Len) + 1, Ch>(m_data + std::min(Start, S - 1), 0) + string("");
|
||||
}
|
||||
} //namespace bt
|
||||
} //namespace dhandy
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace wren {
|
||||
//from:
|
||||
//https://codereview.stackexchange.com/questions/48594/unique-type-id-no-rtti
|
||||
class TypeID {
|
||||
using sig = TypeID();
|
||||
|
||||
sig* m_id;
|
||||
constexpr TypeID(sig* id) : m_id{id} {}
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
friend constexpr TypeID type_id();
|
||||
|
||||
TypeID (const TypeID&) = default;
|
||||
TypeID (TypeID&&) = default;
|
||||
~TypeID() noexcept = default;
|
||||
TypeID& operator= (const TypeID&) = default;
|
||||
TypeID& operator= (TypeID&&) = default;
|
||||
|
||||
constexpr bool operator==(TypeID other) const noexcept;
|
||||
constexpr bool operator!=(TypeID other) const noexcept;
|
||||
constexpr bool operator<(TypeID other) const noexcept;
|
||||
constexpr std::uintptr_t id() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr TypeID type_id() { return &type_id<T>; }
|
||||
|
||||
constexpr bool TypeID::operator==(TypeID other) const noexcept {
|
||||
return id() == other.id();
|
||||
}
|
||||
|
||||
constexpr bool TypeID::operator!=(TypeID other) const noexcept {
|
||||
return id() != other.id();
|
||||
}
|
||||
|
||||
constexpr bool TypeID::operator<(TypeID other) const noexcept {
|
||||
return id() < other.id();
|
||||
}
|
||||
|
||||
constexpr std::uintptr_t TypeID::id() const noexcept {
|
||||
return reinterpret_cast<std::uintptr_t>(m_id);
|
||||
}
|
||||
} //namespace wren
|
|
@ -18,27 +18,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "module_and_name.hpp"
|
||||
#include "type_id.hpp"
|
||||
#include "crc32.hpp"
|
||||
#include <utility>
|
||||
#include <string_view>
|
||||
#include <cstddef>
|
||||
|
||||
namespace wren {
|
||||
typedef std::size_t ClassManagerNameHashType;
|
||||
class VM;
|
||||
|
||||
namespace detail {
|
||||
//TODO: work in progress, make it take a type T and hash that for real
|
||||
template<typename T>
|
||||
inline ClassManagerNameHashType type_hash() {
|
||||
static const ClassManagerNameHashType my_hash = 0;
|
||||
return static_cast<ClassManagerNameHashType>(reinterpret_cast<std::uintptr_t>(&my_hash));
|
||||
}
|
||||
|
||||
//Just an utility function to call a method on the class manager in vm
|
||||
//and return its return value without including the header for the
|
||||
//class manager. Useful in inline functions in header files where
|
||||
//including class_manager.hpp would propagate it everywhere.
|
||||
ModuleAndName fetch_class_name_from_manager (
|
||||
const VM& vm,
|
||||
TypeID hash
|
||||
ClassManagerNameHashType hash
|
||||
);
|
||||
|
||||
template <typename T>
|
||||
inline ModuleAndName wren_class_name_from_type (const VM& vm) {
|
||||
return fetch_class_name_from_manager(vm, type_id<T>());
|
||||
return fetch_class_name_from_manager(vm, type_hash<T>());
|
||||
}
|
||||
} //namespace detail
|
||||
} //namespace wren
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -27,7 +27,6 @@ namespace wren {
|
|||
Handle() noexcept;
|
||||
Handle (const Handle&) = delete;
|
||||
Handle (Handle&& other) noexcept;
|
||||
Handle (VM* vm, int slot_num);
|
||||
Handle (VM* vm, WrenHandle* handle) noexcept :
|
||||
m_handle(handle),
|
||||
m_vm(vm)
|
||||
|
@ -43,8 +42,6 @@ namespace wren {
|
|||
operator WrenHandle*() const { return m_handle; }
|
||||
operator bool() const { return nullptr != m_handle; }
|
||||
|
||||
void set_to_slot (int num);
|
||||
|
||||
private:
|
||||
WrenHandle* m_handle;
|
||||
VM* m_vm;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "detail/has_method.hpp"
|
||||
#include "detail/error_type.hpp"
|
||||
#include "detail/type_id.hpp"
|
||||
#include "detail/StringCRC32.hpp"
|
||||
#include "detail/wren_types.hpp"
|
||||
#include "handle.hpp"
|
||||
#include <memory>
|
||||
|
@ -116,11 +116,11 @@ namespace wren {
|
|||
private:
|
||||
struct LocalData;
|
||||
|
||||
VM (Configuration* conf, const detail::Callbacks&, void* user_data, TypeID user_data_type);
|
||||
VM (Configuration* conf, const detail::Callbacks&, void* user_data, std::uint32_t user_data_type);
|
||||
DynafuncMaker* dynafunc_maker();
|
||||
TypeID user_data_type() const;
|
||||
std::uint32_t user_data_type() const;
|
||||
void* void_user_data();
|
||||
void set_user_data (void* user_data, TypeID user_data_type);
|
||||
void set_user_data (void* user_data, std::uint32_t user_data_type);
|
||||
template <typename T> detail::Callbacks to_callbacks (T& conf);
|
||||
|
||||
std::unique_ptr<LocalData> m_local;
|
||||
|
@ -151,6 +151,12 @@ namespace wren {
|
|||
return (*M)(args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
[[gnu::const]]
|
||||
inline constexpr std::uint32_t type_id() {
|
||||
return duckcore::StringCRC32(__PRETTY_FUNCTION__);
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
template <typename T>
|
||||
|
@ -192,7 +198,7 @@ namespace wren {
|
|||
|
||||
template <typename U>
|
||||
inline U* VM::user_data() {
|
||||
if (user_data_type() != type_id<U>()) {
|
||||
if (user_data_type() != detail::type_id<U>()) {
|
||||
throw std::runtime_error("Wrong user data type requested");
|
||||
}
|
||||
return reinterpret_cast<U*>(void_user_data());
|
||||
|
@ -200,7 +206,7 @@ namespace wren {
|
|||
|
||||
template <typename U>
|
||||
inline void VM::set_user_data (U* user_data) {
|
||||
set_user_data(reinterpret_cast<void*>(user_data), type_id<U>());
|
||||
set_user_data(reinterpret_cast<void*>(user_data), detail::type_id<U>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -209,7 +215,7 @@ namespace wren {
|
|||
static_cast<Configuration*>(conf),
|
||||
to_callbacks(*conf),
|
||||
nullptr,
|
||||
type_id<std::nullptr_t>()
|
||||
detail::type_id<std::nullptr_t>()
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -220,7 +226,7 @@ namespace wren {
|
|||
static_cast<Configuration*>(conf),
|
||||
to_callbacks(*conf),
|
||||
reinterpret_cast<void*>(user_data),
|
||||
type_id<U>()
|
||||
detail::type_id<U>()
|
||||
)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -26,8 +26,6 @@
|
|||
#include "detail/construct_foreign_class.hpp"
|
||||
#include "detail/setters_getters.hpp"
|
||||
#include "detail/wren_class_name_from_type.hpp"
|
||||
#include "detail/is_kindof_handle.hpp"
|
||||
#include "detail/foreign_object.hpp"
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
@ -48,11 +46,11 @@ namespace wren {
|
|||
R call (VM& vm, ModuleAndName object, const char (&method)[N], const Args&... args);
|
||||
|
||||
template <typename T, typename... Args>
|
||||
ForeignObject<T> make_wren_object(VM& vm, ModuleAndName mn, Args&&... args);
|
||||
T* make_wren_object(VM& vm, ModuleAndName mn, Args&&... args);
|
||||
|
||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||
template <typename T, dhandy::bt::string Mod, typename... Args>
|
||||
ForeignObject<T> make_wren_object(VM& vm, Args&&... args);
|
||||
T* make_wren_object(VM& vm, Args&&... args);
|
||||
#endif
|
||||
|
||||
void interpret (VM& vm, const std::string& module_name, const std::string& script);
|
||||
|
@ -60,15 +58,22 @@ namespace wren {
|
|||
void variable(VM& vm, const Handle& handle, int slot);
|
||||
void variable_ensure_slot(VM& vm, ModuleAndName mod_and_name, int slot);
|
||||
void variable_ensure_slot(VM& vm, const Handle& handle, int slot);
|
||||
void abort_fiber_with_error (VM& vm, int slot, std::string_view message);
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct CleanParamForGet { typedef typename std::decay<T>::type type; };
|
||||
template <typename T>
|
||||
struct CleanParamForGet<ForeignObject<T>> { typedef T type; };
|
||||
template <typename T>
|
||||
using CleanParamForGetT = typename CleanParamForGet<T>::type;
|
||||
inline void set_single_for_call (VM& vm, int slot, const T& value) {
|
||||
set(vm, slot, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void set_single_for_call (VM& vm, int slot_num, const Handle& handle) {
|
||||
vm.set_slot_handle(handle, slot_num);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void set_single_for_call (VM& vm, int slot_num, const ModuleAndName& name) {
|
||||
variable(vm, name, slot_num);
|
||||
}
|
||||
|
||||
//Sets arguments so wren is ready to perform a function call. It doesn't
|
||||
//touch at slot 0, so eventual objects for method calls must be set
|
||||
|
@ -76,7 +81,7 @@ namespace wren {
|
|||
template <typename... Args, int... Indices>
|
||||
inline void set_for_call (std::integer_sequence<int, Indices...>, VM& vm, const Args&... args) {
|
||||
vm.ensure_slots(sizeof...(Args));
|
||||
(set(vm, Indices + 1, args), ...);
|
||||
(set_single_for_call(vm, Indices + 1, args), ...);
|
||||
}
|
||||
|
||||
template <auto V>
|
||||
|
@ -90,8 +95,8 @@ namespace wren {
|
|||
template <int... Indices>
|
||||
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
||||
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
||||
T* const obj = foreign<T>(vm, 0);
|
||||
return (obj->*Method)(get<CleanParamForGetT<Args>>(vm, Indices + 1)...);
|
||||
T* obj = foreign<T>(vm, 0);
|
||||
return (obj->*Method)(get<std::decay_t<Args>>(vm, Indices + 1)...);
|
||||
}
|
||||
};
|
||||
template <typename T, typename R, typename... Args, R(T::*ConstMethod)(Args...)const>
|
||||
|
@ -103,8 +108,8 @@ namespace wren {
|
|||
template <int... Indices>
|
||||
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
||||
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
||||
T* const obj = foreign<T>(vm, 0);
|
||||
return (obj->*ConstMethod)(get<CleanParamForGetT<Args>>(vm, Indices + 1)...);
|
||||
T* obj = foreign<T>(vm, 0);
|
||||
return (obj->*ConstMethod)(get<std::decay_t<Args>>(vm, Indices + 1)...);
|
||||
}
|
||||
};
|
||||
template <typename R, typename... Args, R(*Function)(Args...)>
|
||||
|
@ -116,7 +121,7 @@ namespace wren {
|
|||
template <int... Indices>
|
||||
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
||||
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
||||
return (*Function)(get<CleanParamForGetT<Args>>(vm, Indices + 1)...);
|
||||
return (*Function)(get<std::decay_t<Args>>(vm, Indices + 1)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -133,17 +138,13 @@ namespace wren {
|
|||
else {
|
||||
auto ret = CallImplemProvider<V>::call_implem(std::make_integer_sequence<int, argument_count>(), vm);
|
||||
//TODO: check for errors
|
||||
assert(vm.slot_count() >= 1); //vm.ensure_slots(1);
|
||||
vm.ensure_slots(1);
|
||||
if constexpr (std::is_fundamental<R>::value) {
|
||||
set(vm, 0, ret);
|
||||
}
|
||||
else if constexpr (IsKindOfHandle<R>::value) {
|
||||
IsKindOfHandle<R>::set_to_slot(0, ret);
|
||||
assert(vm.slot_type(0) == SlotType::Foreign);
|
||||
}
|
||||
else {
|
||||
ModuleAndName wren_name = wren_class_name_from_type<R>(vm);
|
||||
ForeignObject<R> new_object = make_wren_object<R>(vm, wren_name, std::move(ret));
|
||||
R* const new_object = make_wren_object<R>(vm, wren_name, std::move(ret));
|
||||
static_cast<void>(new_object);
|
||||
}
|
||||
}
|
||||
|
@ -195,13 +196,15 @@ namespace wren {
|
|||
inline R call (VM& vm, const Handle& object, const char (&method)[N], const Args&... args) {
|
||||
using dhandy::bt::string;
|
||||
|
||||
const constexpr auto params = string("(") +
|
||||
const constexpr char dummy_name_buff[N] = {0};
|
||||
const constexpr auto params = string<N, char>(dummy_name_buff) +
|
||||
string("(") +
|
||||
((static_cast<void>(args), string(",_")) + ... + string("")).template substr<1>() +
|
||||
string(")");
|
||||
;
|
||||
char cat_buff[params.size() + 1 + N - 1];
|
||||
char cat_buff[params.size() + 1];
|
||||
std::copy(method, method + N - 1, cat_buff);
|
||||
std::copy(params.data(), params.data() + params.size() + 1, cat_buff + N - 1);
|
||||
std::copy(params.data() + N - 1, params.data() + params.size() + 1, cat_buff + N - 1);
|
||||
return call<R, Args...>(vm, object, vm.make_call_handle(cat_buff), args...);
|
||||
}
|
||||
|
||||
|
@ -214,22 +217,16 @@ namespace wren {
|
|||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline ForeignObject<T> make_wren_object(VM& vm, ModuleAndName mn, Args&&... args) {
|
||||
variable_ensure_slot(vm, mn, 0);
|
||||
inline T* make_wren_object(VM& vm, ModuleAndName mn, Args&&... args) {
|
||||
variable(vm, mn, 0);
|
||||
void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T));
|
||||
try {
|
||||
T* const obj = new(mem) T{std::forward<Args>(args)...};
|
||||
return {obj, vm.slot_handle(0)};
|
||||
}
|
||||
catch (const std::runtime_error& err) {
|
||||
abort_fiber_with_error(vm, 1, err.what());
|
||||
return nullptr;
|
||||
}
|
||||
T* const obj = new(mem) T{std::forward<Args>(args)...};
|
||||
return obj;
|
||||
}
|
||||
|
||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||
template <typename T, dhandy::bt::string Mod, typename... Args>
|
||||
inline ForeignObject<T> make_wren_object(VM& vm, Args&&... args) {
|
||||
inline T* make_wren_object(VM& vm, Args&&... args) {
|
||||
return make_wren_object<T>(
|
||||
vm,
|
||||
MN<Mod, g_guessed_class_name<T>>,
|
||||
|
|
39
meson.build
39
meson.build
|
@ -1,6 +1,6 @@
|
|||
project('wrenpp', 'cpp',
|
||||
version: '0.2.0',
|
||||
meson_version: '>=0.55.0',
|
||||
version: '0.1.3',
|
||||
meson_version: '>=0.49.2',
|
||||
default_options: ['buildtype=release', 'cpp_std=c++20', 'b_ndebug=if-release']
|
||||
)
|
||||
|
||||
|
@ -40,17 +40,46 @@ elif os == 'gnu' and arch == 'aarch64'
|
|||
func_ptr_size = 8
|
||||
endif
|
||||
|
||||
global_compiler_opts = []
|
||||
compiler_opts = []
|
||||
if get_option('wrenpp_with_name_guessing')
|
||||
global_compiler_opts += ['-DWRENPP_WITH_NAME_GUESSING']
|
||||
compiler_opts += ['-DWRENPP_WITH_NAME_GUESSING']
|
||||
endif
|
||||
|
||||
conf.set('POINTER_SIZE', ptr_size)
|
||||
conf.set('FUNC_POINTER_SIZE', func_ptr_size)
|
||||
conf.set('WRENPP_NAME', meson.project_name())
|
||||
|
||||
project_config_file = configure_file(
|
||||
input: 'src/pvt_config.h.in',
|
||||
output: 'pvt_config.h',
|
||||
configuration: conf
|
||||
)
|
||||
|
||||
subdir('include')
|
||||
subdir('src')
|
||||
|
||||
wrenpp = library(meson.project_name(),
|
||||
project_config_file,
|
||||
'src/vm.cpp',
|
||||
'src/configuration.cpp',
|
||||
'src/def_configuration.cpp',
|
||||
'src/dynafunc_maker.cpp',
|
||||
'src/dynafunc_' + arch + '_' + os + '.S',
|
||||
'src/handle.cpp',
|
||||
'src/vm_fun.cpp',
|
||||
'src/callback_manager.cpp',
|
||||
'src/class_manager.cpp',
|
||||
'src/wren_class_name_from_type.cpp',
|
||||
dependencies: [wren_dep],
|
||||
include_directories: public_incl,
|
||||
install: (not meson.is_subproject() or get_option('default_library')=='shared'),
|
||||
c_args: compiler_opts,
|
||||
cpp_args: compiler_opts,
|
||||
)
|
||||
wrenpp_dep = declare_dependency(
|
||||
link_with: wrenpp,
|
||||
include_directories: public_incl,
|
||||
compile_args: compiler_opts,
|
||||
)
|
||||
|
||||
if get_option('build_examples')
|
||||
subdir('examples')
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace wren {
|
|||
ClassNameOwning::operator ModuleAndName() const {
|
||||
return ModuleAndName{
|
||||
this->raw_buffer(),
|
||||
0, //TODO: replace with hash
|
||||
this->module_name().size(),
|
||||
this->class_name().size()
|
||||
};
|
||||
|
@ -78,15 +79,6 @@ namespace wren {
|
|||
std::size_t ClassNameHash::operator()(TempClassName value) const {
|
||||
return value.module_hash() ^ (value.class_hash() << 1);
|
||||
}
|
||||
|
||||
std::size_t TypeIDHash::operator()(TypeID tid) const {
|
||||
if constexpr (sizeof(tid.id()) > sizeof(std::size_t)) {
|
||||
return std::hash<decltype(tid.id())>{}(tid.id());
|
||||
}
|
||||
else {
|
||||
return static_cast<std::size_t>(tid.id());
|
||||
}
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
ClassManager::ClassManager() = default;
|
||||
|
@ -126,15 +118,15 @@ namespace wren {
|
|||
return retval;
|
||||
}
|
||||
|
||||
void ClassManager::add_type (TypeID hash, const detail::ClassNameOwning* name) {
|
||||
void ClassManager::add_type (ClassManagerNameHashType hash, const detail::ClassNameOwning* name) {
|
||||
using detail::TempClassName;
|
||||
|
||||
assert(m_types.count(hash) == 0 or *m_types.at(hash) == *name);
|
||||
assert(m_types.count(hash) == 0 or m_types.at(hash) == name);
|
||||
//insert if not present, leave old value if hash is already there
|
||||
m_types.insert(std::make_pair(hash, name));
|
||||
}
|
||||
|
||||
ModuleAndName ClassManager::wren_class_name_from_hash(TypeID hash) const {
|
||||
ModuleAndName ClassManager::wren_class_name_from_hash(ClassManagerNameHashType hash) const {
|
||||
const auto it_found = m_types.find(hash);
|
||||
if (m_types.cend() != it_found) {
|
||||
const detail::ClassNameOwning* const name = it_found->second;
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wrenpp/detail/crc32.hpp"
|
||||
#include "crc32_config.h"
|
||||
|
||||
namespace wren::detail {
|
||||
#if HAVE_NEON
|
||||
[[gnu::const]] bool has_crc32_neon() noexcept;
|
||||
[[gnu::pure]] std::uint32_t crc32c_neon(const char*, std::size_t, std::uint32_t) noexcept;
|
||||
#endif
|
||||
#if HAVE_SSE42
|
||||
[[gnu::const]] bool has_crc32_sse42() noexcept;
|
||||
[[gnu::pure]] std::uint32_t crc32c_sse42(const char*, std::size_t, std::uint32_t) noexcept;
|
||||
#endif
|
||||
} //namespace wren::detail
|
||||
|
||||
namespace wren::detail {
|
||||
//Some useful polynomials:
|
||||
// zlib: 0x04C11DB7
|
||||
// castagnoli (intel): 0x1EDC6F41
|
||||
|
||||
namespace {
|
||||
[[gnu::const]]
|
||||
auto best_crc32_function() {
|
||||
#if HAVE_NEON
|
||||
if (has_crc32_neon())
|
||||
return &crc32c_neon;
|
||||
#endif
|
||||
|
||||
#if HAVE_SSE42
|
||||
if (has_crc32_sse42())
|
||||
return &crc32c_sse42;
|
||||
#endif
|
||||
|
||||
return &crc32<detail::g_castagnoli_polynomial>;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
[[gnu::const]]
|
||||
std::uint32_t runtime_crc32c (const char* data, std::size_t size, std::uint32_t crc) {
|
||||
static const auto crc32c_implem = best_crc32_function();
|
||||
return (*crc32c_implem)(data, size, crc);
|
||||
}
|
||||
} //namespace wren::detail
|
|
@ -1,104 +0,0 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <cstdint>
|
||||
|
||||
// Byte-boundary alignment issues
|
||||
#define CALC_CRC(op, crc, type, buf, len) \
|
||||
do { \
|
||||
for (; (len) >= sizeof (type); (len) -= sizeof(type), buf += sizeof (type)) { \
|
||||
(crc) = op((crc), *(type *) (buf)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
namespace wren::detail {
|
||||
//King_DuckZ - adapted from
|
||||
//https://github.com/rurban/smhasher/blob/master/sse2neon.h
|
||||
namespace {
|
||||
[[gnu::always_inline]] [[gnu::const]]
|
||||
inline std::uint32_t neon_crc32cb(std::uint32_t crc, std::uint8_t v) {
|
||||
__asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t"
|
||||
: [c] "+r"(crc)
|
||||
: [v] "r"(v));
|
||||
return crc;
|
||||
}
|
||||
|
||||
[[gnu::always_inline]] [[gnu::const]]
|
||||
inline std::uint32_t neon_crc32ch (std::uint32_t crc, std::uint16_t v) {
|
||||
__asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t"
|
||||
: [c] "+r"(crc)
|
||||
: [v] "r"(v));
|
||||
return crc;
|
||||
}
|
||||
|
||||
[[gnu::always_inline]] [[gnu::const]]
|
||||
inline std::uint32_t neon_crc32cw(std::uint32_t crc, std::uint32_t v) {
|
||||
__asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t"
|
||||
: [c] "+r"(crc)
|
||||
: [v] "r"(v));
|
||||
return crc;
|
||||
}
|
||||
|
||||
[[gnu::always_inline]] [[gnu::const]]
|
||||
inline std::uint64_t neon_crc32cx (std::uint64_t crc, std::uint64_t v) {
|
||||
__asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t"
|
||||
: [c] "+r"(crc)
|
||||
: [v] "r"(v));
|
||||
return crc;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
[[gnu::const]]
|
||||
bool has_crc32_neon() noexcept {
|
||||
//see
|
||||
//https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/runtime-detection-of-cpu-features-on-an-armv8-a-cpu
|
||||
const bool has_hw_crc32 = (getauxval(AT_HWCAP) & HWCAP_CRC32 ? true : false);
|
||||
return has_hw_crc32;
|
||||
}
|
||||
|
||||
/* Compute CRC-32C using the Intel hardware instruction. */
|
||||
/* for better parallelization with bigger buffers see
|
||||
http://www.drdobbs.com/parallel/fast-parallelized-crc-computation-using/229401411 */
|
||||
[[gnu::pure]]
|
||||
std::uint32_t crc32c_neon(const char* input, std::size_t len, std::uint32_t crc) noexcept {
|
||||
//see https://github.com/rurban/smhasher/blob/master/crc32_hw.c
|
||||
constexpr std::size_t align_size = alignof(std::uint64_t);
|
||||
constexpr std::size_t align_mask = align_size - 1;
|
||||
|
||||
// XOR the initial CRC with INT_MAX
|
||||
//crc ^= 0xFFFFFFFF;
|
||||
crc = ~crc;
|
||||
|
||||
// Align the input to the word boundary
|
||||
for (; (len > 0) && (reinterpret_cast<std::uintptr_t>(input) & align_mask); len--, input++) {
|
||||
crc = neon_crc32cb(crc, *input);
|
||||
}
|
||||
|
||||
// Blast off the CRC32 calculation
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
CALC_CRC(neon_crc32cx, crc, std::uint64_t, input, len);
|
||||
#endif
|
||||
CALC_CRC(neon_crc32cw, crc, std::uint32_t, input, len);
|
||||
CALC_CRC(neon_crc32ch, crc, std::uint16_t, input, len);
|
||||
CALC_CRC(neon_crc32cb, crc, std::uint8_t, input, len);
|
||||
|
||||
// Post-process the crc
|
||||
return ~crc;
|
||||
}
|
||||
} //namespace wren::detail
|
|
@ -1,66 +0,0 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <smmintrin.h>
|
||||
#include <immintrin.h>
|
||||
#include <cstdint>
|
||||
|
||||
// Byte-boundary alignment issues
|
||||
#define CALC_CRC(op, crc, type, buf, len) \
|
||||
do { \
|
||||
for (; (len) >= sizeof (type); (len) -= sizeof(type), buf += sizeof (type)) { \
|
||||
(crc) = op((crc), *(type *) (buf)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
namespace wren::detail {
|
||||
[[gnu::const]]
|
||||
bool has_crc32_sse42() noexcept {
|
||||
const bool has_hw_crc32 = (__builtin_cpu_supports("sse4.2") ? true : false);
|
||||
return has_hw_crc32;
|
||||
}
|
||||
|
||||
/* Compute CRC-32C using the Intel hardware instruction. */
|
||||
/* for better parallelization with bigger buffers see
|
||||
http://www.drdobbs.com/parallel/fast-parallelized-crc-computation-using/229401411 */
|
||||
[[gnu::pure]]
|
||||
std::uint32_t crc32c_sse42(const char* input, std::size_t len, std::uint32_t crc) noexcept {
|
||||
//see https://github.com/rurban/smhasher/blob/master/crc32_hw.c
|
||||
constexpr std::size_t align_size = alignof(std::uint64_t);
|
||||
constexpr std::size_t align_mask = align_size - 1;
|
||||
|
||||
// XOR the initial CRC with INT_MAX
|
||||
//crc ^= 0xFFFFFFFF;
|
||||
crc = ~crc;
|
||||
|
||||
// Align the input to the word boundary
|
||||
for (; (len > 0) && (reinterpret_cast<std::uintptr_t>(input) & align_mask); len--, input++) {
|
||||
crc = _mm_crc32_u8(crc, *input);
|
||||
}
|
||||
|
||||
// Blast off the CRC32 calculation
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
CALC_CRC(_mm_crc32_u64, crc, std::uint64_t, input, len);
|
||||
#endif
|
||||
CALC_CRC(_mm_crc32_u32, crc, std::uint32_t, input, len);
|
||||
CALC_CRC(_mm_crc32_u16, crc, std::uint16_t, input, len);
|
||||
CALC_CRC(_mm_crc32_u8, crc, std::uint8_t, input, len);
|
||||
|
||||
// Post-process the crc
|
||||
return ~crc;
|
||||
}
|
||||
} //namespace wren::detail
|
|
@ -1,40 +0,0 @@
|
|||
simd = import('unstable-simd')
|
||||
|
||||
compiler_opts = []
|
||||
if arch == 'amd64'
|
||||
compiler_opts += ['-msse4.2']
|
||||
elif arch == 'aarch64'
|
||||
#gcc options here:
|
||||
#https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/AArch64-Options.html
|
||||
compiler_opts += ['-mcpu=generic+crc']
|
||||
endif
|
||||
|
||||
cpp = meson.get_compiler('cpp')
|
||||
crc32_simd = simd.check('crc32_hw',
|
||||
sse42: 'crc32_sse42.cpp',
|
||||
neon: 'crc32_neon.cpp',
|
||||
compiler: cpp,
|
||||
cpp_args: compiler_opts,
|
||||
)
|
||||
|
||||
crc32_objs = crc32_simd[0]
|
||||
crc32_config = crc32_simd[1]
|
||||
|
||||
project_config_file = configure_file(
|
||||
output: 'crc32_config.h',
|
||||
configuration: crc32_config
|
||||
)
|
||||
|
||||
crc32 = static_library('crc32',
|
||||
'crc32.cpp',
|
||||
include_directories: [public_incl],
|
||||
install: false,
|
||||
cpp_args: global_compiler_opts,
|
||||
link_with: crc32_objs,
|
||||
)
|
||||
|
||||
crc32_dep = declare_dependency(
|
||||
include_directories: public_incl,
|
||||
link_with: crc32,
|
||||
compile_args: global_compiler_opts,
|
||||
)
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
.global g_dynafunc
|
||||
.global g_dynafunc_end
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
.text
|
||||
|
||||
g_dynafunc:
|
||||
ldr x0, .+20
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
.global g_dynafunc
|
||||
.global g_dynafunc_end
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
.text
|
||||
|
||||
g_dynafunc:
|
||||
//VM pointer, parameter 1
|
||||
|
|
|
@ -111,14 +111,15 @@ namespace wren {
|
|||
);
|
||||
|
||||
const CharVec* source_mem;
|
||||
if (dst.cend() != it_found && std::equal(it_found->cbegin(), it_found->cend(), new_entry.cbegin(), new_entry.cend())) {
|
||||
if (dst.cend() != it_found) {
|
||||
assert(std::equal(it_found->cbegin(), it_found->cend(), new_entry.cbegin(), new_entry.cend()));
|
||||
source_mem = &*it_found;
|
||||
}
|
||||
else {
|
||||
source_mem = &*dst.insert(it_found, std::move(new_entry));
|
||||
}
|
||||
|
||||
return {source_mem->data(), mod_name.size(), cls_name.size()};
|
||||
return {source_mem->data(), 0, mod_name.size(), cls_name.size()};
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
|
@ -18,25 +18,14 @@
|
|||
#include "wrenpp/handle.hpp"
|
||||
#include "wrenpp/vm.hpp"
|
||||
#include <cassert>
|
||||
#include <ciso646>
|
||||
|
||||
namespace wren {
|
||||
Handle::Handle (VM* vm, int slot_num) :
|
||||
Handle(vm->slot_handle(slot_num))
|
||||
{
|
||||
}
|
||||
|
||||
Handle::~Handle() noexcept {
|
||||
release();
|
||||
}
|
||||
|
||||
void Handle::release() noexcept {
|
||||
assert(m_vm or not m_handle);
|
||||
if (m_vm)
|
||||
m_vm->release_handle(*this);
|
||||
}
|
||||
|
||||
void Handle::set_to_slot (int slot) {
|
||||
m_vm->set_slot_handle(*this, slot);
|
||||
assert(m_vm);
|
||||
m_vm->release_handle(*this);
|
||||
}
|
||||
} //namespace wren
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
subdir('crc32')
|
||||
|
||||
project_config_file = configure_file(
|
||||
input: 'pvt_config.h.in',
|
||||
output: 'pvt_config.h',
|
||||
configuration: conf
|
||||
)
|
||||
|
||||
wrenpp = library(meson.project_name(),
|
||||
project_config_file,
|
||||
'vm.cpp',
|
||||
'configuration.cpp',
|
||||
'def_configuration.cpp',
|
||||
'dynafunc_maker.cpp',
|
||||
'dynafunc_' + arch + '_' + os + '.S',
|
||||
'handle.cpp',
|
||||
'vm_fun.cpp',
|
||||
'callback_manager.cpp',
|
||||
'class_manager.cpp',
|
||||
'wren_class_name_from_type.cpp',
|
||||
'module_and_name.cpp',
|
||||
'setters_getters.cpp',
|
||||
dependencies: [wren_dep, crc32_dep],
|
||||
include_directories: public_incl,
|
||||
install: (not meson.is_subproject() or get_option('default_library')=='shared'),
|
||||
c_args: global_compiler_opts,
|
||||
cpp_args: global_compiler_opts,
|
||||
)
|
||||
|
||||
wrenpp_dep = declare_dependency(
|
||||
link_with: wrenpp,
|
||||
include_directories: public_incl,
|
||||
compile_args: global_compiler_opts,
|
||||
)
|
||||
|
||||
meson.override_dependency(meson.project_name(), wrenpp_dep)
|
|
@ -1,30 +0,0 @@
|
|||
/* Copyright 2020-2022, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wrenpp/detail/module_and_name.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace wren::detail {
|
||||
bool deep_equal(const ModuleAndName& a, const ModuleAndName& b) noexcept {
|
||||
const auto a_size = a.raw_buffer_size();
|
||||
const auto b_size = b.raw_buffer_size();
|
||||
if (a_size != b_size)
|
||||
return false;
|
||||
|
||||
return std::equal(a.m_base, a.m_base + a_size, b.m_base);
|
||||
}
|
||||
} //namespace wren::detail
|
|
@ -1,21 +0,0 @@
|
|||
/* Copyright 2020-2024, Michele Santullo
|
||||
* This file is part of wrenpp.
|
||||
*
|
||||
* Wrenpp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Wrenpp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wrenpp/detail/setters_getters.hpp"
|
||||
|
||||
namespace wren {
|
||||
} //namespace wren
|
13
src/vm.cpp
13
src/vm.cpp
|
@ -162,8 +162,7 @@ namespace wren {
|
|||
struct VM::LocalData {
|
||||
explicit LocalData (const detail::Callbacks& cb) :
|
||||
callbacks(cb),
|
||||
wvm(nullptr),
|
||||
user_data_type(type_id<std::nullptr_t>())
|
||||
wvm(nullptr)
|
||||
{
|
||||
callbacks.dynafunc = &dynafunc;
|
||||
}
|
||||
|
@ -181,10 +180,10 @@ namespace wren {
|
|||
DynafuncMaker dynafunc;
|
||||
WrenVM* wvm;
|
||||
void* user_data;
|
||||
TypeID user_data_type;
|
||||
std::uint32_t user_data_type;
|
||||
};
|
||||
|
||||
VM::VM (Configuration* conf, const detail::Callbacks& cb, void* user_data, TypeID user_data_type) :
|
||||
VM::VM (Configuration* conf, const detail::Callbacks& cb, void* user_data, std::uint32_t user_data_type) :
|
||||
m_local(std::make_unique<LocalData>(cb))
|
||||
{
|
||||
this->reset(conf);
|
||||
|
@ -198,7 +197,7 @@ namespace wren {
|
|||
return &m_local->dynafunc;
|
||||
}
|
||||
|
||||
TypeID VM::user_data_type() const {
|
||||
std::uint32_t VM::user_data_type() const {
|
||||
return m_local->user_data_type;
|
||||
}
|
||||
|
||||
|
@ -206,7 +205,7 @@ namespace wren {
|
|||
return m_local->user_data;
|
||||
}
|
||||
|
||||
void VM::set_user_data (void* user_data, TypeID user_data_type) {
|
||||
void VM::set_user_data (void* user_data, std::uint32_t user_data_type) {
|
||||
m_local->user_data = user_data;
|
||||
m_local->user_data_type = user_data_type;
|
||||
}
|
||||
|
@ -282,7 +281,7 @@ namespace wren {
|
|||
|
||||
void VM::set_user_data (std::nullptr_t) {
|
||||
m_local->user_data = nullptr;
|
||||
m_local->user_data_type = type_id<std::nullptr_t>();
|
||||
m_local->user_data_type = detail::type_id<std::nullptr_t>();
|
||||
}
|
||||
|
||||
bool VM::has_user_data() const noexcept {
|
||||
|
|
|
@ -89,9 +89,4 @@ namespace wren {
|
|||
vm.ensure_slots(1);
|
||||
variable(vm, handle, slot);
|
||||
}
|
||||
|
||||
void abort_fiber_with_error (VM& vm, int slot, std::string_view message) {
|
||||
set(vm, slot, message);
|
||||
vm.abort_fiber(slot);
|
||||
}
|
||||
} //namespace wren
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace wren {
|
|||
namespace detail {
|
||||
ModuleAndName fetch_class_name_from_manager (
|
||||
const VM& vm,
|
||||
TypeID hash
|
||||
ClassManagerNameHashType hash
|
||||
) {
|
||||
return vm.class_manager().wren_class_name_from_hash(hash);
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/wren-lang/wren.git
|
||||
revision = 4a18fc489f9ea3d253b20dd40f4cdad0d6bb40eb
|
||||
patch_directory = wren
|
||||
|
||||
[provide]
|
||||
dependency_names = wren-0.4.0
|
||||
wren = wren_dep
|
|
@ -17,27 +17,27 @@ else
|
|||
c_opts += '-DWREN_OPT_META=0'
|
||||
endif
|
||||
|
||||
wren_incl = include_directories('src/include', is_system: true)
|
||||
wren_pvt_incl = include_directories('src/vm', 'src/optional')
|
||||
test_incl = include_directories('test')
|
||||
wren_incl = include_directories('wren/src/include', is_system: true)
|
||||
wren_pvt_incl = include_directories('wren/src/vm', 'wren/src/optional')
|
||||
test_incl = include_directories('wren/test')
|
||||
|
||||
threads_dep = dependency('threads')
|
||||
libuv_dep = c_compiler.find_library('uv', required: true)
|
||||
libuv_dep = c_compiler.find_library('libuv', required: true)
|
||||
m_dep = c_compiler.find_library('m', required: true)
|
||||
|
||||
opt_src = [
|
||||
'src/optional/wren_opt_random.c',
|
||||
'src/optional/wren_opt_meta.c',
|
||||
'wren/src/optional/wren_opt_random.c',
|
||||
'wren/src/optional/wren_opt_meta.c',
|
||||
]
|
||||
|
||||
vm_src = [
|
||||
'src/vm/wren_compiler.c',
|
||||
'src/vm/wren_core.c',
|
||||
'src/vm/wren_debug.c',
|
||||
'src/vm/wren_primitive.c',
|
||||
'src/vm/wren_utils.c',
|
||||
'src/vm/wren_value.c',
|
||||
'src/vm/wren_vm.c',
|
||||
'wren/src/vm/wren_compiler.c',
|
||||
'wren/src/vm/wren_core.c',
|
||||
'wren/src/vm/wren_debug.c',
|
||||
'wren/src/vm/wren_primitive.c',
|
||||
'wren/src/vm/wren_utils.c',
|
||||
'wren/src/vm/wren_value.c',
|
||||
'wren/src/vm/wren_vm.c',
|
||||
]
|
||||
|
||||
force_static = meson.is_subproject()
|
||||
|
@ -69,25 +69,24 @@ if get_option('build_testing')
|
|||
fs = import('fs')
|
||||
|
||||
test_src = [
|
||||
'test/api/api_tests.c',
|
||||
'test/api/benchmark.c',
|
||||
'test/api/call.c',
|
||||
'test/api/call_calls_foreign.c',
|
||||
'test/api/call_wren_call_root.c',
|
||||
'test/api/error.c',
|
||||
'test/api/foreign_class.c',
|
||||
'test/api/get_variable.c',
|
||||
'test/api/handle.c',
|
||||
'test/api/lists.c',
|
||||
'test/api/maps.c',
|
||||
'test/api/new_vm.c',
|
||||
'test/api/reset_stack_after_call_abort.c',
|
||||
'test/api/reset_stack_after_foreign_construct.c',
|
||||
'test/api/resolution.c',
|
||||
'test/api/slots.c',
|
||||
'test/api/user_data.c',
|
||||
'test/main.c',
|
||||
'test/test.c',
|
||||
'wren/test/api/api_tests.c',
|
||||
'wren/test/api/benchmark.c',
|
||||
'wren/test/api/call.c',
|
||||
'wren/test/api/call_calls_foreign.c',
|
||||
'wren/test/api/call_wren_call_root.c',
|
||||
'wren/test/api/error.c',
|
||||
'wren/test/api/foreign_class.c',
|
||||
'wren/test/api/get_variable.c',
|
||||
'wren/test/api/handle.c',
|
||||
'wren/test/api/lists.c',
|
||||
'wren/test/api/new_vm.c',
|
||||
'wren/test/api/reset_stack_after_call_abort.c',
|
||||
'wren/test/api/reset_stack_after_foreign_construct.c',
|
||||
'wren/test/api/resolution.c',
|
||||
'wren/test/api/slots.c',
|
||||
'wren/test/api/user_data.c',
|
||||
'wren/test/main.c',
|
||||
'wren/test/test.c',
|
||||
]
|
||||
|
||||
test_script_paths = [
|
||||
|
@ -104,7 +103,7 @@ if get_option('build_testing')
|
|||
|
||||
test_scripts = run_command(
|
||||
files('find_scripts.py'),
|
||||
meson.current_source_dir() / 'test',
|
||||
meson.current_source_dir() / 'wren/test',
|
||||
test_script_paths,
|
||||
).stdout().strip().split('\n')
|
||||
|
||||
|
@ -136,7 +135,7 @@ endif
|
|||
|
||||
if not force_static
|
||||
install_headers(
|
||||
'src/include/wren.h',
|
||||
'src/include/wren.hpp',
|
||||
'wren/src/include/wren.h',
|
||||
'wren/src/include/wren.hpp',
|
||||
)
|
||||
endif
|
1
subprojects/wren/wren
Submodule
1
subprojects/wren/wren
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 4ffe2ed38b238ff410e70654cbe38883f7533d3f
|
Loading…
Reference in a new issue