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