@ -1,3 +1,5 @@ | |||||
# Crank | # Crank | ||||
A Tcl like command language made for the Clinl kernel testing | |||||
A Tcl like command language made for the Clinl kernel testing | |||||
Build it just by building crank.cpp and main.cpp together in a C++17 compiler and you are done. |
@ -0,0 +1,68 @@ | |||||
#pragma once | |||||
#include "buffer.hpp" | |||||
#include "stdlib.h" | |||||
#include "string.h" | |||||
class arena{ | |||||
ksdk::buffer<char> data; | |||||
size_t last; | |||||
size_t count; | |||||
public: | |||||
arena() | |||||
:last(0) | |||||
,count(0) | |||||
,data(ksdk::buffer<char>(nullptr,(size_t)0)) | |||||
{} | |||||
arena(size_t sz) | |||||
:last(0) | |||||
,count(0) | |||||
,data(ksdk::buffer<char>(nullptr,(size_t)0)) | |||||
{ | |||||
if(sz!=0) | |||||
{ | |||||
auto v=malloc(sz); | |||||
if(v!=nullptr) | |||||
{ | |||||
data=ksdk::buffer<char>((char*)v,sz); | |||||
} | |||||
} | |||||
} | |||||
arena(char* pos,size_t sz) | |||||
:last(0) | |||||
,count(0) | |||||
,data(ksdk::buffer<char>(pos,(size_t)sz)) | |||||
{ | |||||
} | |||||
void* allocate(size_t sz) | |||||
{ | |||||
auto ret=data.begin()+last; | |||||
if(ret<data.end()) | |||||
{ | |||||
count++; | |||||
last+=sz; | |||||
return ret; | |||||
} | |||||
else | |||||
{ | |||||
return nullptr; | |||||
} | |||||
} | |||||
bool desallocate(void* ptr) | |||||
{ | |||||
if(ptr>=data.begin() && ptr<data.end()) | |||||
{ | |||||
count--; | |||||
if(count==0) | |||||
{ | |||||
memset(data.begin(),data.size(),0); | |||||
last=0; | |||||
} | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
}; |
@ -0,0 +1,136 @@ | |||||
#pragma once | |||||
#include <stddef.h> | |||||
#include "container.hpp" | |||||
namespace __internals{ | |||||
template<typename T> | |||||
T& ref(T& n) | |||||
{ | |||||
return n; | |||||
} | |||||
template<class T> | |||||
struct r_op_iterator | |||||
{ | |||||
r_op_iterator(T* in):it(in){} | |||||
T* it; | |||||
auto operator++() | |||||
{ | |||||
return it--; | |||||
} | |||||
auto operator++(int) | |||||
{ | |||||
return --it; | |||||
} | |||||
auto operator--() | |||||
{ | |||||
return it--; | |||||
} | |||||
auto operator--(int) | |||||
{ | |||||
return --it; | |||||
} | |||||
T& operator*() | |||||
{ | |||||
return *it; | |||||
} | |||||
T& operator[](const size_t idx) | |||||
{ | |||||
return *(it-idx); | |||||
} | |||||
auto operator==(const r_op_iterator& rhs) | |||||
{ | |||||
return it==rhs.it; | |||||
} | |||||
auto operator!=(const r_op_iterator& rhs) | |||||
{ | |||||
return it!=rhs.it; | |||||
} | |||||
auto operator<=(const r_op_iterator& rhs) | |||||
{ | |||||
return (rhs.it<=it); | |||||
} | |||||
auto operator>=(const r_op_iterator& rhs) | |||||
{ | |||||
return (rhs.it>=it); | |||||
} | |||||
auto operator<(const r_op_iterator& rhs) | |||||
{ | |||||
return (rhs.it<it); | |||||
} | |||||
auto operator>(const r_op_iterator& rhs) | |||||
{ | |||||
return (rhs.it>it); | |||||
} | |||||
}; | |||||
} | |||||
namespace ksdk{ | |||||
template<typename T> | |||||
class buffer : public typed_container<T> | |||||
{ | |||||
protected: | |||||
T* _buffer; | |||||
size_t _size; | |||||
public: | |||||
constexpr buffer(T* b, T* e) | |||||
:_buffer(b) | |||||
,_size(e-b) | |||||
{ | |||||
} | |||||
constexpr buffer() | |||||
:_buffer(nullptr) | |||||
,_size(0) | |||||
{ | |||||
} | |||||
constexpr buffer(T* b, size_t sz) | |||||
:_buffer(b) | |||||
,_size(sz) | |||||
{ | |||||
} | |||||
size_t size() | |||||
{ | |||||
return _size; | |||||
} | |||||
T* begin() | |||||
{ | |||||
return _buffer; | |||||
} | |||||
T* end() | |||||
{ | |||||
return _buffer+_size; | |||||
} | |||||
__internals::r_op_iterator<T> rbegin() | |||||
{ | |||||
return __internals::r_op_iterator<T>(_buffer-1+_size); | |||||
} | |||||
__internals::r_op_iterator<T> rend() | |||||
{ | |||||
return __internals::r_op_iterator<T>(_buffer-1); | |||||
} | |||||
T& operator[](size_t idx) | |||||
{ | |||||
return _buffer[idx]; | |||||
} | |||||
bool operator==(buffer<T> oth) | |||||
{ | |||||
if(size()!=oth.size()) | |||||
return false; | |||||
for(size_t i=0; i<size(); i++) | |||||
if(_buffer[i]!=oth[i]) | |||||
return false; | |||||
return true; | |||||
} | |||||
}; | |||||
} |
@ -0,0 +1,37 @@ | |||||
#pragma once | |||||
#include <stddef.h> | |||||
namespace __internals{ | |||||
/* Enable_if implementation */ | |||||
template<bool b, class T = void> | |||||
struct enable_if{}; | |||||
template<class T> | |||||
struct enable_if<true,T>{ | |||||
typedef T type; | |||||
}; | |||||
/* Enable_if helper implementation */ | |||||
template<bool b, class T = void> | |||||
using enable_if_t = typename enable_if<b,T>::type; | |||||
/* static_assert implementaion for comparing integers */ | |||||
template<bool b, typename t = enable_if_t<b>> | |||||
class check{ | |||||
}; | |||||
} | |||||
namespace ksdk{ | |||||
class container | |||||
{ | |||||
public: | |||||
size_t size(); | |||||
}; | |||||
template<class T> | |||||
class typed_container : public container | |||||
{ | |||||
}; | |||||
} |
@ -0,0 +1,203 @@ | |||||
#include "crank.h" | |||||
kstd::string_view crank_context::eval(kstd::string_view code) | |||||
{ | |||||
auto ret = eval_no_copy(copy(code)); | |||||
return ret; | |||||
} | |||||
kstd::string_view identity(kstd::string_view args, crank_context& ctx) | |||||
{ | |||||
return args; | |||||
} | |||||
kstd::string_view set(kstd::string_view args, crank_context& ctx) | |||||
{ | |||||
args = skip_whitespace(args); | |||||
auto key = extract_token(args); | |||||
auto value = skip_linearspace(kstd::string_view(args.begin()+key.size(),args.end())); | |||||
return ctx.store(key,value); | |||||
} | |||||
bool istokenok(int m) | |||||
{ | |||||
return ( | |||||
isalpha(m) | |||||
|| isdigit(m) | |||||
|| m=='$' | |||||
|| m=='-' | |||||
|| m=='_' | |||||
); | |||||
} | |||||
bool islinearspace(int m) | |||||
{ | |||||
return ( | |||||
m==' ' | |||||
|| m=='\t' | |||||
); | |||||
} | |||||
kstd::string_view skip_whitespace(kstd::string_view code) | |||||
{ | |||||
auto m = code.begin(); | |||||
while(m<code.end() && isspace(*m)) | |||||
{ | |||||
m++; | |||||
} | |||||
return kstd::string_view(m,code.end()); | |||||
} | |||||
kstd::string_view skip_linearspace(kstd::string_view code) | |||||
{ | |||||
auto m = code.begin(); | |||||
while(m<code.end() && islinearspace(*m)) | |||||
{ | |||||
m++; | |||||
} | |||||
return kstd::string_view(m,code.end()); | |||||
} | |||||
template<char bound> | |||||
kstd::string_view extract_bounded(kstd::string_view code) | |||||
{ | |||||
auto m = code.begin(); | |||||
while(m<code.end() && *m!=bound) | |||||
{ | |||||
if(*m=='"') | |||||
{ | |||||
m++; | |||||
m+=extract_string(kstd::string_view(m,code.end())).size(); | |||||
m++; | |||||
} | |||||
else if(*m=='{') | |||||
{ | |||||
m++; | |||||
m+=extract_array(kstd::string_view(m,code.end())).size(); | |||||
m++; | |||||
} | |||||
else if(*m=='[') | |||||
{ | |||||
m++; | |||||
m+=extract_subcommand(kstd::string_view(m,code.end())).size(); | |||||
m++; | |||||
} | |||||
else if(istokenok(*m)) | |||||
{ | |||||
m+=extract_token(kstd::string_view(m,code.end())).size(); | |||||
} | |||||
else | |||||
{ | |||||
m = skip_whitespace(kstd::string_view(m,code.end())).begin(); | |||||
} | |||||
} | |||||
return kstd::string_view(code.begin(), m); | |||||
} | |||||
kstd::string_view extract_command(kstd::string_view code) | |||||
{ | |||||
code = skip_whitespace(code); | |||||
return extract_bounded<'\n'>(code); | |||||
} | |||||
kstd::string_view extract_subcommand(kstd::string_view code) | |||||
{ | |||||
return extract_bounded<']'>(code); | |||||
} | |||||
kstd::string_view extract_string(kstd::string_view code) | |||||
{ | |||||
auto m = code.begin(); | |||||
while(m<code.end() && *m!='"') | |||||
{ | |||||
m+=(*m!='\\')?1:2; | |||||
} | |||||
return kstd::string_view(code.begin(), m); | |||||
} | |||||
kstd::string_view extract_token(kstd::string_view code) | |||||
{ | |||||
auto m = code.begin(); | |||||
while(m<code.end() && istokenok(*m)) | |||||
{ | |||||
m++; | |||||
} | |||||
return kstd::string_view(code.begin(), m); | |||||
} | |||||
kstd::string_view extract_array(kstd::string_view code) | |||||
{ | |||||
return extract_bounded<'}'>(code); | |||||
} | |||||
kstd::string_view crank_context::execute_command(kstd::string_view code) | |||||
{ | |||||
code = copy_replace(code); | |||||
auto token = extract_token(code); | |||||
auto symbol = get_symbol(token); | |||||
auto args = skip_linearspace(kstd::string_view(code.begin()+token.size(),code.end())); | |||||
if(symbol.size()) | |||||
{ | |||||
if(symbol[0]=='@') | |||||
{ | |||||
symbol = skip_linearspace(kstd::string_view(symbol.begin()+1, symbol.end())); | |||||
while(istokenok(args[0])) | |||||
{ | |||||
auto argname = extract_token(symbol); | |||||
symbol = skip_linearspace(kstd::string_view(symbol.begin()+argname.size(), symbol.end())); | |||||
auto argvalue = kstd::string_view(); | |||||
if(args[0]=='{') | |||||
{ | |||||
argvalue=extract_array(kstd::string_view(args.begin()+1, args.end())); | |||||
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end())); | |||||
} | |||||
else if(args[0]=='[') | |||||
{ | |||||
argvalue=crank_context::execute_command(extract_subcommand(kstd::string_view(args.begin()+1, args.end()))); | |||||
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end())); | |||||
} | |||||
else if(args[0]=='"') | |||||
{ | |||||
argvalue=extract_string(kstd::string_view(args.begin()+1, args.end())); | |||||
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end())); | |||||
} | |||||
else | |||||
{ | |||||
argvalue=extract_token(kstd::string_view(args.begin()+1, args.end())); | |||||
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size(), args.end())); | |||||
} | |||||
store(argname,argvalue); | |||||
} | |||||
symbol = extract_array(symbol); | |||||
auto command = extract_command(symbol); | |||||
auto ret = kstd::string_view(); | |||||
while(command.size()) | |||||
{ | |||||
ret = execute_command(command); | |||||
symbol = kstd::string_view(symbol.begin()+command.size(),symbol.end()); | |||||
command = extract_command(symbol); | |||||
} | |||||
return ret; | |||||
} | |||||
else | |||||
{ | |||||
return symbol; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
return get_native(token)(args,this); | |||||
} | |||||
} | |||||
kstd::string_view crank_context::eval_no_copy(kstd::string_view code) | |||||
{ | |||||
auto command = extract_command(code); | |||||
auto ret = kstd::string_view();; | |||||
while(command.size()) | |||||
{ | |||||
ret = execute_command(command); | |||||
code = kstd::string_view(code.begin()+command.size(),code.end()); | |||||
command = extract_command(code); | |||||
} | |||||
return ret; | |||||
} |
@ -0,0 +1,319 @@ | |||||
#pragma once | |||||
#include "memory_pool.hpp" | |||||
#include "string_view.hpp" | |||||
#include "2CL.hpp" | |||||
class crank_context; | |||||
kstd::string_view identity(kstd::string_view args, crank_context& ctx); | |||||
kstd::string_view set(kstd::string_view args, crank_context& ctx); | |||||
bool istokenok(int m); | |||||
bool islinearspace(int m); | |||||
kstd::string_view skip_whitespace(kstd::string_view code); | |||||
kstd::string_view skip_linearspace(kstd::string_view code); | |||||
template<typename t1, typename t2> | |||||
struct pair{ | |||||
pair(t1 f, t2 s) | |||||
: first{f} | |||||
, second{s} | |||||
{} | |||||
t1 first; | |||||
t2 second; | |||||
}; | |||||
struct crank_macro{ | |||||
kstd::string_view(*execute)(kstd::string_view, crank_context&); | |||||
crank_macro() | |||||
{ | |||||
execute=identity; | |||||
} | |||||
crank_macro(kstd::string_view(*f)(kstd::string_view, crank_context&)) | |||||
{ | |||||
execute=f; | |||||
} | |||||
kstd::string_view operator()(kstd::string_view args, crank_context* ctx) | |||||
{ | |||||
return execute(args, *ctx); | |||||
} | |||||
}; | |||||
struct crank_elem; | |||||
template<typename T> | |||||
struct crank_ptr{ | |||||
T* ptr=nullptr; | |||||
memory_pool* memory=nullptr; | |||||
crank_ptr(T* _ptr, memory_pool* _memory) | |||||
: ptr{_ptr} | |||||
, memory{_memory} | |||||
{} | |||||
crank_ptr(){} | |||||
crank_ptr(crank_ptr&) = delete; | |||||
crank_ptr(crank_ptr&& oth) | |||||
{ | |||||
auto tmp = oth.ptr; | |||||
oth.ptr=ptr; | |||||
ptr=tmp; | |||||
auto tmpm = oth.memory; | |||||
oth.memory=memory; | |||||
memory=tmpm; | |||||
} | |||||
void operator=(crank_ptr&& oth) | |||||
{ | |||||
auto tmp = oth.ptr; | |||||
oth.ptr=ptr; | |||||
ptr=tmp; | |||||
auto tmpm = oth.memory; | |||||
oth.memory=memory; | |||||
memory=tmpm; | |||||
} | |||||
~crank_ptr() | |||||
{ | |||||
if(ptr&&memory) | |||||
{ | |||||
memory->desallocate(ptr); | |||||
} | |||||
} | |||||
}; | |||||
struct crank_elem{ | |||||
crank_ptr<crank_elem> next; | |||||
pair<kstd::string_view,kstd::string_view> data; | |||||
}; | |||||
struct crank_copy{ | |||||
crank_ptr<crank_copy> next; | |||||
kstd::string_view data; | |||||
}; | |||||
struct crank_native{ | |||||
crank_ptr<crank_native> next; | |||||
pair<kstd::string_view,crank_macro> data; | |||||
}; | |||||
kstd::string_view skip_whitespace(kstd::string_view code); | |||||
kstd::string_view extract_subcommand(kstd::string_view code); | |||||
kstd::string_view extract_array(kstd::string_view code); | |||||
kstd::string_view extract_token(kstd::string_view code); | |||||
kstd::string_view extract_command(kstd::string_view code); | |||||
kstd::string_view extract_string(kstd::string_view code); | |||||
class crank_context{ | |||||
memory_pool memory; | |||||
crank_ptr<crank_elem> elements; | |||||
crank_ptr<crank_copy> copies; | |||||
crank_ptr<crank_native> natives; | |||||
public: | |||||
kstd::string_view copy(kstd::string_view src) | |||||
{ | |||||
char* ptr = (char*)memory.allocate(src.size()); | |||||
if(ptr) | |||||
{ | |||||
crank_copy* cpy = (crank_copy*)memory.allocate(sizeof(crank_copy)); | |||||
if(cpy) | |||||
{ | |||||
new(cpy) crank_copy{.next=std::move(copies), .data=kstd::string_view(ptr,src.size())}; | |||||
copies = std::move(crank_ptr{cpy, &memory}); | |||||
memcpy(ptr,src.begin(),src.size()); | |||||
return copies.ptr->data; | |||||
} | |||||
else | |||||
{ | |||||
memory.desallocate(ptr); | |||||
return kstd::string_view(); | |||||
} | |||||
} | |||||
return kstd::string_view(); | |||||
} | |||||
kstd::string_view copy_replace(kstd::string_view src) | |||||
{ | |||||
size_t new_len=src.size(); | |||||
auto m = src.begin(); | |||||
while(m!=src.end()) | |||||
{ | |||||
if(!istokenok(*m)) | |||||
{ | |||||
m++; | |||||
} | |||||
else | |||||
{ | |||||
auto token = extract_token(kstd::string_view(m,src.end())); | |||||
if(token[0]=='$') | |||||
{ | |||||
new_len-=token.size(); | |||||
new_len+=get_symbol(kstd::string_view(token.begin()+1,token.end())).size(); | |||||
} | |||||
m+=token.size(); | |||||
} | |||||
} | |||||
char* ptr = (char*)memory.allocate(new_len); | |||||
if(ptr) | |||||
{ | |||||
crank_copy* cpy = (crank_copy*)memory.allocate(sizeof(crank_copy)); | |||||
if(cpy) | |||||
{ | |||||
new(cpy) crank_copy{.next=std::move(copies), .data=kstd::string_view(ptr,src.size())}; | |||||
copies = std::move(crank_ptr{cpy, &memory}); | |||||
auto dest = kstd::string_view(ptr,new_len); | |||||
auto src_it = src.begin(); | |||||
auto dest_it = dest.begin(); | |||||
while(src_it!=src.end() && dest_it!=dest.end()) | |||||
{ | |||||
if(!istokenok(*src_it)) | |||||
{ | |||||
*dest_it = *src_it; | |||||
dest_it++; | |||||
src_it++; | |||||
} | |||||
else | |||||
{ | |||||
auto token = extract_token(kstd::string_view(src_it,src.end())); | |||||
if(token[0]=='$') | |||||
{ | |||||
auto resolved = get_symbol(kstd::string_view(token.begin()+1,token.end())); | |||||
memcpy(dest_it,resolved.begin(),resolved.size()); | |||||
src_it+=token.size(); | |||||
dest_it+=resolved.size(); | |||||
} | |||||
else | |||||
{ | |||||
memcpy(dest_it,token.begin(),token.size()); | |||||
src_it+=token.size(); | |||||
dest_it+=token.size(); | |||||
} | |||||
} | |||||
} | |||||
return copies.ptr->data; | |||||
} | |||||
else | |||||
{ | |||||
memory.desallocate(ptr); | |||||
return kstd::string_view(); | |||||
} | |||||
} | |||||
return kstd::string_view(); | |||||
} | |||||
kstd::string_view store(kstd::string_view key, kstd::string_view value) | |||||
{ | |||||
crank_elem* elem = (crank_elem*)memory.allocate(sizeof(crank_elem)); | |||||
if(elem) | |||||
{ | |||||
new(elem) crank_elem{.next=std::move(elements), .data=pair(key, value)}; | |||||
elements = std::move(crank_ptr{elem, &memory}); | |||||
return value; | |||||
} | |||||
return kstd::string_view(); | |||||
} | |||||
kstd::string_view add_native(kstd::string_view key, crank_macro value) | |||||
{ | |||||
crank_native* native = (crank_native*)memory.allocate(sizeof(crank_native)); | |||||
if(native) | |||||
{ | |||||
new(native) crank_native{.next=std::move(natives), .data=pair(key, value)}; | |||||
natives = std::move(crank_ptr{native, &memory}); | |||||
return key; | |||||
} | |||||
return kstd::string_view(); | |||||
} | |||||
bool string_is_in_range(kstd::string_view range, char* ptr) | |||||
{ | |||||
return ptr>=range.begin() && ptr<range.end(); | |||||
} | |||||
bool any_elem_is_in_range(kstd::string_view range) | |||||
{ | |||||
auto elems = &elements; | |||||
while(elems->ptr) | |||||
{ | |||||
if( | |||||
string_is_in_range(range, elems->ptr->data.first.begin()) | |||||
|| string_is_in_range(range, elems->ptr->data.second.begin()) | |||||
) | |||||
{ | |||||
return true; | |||||
} | |||||
elems = &(elems->ptr->next); | |||||
} | |||||
return false; | |||||
} | |||||
kstd::string_view get_symbol(kstd::string_view key) | |||||
{ | |||||
auto elems = &elements; | |||||
while(elems->ptr) | |||||
{ | |||||
if( | |||||
elems->ptr->data.first == key | |||||
) | |||||
{ | |||||
return elems->ptr->data.second; | |||||
} | |||||
elems = &(elems->ptr->next); | |||||
} | |||||
return kstd::string_view(); | |||||
} | |||||
crank_macro& get_native(kstd::string_view key) | |||||
{ | |||||
auto elems = &natives; | |||||
while(elems->ptr) | |||||
{ | |||||
if( | |||||
elems->ptr->data.first == key | |||||
) | |||||
{ | |||||
return elems->ptr->data.second; | |||||
} | |||||
elems = &(elems->ptr->next); | |||||
} | |||||
static const char* id = "identity"; | |||||
return get_native(kstd::string_view((char*)id,8)); | |||||
} | |||||
void collect() | |||||
{ | |||||
auto cps = &copies; | |||||
while(cps->ptr) | |||||
{ | |||||
if( | |||||
! any_elem_is_in_range(cps->ptr->data) | |||||
) | |||||
{ | |||||
memory.desallocate(cps->ptr->data.begin()); | |||||
*cps=std::move(cps->ptr->next); | |||||
} | |||||
else | |||||
{ | |||||
cps = &(cps->ptr->next); | |||||
} | |||||
} | |||||
} | |||||
crank_context() | |||||
{ | |||||
static const char* str_set = "set"; | |||||
add_native(kstd::string_view((char*)str_set,3), set); | |||||
static const char* str_identity = "identity"; | |||||
add_native(kstd::string_view((char*)str_identity,8), identity); | |||||
} | |||||
kstd::string_view execute_command(kstd::string_view code); | |||||
kstd::string_view eval(kstd::string_view); | |||||
kstd::string_view eval_no_copy(kstd::string_view); | |||||
}; |
@ -0,0 +1,46 @@ | |||||
/*#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file | |||||
#include "catch.hpp" | |||||
*/ | |||||
#include "crank.h" | |||||
#include <iostream> | |||||
#include <string> | |||||
kstd::string_view set2(kstd::string_view args, crank_context& ctx) | |||||
{ | |||||
args = skip_whitespace(args); | |||||
auto key = extract_token(args); | |||||
auto value = skip_linearspace(kstd::string_view(args.begin()+key.size(),args.end())); | |||||
for(auto c : value) | |||||
std::cout<<c; | |||||
std::cout<<" out:"<<value.size()<<std::endl; | |||||
return ctx.store(key,value); | |||||
} | |||||
int main() | |||||
{ | |||||
const char* set2text = "set2"; | |||||
std::string get=""; | |||||
crank_context ctx; | |||||
ctx.add_native(kstd::string_view((char*)set2text,4), set2); | |||||
while((std::getline(std::cin,get)).good()) | |||||
{ | |||||
auto ret = ctx.eval(kstd::string_view(get.data(), get.size())); | |||||
for(auto c : ret) | |||||
std::cout<<c; | |||||
std::cout<<" out:"<<ret.size()<<std::endl; | |||||
} | |||||
} | |||||
/* | |||||
TEST_CASE("crank") | |||||
{ | |||||
crank_context ctx; | |||||
static const char* setter_code = "set sample \"Hello world\""; | |||||
kstd::string_view setter_c{(char*)setter_code, 24}; | |||||
ctx.eval_no_copy(setter_c); | |||||
static const char* getter_code = "$sample"; | |||||
kstd::string_view getter_c{(char*)getter_code, 7}; | |||||
ctx.eval_no_copy(getter_c); | |||||
}*/ |
@ -0,0 +1,39 @@ | |||||
#pragma once | |||||
#include "arena.hpp" | |||||
#include <array> | |||||
class memory_pool{ | |||||
std::array<arena,256> _pool; | |||||
public: | |||||
memory_pool() | |||||
: _pool() | |||||
{ | |||||
_pool.fill(arena()); | |||||
for(auto& a : _pool) | |||||
a = arena(4096); | |||||
} | |||||
memory_pool(memory_pool&) = delete; | |||||
memory_pool(memory_pool&&) = delete; | |||||
void* allocate(size_t sz) | |||||
{ | |||||
for(auto& a : _pool) | |||||
{ | |||||
void* ptr = a.allocate(sz); | |||||
if(ptr!=nullptr) | |||||
return ptr; | |||||
} | |||||
return nullptr; | |||||
} | |||||
void desallocate(void* ptr) | |||||
{ | |||||
for(auto& a : _pool) | |||||
{ | |||||
bool success = a.desallocate(ptr); | |||||
if(success) | |||||
return; | |||||
} | |||||
} | |||||
}; |
@ -0,0 +1,6 @@ | |||||
#pragma once | |||||
#include "buffer.hpp" | |||||
namespace kstd{ | |||||
using string_view = ksdk::buffer<char>; | |||||
} |