lua++
C:/Documents and Settings/Kalith/My Documents/Programmation/luapp/src/luapp_function.cpp
Go to the documentation of this file.
00001 /* ###################################### */
00002 /* ###     Frost Engine, by Kalith    ### */
00003 /* ###################################### */
00004 /*               Lua source               */
00005 /*                                        */
00006 
00007 #include "luapp_state.hpp"
00008 #include "luapp_function.hpp"
00009 #include <utils_string.hpp>
00010 
00011 namespace lua
00012 {
00013 function::function(const std::string& sName, lua_State* pLua, uint uiReturnNbr) :
00014     sName_(sName), uiReturnNbr_(uiReturnNbr)
00015 {
00016     pLua_ = state::get_state(pLua);
00017     new_param_set();
00018 }
00019 
00020 function::function(const std::string& sName, state* pLua, uint uiReturnNbr) :
00021     sName_(sName), pLua_(pLua), uiReturnNbr_(uiReturnNbr)
00022 {
00023     new_param_set();
00024 }
00025 
00026 function::~function()
00027 {
00028     /*std::vector<argument_list>::iterator iterArgList;
00029     foreach (iterArgList, lArgListStack_)
00030     {
00031         std::map<uint, argument*>::iterator iter;
00032         foreach (iter, iterArgList->lOptional_)
00033         {
00034             iter->second.Delete();
00035         }
00036         foreach (iter, iterArgList->lArg_)
00037         {
00038             iter->second.Delete();
00039         }
00040     }*/
00041 }
00042 
00043 void function::add(uint uiIndex, const std::string& sName, type mLuaType, bool bOptional)
00044 {
00045     if (bOptional)
00046     {
00047         if (pArgList_->lOptional_.find(uiIndex) != pArgList_->lOptional_.end())
00048             pArgList_->lOptional_[uiIndex]->add(sName, mLuaType);
00049         else
00050             pArgList_->lOptional_[uiIndex] = utils::refptr<argument>(new argument(sName, mLuaType, this));
00051     }
00052     else
00053     {
00054         if (pArgList_->lArg_.find(uiIndex) != pArgList_->lArg_.end())
00055             pArgList_->lArg_[uiIndex]->add(sName, mLuaType);
00056         else
00057             pArgList_->lArg_[uiIndex] = utils::refptr<argument>(new argument(sName, mLuaType, this));
00058     }
00059 }
00060 
00061 void function::new_param_set()
00062 {
00063     lArgListStack_.push_back(argument_list());
00064     pArgList_ = &lArgListStack_.back();
00065     pArgList_->uiRank_ = lArgListStack_.size()-1;
00066 }
00067 
00068 uint function::get_param_set_rank()
00069 {
00070     return pArgList_->uiRank_;
00071 }
00072 
00073 utils::wptr<argument> function::get(uint uiIndex)
00074 {
00075     if (pArgList_->lArg_.find(uiIndex) != pArgList_->lArg_.end())
00076     {
00077         return pArgList_->lArg_[uiIndex];
00078     }
00079     if (pArgList_->lOptional_.find(uiIndex) != pArgList_->lOptional_.end())
00080     {
00081         return pArgList_->lOptional_[uiIndex];
00082     }
00083 
00084     return nullptr;
00085 }
00086 
00087 bool function::is_provided( uint uiIndex ) const
00088 {
00089     std::map<uint, utils::refptr<argument>>::const_iterator iter = pArgList_->lArg_.find(uiIndex);
00090     if (iter != pArgList_->lArg_.end())
00091     {
00092         return iter->second->is_provided();
00093     }
00094     iter = pArgList_->lOptional_.find(uiIndex);
00095     if (iter != pArgList_->lOptional_.end())
00096     {
00097         return iter->second->is_provided();
00098     }
00099 
00100     return false;
00101 }
00102 
00103 uint function::get_argument_count() const
00104 {
00105     return uiArgumentCount_;
00106 }
00107 
00108 bool function::check(bool bPrintError)
00109 {
00110     uiArgumentCount_ = pLua_->get_top();
00111 
00112     // Check if that's enough
00113     std::vector<argument_list>::iterator iterArgList;
00114     std::vector<argument_list*> lValidArgList;
00115     foreach (iterArgList, lArgListStack_)
00116     {
00117         if (uiArgumentCount_ >= iterArgList->lArg_.size())
00118             lValidArgList.push_back(&(*iterArgList));
00119     }
00120 
00121     if (lValidArgList.empty())
00122     {
00123         if (bPrintError)
00124         {
00125             std::string sError;
00126             foreach (iterArgList, lArgListStack_)
00127             {
00128                 std::string sarguments = "\n  - ["+utils::to_string(iterArgList->lArg_.size())+"] : ";
00129                 std::map<uint, utils::refptr<argument>>::iterator iterArg;
00130                 foreach (iterArg, iterArgList->lArg_)
00131                 {
00132                     if (iterArg != iterArgList->lArg_.begin())
00133                         sarguments += ", ";
00134                     sarguments += iterArg->second->get_data()->get_name();
00135                 }
00136                 if (iterArgList->lOptional_.size() > 0)
00137                 {
00138                     if (sarguments != "")
00139                         sarguments += ", ";
00140                     sarguments += "(+";
00141                     foreach (iterArg, iterArgList->lOptional_)
00142                     {
00143                         if (iterArg != iterArgList->lOptional_.begin())
00144                             sarguments += ", ";
00145                         sarguments += iterArg->second->get_data()->get_name();
00146                     }
00147                     sarguments += ")";
00148                 }
00149                 sError += sarguments;
00150             }
00151 
00152             if (lArgListStack_.size() == 1)
00153             {
00154                 pLua_->print_error(
00155                     "Too few arguments in \""+sName_+"\". Expected :"+sError
00156                 );
00157             }
00158             else
00159             {
00160                 pLua_->print_error(
00161                     "Too few arguments in \""+sName_+"\". Expected either :"+sError
00162                 );
00163             }
00164         }
00165         // So if there isn't enough, just return false
00166         return false;
00167     }
00168 
00169     // We then check the value type
00170     int i;
00171     std::map<uint, utils::refptr<argument>>::iterator iterArg;
00172     if (lValidArgList.size() > 1)
00173     {
00174         std::vector<argument_list*>::iterator iterArgListPtr;
00175         pArgList_ = nullptr;
00176         foreach (iterArgListPtr, lValidArgList)
00177         {
00178             i = 1;
00179             bool bValid = true;
00180             foreach (iterArg, (*iterArgListPtr)->lArg_)
00181             {
00182                 if (!iterArg->second->test(pLua_, i, false))
00183                 {
00184                     bValid = false;
00185                     break;
00186                 }
00187                 ++i;
00188             }
00189             if (bValid)
00190             {
00191                 pArgList_ = (*iterArgListPtr);
00192                 break;
00193             }
00194         }
00195 
00196         if (!pArgList_)
00197         {
00198             if (bPrintError)
00199             {
00200                 std::string sError;
00201                 foreach (iterArgList, lArgListStack_)
00202                 {
00203                     std::string sarguments = "\n  - ["+utils::to_string(iterArgList->lArg_.size())+"] : ";
00204                     std::map<uint, utils::refptr<argument>>::iterator iterArg;
00205                     foreach (iterArg, iterArgList->lArg_)
00206                     {
00207                         if (iterArg != iterArgList->lArg_.begin())
00208                             sarguments += ", ";
00209                         sarguments += iterArg->second->get_data()->get_name();
00210                     }
00211                     if (iterArgList->lOptional_.size() > 0)
00212                     {
00213                         if (sarguments != "")
00214                             sarguments += ", ";
00215                         sarguments += "(+";
00216                         foreach (iterArg, iterArgList->lOptional_)
00217                         {
00218                             if (iterArg != iterArgList->lOptional_.begin())
00219                                 sarguments += ", ";
00220                             sarguments += iterArg->second->get_data()->get_name();
00221                         }
00222                         sarguments += ")";
00223                     }
00224                     sError += sarguments;
00225                 }
00226 
00227                 pLua_->print_error(
00228                     "Wrong arguments provided to \""+sName_+"\". Expected either :"+sError
00229                 );
00230             }
00231             return false;
00232         }
00233     }
00234     else
00235     {
00236         pArgList_ = lValidArgList[0];
00237         i = 1;
00238         bool bValid = true;
00239         foreach (iterArg, pArgList_->lArg_)
00240         {
00241             if (!iterArg->second->test(pLua_, i, bPrintError))
00242                 bValid = false;
00243             ++i;
00244         }
00245 
00246         if (!bValid)
00247             return false;
00248     }
00249 
00250     // We fill the stack with nil value until there are enough for optional arguments
00251     uint uiMaxArgs = pArgList_->lArg_.size() + pArgList_->lOptional_.size();
00252     if (uiArgumentCount_ < uiMaxArgs)
00253         pLua_->push_nil(uiMaxArgs - uiArgumentCount_);
00254 
00255     // And we check optional arguments
00256     bool bValid = true;
00257     foreach (iterArg, pArgList_->lOptional_)
00258     {
00259         if (pLua_->get_type(i) != TYPE_NIL)
00260         {
00261             if (!iterArg->second->test(pLua_, i, bPrintError))
00262                 bValid = false;
00263         }
00264         ++i;
00265     }
00266 
00267     return bValid;
00268 }
00269 
00270 const std::string& function::get_name() const
00271 {
00272     return sName_;
00273 }
00274 
00275 void function::push( const var& vValue )
00276 {
00277     if (uiReturnCount_ == uiReturnNbr_)
00278         ++uiReturnNbr_;
00279 
00280     pLua_->push_var(vValue);
00281 
00282     ++uiReturnCount_;
00283 }
00284 
00285 void function::push_nil( uint uiNbr )
00286 {
00287     for (uint ui = 0; ui < uiNbr; ++ui)
00288     {
00289         if (uiReturnCount_ == uiReturnNbr_)
00290             ++uiReturnNbr_;
00291 
00292         pLua_->push_nil();
00293 
00294         ++uiReturnCount_;
00295     }
00296 }
00297 
00298 void function::notify_pushed()
00299 {
00300     if (uiReturnCount_ == uiReturnNbr_)
00301         ++uiReturnNbr_;
00302 
00303     ++uiReturnCount_;
00304 }
00305 
00306 int function::on_return()
00307 {
00308     if (uiReturnNbr_ != 0)
00309     {
00310         // Fill with nil value
00311         if (uiReturnCount_ < uiReturnNbr_)
00312             pLua_->push_nil(uiReturnNbr_ - uiReturnCount_);
00313 
00314         // Return the number of returned value
00315         return static_cast<int>(uiReturnNbr_);
00316     }
00317     else
00318         return 0;
00319 }
00320 
00321 state* function::get_state() const
00322 {
00323     return pLua_;
00324 }
00325 }