From dff2d2085ef92b408ea7c796b6a45ae57cc64f60 Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Sat, 9 Jun 2007 17:54:13 +0000 Subject: [PATCH] * implemented DefScript "list" datatype. * wiki information & documentation will come soon. --- src/Client/DefScript/DefScript.cpp | 53 ++-- src/Client/DefScript/DefScript.h | 28 +- src/Client/DefScript/DefScriptDefines.h | 37 ++- .../DefScript/DefScriptListFunctions.cpp | 274 ++++++++++++++++++ src/Client/DefScript/ListStorage.cpp | 45 +++ src/Client/DefScript/ListStorage.h | 25 ++ src/PseuWoW.vcproj | 9 + 7 files changed, 425 insertions(+), 46 deletions(-) create mode 100644 src/Client/DefScript/DefScriptListFunctions.cpp create mode 100644 src/Client/DefScript/ListStorage.cpp create mode 100644 src/Client/DefScript/ListStorage.h diff --git a/src/Client/DefScript/DefScript.cpp b/src/Client/DefScript/DefScript.cpp index 4916b69..f0ed456 100644 --- a/src/Client/DefScript/DefScript.cpp +++ b/src/Client/DefScript/DefScript.cpp @@ -89,6 +89,24 @@ void DefScriptPackage::_InitFunctions(void) AddFunc("lowercase",&DefScriptPackage::func_lowercase); AddFunc("random",&DefScriptPackage::func_random); AddFunc("fileexists",&DefScriptPackage::func_fileexists); + + // list functions + AddFunc("lpushback",&DefScriptPackage::func_lpushback); + AddFunc("lappend",&DefScriptPackage::func_lpushback); // alias for lpushback + AddFunc("lpushfront",&DefScriptPackage::func_lpushfront); + AddFunc("lpopback",&DefScriptPackage::func_lpopback); + AddFunc("lpopfront",&DefScriptPackage::func_lpopfront); + AddFunc("ldelete",&DefScriptPackage::func_ldelete); + AddFunc("lexists",&DefScriptPackage::func_lexists); + AddFunc("llen",&DefScriptPackage::func_llen); + AddFunc("linsert",&DefScriptPackage::func_linsert); + AddFunc("lsplit",&DefScriptPackage::func_lsplit); + AddFunc("lcsplit",&DefScriptPackage::func_lcsplit); + AddFunc("ljoin",&DefScriptPackage::func_ljoin); + AddFunc("lindex",&DefScriptPackage::func_lindex); + AddFunc("lclean",&DefScriptPackage::func_lclean); + AddFunc("lmclean",&DefScriptPackage::func_lmclean); + AddFunc("lerase",&DefScriptPackage::func_lerase); } void DefScriptPackage::AddFunc(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set)) @@ -386,12 +404,11 @@ CmdSet::~CmdSet() void CmdSet::Clear() { - for(unsigned int i=0;isecond=RemoveBracketsFromString(i->second); } } diff --git a/src/Client/DefScript/DefScript.h b/src/Client/DefScript/DefScript.h index f5d7890..94aa6ac 100644 --- a/src/Client/DefScript/DefScript.h +++ b/src/Client/DefScript/DefScript.h @@ -6,6 +6,7 @@ #include #include "VarSet.h" #include "DynamicEvent.h" +#include "ListStorage.h" #include "DefScriptDefines.h" @@ -24,6 +25,8 @@ struct DefReturnResult { DefReturnResult() { ok=true; mustreturn=false; ret="true"; } DefReturnResult(bool b) { ok=true; mustreturn=false; ret=b?"true":"false"; } + DefReturnResult(std::string s) { ok=true; mustreturn=false; ret=s; } + DefReturnResult(const char *s) { DefReturnResult(std::string(s)); } bool ok; // true if the execution of the current statement was successful bool mustreturn; std::string ret; // return value used by ?{..} @@ -39,7 +42,9 @@ struct DefXChgResult bool changed; std::string str; DefReturnResult result; -}; +}; + +typedef std::map _CmdSetArgMap; class CmdSet { public: @@ -47,7 +52,7 @@ class CmdSet { ~CmdSet(); void Clear(); std::string cmd; - std::string arg[MAXARGS]; + _CmdSetArgMap arg; std::string defaultarg; std::string myname; std::string caller; @@ -118,6 +123,7 @@ public: void AddFunc(std::string n,DefReturnResult (DefScriptPackage::*)(CmdSet& Set)); bool HasFunc(std::string); void DelFunc(std::string); + ListStorage lists; std::string scPath; @@ -178,6 +184,24 @@ private: DefReturnResult func_lowercase(CmdSet&); DefReturnResult func_random(CmdSet&); DefReturnResult func_fileexists(CmdSet&); + + // list functions + DefReturnResult func_lpushback(CmdSet&); + DefReturnResult func_lpushfront(CmdSet&); + DefReturnResult func_lpopback(CmdSet&); + DefReturnResult func_lpopfront(CmdSet&); + DefReturnResult func_ldelete(CmdSet&); + DefReturnResult func_lexists(CmdSet&); + DefReturnResult func_llen(CmdSet&); + DefReturnResult func_linsert(CmdSet&); + DefReturnResult func_lsplit(CmdSet&); + DefReturnResult func_lcsplit(CmdSet&); + DefReturnResult func_ljoin(CmdSet&); + DefReturnResult func_lindex(CmdSet&); + DefReturnResult func_lclean(CmdSet&); + DefReturnResult func_lmclean(CmdSet&); + DefReturnResult func_lerase(CmdSet&); + // setup own function declarations here # include "DefScriptInterfaceInclude.h" diff --git a/src/Client/DefScript/DefScriptDefines.h b/src/Client/DefScript/DefScriptDefines.h index 9e663eb..33e45c2 100644 --- a/src/Client/DefScript/DefScriptDefines.h +++ b/src/Client/DefScript/DefScriptDefines.h @@ -1,29 +1,28 @@ #ifndef DEFSCRIPTDEFINES_H #define DEFSCRIPTDEFINES_H -#define MAXARGS 99 #ifdef _DEBUG # define _DEFSC_DEBUG(code) code; #else # define _DEFSC_DEBUG(code) #endif -#if COMPILER == COMPILER_MICROSOFT -typedef __int64 int64; -typedef unsigned __int64 uint64; -#else -typedef __int64_t int64; -typedef __uint64_t uint64; -// TODO: correct ATOI64 for linux if necessary -#endif - -enum VariableType -{ - DEFSCRIPT_NONE=0, - DEFSCRIPT_VAR, - DEFSCRIPT_FUNC -}; - -typedef long double ldbl; - +#if COMPILER == COMPILER_MICROSOFT +typedef __int64 int64; +typedef unsigned __int64 uint64; +#else +typedef __int64_t int64; +typedef __uint64_t uint64; +// TODO: correct ATOI64 for linux if necessary +#endif + +enum VariableType +{ + DEFSCRIPT_NONE=0, + DEFSCRIPT_VAR, + DEFSCRIPT_FUNC +}; + +typedef long double ldbl; + #endif \ No newline at end of file diff --git a/src/Client/DefScript/DefScriptListFunctions.cpp b/src/Client/DefScript/DefScriptListFunctions.cpp new file mode 100644 index 0000000..72944c3 --- /dev/null +++ b/src/Client/DefScript/DefScriptListFunctions.cpp @@ -0,0 +1,274 @@ +#include +#include +#include +#include "DefScript.h" +#include "DefScriptTools.h" + +using namespace DefScriptTools; + +DefReturnResult DefScriptPackage::func_lpushback(CmdSet& Set) +{ + DefList *l = lists.Get(_NormalizeVarName(Set.arg[0],Set.myname)); + l->push_back(Set.defaultarg); + return true; +} + +DefReturnResult DefScriptPackage::func_lpushfront(CmdSet& Set) +{ + DefList *l = lists.Get(_NormalizeVarName(Set.arg[0],Set.myname)); + l->push_front(Set.defaultarg); + return true; +} + +DefReturnResult DefScriptPackage::func_lpopback(CmdSet& Set) +{ + std::string r; + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.defaultarg,Set.myname)); + if( (!l) || (!l->size()) ) // cant pop any element if the list doesnt exist or is empty + return ""; + r= l->back(); + l->pop_back(); + return r; +} + +DefReturnResult DefScriptPackage::func_lpopfront(CmdSet& Set) +{ + std::string r; + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.defaultarg,Set.myname)); + if( (!l) || (!l->size()) ) // cant pop any element if the list doesnt exist or is empty + return ""; + r = l->front(); + l->pop_front(); + return r; +} + +// delete a list and all its elements +DefReturnResult DefScriptPackage::func_ldelete(CmdSet& Set) +{ + lists.Delete(_NormalizeVarName(Set.defaultarg,Set.myname)); + return true; +} + +// returns true if a list with the given name exists, else false +DefReturnResult DefScriptPackage::func_lexists(CmdSet& Set) +{ + return lists.Exists(_NormalizeVarName(Set.defaultarg,Set.myname)); +} + +// return list element count +DefReturnResult DefScriptPackage::func_llen(CmdSet& Set) +{ + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.defaultarg,Set.myname)); + if(!l) + return ""; // return nothing if list doesnt exist + return toString((uint64)l->size()); // return any number +} + +// insert item at some position in the list +DefReturnResult DefScriptPackage::func_linsert(CmdSet& Set) +{ + bool result; + DefList *l = lists.Get(_NormalizeVarName(Set.arg[0],Set.myname)); + unsigned int pos = (unsigned int)toNumber(Set.arg[1]); + if(pos > l->size()) // if the list is too short to insert at that pos... + { + l->push_back(Set.defaultarg); // ... just append at the end + result = false; + } + else + { + DefList::iterator it = l->begin(); + advance(it,pos); + l->insert(it,Set.defaultarg); // ... else insert at correct position + result = true; + } + return result; +} + +// returns the amount of string fragments added to the list +// arg0: list name; arg1: delimiter string; defaultarg: string to split +DefReturnResult DefScriptPackage::func_lsplit(CmdSet& Set) +{ + // 1st create a new list, or get an already existing one and clear it + DefList *l = lists.Get(_NormalizeVarName(Set.arg[0],Set.myname)); + l->clear(); + if(Set.defaultarg.empty()) // we cant split an empty string, return nothing, and keep empty list + return ""; + + // special case: empty delimiter -> split in chars + if(Set.arg[1].empty()) + { + for(unsigned int i=0; ipush_back(tmp); + } + return toString((uint64)l->size()); + } + + unsigned int p,q=0; // p=position of substr; q=next pos to start searching at + while( (p = Set.defaultarg.find(Set.arg[1].c_str(),q)) != std::string::npos) + { + l->push_back( Set.defaultarg.substr(q,p - q) ); + q = p + Set.arg[1].length(); + } + if(q < Set.defaultarg.length()) // also append the last string fragment (that has no delimiter) + { + l->push_back(Set.defaultarg.c_str() + q); + } + return toString((uint64)l->size()); +} + +// multi-split by chars +// returns the amount of string fragments added to the list +// arg0: list name; args: delimit; defaultarg: string to split +DefReturnResult DefScriptPackage::func_lcsplit(CmdSet& Set) +{ + // 1st create a new list, or get an already existing one and clear it + DefList *l = lists.Get(_NormalizeVarName(Set.arg[0],Set.myname)); + l->clear(); + if(Set.defaultarg.empty()) // we cant split an empty string, return nothing, and keep empty list + return ""; + + unsigned int p,q=0; // p=position of substr; q=next pos to start searching at + while( (p = Set.defaultarg.find_first_of(Set.arg[1].c_str(),q)) != std::string::npos) + { + l->push_back( Set.defaultarg.substr(q,p - q) ); + q = p + 1; + } + if(q < Set.defaultarg.length()) // also append the last string fragment (that has no delimiter) + { + l->push_back(Set.defaultarg.c_str() + q); + } + return toString((uint64)l->size()); +} + +// create a string from a list, using as delimiter +DefReturnResult DefScriptPackage::func_ljoin(CmdSet& Set) +{ + std::string r; + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.arg[0],Set.myname)); + if(!l) + return ""; + for(unsigned int i = 0; i < l->size(); i++) + { + r += (*l)[i]; + if( i+1 != l->size() ) + r += Set.defaultarg; + } + return r; +} + +// return list item at position xx +DefReturnResult DefScriptPackage::func_lindex(CmdSet& Set) +{ + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.arg[0],Set.myname)); + if(!l) + return ""; + unsigned int pos = (unsigned int)toNumber(Set.defaultarg); + if(pos+1 > l->size()) // ot of bounds? + return ""; + return (*l)[pos]; +} + +// clean list: remove every element that matches @def +// use this function only to remove empty straings from a list +DefReturnResult DefScriptPackage::func_lclean(CmdSet& Set) +{ + unsigned int r=0; + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.arg[0],Set.myname)); + if(!l) + return ""; + for(DefList::iterator i=l->begin(); i!=l->end(); i++) + { + if(*i == Set.defaultarg) + { + l->erase(i); + r++; + } + } + return toString((uint64)r); +} + +// multi-clean list: remove every element that matches any of the args, if it isn't empty +// NOTE: arg0 = list name, this one is skipped! +// this func does NOT remove empty strings from a list, use lclean instead!! +DefReturnResult DefScriptPackage::func_lmclean(CmdSet& Set) +{ + unsigned int r=0; + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.arg[0],Set.myname)); + if(!l) + return ""; + + _CmdSetArgMap::iterator it=Set.arg.begin(); + advance(it,1); // skip list name + + for( ; it != Set.arg.end(); it++) + { + if(it->second.length()) + { + for(DefList::iterator i=l->begin(); i!=l->end(); i++) + { + if(*i == it->second) + { + l->erase(i); + r++; + if(i==l->end()) // must be checked here, else causing crash (?!) + break; + } + } + } + } + + // erase defaultarg if given + if(Set.defaultarg.length()) + { + for(DefList::iterator i=l->begin(); i!=l->end(); i++) + { + if(*i == Set.defaultarg) + { + l->erase(i); + r++; + } + } + } + return toString((uint64)r); +} + +DefReturnResult DefScriptPackage::func_lerase(CmdSet& Set) +{ + DefList *l = lists.GetNoCreate(_NormalizeVarName(Set.arg[0],Set.myname)); + if(!l) + return ""; + std::string r; + unsigned int pos = (unsigned int)toNumber(Set.defaultarg); + if(pos > l->size()) // if the list is too short to erase at that pos... + return ""; // ... return nothing + + DefList::iterator it = l->begin(); + advance(it,pos); + r = *it; + l->erase(it); // ... else erase at correct position + + return r; +} + + + + + +//DefReturnResult DefScriptPackage::func_lmerge(CmdSet& Set) +//{ + +// to be continued... + + + + + + + + + + diff --git a/src/Client/DefScript/ListStorage.cpp b/src/Client/DefScript/ListStorage.cpp new file mode 100644 index 0000000..7d1ee5f --- /dev/null +++ b/src/Client/DefScript/ListStorage.cpp @@ -0,0 +1,45 @@ +#include "ListStorage.h" + +bool ListStorage::Exists(std::string s) +{ + for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) + { + if(it->first == s) + return true; + } + return false; +} + +DefList *ListStorage::_Create(std::string s) +{ + DefList *l = new DefList(); + _storage[s] = l; + return l; +} + +void ListStorage::Delete(std::string s) +{ + for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) + { + if(it->first == s) + { + delete it->second; + _storage.erase(it); + return; + } + } +} + +DefList *ListStorage::GetNoCreate(std::string s) +{ + for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) + if(it->first == s) + return it->second; + return NULL; +} + +DefList *ListStorage::Get(std::string s) +{ + DefList *l = GetNoCreate(s); + return l ? l : _Create(s); +} diff --git a/src/Client/DefScript/ListStorage.h b/src/Client/DefScript/ListStorage.h new file mode 100644 index 0000000..3d7ef7f --- /dev/null +++ b/src/Client/DefScript/ListStorage.h @@ -0,0 +1,25 @@ +#ifndef DEFSCRIPT_LISTSTORAGE_H +#define DEFSCRIPT_LISTSTORAGE_H + +#include +#include +#include + +typedef std::deque DefList; +typedef std::map DefListMap; + +class ListStorage +{ +public: + bool Exists(std::string); + void Delete(std::string); + DefList *Get(std::string); + DefList *GetNoCreate(std::string); + inline void Assign(std::string s,DefList *l) { _storage[s] = l; } + +private: + DefList *_Create(std::string); + DefListMap _storage; +}; + +#endif diff --git a/src/PseuWoW.vcproj b/src/PseuWoW.vcproj index fd5b311..45cb2f1 100644 --- a/src/PseuWoW.vcproj +++ b/src/PseuWoW.vcproj @@ -246,6 +246,9 @@ + + @@ -258,6 +261,12 @@ + + + +