Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-format-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
inkcpp_compiler/json.hpp
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,20 @@ jobs:
working-directory: ${{github.workspace}}/build
shell: bash
run: |
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.7" -DINKCPP_UNREAL=ON
cmake --install . --config $BUILD_TYPE --prefix comp_unreal_5_7 --component unreal
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.6" -DINKCPP_UNREAL=ON
cmake --install . --config $BUILD_TYPE --prefix comp_unreal_5_6 --component unreal
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.5" -DINKCPP_UNREAL=ON
cmake --install . --config $BUILD_TYPE --prefix comp_unreal_5_5 --component unreal
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.4" -DINKCPP_UNREAL=ON
cmake --install . --config $BUILD_TYPE --prefix comp_unreal_5_4 --component unreal
- name: Upload UE 5.7
if: ${{ matrix.unreal }}
uses: actions/upload-artifact@v4
with:
name: unreal_5_7
path: build/comp_unreal_5_7/
- name: Upload UE 5.6
if: ${{ matrix.unreal }}
uses: actions/upload-artifact@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ jobs:
run: |
mkdir artifacts
ID=$(gh run list -b master --limit 1 --json databaseId | jq '.[0].databaseId')
gh run download $ID -D artifacts -n linux-cl -n linux-lib -n linux-clib -n unreal_5_6 -n unreal_5_5 -n unreal_5_4 -n macos-cl -n macos-lib -n macos-clib -n macos-arm-cl -n macos-arm-lib -n macos-arm-clib -n win64-cl -n win64-lib -n win64-clib -n python-package-distribution
gh run download $ID -D artifacts -n linux-cl -n linux-lib -n linux-clib -n unreal_5_7 -n unreal_5_6 -n unreal_5_5 -n unreal_5_4 -n macos-cl -n macos-lib -n macos-clib -n macos-arm-cl -n macos-arm-lib -n macos-arm-clib -n win64-cl -n win64-lib -n win64-clib -n python-package-distribution
mv artifacts/python-package-distribution dist
- name: Zip
working-directory: ${{github.workspace}}/artifacts
run: |
for f in linux-cl linux-lib linux-clib unreal_5_6 unreal_5_5 unreal_5_4 macos-cl macos-lib macos-clib macos-arm-cl macos-arm-lib macos-arm-clib win64-cl win64-lib win64-clib; do zip -r ../$f.zip $f; done
for f in linux-cl linux-lib linux-clib unreal_5_7 unreal_5_6 unreal_5_5 unreal_5_4 macos-cl macos-lib macos-clib macos-arm-cl macos-arm-lib macos-arm-clib win64-cl win64-lib win64-clib; do zip -r ../$f.zip $f; done
- name: List
run: tree
- name: Publish to PyPI
Expand All @@ -45,5 +45,5 @@ jobs:
--repo="$GITHUB_REPOSITORY" \
--title="${GITHUB_REPOSITORY#*/} ${tag#v}" \
--generate-notes \
"$tag" "linux-cl.zip" "linux-lib.zip" "linux-clib.zip" "unreal_5_6.zip" "unreal_5_5.zip" "unreal_5_4.zip" "macos-cl.zip" "macos-lib.zip" "macos-clib.zip" "win64-cl.zip" "macos-arm-cl.zip" "macos-arm-lib.zip" "macos-arm-clib.zip" "win64-lib.zip" "win64-clib.zip"
"$tag" "linux-cl.zip" "linux-lib.zip" "linux-clib.zip" "unreal_5_7.zip" "unreal_5_6.zip" "unreal_5_5.zip" "unreal_5_4.zip" "macos-cl.zip" "macos-lib.zip" "macos-clib.zip" "win64-cl.zip" "macos-arm-cl.zip" "macos-arm-lib.zip" "macos-arm-clib.zip" "win64-lib.zip" "win64-clib.zip"

3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v18.1.0
rev: v18.1.8
hooks:
- id: clang-format
types_or: [c++, c, cuda]
exclude: inkcpp_compiler/json.hpp

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
Expand Down
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_INSTALL_LIBRARY_DIR lib)
SET(CMAKE_INSTALL_INCLUDE_DIR include)

if (MSVC)
# disable:
# aligment problems
# non explicit switch case
add_compile_options(/W4 /wd4820 /wd4061)
else()
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# Add subdirectories
include(CMakeDependentOption)
option(INKCPP_PY "Build python bindings" OFF)
Expand Down
3 changes: 2 additions & 1 deletion Documentation/cmake_example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <ink/story.h>
#include <ink/compiler.h>

#include <memory.h>
#include <iostream>

using namespace ink::runtime;
Expand All @@ -14,7 +15,7 @@ int main()
{
ink::compiler::run("test.ink.json", "test.bin");
// Load ink binary story, generated from the inkCPP compiler
story* myInk = story::from_file("test.bin");
std::unique_ptr<story> myInk{story::from_file("test.bin")};

// Create a new thread
runner thread = myInk->new_runner();
Expand Down
Binary file modified Documentation/unreal/InkCPP_DEMO.zip
Binary file not shown.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Alternativly is the latest version of the UE plugin can be downloaded from the [
Place the content of this file at your plugin folder of your UE project and at the next start up it will be intigrated.


A example project can be found [here](https://jbenda.github.io/inkcpp/unreal/InkCPP_DEMO.zip). And here the [Documentation](https://jbenda.github.io/inkcpp/html/group__unreal.html).
A example project can be found [here](https://jbenda.github.io/inkcpp/unreal/InkCPP_DEMO.zip). And here the [Documentation](https://jbenda.github.io/inkcpp/html/group__unreal.html).

Code for the Unreal plugin is located in the `unreal` directory. In order to install it, run
```sh
Expand Down Expand Up @@ -104,6 +104,7 @@ Instructions:
#include <ink/story.h>
#include <ink/runner.h>
#include <ink/choice.h>
#include <memory.h>

using namespace ink::runtime;

Expand All @@ -112,7 +113,7 @@ int MyInkFunction(int a, int b) { return a + b; }
...

// Load ink binary story, generated from the inkCPP compiler
story* myInk = story::from_file("test.bin");
std::unique_ptr<story> myInk{story::from_file("test.bin")};

// Create a new thread
runner thread = myInk->new_runner();
Expand Down Expand Up @@ -208,6 +209,6 @@ The python bindnigs are defined in `inkcpp_python` subfolder.
## Dependencies
The compiler depends on Nlohmann's JSON library and the C++ STL.

The runtime does not depend on either. If `INK_ENABLE_STL` is defined then STL extensions are added such as stream operators and `std::string` support. If `INK_ENABLE_UNREAL`, then FStrings, Delegates and other Unreal classes will be supported.
The runtime does not depend on either. If `INK_ENABLE_STL` is defined then STL extensions are added such as stream operators and `std::string` support. If `INK_ENABLE_UNREAL`, then FStrings, Delegates and other Unreal classes will be supported.

NOTE: There is still some lingering C standard library calls in the runtime. I will be guarding them with an `INK_ENABLE_CSTD` or something soon.
83 changes: 58 additions & 25 deletions inkcpp/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,29 @@

namespace ink::runtime::internal
{
template<typename T, bool dynamic, size_t initialCapacity>
/** Managed array of objects.
*
* @tparam simple if the object has a trivial destructor, so delete[](char*) can be used instead of
* calling the constructor.
* @tparam dynamic if the memory should be allocated on the heap and grow if needed
* @tparam initialCapacitiy number of elements to allocate at construction, if !dynamic, this is
* allocated in place and can not be changed.
*/
template<typename T, bool dynamic, size_t initialCapacity, bool simple>
class managed_array : public snapshot_interface
{
public:
managed_array()
: _static_data{}
, _capacity{initialCapacity}
: _capacity{initialCapacity}
, _size{0}
, _static_data{}
{
if constexpr (dynamic) {
_dynamic_data = new T[initialCapacity];
if constexpr (simple) {
_dynamic_data = reinterpret_cast<T*>(new char[sizeof(T) * initialCapacity]);
} else {
_dynamic_data = new T[initialCapacity];
}
}
}

Expand All @@ -37,13 +49,25 @@ class managed_array : public snapshot_interface
virtual ~managed_array()
{
if constexpr (dynamic) {
delete[] _dynamic_data;
if constexpr (simple) {
delete[] reinterpret_cast<char*>(_dynamic_data);
} else {
delete[] _dynamic_data;
}
}
}

const T& operator[](size_t i) const { return data()[i]; }
const T& operator[](size_t i) const
{
inkAssert(i < _size, "Access array out of bounds, index %u in array of size %u", i, _size);
return data()[i];
}

T& operator[](size_t i) { return data()[i]; }
T& operator[](size_t i)
{
inkAssert(i < _size, "Access array out of bounds, index %u in array of size %u", i, _size);
return data()[i];
}

const T* data() const
{
Expand Down Expand Up @@ -75,9 +99,9 @@ class managed_array : public snapshot_interface

T& back() { return end()[-1]; }

const size_t size() const { return _size; }
size_t size() const { return _size; }

const size_t capacity() const { return _capacity; }
size_t capacity() const { return _capacity; }

T& push()
{
Expand Down Expand Up @@ -146,7 +170,7 @@ class managed_array : public snapshot_interface
ptr = snap_write(ptr, e, should_write);
}
}
return ptr - data;
return static_cast<size_t>(ptr - data);
}

const unsigned char* snap_load(const unsigned char* ptr, const loader& loader)
Expand All @@ -170,10 +194,10 @@ class managed_array : public snapshot_interface
}

private:
if_t<dynamic, char, T> _static_data[dynamic ? 1 : initialCapacity];
T* _dynamic_data = nullptr;
size_t _capacity;
size_t _size;
if_t<dynamic, char, T> _static_data[dynamic ? 1 : initialCapacity];
};

template<typename T, bool dynamic, size_t initialCapacity>
Expand Down Expand Up @@ -219,7 +243,7 @@ class managed_restorable_array : public managed_array<T, dynamic, initialCapacit
bool should_write = data != nullptr;
ptr += base::snap(ptr, snapper);
ptr = base::snap_write(ptr, _last_size, should_write);
return ptr - data;
return static_cast<size_t>(ptr - data);
}

const unsigned char* snap_load(const unsigned char* ptr, const snapshot_interface::loader& loader)
Expand All @@ -233,21 +257,30 @@ class managed_restorable_array : public managed_array<T, dynamic, initialCapacit
size_t _last_size = 0;
};

template<typename T, bool dynamic, size_t initialCapacity>
void managed_array<T, dynamic, initialCapacity>::extend(size_t capacity)
template<typename T, bool dynamic, size_t initialCapacity, bool simple>
void managed_array<T, dynamic, initialCapacity, simple>::extend(size_t capacity)
{
static_assert(dynamic, "Can only extend if array is dynamic!");
size_t new_capacity = capacity > _capacity ? capacity : 1.5f * _capacity;
size_t new_capacity = capacity > _capacity ? capacity : _capacity + _capacity / 2U;
if (new_capacity < 5) {
new_capacity = 5;
}
T* new_data = new T[new_capacity];
T* new_data = nullptr;
if constexpr (simple) {
new_data = reinterpret_cast<T*>(new char[sizeof(T) * new_capacity]);
} else {
new_data = new T[new_capacity];
}

for (size_t i = 0; i < _capacity; ++i) {
new_data[i] = _dynamic_data[i];
}

delete[] _dynamic_data;
if constexpr (simple) {
delete[] reinterpret_cast<char*>(_dynamic_data);
} else {
delete[] _dynamic_data;
}
_dynamic_data = new_data;
_capacity = new_capacity;
}
Expand Down Expand Up @@ -459,15 +492,15 @@ class allocated_restorable_array final : public basic_restorable_array<T>
T* new_buffer = new T[new_capacity];
if (_buffer) {
for (size_t i = 0; i < base::capacity(); ++i) {
new_buffer[i] = _buffer[i];
new_buffer[i] = _buffer[i];
// copy temp
new_buffer[i + base::capacity()] = _buffer[i + base::capacity()];
new_buffer[i + n] = _buffer[i + base::capacity()];
}
delete[] _buffer;
}
for (size_t i = base::capacity(); i < new_capacity / 2; ++i) {
new_buffer[i] = _initialValue;
new_buffer[i + base::capacity()] = _nullValue;
for (size_t i = base::capacity(); i < n; ++i) {
new_buffer[i] = _initialValue;
new_buffer[i + n] = _nullValue;
}

_buffer = new_buffer;
Expand All @@ -489,7 +522,7 @@ class allocated_restorable_array final : public basic_restorable_array<T>
};

template<typename T>
inline size_t basic_restorable_array<T>::snap(unsigned char* data, const snapper& snapper) const
inline size_t basic_restorable_array<T>::snap(unsigned char* data, const snapper&) const
{
unsigned char* ptr = data;
bool should_write = data != nullptr;
Expand All @@ -500,12 +533,12 @@ inline size_t basic_restorable_array<T>::snap(unsigned char* data, const snapper
ptr = snap_write(ptr, _array[i], should_write);
ptr = snap_write(ptr, _temp[i], should_write);
}
return ptr - data;
return static_cast<size_t>(ptr - data);
}

template<typename T>
inline const unsigned char*
basic_restorable_array<T>::snap_load(const unsigned char* data, const loader& loader)
basic_restorable_array<T>::snap_load(const unsigned char* data, const loader&)
{
auto ptr = data;
ptr = snap_read(ptr, _saved);
Expand Down
17 changes: 12 additions & 5 deletions inkcpp/avl_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@

#include "system.h"

#include <cstdint>

/**
* \param Key The key type. The type (class) must provide a 'less than' and 'equal to' operator
* \param T The Data type
Expand All @@ -72,7 +70,7 @@ class avl_array
ink::runtime::internal::if_t<dynamic, std::int8_t*, std::int8_t[Size]> balance_;
ink::runtime::internal::if_t<dynamic, child_type*, child_type[Size]> child_;
size_type size_; // actual size
size_t _capacity;
size_type _capacity;
size_type root_; // root node
ink::runtime::internal::if_t<dynamic, size_type*, size_type[Fast ? Size : 1]> parent_;

Expand Down Expand Up @@ -114,6 +112,12 @@ class avl_array
return *this;
}

tag_avl_array_iterator(const tag_avl_array_iterator& other)
: instance_{other.instance_}
, idx_{other.idx_}
{
}

inline bool operator==(const tag_avl_array_iterator& rhs) const { return idx_ == rhs.idx_; }

inline bool operator!=(const tag_avl_array_iterator& rhs) const { return ! (*this == rhs); }
Expand All @@ -130,7 +134,7 @@ class avl_array
// returns unique number for each entry
// the numbers are unique as long no operation are executed
// on the avl
inline size_t temp_identifier() const { return instance_->size() - idx_ - 1; }
inline size_type temp_identifier() const { return instance_->size() - idx_ - 1; }

// preincrement
tag_avl_array_iterator& operator++()
Expand Down Expand Up @@ -208,6 +212,9 @@ class avl_array
delete[] val_;
delete[] balance_;
delete[] child_;
if (parent_) {
delete[] parent_;
}
}
}

Expand Down Expand Up @@ -257,7 +264,7 @@ class avl_array

void extend()
{
size_t new_size = _capacity * 1.5;
size_type new_size = _capacity + _capacity / 2;
if (new_size < 5) {
new_size = 5;
}
Expand Down
5 changes: 4 additions & 1 deletion inkcpp/choice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ namespace ink
namespace runtime
{

size_t choice::num_tags() const { return std::distance(_tags_start, _tags_end); }
size_t choice::num_tags() const
{
return static_cast<size_t>(std::distance(_tags_start, _tags_end));
}

const char* choice::get_tag(size_t index) const
{
Expand Down
Loading