00001
00002
00003
00004
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), pLua_(state::get_state(pLua)), uiArgumentCount_(0u),
00015 uiReturnNbr_(uiReturnNbr), uiReturnCount_(0u), pArgList_(nullptr)
00016 {
00017 new_param_set();
00018 }
00019
00020 function::function(const std::string& sName, state* pLua, uint uiReturnNbr) :
00021 sName_(sName), pLua_(pLua), uiArgumentCount_(0u),
00022 uiReturnNbr_(uiReturnNbr), uiReturnCount_(0u), pArgList_(nullptr)
00023 {
00024 new_param_set();
00025 }
00026
00027 function::~function()
00028 {
00029 }
00030
00031 void function::add(uint uiIndex, const std::string& sName, type mLuaType, bool bOptional)
00032 {
00033 if (bOptional)
00034 {
00035 if (pArgList_->lOptional_.find(uiIndex) != pArgList_->lOptional_.end())
00036 pArgList_->lOptional_[uiIndex]->add(sName, mLuaType);
00037 else
00038 pArgList_->lOptional_[uiIndex] = utils::refptr<argument>(new argument(sName, mLuaType, this));
00039 }
00040 else
00041 {
00042 if (pArgList_->lArg_.find(uiIndex) != pArgList_->lArg_.end())
00043 pArgList_->lArg_[uiIndex]->add(sName, mLuaType);
00044 else
00045 pArgList_->lArg_[uiIndex] = utils::refptr<argument>(new argument(sName, mLuaType, this));
00046 }
00047 }
00048
00049 void function::new_param_set()
00050 {
00051 lArgListStack_.push_back(argument_list());
00052 pArgList_ = &lArgListStack_.back();
00053 pArgList_->uiRank_ = lArgListStack_.size()-1;
00054 }
00055
00056 uint function::get_param_set_rank()
00057 {
00058 return pArgList_->uiRank_;
00059 }
00060
00061 utils::wptr<argument> function::get(uint uiIndex)
00062 {
00063 if (pArgList_->lArg_.find(uiIndex) != pArgList_->lArg_.end())
00064 return pArgList_->lArg_[uiIndex];
00065
00066 if (pArgList_->lOptional_.find(uiIndex) != pArgList_->lOptional_.end())
00067 return pArgList_->lOptional_[uiIndex];
00068
00069 return nullptr;
00070 }
00071
00072 bool function::is_provided(uint uiIndex) const
00073 {
00074 std::map<uint, utils::refptr<argument>>::const_iterator iter = pArgList_->lArg_.find(uiIndex);
00075 if (iter != pArgList_->lArg_.end())
00076 return iter->second->is_provided();
00077
00078 iter = pArgList_->lOptional_.find(uiIndex);
00079 if (iter != pArgList_->lOptional_.end())
00080 return iter->second->is_provided();
00081
00082 return false;
00083 }
00084
00085 uint function::get_argument_count() const
00086 {
00087 return uiArgumentCount_;
00088 }
00089
00090 bool function::check(bool bPrintError)
00091 {
00092 uiArgumentCount_ = pLua_->get_top();
00093
00094
00095 std::vector<argument_list>::iterator iterArgList;
00096 std::vector<argument_list*> lValidArgList;
00097 foreach (iterArgList, lArgListStack_)
00098 {
00099 if (uiArgumentCount_ >= iterArgList->lArg_.size())
00100 lValidArgList.push_back(&(*iterArgList));
00101 }
00102
00103 if (lValidArgList.empty())
00104 {
00105 if (bPrintError)
00106 {
00107 std::string sError;
00108 foreach (iterArgList, lArgListStack_)
00109 {
00110 std::string sArguments = "\n - ["+utils::to_string(iterArgList->lArg_.size())+"] : ";
00111 std::map<uint, utils::refptr<argument>>::iterator iterArg;
00112 foreach (iterArg, iterArgList->lArg_)
00113 {
00114 if (iterArg != iterArgList->lArg_.begin())
00115 sArguments += ", ";
00116 sArguments += iterArg->second->get_data()->get_name();
00117 }
00118 if (iterArgList->lOptional_.size() > 0)
00119 {
00120 if (sArguments != "")
00121 sArguments += ", ";
00122 sArguments += "(+";
00123 foreach (iterArg, iterArgList->lOptional_)
00124 {
00125 if (iterArg != iterArgList->lOptional_.begin())
00126 sArguments += ", ";
00127 sArguments += iterArg->second->get_data()->get_name();
00128 }
00129 sArguments += ")";
00130 }
00131 sError += sArguments;
00132 }
00133
00134 if (lArgListStack_.size() == 1)
00135 {
00136 pLua_->print_error(
00137 "Too few arguments in \""+sName_+"\". Expected :"+sError
00138 );
00139 }
00140 else
00141 {
00142 pLua_->print_error(
00143 "Too few arguments in \""+sName_+"\". Expected either :"+sError
00144 );
00145 }
00146 }
00147
00148 return false;
00149 }
00150
00151
00152 int i = 0;
00153 std::map<uint, utils::refptr<argument>>::iterator iterArg;
00154 if (lValidArgList.size() > 1)
00155 {
00156 std::vector<argument_list*>::iterator iterArgListPtr;
00157 pArgList_ = nullptr;
00158 foreach (iterArgListPtr, lValidArgList)
00159 {
00160 i = 1;
00161 bool bValid = true;
00162 foreach (iterArg, (*iterArgListPtr)->lArg_)
00163 {
00164 if (!iterArg->second->test(pLua_, i, false))
00165 {
00166 bValid = false;
00167 break;
00168 }
00169 ++i;
00170 }
00171 if (bValid)
00172 {
00173 pArgList_ = (*iterArgListPtr);
00174 break;
00175 }
00176 }
00177
00178 if (!pArgList_)
00179 {
00180 if (bPrintError)
00181 {
00182 std::string sError;
00183 foreach (iterArgList, lArgListStack_)
00184 {
00185 std::string sArguments = "\n - ["+utils::to_string(iterArgList->lArg_.size())+"] : ";
00186 std::map<uint, utils::refptr<argument>>::iterator iterArg;
00187 foreach (iterArg, iterArgList->lArg_)
00188 {
00189 if (iterArg != iterArgList->lArg_.begin())
00190 sArguments += ", ";
00191 sArguments += iterArg->second->get_data()->get_name();
00192 }
00193 if (iterArgList->lOptional_.size() > 0)
00194 {
00195 if (sArguments != "")
00196 sArguments += ", ";
00197 sArguments += "(+";
00198 foreach (iterArg, iterArgList->lOptional_)
00199 {
00200 if (iterArg != iterArgList->lOptional_.begin())
00201 sArguments += ", ";
00202 sArguments += iterArg->second->get_data()->get_name();
00203 }
00204 sArguments += ")";
00205 }
00206 sError += sArguments;
00207 }
00208
00209 pLua_->print_error(
00210 "Wrong arguments provided to \""+sName_+"\". Expected either :"+sError
00211 );
00212 }
00213 return false;
00214 }
00215 }
00216 else
00217 {
00218 pArgList_ = lValidArgList[0];
00219 i = 1;
00220 bool bValid = true;
00221 foreach (iterArg, pArgList_->lArg_)
00222 {
00223 if (!iterArg->second->test(pLua_, i, bPrintError))
00224 bValid = false;
00225 ++i;
00226 }
00227
00228 if (!bValid)
00229 return false;
00230 }
00231
00232
00233 uint uiMaxArgs = pArgList_->lArg_.size() + pArgList_->lOptional_.size();
00234 if (uiArgumentCount_ < uiMaxArgs)
00235 pLua_->push_nil(uiMaxArgs - uiArgumentCount_);
00236
00237
00238 bool bValid = true;
00239 foreach (iterArg, pArgList_->lOptional_)
00240 {
00241 if (pLua_->get_type(i) != TYPE_NIL)
00242 {
00243 if (!iterArg->second->test(pLua_, i, bPrintError))
00244 bValid = false;
00245 }
00246 ++i;
00247 }
00248
00249 return bValid;
00250 }
00251
00252 const std::string& function::get_name() const
00253 {
00254 return sName_;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 void function::push(const std::string& sValue)
00268 {
00269 if (uiReturnCount_ == uiReturnNbr_)
00270 ++uiReturnNbr_;
00271
00272 pLua_->push_string(sValue);
00273
00274 ++uiReturnCount_;
00275 }
00276
00277 void function::push(const double& dValue)
00278 {
00279 if (uiReturnCount_ == uiReturnNbr_)
00280 ++uiReturnNbr_;
00281
00282 pLua_->push_number(dValue);
00283
00284 ++uiReturnCount_;
00285 }
00286
00287 void function::push(float fValue)
00288 {
00289 if (uiReturnCount_ == uiReturnNbr_)
00290 ++uiReturnNbr_;
00291
00292 pLua_->push_number(fValue);
00293
00294 ++uiReturnCount_;
00295 }
00296
00297 void function::push(int iValue)
00298 {
00299 if (uiReturnCount_ == uiReturnNbr_)
00300 ++uiReturnNbr_;
00301
00302 pLua_->push_number(iValue);
00303
00304 ++uiReturnCount_;
00305 }
00306
00307 void function::push(uint uiValue)
00308 {
00309 if (uiReturnCount_ == uiReturnNbr_)
00310 ++uiReturnNbr_;
00311
00312 pLua_->push_number(uiValue);
00313
00314 ++uiReturnCount_;
00315 }
00316
00317 void function::push(bool bValue)
00318 {
00319 if (uiReturnCount_ == uiReturnNbr_)
00320 ++uiReturnNbr_;
00321
00322 pLua_->push_bool(bValue);
00323
00324 ++uiReturnCount_;
00325 }
00326
00327 void function::push_nil(uint uiNbr)
00328 {
00329 for (uint ui = 0; ui < uiNbr; ++ui)
00330 {
00331 if (uiReturnCount_ == uiReturnNbr_)
00332 ++uiReturnNbr_;
00333
00334 pLua_->push_nil();
00335
00336 ++uiReturnCount_;
00337 }
00338 }
00339
00340 void function::notify_pushed()
00341 {
00342 if (uiReturnCount_ == uiReturnNbr_)
00343 ++uiReturnNbr_;
00344
00345 ++uiReturnCount_;
00346 }
00347
00348 int function::on_return()
00349 {
00350
00351 if (uiReturnCount_ < uiReturnNbr_)
00352 pLua_->push_nil(uiReturnNbr_ - uiReturnCount_);
00353
00354
00355 return uiReturnNbr_;
00356 }
00357
00358 state* function::get_state() const
00359 {
00360 return pLua_;
00361 }
00362 }