| @ -1,3 +1,5 @@ | |||
| # 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>; | |||
| } | |||