#define STRICT #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sl { class stringizable { public: virtual operator std::string() const = 0; }; template T fill(char n = 0) { T dst; std::fill(reinterpret_cast(&dst), reinterpret_cast(&dst) + sizeof(T), n); return dst; } class stacktrace32 : public stringizable { public: class module { public: typedef struct { std::string name; } value_type; value_type get(DWORD address) const; private: IMAGEHLP_MODULE make_imagehlp_module() const; const char * make_image_name(const char * x) const; }; class symbol { public: typedef struct { std::string name; long displacement; } value_type; bool is_exist(DWORD address) const; value_type get(DWORD address) const; private: PIMAGEHLP_SYMBOL new_imagehlp_symbol(DWORD address) const; void delete_imagehlp_symbol(PIMAGEHLP_SYMBOL p) const; }; class file { public: typedef struct { std::string name; long line; long displacement; } value_type; bool is_exist(DWORD address) const; value_type get(DWORD address) const; private: IMAGEHLP_LINE make_imagehlp_line() const; }; typedef struct { DWORD address; module::value_type module; symbol::value_type symbol; file::value_type file; } value_type; stacktrace32(); template void get(inserterT inserter) const { std::for_each(addresses.begin(), addresses.end(), [&](DWORD I){inserter++ = get_value(I);}); } virtual operator std::string() const; private: value_type get_value(DWORD address) const; void debug_module_initialize(); CONTEXT get_thread_context(); STACKFRAME make_stackframe(CONTEXT context); template void execute_stackwalk(STACKFRAME stackframe, CONTEXT context, inserterT inserter) { for(auto i = 0; i < 256; i++) { if(!StackWalk( IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &stackframe, &context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL )) { break; } else { if(stackframe.AddrPC.Offset != 0) { inserter = stackframe.AddrPC.Offset; } } } } module module; symbol symbol; file file; std::vector addresses; }; class exception : public stringizable { public: explicit exception(const std::string & cause) { } virtual ~exception() { } const std::string get_stacktrace() const { return stacktrace; } virtual operator std::string() const { return cause; } private: std::string cause; stacktrace32 stacktrace; }; #define SL_EXCEPTION(derived, base) \ class derived : public base { \ public: \ explicit derived(const std::string & cause) : base(cause) { \ } \ }; SL_EXCEPTION(bad_value_cast, exception) SL_EXCEPTION(logic_error, exception) SL_EXCEPTION(domain_error, logic_error) SL_EXCEPTION(invalid_argument, logic_error) SL_EXCEPTION(length_error, logic_error) SL_EXCEPTION(not_implemented, logic_error) SL_EXCEPTION(out_of_range, logic_error) SL_EXCEPTION(runtime_error, exception) SL_EXCEPTION(failure, runtime_error) SL_EXCEPTION(io_error, runtime_error) SL_EXCEPTION(file_not_found, io_error) SL_EXCEPTION(overflow_error, runtime_error) SL_EXCEPTION(range_error, runtime_error) SL_EXCEPTION(underflow_error, runtime_error) inline void check(bool condition, const std::string & description) { if(!condition) throw failure(description); } inline void check_true(bool value, const std::string & description) { check(value, "expected true: " + description); } inline void check_false(bool value, const std::string & description) { check(value, "expected false: " + description); } template inline void check_equal(const LhsType & lhs, const RhsType & rhs, const std::string & description) { check(lhs == rhs, "expected equal values: " + description); } template inline void check_unequal(const LhsType & lhs, const RhsType & rhs, const std::string & description) { check(lhs != rhs, "expected unequal values: " + description); } inline void check_null(const void * p, const std::string & description) { check(p == nullptr, "expected null pointer: " + description); } inline void check_non_null(const void * p, const std::string & description) { check(p != nullptr, "expected non-null pointer: " + description); } template std::list & get_values() { static std::list values; return values; } class testbase { public: typedef struct { std::string classname; std::string description; testbase * base; } value_type; testbase(); testbase(const std::string & classname, const std::string & description); std::tuple run(); virtual void harness(); }; extern testbase test; #define TEST(classname, description) \ class classname##description##initializer : public testbase { \ public: \ classname##description##initializer() : testbase(#classname, #description) { \ } \ void harness(); \ } classname##description##instance; \ void classname##description##initializer::harness() template class property { Type(Class::*getter)(); void(Class::*setter)(Type); Class * master; public: property() { master = nullptr; getter = nullptr; setter = nullptr; } void set(Class * master, Type(Class::*getter)(), void(Class::*setter)(Type)) { this->master = master; this->getter = getter; this->setter = setter; } Type operator=(const Type & rhs) { (master->*setter)(rhs); return rhs; } Type operator=(property & rhs) { (master->*setter)(rhs); return rhs; } operator Type() const { return (master->*getter)(); } bool operator==(const Type & rhs) const { Type lhstmp = *this; Type rhstmp = rhs; return lhstmp == rhstmp; } bool operator!=(const Type & rhs) const { return !(*this == rhs); } }; class mutex { public: class scoped_lock { public: scoped_lock(mutex & x); ~scoped_lock(); private: mutex & value; }; mutex(); ~mutex(); void lock(); void unlock(); operator HANDLE() const; private: HANDLE value; }; DWORD WINAPI thread_thunk(LPVOID param); class thread { public: typedef struct thunk_parameter { thread * self; DWORD(thread::*function)(LPVOID); LPVOID arg; }; thread(); virtual ~thread(); virtual DWORD run(LPVOID param); virtual void start(LPVOID thread_func_arg); void join(long ms = 0) const; void abort(); bool is_active() const; protected: bool receive_terminate() const; private: thunk_parameter hold; HANDLE thread_handle; bool terminate_request; }; class atom { public: typedef struct bucket { bucket * next; } bucket; typedef bucket * value_type; atom(); ~atom(); value_type create(); bool remove(value_type x); private: bucket * head; }; class value { template friend T * value_cast(value *); template friend T * reinterpret_value_cast(value *); class holder_base { public: virtual holder_base * clone() const = 0; virtual const std::type_info & type() const = 0; }; template class holder : public holder_base { holder & operator=(const holder &); public: T value; holder(const T & x) : value(x) { } holder_base * clone() const { return new holder(value); } const std::type_info & type() const { return typeid(value); } }; public: holder_base * base; value(); template value(const T & x) : base(new holder(x)) { } value(const value & x); template value & operator=(const T & rhs) { value(rhs).swap(*this); return *this; } value & operator=(value & rhs); ~value(); bool empty() const; const std::type_info & type() const; template operator T() { return value_cast(*this); } template bool operator==(const T & rhs) { if(base == nullptr || static_cast *>(base)->value == NULL) return false; return value_cast(*this) == rhs; } template bool operator!=(const T & rhs) { return !(*this == rhs); } value & swap(value & x); }; template T * value_cast(value * x) { return x != nullptr && x->type() == typeid(T) ? &static_cast *>(x->base)->value : NULL; } template const T * value_cast(const value * x) { return value_cast(const_cast(x)); } template T value_cast(value & x) { typedef std::remove_reference::type type; type * r = value_cast(&x); if(r == nullptr) throw bad_value_cast(""); return *r; } template T value_cast(const value & x) { return value_cast::type &>(const_cast(x)); } template T * reinterpert_value_cast(value * x) { return &static_cast *>(x->base)->value; } template const T * reinterpret_value_cast(const value * x) { return reinterpret_value_cast(const_cast(x)); } class point { public: typedef long value_type; point(); point(value_type x, value_type y); point & operator+=(const point & rhs); point & operator-=(const point & rhs); value_type x; value_type y; }; point operator+(const point & lhs, const point & rhs); point operator-(const point & lhs, const point & rhs); bool operator==(const point & lhs, const point & rhs); bool operator!=(const point & lhs, const point & rhs); class dimension { public: typedef long value_type; dimension(); dimension(value_type width, value_type height); bool contains(const point & position) const; value_type width; value_type height; }; bool operator==(const dimension & lhs, const dimension & rhs); bool operator!=(const dimension & lhs, const dimension & rhs); class rectangle { public: typedef long position_type; typedef long size_type; rectangle(); rectangle(position_type x, position_type y, size_type width, size_type height); rectangle(const point & position, const dimension & size); position_type x; position_type y; size_type width; size_type height; }; bool operator==(const rectangle & lhs, const rectangle & rhs); bool operator!=(const rectangle & lhs, const rectangle & rhs); template> class region_base { public: typedef Value value_type; typedef Allocator allocator_type; region_base() { initialize_properties(); } region_base(const dimension & size) { initialize_properties(); initialize_members(size); } region_base(const region_base & x) { initialize_properties(); copy_members(x); } virtual region_base & operator=(const region_base & rhs) { if(this != &rhs) copy_members(rhs); return *this; } virtual ~region_base() { } value_type & get(const point & position) const { return values[calc_sequential_index(position)]; } void set(const point & position, const value_type & x) { values[calc_sequential_index(position)] = x; } void fill(const value_type & x = value_type()) { fill(rectangle(point(0, 0), size), x); } void fill(const rectangle & bounds, const value_type & x = value_type()) { for(auto posy = 0; posy < bounds.height; ++posy) { for(auto posx = 0; posx < bounds.width; ++posx) { set(point(posx + bounds.x, posy + bounds.y), x); } } } property size; protected: dimension size_value; std::vector values; typename std::vector::difference_type calc_sequential_index(const point & position) const { return position.y * ((dimension)size).width + position.x; } private: void initialize_properties() { size.set(this, ®ion_base::getter_size, ®ion_base::setter_size); } void initialize_members(const dimension & x) { size = x; } void copy_members(const region_base & x) { size = x.size; values = x.values; } void allocate_values(const dimension & size) { values.resize(size.width * size.height); decltype(values) tmp(values); tmp.swap(values); } dimension getter_size() { return size_value; } void setter_size(dimension size) { size_value = size; allocate_values(size); } }; template> class region : public region_base { public: typedef region_base super; typedef typename super::value_type value_type; typedef typename super::allocator_type allocator_type; region() { } region(const dimension & x) : region_base(x) { } region(const region & x) : region_base(x) { } virtual region & operator=(const region & rhs) { super::operator=(rhs); return *this; } }; template<> class region : public region_base { public: typedef region_base super; typedef super::value_type value_type; typedef super::allocator_type allocator_type; region() { } region(const dimension & x) : region_base(x) { } region(const region & x) : region_base(x) { } virtual region & operator=(const region & rhs) { super::operator=(rhs); return *this; } bool peek(const point & position) const{ return dimension(size).contains(position) && values[calc_sequential_index(position)]; } }; class message { public: typedef std::string key_type; typedef value value_type; typedef std::map container_type; message(); message(const message & x); message & operator=(const message & rhs); ~message(); bool is_exist(const key_type & x) const; value_type & operator[](key_type x); private: container_type * values; long * ref; }; class delivery_message { public: typedef std::deque container_type; delivery_message(); bool empty() const; void post(const message & x); message get(); message peek(); private: std::shared_ptr messages; mutable struct { mutex global; } mutexes; }; class atom_unit; class message_unit; class mvc_unit; class thread_unit; class token_unit; class tree_unit; extern atom_unit atom_units; extern message_unit message_units; extern mvc_unit mvc_units; extern thread_unit thread_units; extern token_unit token_units; extern tree_unit tree_units; class device_unit; class hwnd_unit; class hwndmap_unit; class win32_unit; extern device_unit device_units; extern hwnd_unit hwnd_units; extern hwndmap_unit hwndmap_units; extern win32_unit win32_units; class widget_model; class widget_view; class widget_controller; class token; class mvc_unit { public: typedef struct mvc_unit_value { widget_model * model; widget_view * view; widget_controller * controller; mvc_unit_value(); void set(widget_model * model, widget_view * view, widget_controller * controller); } value_type; mvc_unit(); ~mvc_unit(); bool is_exist(const token & x) const; bool empty(const token & x); value_type & create(const token & x, widget_model * model, widget_view * view, widget_controller * controller); void remove(const token & x); void attach_objects(const token & x); value_type & operator[](const token & x); private: std::map units; }; struct wmsl_createwindow { rectangle bounds; widget_controller * controller; }; class token { public: typedef atom::value_type value_type; token(); token(const token & x); token & operator=(const token & rhs); ~token(); bool operator==(const token & rhs) const; bool operator!=(const token & rhs) const; operator value_type() const; operator std::string() const; private: value_type value; long * ref; }; class mvc_base { public: virtual ~mvc_base(); void attach(const token & x); virtual bool step(message & msg); protected: mvc_unit::value_type * mvc; token this_token; }; class widget_model : public mvc_base { public: widget_model(); virtual bool step(message & msg); private: bool visible_flag; dimension size_value; point position; }; class widget_view : public mvc_base { public: virtual bool step(message & msg); private: region clipping_region; }; class widget_controller : public mvc_base { public: widget_controller(); bool in_region(const point & pos) const; virtual bool step(message & msg); }; class atom_unit { public: atom::value_type create(); void remove(atom::value_type x); atom unit; }; class message_unit { public: class command_model { std::string name; std::string command; public: command_model(const std::string & name, const std::string & command); command_model & operator=(const value & rhs); operator value() const; }; class command_view { std::string name; std::string command; public: command_view(const std::string & name, const std::string & command); command_view & operator=(const value & rhs); operator value() const; }; class command_controller { std::string name; std::string command; public: command_controller(const std::string & name, const std::string & command); command_controller & operator=(const value & rhs); operator value() const; }; class trigger_command { std::string name; public: trigger_command(const std::string & name); command_model model(const std::string & command); command_view view(const std::string & command); command_controller controller(const std::string & command); }; class proxy_name { public: trigger_command operator()(const std::string & name); }; proxy_name name; class proxy_broadcast { std::string command; public: explicit proxy_broadcast(const std::string & command); proxy_broadcast & operator=(const value & rhs); }; class trigger_broadcast { public: proxy_broadcast operator()(const std::string & command); }; trigger_broadcast broadcast; }; class hwnd_unit { public: typedef token key_type; typedef struct { HWND hwnd; } value_type; bool is_exist(const token & x) const; value_type & create(const token & x, HWND hwnd); void remove(const token & x); value_type & operator[](const token & x); private: std::map units; }; class thread_unit { public: typedef struct { struct { delivery_message * rapid; delivery_message * idle; } message; HANDLE thread_handle; value self; value function; } value_type; bool is_exist(const token & x) const; value_type & create(const token & x, HANDLE thread_handle); void remove(const token & x); value_type & operator[](const token & x); private: std::map units; }; class token_unit { public: typedef std::map container_type; typedef container_type::value_type value_type; bool is_exist(const std::string & key) const; bool is_exist(const token & x) const; template void for_each(Predicate pred) { std::for_each(units.begin(), units.end(), pred); } token & operator[](const std::string & key); const std::string & operator[](const token & value); void remove(const std::string & key); void remove(const token & value); void rename(const token & value, const std::string & newname); private: container_type units; }; class tree_unit { public: typedef class tree_control { public: typedef class value_class { public: token token; point position; bool operator==(const value_class & rhs); bool operator!=(const value_class & rhs); } value_type; typedef std::list container_type; container_type::size_type size() const; void set_outer(tree_unit * outer); container_type::iterator begin(); container_type::iterator end(); value_type front() const; value_type back() const; void to_top(value_type x); void to_bottom(value_type x); void shift_front(); void shift_back(); void push_front(value_type x); void push_back(value_type x); container_type pickup(const point & pos) const; void recursively_step(message & msg); private: tree_unit * outer; container_type units; container_type get_flat_tree() const; container_type get_first_children_s_siblings(container_type::iterator first, container_type::iterator last) const; container_type get_first_children(container_type::iterator first, container_type::iterator last) const; container_type get_all_siblings(container_type::iterator first, container_type::iterator last) const; } value_type; value_type & operator[](const token & x); private: std::map units; }; class broadcastable { public: class proxy { std::string command; token this_token; public: proxy(const std::string & command, const token & x); proxy & operator=(const value & rhs); }; class trigger { std::string command; token this_token; public: void set(const token & x); proxy operator()(const std::string & command); }; trigger broadcast; }; template class childable { public: class trigger; class proxy_position; class proxy_front { point position; token this_token; public: void set(const point & pos, const token & x) { position = pos; this_token = x; } proxy_front operator=(const Type & rhs) { tree_unit::value_type::value_type dst; dst.position = position; dst.token = rhs.attached_token(); tree_units[this_token].push_front(dst); message msg; msg["command"] = std::string("setposition"); msg["value"] = position; mvc_units[rhs.attached_token()].controller->step(msg); return *this; } }; class proxy_back { point position; token this_token; public: void set(const point & pos, const token & x) { this_token = x; } proxy_back operator=(const Type & rhs) { tree_unit::value_type::value_type dst; dst.position = position; dst.token = rhs.attached_token(); tree_units[this_token].push_back(dst); message msg; msg["command"] = std::string("setposition"); msg["value"] = position; mvc_units[rhs.attached_token()].controller->step(msg); return *this; } }; class children { public: typedef tree_unit::tree_control::value_type value_type; typedef std::list container_type; children(const point & position, const token & x) { this->position = position; this_token = x; } class proxy { message children_walk(const message & x) { message dst = x; if(!child.empty()) { container_type::const_iterator I = child.begin(); bool forward_break = false; for(; I != child.end(); ++I) { if(mvc_units[I->token].controller->step(dst) != false) { forward_break = true; break; } } if(!forward_break) { container_type::const_reverse_iterator rI(I); ++rI; for(; rI != child.rend(); ++rI) { if(mvc_units[rI->token].controller->step(dst) != false) break; } } } return dst; } std::string command; container_type child; public: proxy(const std::string & command, const point & position, const token & x) { this->command = command; child = tree_units[x].pickup(position); } proxy & operator=(const value & rhs) { message msg; msg["command"] = command; msg["value"] = rhs; msg = children_walk(msg); return *this; } operator value() const { message msg; msg["command"] = command; msg = children_walk(msg); return msg["value"]; } }; proxy operator[](const std::string & command) { return proxy(command, position, this_token); } }; class proxy_position { point position; token this_token; public: proxy_position(const point & pos, const token & x) { this_token = x; position = pos; front.set(pos, x); back.set(pos, x); } operator children() { return children(position, this_token); } typename children::proxy operator()(const std::string & command) { return children::proxy(command, position, this_token); } proxy_front front; proxy_back back; }; class trigger { token this_token; public: void set(const token & x) { this_token = x; } proxy_position operator()(const point & pos) { return proxy_position(pos, this_token); } }; trigger child; }; class gettable { public: class proxy_model { std::string command; token this_token; public: proxy_model(const std::string & command, const token & x); operator value() const; }; class proxy_view { std::string command; token this_token; public: proxy_view(const std::string & command, const token & x); operator value() const; }; class proxy_controller { std::string command; token this_token; public: proxy_controller(const std::string & command, const token & x); operator value() const; }; class trigger { std::string command; token this_token; public: void set(const token & x); proxy_model model(const std::string & command); proxy_view view(const std::string & command); proxy_controller controller(const std::string & command); }; trigger get; }; class postable { public: class proxy_property { std::string command; token this_token; public: proxy_property(const std::string & command, const token & x); proxy_property & operator=(const value & rhs); }; class proxy_command { std::string command; token this_token; public: proxy_command(const std::string & command, const token & x); proxy_command & operator=(const value & rhs); }; class proxy { token this_token; public: void set(const token & x); proxy_property operator[](const std::string & command); proxy_command operator()(const std::string & command); }; proxy post; }; class sendable { public: class proxy_model { std::string command; token this_token; public: proxy_model(const std::string & command, const token & x); proxy_model & operator=(const value & rhs); }; class proxy_view { std::string command; token this_token; public: proxy_view(const std::string & command, const token & x); proxy_view & operator=(const value & rhs); }; class proxy_controller { std::string command; token this_token; public: proxy_controller(const std::string & command, const token & x); proxy_controller & operator=(const value & rhs); }; class trigger { token this_token; public: void set(const token & x); proxy_model model(const std::string & command); proxy_view view(const std::string & command); proxy_controller controller(const std::string & command); }; trigger send; }; void threadable_thunk(void * param); class threadable { public: typedef struct { token this_token; void * param; } params_type; void set(const token & x); virtual void run(void * param); void start(void * param); void join(DWORD ms = 0); DWORD result; private: params_type params; token this_token; }; class widget : public broadcastable, public childable, public gettable, public postable, public sendable, public threadable { public: typedef mvc_unit::value_type * mvc_type; widget(const std::string & name = ""); virtual ~widget(); void destroy(); token attached_token() const; void rename(const std::string & newname); virtual bool step(message & msg); virtual void run(void * param); class property_proxy { public: property_proxy(widget * parent, const std::string & command); property_proxy & operator=(const value & rhs); operator value() const; private: widget * parent; std::string command; }; property_proxy operator[](const std::string & command); class command_proxy { public: command_proxy(widget * parent, const std::string & command); command_proxy & operator=(const value & rhs); operator value() const; private: widget * parent; std::string command; }; command_proxy operator()(const std::string & command); protected: token this_token; mvc_unit::value_type * mvc; bool is_blank(const std::string & name) const; std::string initialize_mvc(const std::string & name, widget_model * model, widget_view * view, widget_controller * controller); }; class window_model : public widget_model { public: typedef widget_model super; window_model(); virtual bool step(message & msg); }; class window_view : public widget_view { public: typedef widget_view super; virtual bool step(message & msg); }; class window_controller : public widget_controller { public: typedef widget_controller super; window_controller(); virtual bool step(message & msg); }; class window : public widget { public: window(const std::string & name = ""); std::string initial_base(const std::string & name); }; class frame_model : public window_model { public: typedef window_model super; frame_model(); virtual bool step(message & msg); public: property title; private: std::string title_value; std::string getter_title(); void setter_title(std::string x); }; class frame_view : public window_view { public: typedef window_view super; frame_view(); virtual bool step(message & msg); }; class frame_controller : public window_controller { public: typedef window_controller super; frame_controller(); virtual bool step(message & msg); }; class frame : public window { public: frame(const std::string & name = ""); std::string initial_base(const std::string & name); }; class device_base { public: virtual ~device_base(); virtual value device_proc(value param); }; enum device_list { SL_DEVICE_WIN32, }; class device_unit { public: device_unit(); ~device_unit(); void set_device(device_list device); device_base * operator->() const; operator device_base *() const; private: device_base * device; }; class hwndmap_unit { public: typedef HWND key_type; typedef struct { device_base * parent; value(device_base::*function)(value); widget_controller * controller; } value_type; bool is_exist(HWND x) const; value_type & operator[](HWND x); value_type & create(HWND hwnd, device_base * parent, value(device_base::*function)(value), widget_controller * controller); void remove(HWND hwnd); private: std::map units; }; class win32_device : public device_base { public: virtual value device_proc(value param); }; LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); enum { WMSL_CREATE = WM_USER + 1, WMSL_SHOW, WMSL_HIDE, WMSL_SIZE, WMSL_MOVE, }; class win32_unit : public thread { public: friend LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM); typedef thread super; typedef struct { win32_unit * self; LRESULT(win32_unit::*function)(HWND, UINT, WPARAM, LPARAM); } callback_thunk_param; win32_unit(); virtual ~win32_unit(); virtual DWORD run(LPVOID param); virtual void start(LPVOID param); LRESULT send(UINT msg, WPARAM wparam, LPARAM lparam); LRESULT send(const token & x, UINT msg, WPARAM wparam, LPARAM lparam); private: HANDLE raised; HWND main_window; callback_thunk_param callbacker; LRESULT main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); void register_window_class(); }; }