DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
// Copyright (c) 2003 Daniel Wallin and Arvid Norberg // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. #include
#include
#include
#include
using namespace luabind::detail; namespace luabind { namespace detail { struct method_name { method_name(char const* n): name(n) {} bool operator()(method_rep const& o) const { return std::strcmp(o.name, name) == 0; } char const* name; }; }} #ifndef LUABIND_NO_ERROR_CHECKING std::string luabind::detail::get_overload_signatures_candidates( lua_State* L , std::vector
::iterator start , std::vector
::iterator end , std::string name) { std::string s; for (; start != end; ++start) { s += name; (*start)->get_signature(L, s); s += "\n"; } return s; } #endif luabind::detail::class_rep::class_rep(LUABIND_TYPE_INFO type , const char* name , lua_State* L , void(*destructor)(void*) , void(*const_holder_destructor)(void*) , LUABIND_TYPE_INFO holder_type , LUABIND_TYPE_INFO const_holder_type , void*(*extractor)(void*) , const void*(*const_extractor)(void*) , void(*const_converter)(void*,void*) , void(*construct_holder)(void*,void*) , void(*construct_const_holder)(void*,void*) , void(*default_construct_holder)(void*) , void(*default_construct_const_holder)(void*) , void(*adopt_fun)(void*) , int holder_size , int holder_alignment) : m_type(type) , m_holder_type(holder_type) , m_const_holder_type(const_holder_type) , m_extractor(extractor) , m_const_extractor(const_extractor) , m_const_converter(const_converter) , m_construct_holder(construct_holder) , m_construct_const_holder(construct_const_holder) , m_default_construct_holder(default_construct_holder) , m_default_construct_const_holder(default_construct_const_holder) , m_adopt_fun(adopt_fun) , m_holder_size(holder_size) , m_holder_alignment(holder_alignment) , m_name(name) , m_class_type(cpp_class) , m_destructor(destructor) , m_const_holder_destructor(const_holder_destructor) , m_operator_cache(0) { assert(m_holder_alignment >= 1 && "internal error"); lua_newtable(L); handle(L, -1).swap(m_table); lua_newtable(L); handle(L, -1).swap(m_default_table); lua_pop(L, 2); class_registry* r = class_registry::get_registry(L); assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()"); detail::getref(L, r->cpp_class()); lua_setmetatable(L, -2); lua_pushvalue(L, -1); // duplicate our user data m_self_ref.set(L); m_instance_metatable = r->cpp_instance(); } luabind::detail::class_rep::class_rep(lua_State* L, const char* name) : m_type(LUABIND_INVALID_TYPE_INFO) , m_holder_type(LUABIND_INVALID_TYPE_INFO) , m_const_holder_type(LUABIND_INVALID_TYPE_INFO) , m_extractor(0) , m_const_extractor(0) , m_const_converter(0) , m_construct_holder(0) , m_construct_const_holder(0) , m_default_construct_holder(0) , m_default_construct_const_holder(0) , m_adopt_fun(0) , m_holder_size(0) , m_holder_alignment(1) , m_name(name) , m_class_type(lua_class) , m_destructor(0) , m_const_holder_destructor(0) , m_operator_cache(0) { lua_newtable(L); handle(L, -1).swap(m_table); lua_newtable(L); handle(L, -1).swap(m_default_table); lua_pop(L, 2); class_registry* r = class_registry::get_registry(L); assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()"); detail::getref(L, r->lua_class()); lua_setmetatable(L, -2); lua_pushvalue(L, -1); // duplicate our user data m_self_ref.set(L); m_instance_metatable = r->lua_instance(); } luabind::detail::class_rep::~class_rep() { } // leaves object on lua stack std::pair
luabind::detail::class_rep::allocate(lua_State* L) const { const int overlap = sizeof(object_rep)&(m_holder_alignment-1); const int padding = overlap==0?0:m_holder_alignment-overlap; const int size = sizeof(object_rep) + padding + m_holder_size; char* mem = static_cast
(lua_newuserdata(L, size)); char* ptr = mem + sizeof(object_rep) + padding; return std::pair
(mem,ptr); } /* #include
namespace { void dump_stack(lua_State* L) { for (int i = 1; i <= lua_gettop(L); ++i) { int t = lua_type(L, i); switch (t) { case LUA_TNUMBER: std::cout << "[" << i << "] number: " << lua_tonumber(L, i) << "\n"; break; case LUA_TSTRING: std::cout << "[" << i << "] string: " << lua_tostring(L, i) << "\n"; break; case LUA_TUSERDATA: std::cout << "[" << i << "] userdata: " << lua_touserdata(L, i) << "\n"; break; case LUA_TTABLE: std::cout << "[" << i << "] table:\n"; break; case LUA_TNIL: std::cout << "[" << i << "] nil:\n"; break; } } } } */ void luabind::detail::class_rep::adopt(bool const_obj, void* obj) { if (m_adopt_fun == 0) return; if (m_extractor) { assert(m_const_extractor); if (const_obj) m_adopt_fun(const_cast
(m_const_extractor(obj))); else m_adopt_fun(m_extractor(obj)); } else { m_adopt_fun(obj); } } // lua stack: userdata, key int luabind::detail::class_rep::gettable(lua_State* L) { // if key is nil, return nil if (lua_isnil(L, 2)) { lua_pushnil(L); return 1; } object_rep* obj = static_cast
(lua_touserdata(L, 1)); // we have to ignore the first argument since this may point to // a method that is not present in this class (but in a subclass) const char* key = lua_tostring(L, 2); #ifndef LUABIND_NO_ERROR_CHECKING if (std::strlen(key) != lua_strlen(L, 2)) { { std::string msg("luabind does not support " "member names with extra nulls:\n"); msg += std::string(lua_tostring(L, 2), lua_strlen(L, 2)); lua_pushstring(L, msg.c_str()); } lua_error(L); } #endif // special case to see if this is a null-pointer if (key && !std::strcmp(key, "__ok")) { class_rep* crep = obj->crep(); void* p = crep->extractor() ? crep->extractor()(obj->ptr()) : obj->ptr(); lua_pushboolean(L, p != 0); return 1; } // First, look in the instance's table detail::lua_reference const& tbl = obj->get_lua_table(); if (tbl.is_valid()) { tbl.get(L); lua_pushvalue(L, 2); lua_gettable(L, -2); if (!lua_isnil(L, -1)) { lua_remove(L, -2); // remove table return 1; } lua_pop(L, 2); } // Then look in the class' table for this member obj->crep()->get_table(L); lua_pushvalue(L, 2); lua_gettable(L, -2); if (!lua_isnil(L, -1)) { lua_remove(L, -2); // remove table return 1; } lua_pop(L, 2); std::map
::iterator j = m_getters.find(key); if (j != m_getters.end()) { // the name is a data member return j->second.func(L, j->second.pointer_offset); } lua_pushnil(L); return 1; } // called from the metamethod for __newindex // the object pointer is passed on the lua stack // lua stack: userdata, key, value bool luabind::detail::class_rep::settable(lua_State* L) { // if the key is 'nil' fail if (lua_isnil(L, 2)) return false; // we have to ignore the first argument since this may point to // a method that is not present in this class (but in a subclass) const char* key = lua_tostring(L, 2); if (std::strlen(key) == lua_strlen(L, 2)) { std::map
::iterator j = m_setters.find(key); if (j != m_setters.end()) { // the name is a data member #ifndef LUABIND_NO_ERROR_CHECKING if (j->second.match(L, 3) < 0) { std::string msg("the attribute '"); msg += m_name; msg += "."; msg += key; msg += "' is of type: "; j->second.sig(L, msg); msg += "\nand does not match: ("; msg += stack_content_by_name(L, 3); msg += ")"; lua_pushstring(L, msg.c_str()); return false; } #endif j->second.func(L, j->second.pointer_offset); return true; } if (m_getters.find(key) != m_getters.end()) { // this means that we have a getter but no // setter for an attribute. We will then fail // because that attribute is read-only std::string msg("the attribute '"); msg += m_name; msg += "."; msg += key; msg += "' is read only"; lua_pushstring(L, msg.c_str()); return false; } } // set the attribute to the object's table object_rep* obj = static_cast
(lua_touserdata(L, 1)); detail::lua_reference& tbl = obj->get_lua_table(); if (!tbl.is_valid()) { // this is the first time we are trying to add // a member to this instance, create the table. lua_newtable(L); lua_pushvalue(L, -1); tbl.set(L); } else { tbl.get(L); } lua_pushvalue(L, 2); lua_pushvalue(L, 3); lua_settable(L, 4); lua_pop(L, 3); return true; } int class_rep::gettable_dispatcher(lua_State* L) { object_rep* obj = static_cast
(lua_touserdata(L, 1)); return obj->crep()->gettable(L); } // this is called as __newindex metamethod on every instance of this class int luabind::detail::class_rep::settable_dispatcher(lua_State* L) { object_rep* obj = static_cast
(lua_touserdata(L, 1)); bool success = obj->crep()->settable(L); #ifndef LUABIND_NO_ERROR_CHECKING if (!success) { // class_rep::settable() will leave // error message on the stack in case // of failure lua_error(L); } #endif return 0; } int luabind::detail::class_rep::operator_dispatcher(lua_State* L) { for (int i = 0; i < 2; ++i) { if (is_class_object(L, 1 + i)) { int nargs = lua_gettop(L); lua_pushvalue(L, lua_upvalueindex(1)); lua_gettable(L, 1 + i); if (lua_isnil(L, -1)) { lua_pop(L, 1); continue; } lua_insert(L, 1); // move the function to the bottom nargs = lua_toboolean(L, lua_upvalueindex(2)) ? 1 : nargs; if (lua_toboolean(L, lua_upvalueindex(2))) // remove trailing nil lua_remove(L, 3); lua_call(L, nargs, 1); return 1; } } lua_pop(L, lua_gettop(L)); lua_pushstring(L, "No such operator defined"); lua_error(L); return 0; } // this is called as metamethod __call on the class_rep. int luabind::detail::class_rep::constructor_dispatcher(lua_State* L) { class_rep* crep = static_cast
(lua_touserdata(L, 1)); construct_rep* rep = &crep->m_constructor; bool ambiguous = false; int match_index = -1; int min_match = std::numeric_limits
::max(); bool found; #ifdef LUABIND_NO_ERROR_CHECKING if (rep->overloads.size() == 1) { match_index = 0; found = true; } else { #endif int num_params = lua_gettop(L) - 1; overload_rep_base const* first = rep->overloads.empty() ? 0 : &rep->overloads.front(); found = find_best_match(L, first, rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params); #ifdef LUABIND_NO_ERROR_CHECKING } #else if (!found) { { std::string msg("no constructor of '"); msg += crep->name(); msg += "' matched the arguments ("; msg += stack_content_by_name(L, 2); msg += ")\n candidates are:\n"; msg += get_overload_signatures(L, rep->overloads.begin(), rep->overloads.end(), crep->name()); lua_pushstring(L, msg.c_str()); } lua_error(L); } else if (ambiguous) { { std::string msg("call of overloaded constructor '"); msg += crep->m_name; msg += "("; msg += stack_content_by_name(L, 2); msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n"; std::vector
candidates; find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates); msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name()); lua_pushstring(L, msg.c_str()); } lua_error(L); } #endif #ifndef LUABIND_NO_EXCEPTIONS try { #endif void* obj_rep; void* held; boost::tie(obj_rep,held) = crep->allocate(L); weak_ref backref(L, -1); void* object_ptr = rep->overloads[match_index].construct(L, backref); if (crep->has_holder()) { crep->m_construct_holder(held, object_ptr); object_ptr = held; } new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor()); detail::getref(L, crep->m_instance_metatable); lua_setmetatable(L, -2); return 1; #ifndef LUABIND_NO_EXCEPTIONS } catch(const error&) { } catch(const std::exception& e) { lua_pushstring(L, e.what()); } catch(const char* s) { lua_pushstring(L, s); } catch(...) { { std::string msg = crep->name(); msg += "() threw an exception"; lua_pushstring(L, msg.c_str()); } } // we can only reach this line if an exception was thrown lua_error(L); return 0; // will never be reached #endif } /* the functions dispatcher assumes the following: upvalues: 1: method_rep* method, points to the method_rep that this dispatcher is to call 2: boolean force_static, is true if this is to be a static call and false if it is a normal call (= virtual if possible). stack: 1: object_rep* self, points to the object the call is being made on */ int luabind::detail::class_rep::function_dispatcher(lua_State* L) { #ifndef NDEBUG /* lua_Debug tmp_; assert(lua_getinfo(L, "u", &tmp_)); assert(tmp_.nups == 2);*/ assert(lua_type(L, lua_upvalueindex(1)) == LUA_TLIGHTUSERDATA); assert(lua_type(L, lua_upvalueindex(2)) == LUA_TBOOLEAN); assert(lua_type(L, lua_upvalueindex(3)) == LUA_TLIGHTUSERDATA); assert(lua_touserdata(L, lua_upvalueindex(3)) == reinterpret_cast
(0x1337)); // assert(lua_type(L, 1) == LUA_TUSERDATA); #endif method_rep* rep = static_cast
(lua_touserdata(L, lua_upvalueindex(1))); int force_static_call = lua_toboolean(L, lua_upvalueindex(2)); bool ambiguous = false; int match_index = -1; int min_match = std::numeric_limits
::max(); bool found; #ifdef LUABIND_NO_ERROR_CHECKING if (rep->overloads().size() == 1) { match_index = 0; } else { #endif int num_params = lua_gettop(L) /*- 1*/; found = find_best_match(L, &rep->overloads().front(), rep->overloads().size() , sizeof(overload_rep), ambiguous, min_match, match_index, num_params); #ifdef LUABIND_NO_ERROR_CHECKING } #else if (!found) { { std::string msg = "no overload of '"; msg += rep->crep->name(); msg += ":"; msg += rep->name; msg += "' matched the arguments ("; msg += stack_content_by_name(L, 1); msg += ")\ncandidates are:\n"; std::string function_name; function_name += rep->crep->name(); function_name += ":"; function_name += rep->name; msg += get_overload_signatures(L, rep->overloads().begin() , rep->overloads().end(), function_name); lua_pushstring(L, msg.c_str()); } lua_error(L); } else if (ambiguous) { { std::string msg = "call of overloaded '"; msg += rep->crep->name(); msg += ":"; msg += rep->name; msg += "("; msg += stack_content_by_name(L, 1); msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n"; std::vector
candidates; find_exact_match(L, &rep->overloads().front(), rep->overloads().size() , sizeof(overload_rep), min_match, num_params, candidates); std::string function_name; function_name += rep->crep->name(); function_name += ":"; function_name += rep->name; msg += get_overload_signatures_candidates(L, candidates.begin() , candidates.end(), function_name); lua_pushstring(L, msg.c_str()); } lua_error(L); } #endif #ifndef LUABIND_NO_EXCEPTIONS try { #endif const overload_rep& o = rep->overloads()[match_index]; if (force_static_call && !o.has_static()) { lua_pushstring(L, "pure virtual function called"); } else { return o.call(L, force_static_call != 0); } #ifndef LUABIND_NO_EXCEPTIONS } catch(const error&) { } catch(const std::exception& e) { lua_pushstring(L, e.what()); } catch (const char* s) { lua_pushstring(L, s); } catch(...) { std::string msg = rep->crep->name(); msg += ":"; msg += rep->name; msg += "() threw an exception"; lua_pushstring(L, msg.c_str()); } #endif // we can only reach this line if an error occured lua_error(L); return 0; // will never be reached } #ifndef NDEBUG #ifndef BOOST_NO_STRINGSTREAM #include
#else #include
#endif namespace { std::string to_string(luabind::object const& o) { using namespace luabind; if (type(o) == LUA_TSTRING) return object_cast
(o); lua_State* L = o.interpreter(); LUABIND_CHECK_STACK(L); #ifdef BOOST_NO_STRINGSTREAM std::strstream s; #else std::stringstream s; #endif if (type(o) == LUA_TNUMBER) { s << object_cast
(o); return s.str(); } s << "<" << lua_typename(L, type(o)) << ">"; #ifdef BOOST_NO_STRINGSTREAM s << std::ends; #endif return s.str(); } std::string member_to_string(luabind::object const& e) { #if !defined(LUABIND_NO_ERROR_CHECKING) using namespace luabind; lua_State* L = e.interpreter(); LUABIND_CHECK_STACK(L); if (type(e) == LUA_TFUNCTION) { e.push(L); detail::stack_pop p(L, 1); { if (lua_getupvalue(L, -1, 3) == 0) return to_string(e); detail::stack_pop p2(L, 1); if (lua_touserdata(L, -1) != reinterpret_cast
(0x1337)) return to_string(e); } #ifdef BOOST_NO_STRINGSTREAM std::strstream s; #else std::stringstream s; #endif { lua_getupvalue(L, -1, 2); detail::stack_pop p2(L, 1); int b = lua_toboolean(L, -1); s << "
"; } { lua_getupvalue(L, -1, 1); detail::stack_pop p2(L, 1); method_rep* m = static_cast
(lua_touserdata(L, -1)); s << m << "\n"; for (std::vector
::const_iterator i = m->overloads().begin(); i != m->overloads().end(); ++i) { std::string str; i->get_signature(L, str); s << " " << str << "\n"; } } #ifdef BOOST_NO_STRINGSTREAM s << std::ends; #endif return s.str(); } return to_string(e); #else return ""; #endif } } std::string luabind::detail::class_rep::class_info_string(lua_State* L) const { #ifdef BOOST_NO_STRINGSTREAM std::strstream ret; #else std::stringstream ret; #endif ret << "CLASS: " << m_name << "\n"; ret << "dynamic dispatch functions:\n------------------\n"; for (luabind::iterator i(m_table), end; i != end; ++i) { luabind::object e = *i; ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n"; } ret << "default implementations:\n------------------\n"; for (luabind::iterator i(m_default_table), end; i != end; ++i) { luabind::object e = *i; ret << " " << to_string(i.key()) << ": " << member_to_string(e) << "\n"; } #ifdef BOOST_NO_STRINGSTREAM ret << std::ends; #endif return ret.str(); } #endif void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo) { // If you hit this assert you are deriving from a type that is not registered // in lua. That is, in the class_<> you are giving a baseclass that isn't registered. // Please note that if you don't need to have access to the base class or the // conversion from the derived class to the base class, you don't need // to tell luabind that it derives. assert(binfo.base && "You cannot derive from an unregistered type"); class_rep* bcrep = binfo.base; // import all functions from the base typedef std::list
methods_t; for (methods_t::const_iterator i = bcrep->m_methods.begin(); i != bcrep->m_methods.end(); ++i) { add_method(*i); } // import all getters from the base for (std::map
::const_iterator i = bcrep->m_getters.begin(); i != bcrep->m_getters.end(); ++i) { callback& m = m_getters[i->first]; m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset; m.func = i->second.func; #ifndef LUABIND_NO_ERROR_CHECKING m.match = i->second.match; m.sig = i->second.sig; #endif } // import all setters from the base for (std::map
::const_iterator i = bcrep->m_setters.begin(); i != bcrep->m_setters.end(); ++i) { callback& m = m_setters[i->first]; m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset; m.func = i->second.func; #ifndef LUABIND_NO_ERROR_CHECKING m.match = i->second.match; m.sig = i->second.sig; #endif } // import all static constants for (std::map
::const_iterator i = bcrep->m_static_constants.begin(); i != bcrep->m_static_constants.end(); ++i) { int& v = m_static_constants[i->first]; v = i->second; } // import all operators for (int i = 0; i < number_of_operators; ++i) { for (std::vector
::const_iterator j = bcrep->m_operators[i].begin(); j != bcrep->m_operators[i].end(); ++j) m_operators[i].push_back(*j); } // also, save the baseclass info to be used for typecasts m_bases.push_back(binfo); } int luabind::detail::class_rep::super_callback(lua_State* L) { int args = lua_gettop(L); object_rep* obj = static_cast
(lua_touserdata(L, lua_upvalueindex(2))); class_rep* crep = static_cast
(lua_touserdata(L, lua_upvalueindex(1))); class_rep* base = crep->bases()[0].base; if (base->get_class_type() == class_rep::lua_class) { if (base->bases().empty()) { obj->set_flags(obj->flags() & ~object_rep::call_super); lua_pushstring(L, "super"); lua_pushnil(L); lua_settable(L, LUA_GLOBALSINDEX); } else { lua_pushstring(L, "super"); lua_pushlightuserdata(L, base); lua_pushvalue(L, lua_upvalueindex(2)); lua_pushcclosure(L, super_callback, 2); lua_settable(L, LUA_GLOBALSINDEX); } base->get_table(L); lua_pushstring(L, "__init"); lua_gettable(L, -2); lua_insert(L, 1); lua_pop(L, 1); lua_pushvalue(L, lua_upvalueindex(2)); lua_insert(L, 2); lua_call(L, args + 1, 0); // TODO: instead of clearing the global variable "super" // store it temporarily in the registry. maybe we should // have some kind of warning if the super global is used? lua_pushstring(L, "super"); lua_pushnil(L); lua_settable(L, LUA_GLOBALSINDEX); } else { obj->set_flags(obj->flags() & ~object_rep::call_super); // we need to push some garbage at index 1 to make the construction work lua_pushboolean(L, 1); lua_insert(L, 1); construct_rep* rep = &base->m_constructor; bool ambiguous = false; int match_index = -1; int min_match = std::numeric_limits
::max(); bool found; #ifdef LUABIND_NO_ERROR_CHECKING if (rep->overloads.size() == 1) { match_index = 0; } else { #endif int num_params = lua_gettop(L) - 1; found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params); #ifdef LUABIND_NO_ERROR_CHECKING } #else if (!found) { { std::string msg = "no constructor of '"; msg += base->m_name; msg += "' matched the arguments ("; msg += stack_content_by_name(L, 2); msg += ")"; lua_pushstring(L, msg.c_str()); } lua_error(L); } else if (ambiguous) { { std::string msg = "call of overloaded constructor '"; msg += base->m_name; msg += "("; msg += stack_content_by_name(L, 2); msg += ")' is ambiguous"; lua_pushstring(L, msg.c_str()); } lua_error(L); } // TODO: should this be a warning or something? /* // since the derived class is a lua class // it may have reimplemented virtual functions // therefore, we have to instantiate the Basewrapper // if there is no basewrapper, throw a run-time error if (!rep->overloads[match_index].has_wrapped_construct()) { { std::string msg = "Cannot derive from C++ class '"; msg += base->name(); msg += "'. It does not have a wrapped type"; lua_pushstring(L, msg.c_str()); } lua_error(L); } */ #endif #ifndef LUABIND_NO_EXCEPTIONS try { #endif lua_pushvalue(L, lua_upvalueindex(2)); weak_ref backref(L, -1); lua_pop(L, 1); void* storage_ptr = obj->ptr(); if (!rep->overloads[match_index].has_wrapped_construct()) { // if the type doesn't have a wrapped type, use the ordinary constructor void* instance = rep->overloads[match_index].construct(L, backref); if (crep->has_holder()) { crep->m_construct_holder(storage_ptr, instance); } else { obj->set_object(instance); } } else { // get reference to lua object /* lua_pushvalue(L, lua_upvalueindex(2)); detail::lua_reference ref; ref.set(L); void* instance = rep->overloads[match_index].construct_wrapped(L, ref);*/ void* instance = rep->overloads[match_index].construct_wrapped(L, backref); if (crep->has_holder()) { crep->m_construct_holder(storage_ptr, instance); } else { obj->set_object(instance); } } // TODO: is the wrapped type destructed correctly? // it should, since the destructor is either the wrapped type's // destructor or the base type's destructor, depending on wether // the type has a wrapped type or not. obj->set_destructor(base->destructor()); return 0; #ifndef LUABIND_NO_EXCEPTIONS } catch(const error&) { } catch(const std::exception& e) { lua_pushstring(L, e.what()); } catch(const char* s) { lua_pushstring(L, s); } catch(...) { std::string msg = base->m_name; msg += "() threw an exception"; lua_pushstring(L, msg.c_str()); } // can only be reached if an exception was thrown lua_error(L); #endif } return 0; } int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L) { class_rep* crep = static_cast
(lua_touserdata(L, 1)); // get first table crep->get_table(L); // copy key, value lua_pushvalue(L, -3); lua_pushvalue(L, -3); lua_rawset(L, -3); // pop table lua_pop(L, 1); // get default table crep->get_default_table(L); lua_replace(L, 1); lua_rawset(L, -3); crep->m_operator_cache = 0; // invalidate cache return 0; } int luabind::detail::class_rep::construct_lua_class_callback(lua_State* L) { class_rep* crep = static_cast
(lua_touserdata(L, 1)); int args = lua_gettop(L); // lua stack: crep
lua_newtable(L); detail::lua_reference ref; ref.set(L); bool has_bases = !crep->bases().empty(); if (has_bases) { lua_pushstring(L, "super"); lua_pushvalue(L, 1); // crep } // lua stack: crep
"super" crep // or // lua stack: crep
// if we have a baseclass we set the flag to say that the super has not yet been called // we will use this flag later to check that it actually was called from __init() int flags = object_rep::lua_class | object_rep::owner | (has_bases ? object_rep::call_super : 0); // void* obj_ptr = lua_newuserdata(L, sizeof(object_rep)); void* obj_ptr; void* held_storage; boost::tie(obj_ptr, held_storage) = crep->allocate(L); (new(obj_ptr) object_rep(crep, flags, ref))->set_object(held_storage); detail::getref(L, crep->metatable_ref()); lua_setmetatable(L, -2); // lua stack: crep
"super" crep obj_ptr // or // lua stack: crep
obj_ptr if (has_bases) lua_pushvalue(L, -1); // obj_ptr lua_replace(L, 1); // obj_ptr // lua stack: obj_ptr
"super" crep obj_ptr // or // lua stack: obj_ptr
if (has_bases) { lua_pushcclosure(L, super_callback, 2); // lua stack: crep
"super" function lua_settable(L, LUA_GLOBALSINDEX); } // lua stack: crep
lua_pushvalue(L, 1); lua_insert(L, 1); crep->get_table(L); lua_pushstring(L, "__init"); lua_gettable(L, -2); #ifndef LUABIND_NO_ERROR_CHECKING // TODO: should this be a run-time error? // maybe the default behavior should be to just call // the base calss' constructor. We should register // the super callback funktion as __init if (!lua_isfunction(L, -1)) { { std::string msg = crep->name(); msg += ":__init is not defined"; lua_pushstring(L, msg.c_str()); } lua_error(L); } #endif lua_insert(L, 2); // function first on stack lua_pop(L, 1); // TODO: lua_call may invoke longjump! make sure we don't have any memory leaks! // we don't have any stack objects here lua_call(L, args, 0); #ifndef LUABIND_NO_ERROR_CHECKING object_rep* obj = static_cast
(obj_ptr); if (obj->flags() & object_rep::call_super) { lua_pushstring(L, "derived class must call super on base"); lua_error(L); } #endif return 1; } // called from the metamethod for __index // obj is the object pointer int luabind::detail::class_rep::lua_class_gettable(lua_State* L) { object_rep* obj = static_cast
(lua_touserdata(L, 1)); class_rep* crep = obj->crep(); #ifndef LUABIND_NO_ERROR_CHECKING if (obj->flags() & object_rep::call_super) { lua_pushstring(L, "derived class must call super on base"); lua_error(L); } #endif // we have to ignore the first argument since this may point to // a method that is not present in this class (but in a subclass) // BUG: This might catch members called "__ok\0foobar" const char* key = lua_tostring(L, 2); if (key && !std::strcmp(key, "__ok")) { class_rep* crep = obj->crep(); void* p = crep->extractor() ? crep->extractor()(obj->ptr()) : obj->ptr(); lua_pushboolean(L, p != 0); return 1; } // first look in the instance's table detail::lua_reference const& tbl = obj->get_lua_table(); assert(tbl.is_valid()); tbl.get(L); lua_pushvalue(L, 2); lua_gettable(L, -2); if (!lua_isnil(L, -1)) { lua_remove(L, -2); // remove table return 1; } lua_pop(L, 2); // then look in the class' table crep->get_table(L); lua_pushvalue(L, 2); lua_gettable(L, -2); if (!lua_isnil(L, -1)) { lua_remove(L, -2); // more table return 1; } lua_pop(L, 2); if (lua_isnil(L, 2)) { lua_pushnil(L); return 1; } std::map
::iterator j = crep->m_getters.find(key); if (j != crep->m_getters.end()) { // the name is a data member return j->second.func(L, j->second.pointer_offset); } lua_pushnil(L); return 1; } // called from the metamethod for __newindex // obj is the object pointer int luabind::detail::class_rep::lua_class_settable(lua_State* L) { object_rep* obj = static_cast
(lua_touserdata(L, 1)); class_rep* crep = obj->crep(); #ifndef LUABIND_NO_ERROR_CHECKING if (obj->flags() & object_rep::call_super) { // this block makes sure the std::string is destructed // before lua_error is called { std::string msg = "derived class '"; msg += crep->name(); msg += "'must call super on base"; lua_pushstring(L, msg.c_str()); } lua_error(L); } #endif // we have to ignore the first argument since this may point to // a method that is not present in this class (but in a subclass) // BUG: This will not work with keys with extra nulls in them const char* key = lua_tostring(L, 2); std::map
::iterator j = crep->m_setters.find(key); // if the strlen(key) is not the true length, // it means that the member-name contains // extra nulls. luabind does not support such // names as member names. So, use the lua // table as fall-back if (j == crep->m_setters.end() || std::strlen(key) != lua_strlen(L, 2)) { std::map
::iterator k = crep->m_getters.find(key); #ifndef LUABIND_NO_ERROR_CHECKING if (k != crep->m_getters.end()) { { std::string msg = "cannot set property '"; msg += crep->name(); msg += "."; msg += key; msg += "', because it's read only"; lua_pushstring(L, msg.c_str()); } lua_error(L); } #endif detail::lua_reference const& tbl = obj->get_lua_table(); assert(tbl.is_valid()); tbl.get(L); lua_replace(L, 1); lua_settable(L, 1); } else { // the name is a data member j->second.func(L, j->second.pointer_offset); } return 0; } /* stack: 1: class_rep 2: member name */ int luabind::detail::class_rep::static_class_gettable(lua_State* L) { class_rep* crep = static_cast
(lua_touserdata(L, 1)); // look in the static function table crep->get_default_table(L); lua_pushvalue(L, 2); lua_gettable(L, -2); if (!lua_isnil(L, -1)) return 1; else lua_pop(L, 2); const char* key = lua_tostring(L, 2); if (std::strlen(key) != lua_strlen(L, 2)) { lua_pushnil(L); return 1; } std::map
::const_iterator j = crep->m_static_constants.find(key); if (j != crep->m_static_constants.end()) { lua_pushnumber(L, j->second); return 1; } #ifndef LUABIND_NO_ERROR_CHECKING { std::string msg = "no static '"; msg += key; msg += "' in class '"; msg += crep->name(); msg += "'"; lua_pushstring(L, msg.c_str()); } lua_error(L); #endif lua_pushnil(L); return 1; } bool luabind::detail::is_class_rep(lua_State* L, int index) { if (lua_getmetatable(L, index) == 0) return false; lua_pushstring(L, "__luabind_classrep"); lua_gettable(L, -2); if (lua_toboolean(L, -1)) { lua_pop(L, 2); return true; } lua_pop(L, 2); return false; } void luabind::detail::finalize(lua_State* L, class_rep* crep) { if (crep->get_class_type() != class_rep::lua_class) return; // lua_pushvalue(L, -1); // copy the object ref crep->get_table(L); lua_pushstring(L, "__finalize"); lua_gettable(L, -2); lua_remove(L, -2); if (lua_isnil(L, -1)) { lua_pop(L, 1); } else { lua_pushvalue(L, -2); lua_call(L, 1, 0); } for (std::vector
::const_iterator i = crep->bases().begin(); i != crep->bases().end(); ++i) { if (i->base) finalize(L, i->base); } } void* luabind::detail::class_rep::convert_to( LUABIND_TYPE_INFO target_type , const object_rep* obj , void* target_memory) const { // TODO: since this is a member function, we don't have to use the accesor functions for // the types and the extractor assert(obj == 0 || obj->crep() == this); int steps = 0; int offset = 0; if (!(LUABIND_TYPE_INFO_EQUAL(holder_type(), target_type)) && !(LUABIND_TYPE_INFO_EQUAL(const_holder_type(), target_type))) { steps = implicit_cast(this, target_type, offset); } // should never be called with a type that can't be cast assert((steps >= 0) && "internal error, please report"); if (LUABIND_TYPE_INFO_EQUAL(target_type, holder_type())) { if (obj == 0) { // we are trying to convert nil to a holder type m_default_construct_holder(target_memory); return target_memory; } // if the type we are trying to convert to is the holder_type // it means that his crep has a holder_type (since it would have // been invalid otherwise, and T cannot be invalid). It also means // that we need no conversion, since the holder_type is what the // object points to. return obj->ptr(); } if (LUABIND_TYPE_INFO_EQUAL(target_type, const_holder_type())) { if (obj == 0) { // we are trying to convert nil to a const holder type m_default_construct_const_holder(target_memory); return target_memory; } if (obj->flags() & object_rep::constant) { // we are holding a constant return obj->ptr(); } else { // we are holding a non-constant, we need to convert it // to a const_holder. m_const_converter(obj->ptr(), target_memory); return target_memory; } } void* raw_pointer; if (has_holder()) { assert(obj); // this means that we have a holder type where the // raw-pointer needs to be extracted raw_pointer = extractor()(obj->ptr()); } else { if (obj == 0) raw_pointer = 0; else raw_pointer = obj->ptr(); } return static_cast
(raw_pointer) + offset; } void luabind::detail::class_rep::cache_operators(lua_State* L) { m_operator_cache = 0x1; for (int i = 0; i < number_of_operators; ++i) { get_table(L); lua_pushstring(L, get_operator_name(i)); lua_rawget(L, -2); if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1); lua_pop(L, 2); } } bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id) { if ((m_operator_cache & 0x1) == 0) cache_operators(L); const int mask = 1 << (id + 1); return (m_operator_cache & mask) != 0; } // this will merge all overloads of fun into the list of // overloads in this class void luabind::detail::class_rep::add_method(luabind::detail::method_rep const& fun) { typedef std::list
methods_t; methods_t::iterator m = std::find_if( m_methods.begin() , m_methods.end() , method_name(fun.name)); if (m == m_methods.end()) { m_methods.push_back(method_rep()); m = m_methods.end(); std::advance(m, -1); m->name = fun.name; } m->crep = this; typedef std::vector
overloads_t; for (overloads_t::const_iterator j = fun.overloads().begin(); j != fun.overloads().end(); ++j) { detail::overload_rep o = *j; m->add_overload(o); } } // this function will add all the overloads in method rep to // this class' lua tables. If there already are overloads with this // name, thses will simply be appended to the overload list void luabind::detail::class_rep::register_methods(lua_State* L) { LUABIND_CHECK_STACK(L); // insert the function in the normal member table // and in the default member table m_default_table.push(L); m_table.push(L); // pops the tables detail::stack_pop pop_tables(L, 2); for (std::list
::const_iterator m = m_methods.begin(); m != m_methods.end(); ++m) { // create the function closure in m_table lua_pushstring(L, m->name); lua_pushlightuserdata(L, const_cast
((const void*)&(*m))); lua_pushboolean(L, 0); lua_pushlightuserdata(L, reinterpret_cast
(0x1337)); lua_pushcclosure(L, function_dispatcher, 3); lua_settable(L, -3); // create the function closure in m_default_table lua_pushstring(L, m->name); lua_pushlightuserdata(L, const_cast
((const void*)&(*m))); lua_pushboolean(L, 1); lua_pushlightuserdata(L, reinterpret_cast
(0x1337)); lua_pushcclosure(L, function_dispatcher, 3); lua_settable(L, -4); } } const class_rep::property_map& luabind::detail::class_rep::properties() const { return m_getters; }
class_rep.cpp
Page URL
File URL
Prev
4/21
Next
Download
( 40 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.