Skip to content
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@ The big things we're missing right now are:

* Fallback functions for externals.
* Variable observers
* Lists and whatever cool, crazy stuff Ink has been adding recently.
* Robust tests using ink-proof.

## Dependencies
The compiler depends on Nlohmann's JSON library and the C++ STL.
Expand Down
1 change: 1 addition & 0 deletions inkcpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ list(APPEND SOURCES
runner_impl.h runner_impl.cpp
simple_restorable_stack.h stack.h stack.cpp
story_impl.h story_impl.cpp
snapshot_impl.h snapshot_impl.cpp snapshot_interface.h
story_ptr.cpp
system.cpp
value.h value.cpp
Expand Down
81 changes: 75 additions & 6 deletions inkcpp/array.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#pragma once

#include "system.h"
#include "traits.h"
#include "snapshot_interface.h"

namespace ink::runtime::internal
{
template<typename T, bool dynamic, size_t initialCapacity>
class managed_array {
class managed_array : snapshot_interface {
public:
managed_array() : _capacity{initialCapacity}, _size{0}{
if constexpr (dynamic) {
Expand Down Expand Up @@ -48,11 +50,42 @@ namespace ink::runtime::internal
}
void clear() { _size = 0; }
void resize(size_t size) {
ink_assert(size <= _size, "Only allow to reduce size");
if constexpr (dynamic) {
if (size > _capacity) {
extend(size);
}
} else {
ink_assert(size <= _size, "Only allow to reduce size");
}
_size = size;
}

void extend();
void extend(size_t capacity = 0);

size_t snap(unsigned char* data, const snapper&) const override
{
inkAssert(!is_pointer<T>{}(), "here is a special case oversight");
unsigned char* ptr = data;
ptr = snap_write(ptr, _size, data);
for(const T& e : *this) {
ptr = snap_write(ptr, e, data);
}
return ptr - data;
}
const unsigned char* snap_load(const unsigned char* ptr, const loader&) override
{
decltype(_size) size;
ptr = snap_read(ptr, size);
if constexpr (dynamic) {
resize(size);
} else {
inkAssert(size <= initialCapacity, "capacity of non dynamic array is to small vor snapshot!");
}
for (T& e : *this) {
ptr = snap_read(ptr, e);
}
return ptr;
}
private:

if_t<dynamic, char, T> _static_data[dynamic ? 1 : initialCapacity];
Expand All @@ -62,10 +95,12 @@ namespace ink::runtime::internal
};

template<typename T, bool dynamic, size_t initialCapacity>
void managed_array<T, dynamic, initialCapacity>::extend()
void managed_array<T, dynamic, initialCapacity>::extend(size_t capacity)
{
static_assert(dynamic, "Can only extend if array is dynamic!");
size_t new_capacity = 1.5f * _capacity;
size_t new_capacity = capacity > _capacity
? capacity
: 1.5f * _capacity;
if (new_capacity < 5) { new_capacity = 5; }
T* new_data = new T[new_capacity];

Expand All @@ -79,7 +114,7 @@ namespace ink::runtime::internal
}

template<typename T>
class basic_restorable_array
class basic_restorable_array : public snapshot_interface
{
public:
basic_restorable_array(T* array, size_t capacity, T nullValue)
Expand Down Expand Up @@ -116,6 +151,10 @@ namespace ink::runtime::internal
// Resets all values and clears any save points
void clear(const T& value);

// snapshot interface
virtual size_t snap(unsigned char* data, const snapper&) const override;
virtual const unsigned char* snap_load(const unsigned char* data, const loader&) override;

protected:
inline T* buffer() { return _array; }
void set_new_buffer(T* buffer, size_t capacity) {
Expand Down Expand Up @@ -144,6 +183,36 @@ namespace ink::runtime::internal
const T _null;
};

template<typename T>
inline size_t basic_restorable_array<T>::snap(unsigned char* data, const snapper& snapper) const
{
unsigned char* ptr = data;
ptr = snap_write(ptr, _saved, data);
ptr = snap_write(ptr, _capacity, data);
ptr = snap_write(ptr, _null, data);
for(size_t i = 0; i < _capacity; ++i) {
ptr = snap_write(ptr, _array[i], data);
ptr = snap_write(ptr, _temp[i], data);
}
return ptr - data;
}

template<typename T>
inline const unsigned char* basic_restorable_array<T>::snap_load(const unsigned char* data, const loader& loader)
{
auto ptr = data;
ptr = snap_read(ptr, _saved);
ptr = snap_read(ptr, _capacity);
T null;
ptr = snap_read(ptr, null);
inkAssert(null == _null, "null value is different to snapshot!");
for(size_t i = 0; i < _capacity; ++i) {
ptr = snap_read(ptr, _array[i]);
ptr = snap_read(ptr, _temp[i]);
}
return ptr;
}

template<typename T>
inline void basic_restorable_array<T>::set(size_t index, const T& value)
{
Expand Down
50 changes: 42 additions & 8 deletions inkcpp/avl_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#ifndef _AVL_ARRAY_H_
#define _AVL_ARRAY_H_

#include "system.h"

#include <cstdint>


Expand Down Expand Up @@ -73,20 +75,31 @@ class avl_array
static const size_type INVALID_IDX = Size;

// iterator class
typedef class tag_avl_array_iterator
template<bool Const>
class tag_avl_array_iterator
{
avl_array* instance_; // array instance
template<bool Con, typename T1, typename T2>
using if_t = ink::runtime::internal::if_t<Con, T1, T2>;
if_t<Const, const avl_array*, avl_array*>
instance_; // array instance
size_type idx_; // actual node

friend avl_array; // avl_array may access index pointer

public:

// ctor
tag_avl_array_iterator(avl_array* instance = nullptr, size_type idx = 0U)
tag_avl_array_iterator(if_t<Const, const avl_array*,avl_array*> instance = nullptr, size_type idx = 0U)
: instance_(instance)
, idx_(idx)
{ }

template<bool C = Const, typename = ink::runtime::internal::enable_if_t<C>>
tag_avl_array_iterator(const tag_avl_array_iterator<false>& itr)
: instance_(itr.instance_)
, idx_(itr.idx_)
{}

inline tag_avl_array_iterator& operator=(const tag_avl_array_iterator& other)
{
instance_ = other.instance_;
Expand All @@ -101,17 +114,22 @@ class avl_array
{ return !(*this == rhs); }

// dereference - access value
inline T& operator*() const
inline if_t<Const, const T&, T&> operator*() const
{ return val(); }

// access value
inline T& val() const
inline if_t<Const, const T&, T&> val() const
{ return instance_->val_[idx_]; }

// access key
inline Key& key() const
inline const Key& key() const
{ return instance_->key_[idx_]; }

// 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; }

// preincrement
tag_avl_array_iterator& operator++()
{
Expand Down Expand Up @@ -152,7 +170,7 @@ class avl_array
++(*this);
return _copy;
}
} avl_array_iterator;
};


public:
Expand All @@ -163,7 +181,8 @@ class avl_array
typedef T& reference;
typedef const T& const_reference;
typedef Key key_type;
typedef avl_array_iterator iterator;
typedef tag_avl_array_iterator<false> iterator;
typedef tag_avl_array_iterator<true> const_iterator;


// ctor
Expand All @@ -184,9 +203,19 @@ class avl_array
return iterator(this, i);
}

inline const_iterator begin() const
{
return const_iterator(const_cast<avl_array&>(*this).begin());
}

inline iterator end()
{ return iterator(this, INVALID_IDX); }

inline const_iterator end() const
{
return const_iterator(this, INVALID_IDX);
}


// capacity
inline size_type size() const
Expand Down Expand Up @@ -319,6 +348,11 @@ class avl_array
return end();
}

inline const_iterator find(const key_type& key) const
{
return const_iterator(const_cast<avl_array&>(*this).find(key));
}


/**
* Count elements with a specific key
Expand Down
96 changes: 96 additions & 0 deletions inkcpp/collections/restorable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "restorable.h"
#include "../stack.h"

namespace ink::runtime::internal {
unsigned char* snap_base(unsigned char* ptr, bool write, size_t pos, size_t jump, size_t save, size_t& max)
{
ptr = snapshot_interface::snap_write(ptr, pos, write);
ptr = snapshot_interface::snap_write(ptr, jump, write);
ptr = snapshot_interface::snap_write(ptr, save, write);
max = pos;
if (jump > max) { max = jump; }
if (save > max) { max = save; }
return ptr;
}
const unsigned char* snap_load_base(const unsigned char* ptr, size_t& pos, size_t& jump, size_t& save, size_t& max)
{
ptr = snapshot_interface::snap_read(ptr, pos);
ptr = snapshot_interface::snap_read(ptr, jump);
ptr = snapshot_interface::snap_read(ptr, save);
max = pos;
if (jump > max) { max = jump; }
if (save > max) { max = save; }
return ptr;
}

template<>
size_t restorable<entry>::snap(unsigned char* data, const snapper& snapper) const
{
unsigned char* ptr = data;
size_t max;
ptr = snap_base(ptr, data, _pos, _jump, _save, max);
for(size_t i = 0; i < max; ++i) {
ptr = snap_write(ptr, _buffer[i].name, data);
ptr += _buffer[i].data.snap(data ? ptr : nullptr, snapper);
}
return ptr - data;
}
template<>
size_t restorable<value>::snap(unsigned char* data, const snapper& snapper) const
{
unsigned char* ptr = data;
size_t max;
ptr = snap_base(ptr, data, _pos, _jump, _save, max);
for(size_t i = 0; i < max; ++i) {
ptr += _buffer[i].snap(data ? ptr : nullptr, snapper);
}
return ptr - data;
}
template<>
size_t restorable<int>::snap(unsigned char* data, const snapper&) const
{
unsigned char* ptr = data;
size_t max;
ptr = snap_base(ptr, data, _pos, _jump, _save, max);
for(size_t i = 0; i < max; ++i) {
ptr = snap_write(ptr, _buffer[i], data);
}
return ptr - data;
}

template<>
const unsigned char* restorable<entry>::snap_load(const unsigned char* ptr, const loader& loader)
{
size_t max;
ptr = snap_load_base(ptr, _pos, _jump, _save, max);
while(_size < max) { overflow(_buffer, _size); }
for(size_t i = 0; i < max; ++i) {
ptr = snap_read(ptr, _buffer[i].name);
ptr = _buffer[i].data.snap_load(ptr, loader);
}
return ptr;
}
template<>
const unsigned char* restorable<value>::snap_load(const unsigned char* ptr, const loader& loader)
{
size_t max;
ptr = snap_load_base(ptr, _pos, _jump, _save, max);
while(_size < max) { overflow(_buffer, _size); }
for(size_t i = 0; i < max; ++i) {
ptr = _buffer[i].snap_load(ptr, loader);
}
return ptr;
}
template<>
const unsigned char* restorable<int>::snap_load(const unsigned char* ptr, const loader& loader)
{
size_t max;
ptr = snap_load_base(ptr, _pos, _jump, _save, max);
while(_size < max) { overflow(_buffer, _size); }
for(size_t i = 0; i < max; ++i) {
ptr = snap_read(ptr, _buffer[i]);
}
return ptr;
}

}
Loading