You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
(153) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(48) |
Feb
(46) |
Mar
(12) |
Apr
(4) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2007 |
Jan
|
Feb
(263) |
Mar
(235) |
Apr
(66) |
May
(42) |
Jun
(270) |
Jul
(65) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/scriptserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11684/scriptserver Added Files: gcvalue.cpp gcvalue.h rubywrapper.cpp rubywrapper.h scriptserver.cpp scriptserver.h scriptserver_c.cpp Log Message: --- NEW FILE: scriptserver.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: scriptserver.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <boost/any.hpp> #include <boost/scoped_array.hpp> #include <sstream> #include "scriptserver.h" #include <zeitgeist/corecontext.h> #include <zeitgeist/core.h> #include <zeitgeist/logserver/logserver.h> #include <zeitgeist/fileserver/fileserver.h> #include <sys/stat.h> using namespace boost; using namespace std; using namespace zeitgeist; boost::shared_ptr<CoreContext> gMyPrivateContext; void getParameterList(VALUE args, ParameterList& params) { int argc = RARRAY(args)->len; for (int i = 0; i<argc; ++i) { VALUE argument = rb_ary_entry(args, i); boost::any var; // do type conversion switch (TYPE(argument)) { case T_STRING: { char *c = STR2CSTR(argument); var = c; //printf("string: '%s'\n",boost::any_cast<char*>(var)); } break; case T_FIXNUM: { int i = FIX2INT(argument); var = i; //printf("int: '%d'\n", boost::any_cast<int>(var)); } break; case T_FLOAT: { float f = (float)NUM2DBL(argument); var = f; //printf("float: '%f'\n", boost::any_cast<float>(var)); } break; case T_TRUE: { var = true; //printf("bool: 'true'\n"); } break; case T_FALSE: { var = false; //printf("bool: 'false'\n"); } break; } params.AddValue(var); } } GCValue ScriptServer::GetZeitgeistObject(boost::shared_ptr<Leaf> leaf) { GCValue v; if (leaf.get() != 0) { stringstream ss; ss << "ZeitgeistObject.new(" << (unsigned long) leaf.get() <<")"; v = RbEvalStringWrap(ss.str()); } return v; } VALUE selectObject(VALUE /*self*/, VALUE path) { shared_ptr<Leaf> leaf = gMyPrivateContext->Select(STR2CSTR(path)); return ScriptServer::GetZeitgeistObject(leaf).Get(); } VALUE selectCall(VALUE /*self*/, VALUE functionName, VALUE args) { ParameterList in; getParameterList(args, in); Class::TCmdProc cmd = gMyPrivateContext->GetObject()->GetClass()->GetCmdProc (STR2CSTR(functionName)); GCValue out; if (cmd != 0) { out = cmd(static_cast<Object*>(gMyPrivateContext->GetObject().get()), in); } else { gMyPrivateContext->GetCore()->GetLogServer()->Error() << "(ScriptServer) ERROR: Unknown function '" << STR2CSTR(functionName) << "'" << endl; } return out.Get(); } VALUE thisCall(VALUE /*self*/, VALUE objPointer, VALUE functionName, VALUE args) { ParameterList in; getParameterList(args, in); Object *obj = (Object*)NUM2INT(objPointer); Class::TCmdProc cmd = obj->GetClass()->GetCmdProc(STR2CSTR(functionName)); GCValue out; if (cmd != 0) { out = cmd(obj, in); } else { gMyPrivateContext->GetCore()->GetLogServer()->Error() << "(ScriptServer) ERROR: Unknown function '" << STR2CSTR(functionName) << "'" << endl; } return out.Get(); } VALUE importBundle(VALUE /*self*/, VALUE path) { gMyPrivateContext->GetCore()->ImportBundle(STR2CSTR(path)); return Qnil; } VALUE run (VALUE /*self*/, VALUE file) { gMyPrivateContext->GetCore()->GetScriptServer()->Run(STR2CSTR(file)); return Qnil; } VALUE newObject(VALUE /*self*/, VALUE className, VALUE pathStr) { shared_ptr<Leaf> leaf = gMyPrivateContext->New(STR2CSTR(className), STR2CSTR(pathStr)); return ScriptServer::GetZeitgeistObject(leaf).Get(); } VALUE deleteObject(VALUE /*self*/, VALUE name) { gMyPrivateContext->Delete(STR2CSTR(name)); return Qnil; } VALUE getObject(VALUE /*self*/, VALUE path) { shared_ptr<Leaf> leaf = gMyPrivateContext->Get(STR2CSTR(path)); return ScriptServer::GetZeitgeistObject(leaf).Get(); } VALUE listObjects(VALUE /*self*/) { gMyPrivateContext->ListObjects(); return Qnil; } VALUE pushd(VALUE /*self*/) { gMyPrivateContext->Push(); return Qnil; } VALUE popd(VALUE /*self*/) { gMyPrivateContext->Pop(); return Qnil; } VALUE dirs(VALUE /*self*/) { gMyPrivateContext->Dir(); return Qnil; } ScriptServer::ScriptServer() { ruby_init(); // register built-in commands rb_define_global_function("selectObject", RUBY_METHOD_FUNC(selectObject), 1); rb_define_global_function("selectCall", RUBY_METHOD_FUNC(selectCall), 2); rb_define_global_function("thisCall", RUBY_METHOD_FUNC(thisCall), 3); rb_define_global_function("importBundle", RUBY_METHOD_FUNC(importBundle), 1); rb_define_global_function("run", RUBY_METHOD_FUNC(run), 1); rb_define_global_function("new", RUBY_METHOD_FUNC(newObject), 2); rb_define_global_function("delete", RUBY_METHOD_FUNC(deleteObject), 1); rb_define_global_function("get", RUBY_METHOD_FUNC(getObject), 1); rb_define_global_function("ls", RUBY_METHOD_FUNC(listObjects), 0); rb_define_global_function("pushd", RUBY_METHOD_FUNC(pushd), 0); rb_define_global_function("popd", RUBY_METHOD_FUNC(popd), 0); rb_define_global_function("dirs", RUBY_METHOD_FUNC(dirs), 0); mRelPathPrefix = "../../"; } ScriptServer::~ScriptServer() { } void ScriptServer::UpdateCachedAllNodes() { GetLog()->Debug() << "(ScriptServer) updating cached script variables\n"; GetCore()->GetRoot()->UpdateCached(); } bool ScriptServer::Run(shared_ptr<salt::RFile> file) { if (file.get() == 0) { return false; } boost::scoped_array<char> buffer(new char[file->Size() + 1]); file->Read(buffer.get(), file->Size()); buffer[file->Size()] = 0; bool ok = Eval(buffer.get()); UpdateCachedAllNodes(); return ok; } bool ScriptServer::Run(const string &fileName) { shared_ptr<salt::RFile> file = GetFile()->Open(fileName.c_str()); if (file.get() == 0) { GetLog()->Error() << "(ScriptServer) ERROR: Cannot locate file '" << fileName << "'\n"; return false; } GetLog()->Debug() << "(ScriptServer) Running " << fileName << endl; return Run(file); } bool ScriptServer::Eval(const string &command) { int error; RbEvalStringWrap(command,error); return (error == 0); } bool ScriptServer::Eval(const std::string &command, GCValue& value) { int error; value = RbEvalStringWrap(command,error); return (error == 0); } void ScriptServer::CreateVariable(const string &varName, int value) { // create a string with: "createVariable 'varName', value" stringstream s; s << "createVariable('" << varName << "', " << value << ")"; Eval(s.str()); } void ScriptServer::CreateVariable(const string &varName, float value) { // create a string with: "createVariable 'ns', 'varName', value" stringstream s; s << "createVariable('" << varName << "', " << value << ")"; Eval(s.str()); } void ScriptServer::CreateVariable(const string &varName, const string &value) { // create a string with: "createVariable 'ns', 'varName', 'value'" stringstream s; s << "createVariable('" << varName << "', '" << value << "')"; Eval(s.str()); } bool ScriptServer::ParseVarName(const string& varName, string& nameSpace, string& name) { stringstream ss(varName); string current; vector<string> tokens; // segment varName while(! ss.eof()) { getline(ss, current,'.'); if (current.size()) { tokens.push_back(current); } } if (tokens.size() != 2) { return false; } nameSpace = tokens[0]; name = tokens[1]; return ( (nameSpace.size() >= 1) && (nameSpace[0] >= 'A') && (nameSpace[0] <= 'Z') && (name.size() >= 1) && (name[0] >= 'A') && (name[0] <= 'Z') ); } bool ScriptServer::ExistsVariable(const string &varName) { return (! GetVariable(varName).IsNil()); } GCValue ScriptServer::GetVariable(const string &varName) { string nameSpace; string name; if (! ParseVarName(varName,nameSpace,name)) { return GCValue(); } GCValue v; if (nameSpace != "") { // get namespace class GCValue ns = rb_const_get(rb_cObject, rb_intern(nameSpace.c_str())); if (! ns.IsNil()) { // get member variable of namespace object ID var = rb_intern(name.c_str()); int error; RbArguments arg(ns.Get(), var, 0, 0); v = rb_protect( RbFuncallWrap, reinterpret_cast<VALUE>(&arg), &error ); if (error) { GetLog()->Debug() << "(ScriptServer) Ruby ERROR: " << RbGetError() << "\n"; v = Qnil; } } } else { v = rb_const_get(rb_cObject, rb_intern(name.c_str())); } return v; } bool ScriptServer::GetVariable(const string &varName, int &value) { return GetVariable(varName).GetInt(value); } bool ScriptServer::GetVariable(const std::string &varName, float &value) { return GetVariable(varName).GetFloat(value); } bool ScriptServer::GetVariable(const string &varName, bool &value) { return GetVariable(varName).GetBool(value); } bool ScriptServer::GetVariable(const string &varName, string &value) { return GetVariable(varName).GetString(value); } boost::shared_ptr<CoreContext> ScriptServer::GetContext() const { return gMyPrivateContext; } bool ScriptServer::ConstructInternal() { if (! Leaf::ConstructInternal()) { return false; } gMyPrivateContext = GetCore()->CreateContext(); return true; } void ScriptServer::SetInitRelPathPrefix(const std::string &relPathPrefix) { mRelPathPrefix = relPathPrefix; } bool ScriptServer::RunInitScriptInternal(const string &sourceDir, const string &name, bool copy, const string& destDir) { // run the init script in the sourceDir string sourcePath = sourceDir + "/" + name; GetLog()->Debug() << "(ScriptServer) Running " << sourcePath << "... "; shared_ptr<salt::StdFile> file(new(salt::StdFile)); if ( (! file->Open(sourcePath.c_str())) || (! Run(file)) ) { GetLog()->Debug() << "failed" << endl; return false; } else { GetLog()->Debug() << "ok" << endl; } // copy it to the destDir if (! copy) { return true; } string destPath = destDir + "/" + name; GetLog()->Normal() << "Copying " << sourcePath << " to " << destPath << endl; stringstream s; s << "cp " << sourcePath << " " << destPath; system(s.str().c_str()); return true; } bool ScriptServer::GetDotDirName(string& dotDir) { if (mDotName == "") { GetLog()->Warning() << "(ScriptServer) WARNING: Dot directory name unset.\n"; return false; } char* home = getenv("HOME"); if (!home) { GetLog()->Warning() << "(ScriptServer) WARNING: $HOME is unset.\n"; return false; } dotDir = string(home) + "/" + mDotName; return true; } bool ScriptServer::CreateDotDir(const string& dotDir) { char cwd[PATH_MAX+1]; if (getcwd(cwd,sizeof(cwd)) == NULL) { GetLog()->Error() << "(ScriptServer) ERROR: Cannot get current directory\n"; return false; } if (chdir(dotDir.c_str()) == 0) { // dot dir exists; change back to original directory chdir(cwd); return true; } // dot dir is not existent, try to create it if (mkdir(dotDir.c_str(),0777) != 0) { GetLog()->Error() << "(ScriptServer) ERROR: Cannot create directory '" << dotDir << "'\n"; return false; } GetLog()->Normal() << "(ScriptServer) Created Directory '" << dotDir << "'\n"; return true; } bool ScriptServer::RunInitScript(const string &fileName, const string &relPath, EInitScriptType type) { string dotDir; bool validDotDir = (type == IS_USERLOCAL) && GetDotDirName(dotDir) && CreateDotDir(dotDir); // some macro magic (not at all) string pkgdatadir = PREFIX "/share/" PACKAGE_NAME; bool ok = ( ( (validDotDir) && (RunInitScriptInternal(dotDir, fileName, false)) ) || (RunInitScriptInternal(pkgdatadir, fileName, validDotDir, dotDir)) || (RunInitScriptInternal(mRelPathPrefix+relPath, fileName, validDotDir, dotDir)) ); if (! ok) { GetLog()->Error() << "(ScriptServer) ERROR: Cannot locate init script '" << fileName << "'\n"; } return ok; } --- NEW FILE: rubywrapper.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: rubywrapper.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ZEITGEIST_RUBYWRAPPER_H #define ZEITGEIST_RUBYWRAPPER_H // // Both <ruby.h> and "config.h" define PACKAGE_ constants. // To suppress compiler warnings about redefinitions they // are #undef'ed in this wrapper // #undef PACKAGE_BUGREPORT #undef PACKAGE_NAME #undef PACKAGE_STRING #undef PACKAGE_TARNAME #undef PACKAGE_VERSION #ifndef __GNUC__ #define EXTERN extern __declspec(dllimport) #endif #include <ruby.h> #undef EXTERN #undef PACKAGE_BUGREPORT #undef PACKAGE_NAME #undef PACKAGE_STRING #undef PACKAGE_TARNAME #undef PACKAGE_VERSION #include <iostream> namespace zeitgeist { /** RbArguments is a structure that describes a ruby function call. \param recv is the ruby object that receives the function call \param id is the ruby id of the receiver member function \param n is the number of parameters passed \param *argv is a pointer to an array containnig the function parameters */ struct RbArguments { VALUE recv; ID id; int n; VALUE *argv; RbArguments(VALUE recv, ID id, int n, VALUE *argv) : recv(recv), id(id), n(n), argv(argv) {}; }; /** a functor for the rb_protect function, used to safely excecute ruby code */ VALUE RbFuncallWrap(VALUE arg); /** calls a safe rb_eval_string variant and prints any ruby error messages along with a backtrace to stdout */ VALUE RbEvalStringWrap(const std::string& str); /** calls a safe rb_eval_string variant and prints any ruby error messages along with a backtrace to stdout. The error code returned from ruby is stored in the 'error' parameter. */ VALUE RbEvalStringWrap(const std::string& str, int& error); /** qeuries ruby for a string that describes the last error */ std::string RbGetError(); /** prints the last ruby error to stdout along with a backtrace */ void RbPrintError(); }; #endif // ZEITGEIST_RUBYWRAPPER_H --- NEW FILE: scriptserver_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: scriptserver_c.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "scriptserver.h" using namespace zeitgeist; void CLASS(ScriptServer)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Leaf); } --- NEW FILE: gcvalue.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: gcvalue.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gcvalue.h" #include <sstream> using namespace zeitgeist; using namespace std; GCValue::GCValue() { mValue = Qnil; } GCValue::GCValue(const GCValue& value) { mValue = Qnil; Set(value.mValue); } GCValue::GCValue(VALUE v) { mValue = Qnil; Set(v); } GCValue::GCValue(bool b) { mValue = Qnil; Set(b ? Qtrue:Qfalse); } GCValue::GCValue(const string& str) { mValue = Qnil; Set(rb_str_new2(str.c_str())); } GCValue::GCValue(const char* str) { mValue = Qnil; Set(rb_str_new2(str)); } GCValue::GCValue(float f) { mValue = Qnil; Set(rb_float_new(f)); } GCValue::GCValue(int i) { mValue = Qnil; Set(rb_int_new(i)); } GCValue::~GCValue() { GC_Unregister(); } void GCValue::operator = (const GCValue& value) { mValue = Qnil; Set(value.mValue); } void GCValue::operator = (const VALUE& value) { mValue = Qnil; Set(value); } VALUE GCValue::Get() { return mValue; } void GCValue::Set(VALUE v) { GC_Unregister(); mValue = v; GC_Register(); } bool GCValue::IsNil() { return NIL_P(mValue); } bool GCValue::GetInt(int& value) { if (IsNil()) { return false; } value = NUM2INT(mValue); return true; } bool GCValue::GetFloat(float& value) { if (IsNil()) { return false; } value = (float)NUM2DBL(mValue); return true; } bool GCValue::GetBool(bool& value) { if (IsNil()) { return false; } switch(TYPE(mValue)) { case T_TRUE : value = true; return true; case T_FALSE : value = false; return true; default: return false; } } bool GCValue::GetString(std::string& value) { if (IsNil()) { return false; } switch(TYPE(mValue)) { case T_STRING: { value = STR2CSTR(mValue); return true; } case T_FLOAT: { stringstream ss; ss << (float)NUM2DBL(mValue); value = ss.str(); return true; } case T_FIXNUM: { stringstream ss; ss << NUM2INT(mValue); value = ss.str(); return true; } default: break; } return false; } void GCValue::GC_Unregister() { if (! IsNil()) { rb_gc_unregister_address(&mValue); } } void GCValue::GC_Register() { if (! IsNil()) { rb_gc_register_address(&mValue); } } --- NEW FILE: rubywrapper.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: rubywrapper.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rubywrapper.h" VALUE zeitgeist::RbFuncallWrap(VALUE arg) { RbArguments &a = *reinterpret_cast<RbArguments*>(arg); return rb_funcall2(a.recv, a.id, a.n, a.argv); } VALUE zeitgeist::RbEvalStringWrap(const std::string& str, int& error) { VALUE v = rb_eval_string_protect(str.c_str(),&error); if (error) { RbPrintError(); return Qnil; } return v; } VALUE zeitgeist::RbEvalStringWrap(const std::string& str) { int error; return RbEvalStringWrap(str,error); } std::string zeitgeist::RbGetError() { VALUE mes = rb_inspect(rb_gv_get("$!")); return RSTRING(mes)->ptr; } void zeitgeist::RbPrintError() { std::cout << RbGetError() << std::endl; rb_backtrace(); } --- NEW FILE: scriptserver.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: scriptserver.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ScriptServer :TODO: Class description for ScriptServer HISTORY: 09.07.2002 MK - initial version */ #ifndef ZEITGEIST_SCRIPTSERVER_H #define ZEITGEIST_SCRIPTSERVER_H #include <zeitgeist/leaf.h> #include <zeitgeist/class.h> #include <salt/fileclasses.h> #include "gcvalue.h" namespace zeitgeist { class CoreContext; /** The ScriptServer provides scripting facilities to the zeitgeist framework. Up to now is realized using Ruby, though the ScritpServer could easily be extended to support other script languages. */ class ScriptServer : public Leaf { // // types // public: enum EInitScriptType { IS_COMMON, // the init script is common for all users, // i.e. it won't be copied to the local dot // directory IS_USERLOCAL // the init script is local to the user, i.e // it will be copied to the user's dot // direcotry }; protected: private: // // functions // public: /** constructs the ScriptServer */ ScriptServer(); virtual ~ScriptServer(); /** loads and runs a ruby script, returns true on success */ bool Run(const std::string &fileName); /** loads and runs a ruby script from an RFile */ bool Run(boost::shared_ptr<salt::RFile> file); /** sets the relative path prefix RunInitScript() searches for an InitScript. Default is '../../', suitable for all applications started from '/app' */ void SetInitRelPathPrefix(const std::string &relPathPrefix); /** searches in ~/<mDotName>/ if dotScript is true, * PREFIX/share/PACKAGE_NAME/ and <mRelPathPrefix><relPath>/ for * the script <fileName>. If found the script is run and if * dotScript is true copied to ~/<dotName>/. If this directory is * missing it is automatically created */ bool RunInitScript(const std::string &fileName, const std::string &relPath, EInitScriptType type = IS_USERLOCAL); /** sets name of the dot directory */ void SetDotName(const std::string &dotName) { mDotName = dotName; } /** evaluates a ruby statement, returns true on success */ bool Eval(const std::string &command); /** evaluates a ruby statement, returns true on success; \param value receives the result value if any */ bool Eval(const std::string &command, GCValue& value); void UpdateCachedAllNodes(); // script variable functions /** returns true if the variable varName exists */ bool ExistsVariable(const std::string &varName); /** creates a ruby integer variable */ void CreateVariable(const std::string &varName, int value); /** creates a ruby float variable */ void CreateVariable(const std::string &varName, float value); /** creates a ruby string variable */ void CreateVariable(const std::string &varName, const std::string &value); /** reads the value of a ruby integer, returns true on success */ bool GetVariable(const std::string &varName, int &value); /** reads the value of a ruby boolean, returns true on success */ bool GetVariable(const std::string &varName, bool &value); /** reads the value of a ruby string, returns true on success */ bool GetVariable(const std::string &varName, std::string &value); /** reads the value of a ruby float, returns true on success */ bool GetVariable(const std::string &varName, float &value); /** returns the context, the ScriptServer operates in */ boost::shared_ptr<CoreContext> GetContext() const; /** constructs the ZeitgeistObject corresponding to a given leaf */ static GCValue GetZeitgeistObject(boost::shared_ptr<Leaf> leaf); protected: /** initializes the ScriptServer and runs the default startup script 'sys/script/zeitgeist.rb', returning true on success. */ virtual bool ConstructInternal(); /** parses a ruby variable into a namespace and variable name part. Valid variable names are 'Namespace.Name'. \returns true if a valid variable name was parsed \param varName is the variable name to parse \param nameSpace receives the namespace \param name receives the variable name */ bool ParseVarName(const std::string& varName, std::string& nameSpace, std::string& name); /** returns the content of a variable*/ GCValue GetVariable(const std::string &varName); /** private helper function */ bool RunInitScriptInternal(const std::string &dir, const std::string &name, bool copy, const std::string& destDir = ""); /** construct the path of the local dot directory that contains the users init scripts */ bool GetDotDirName(std::string& dotDir); /** checks if the directory <dotDir> exists and if not creates it */ bool CreateDotDir(const std::string& dotDir); private: ScriptServer(const ScriptServer& obj); ScriptServer& operator=(const ScriptServer& obj); // // members // public: protected: /** the name of the users dot directory, used by ::RunInitScript to search * for script files: ~/<mDotName> */ std::string mDotName; /** the prefix RunInitScript() prepends all relativ paths */ std::string mRelPathPrefix; private: }; DECLARE_CLASS(ScriptServer); } //namespace zeitgeist #endif //ZEITGEIST_SCRIPTSERVER_H --- NEW FILE: gcvalue.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: gcvalue.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ZEITGEIST_GCVALUE_H #define ZEITGEIST_GCVALUE_H #include <zeitgeist/scriptserver/rubywrapper.h> namespace zeitgeist { /** \class GCValue is a ruby VALUE wrapper. It is responsible to register and unregister the wrapped value as busy with the ruby garbage collector. The ruby garbage collector might be transparently invoked on any call to ruby. If a returned VALUE must stay valid during a series of ruby function calls you should use this wrapper. A simple use case is a VALUE returned from ruby that is used as an argument in a subsequent function call. This wrapper also provides some helpers to access and convert the stored value. */ class GCValue { public: GCValue(); GCValue(const GCValue& value); GCValue(VALUE v); /** constructs the corresponding ruby boolean */ GCValue(bool b); /** constructs a new ruby string object */ GCValue(const std::string& str); /** constructs a new ruby string object */ GCValue(const char* str); /** constructs a new ruby float object */ GCValue(float f); /** constructs a new riby int object */ GCValue(int i); ~GCValue(); void operator = (const GCValue& value); void operator = (const VALUE& value); /** returns the stored ruby VALUE */ VALUE Get(); /** sets the setored value to v. Any previously stored value is properly unregistered */ void Set(VALUE v); /** returns true if the stored value equals QNil */ bool IsNil(); /** tries to convert the stored value to an integer value, returns true on success */ bool GetInt(int& value); /** tries to convert the stored value to a float value, returns true on success */ bool GetFloat(float& value); /** tries to convert the stored value to a bool value, returns true on success */ bool GetBool(bool& value); /** tries to convert the stored value to a string, returns true on success */ bool GetString(std::string& value); protected: /** unregisters the stored VALUE from the ruby garbage collector, i.e marks mValue no longer as busy */ void GC_Unregister(); /** registers the stored VALUE to the ruby garbage collector, i.e. marks it as busy */ void GC_Register(); protected: /** the wrapped ruby VALUE */ VALUE mValue; }; } // namespace zeitgeist #endif // ZEITGEIST_GCVALUE_H |
From: Markus R. <rol...@us...> - 2005-12-05 21:05:13
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/fileserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11684/fileserver Added Files: fileserver.cpp fileserver.h fileserver_c.cpp filesystem.h filesystem_c.cpp Log Message: --- NEW FILE: fileserver.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: fileserver.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "fileserver.h" #include <salt/fileclasses.h> #include <zeitgeist/logserver/logserver.h> #include <zeitgeist/core.h> using namespace boost; using namespace salt; using namespace zeitgeist; using namespace std; FileServer::FileServer() : Node(), mNextHandle(1) { } FileServer::~FileServer() { } shared_ptr<salt::RFile> FileServer::Open(const string& inName) { for (TLeafList::iterator i = mChildren.begin(); i != mChildren.end(); ++i) { shared_ptr<FileSystem> fileSys = shared_static_cast<FileSystem>(*i); shared_ptr<salt::RFile> file(fileSys->Open(inName)); //first successful is returned if(file.get() != 0) { return file; } } // try to open it via the regular file system shared_ptr<salt::RFile> file(new StdFile()); if (! file->Open(inName.c_str())) { file.reset(); } return file; } FileServer::THandle FileServer::Register(const string& inName) { shared_ptr<salt::RFile> file = Open(inName); if (file.get() == 0) { return 0; } mFileMap[mNextHandle] = file; THandle h = mNextHandle; ++mNextHandle; return h; } shared_ptr<salt::RFile> FileServer::Get(THandle handle) const { TFileMap::const_iterator iter = mFileMap.find(handle); if (iter == mFileMap.end()) { GetLog()->Warning() << "(FileServer::Get) Warning: Unknown file handle " << handle << "\n"; return shared_ptr<salt::RFile>(); } return (*iter).second; } void FileServer::Close(THandle handle) { TFileMap::iterator iter = mFileMap.find(handle); if (iter == mFileMap.end()) { GetLog()->Warning() << "(FileServer::Close) Warning: Unknown file handle " << handle << "\n"; return; } mFileMap.erase(iter); if (mFileMap.empty()) { // restart handle counting on empty FileMap mNextHandle = 1; } } void FileServer::OnUnlink() { if (! mFileMap.empty()) { GetLog()->Warning() << "(FileServer) There are " << mFileMap.size() << " files left in the registry\n"; } } bool FileServer::Exist(const string& inName) { return (Open(inName).get() != 0); } // this routine registers a new file system instance with the server bool FileServer::Mount(const string& inFileSysName, const string& inPath) { shared_ptr<FileSystem> fileSys = shared_static_cast<FileSystem>(GetChild(inPath)); if (fileSys) { // we already have a file system which is bound to the same name if (fileSys->GetClass()->GetName().compare(inFileSysName) == 0) { // as the file system has the same type, we can return true return true; } else { // already have a file system of a different type, so return false GetLog()->Error() << "(FileServer) ERROR: a FileSystem is already mounted a " << inPath << "\n"; return false; } } // try to instantiate the file system fileSys = shared_static_cast<FileSystem>(GetCore()->New(inFileSysName)); if ( (fileSys.get() == 0) || (! fileSys->SetPath(inPath)) ) { return false; } // link it into our hierarchy AddChildReference(fileSys); GetLog()->Normal() << "(FileServer) successfully mounted a '" << inFileSysName << "' at '" << inPath << "'\n"; return true; } bool FileServer::Unmount(const string& inPath) { // try to remove a std file system first if (Unmount ("FileSystemSTD", inPath)) { return true; } shared_ptr<Leaf> leaf = GetChild(inPath); if(leaf) { leaf->Unlink(); return true; } return false; } bool FileServer::Unmount(const string& inFileSysName, const string& inPath) { shared_ptr<FileSystem> fileSystem = shared_static_cast<FileSystem>(GetChild(inPath)); if(fileSystem) { if (fileSystem->GetClass()->GetName().compare(inFileSysName) == 0) { fileSystem->Unlink(); return true; } } return false; } int FileServer::ForEachFile(const string& /*directory*/, const string& /*name*/, const string& /*extension*/, FileSystem::TCallback /*callback*/, void* /*param*/) { int count = 0; /*for (TDescriptionList::iterator iter = mFileSystems.begin (); iter != mFileSystems.end (); ++iter) { count += iter->fileSystem->ForEachFile(directory,name,extension,callback,param); }*/ return count; } --- NEW FILE: fileserver.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: fileserver.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. FileServer - global interface for file system access HISTORY: 12.07.01 - MK - Initial version 14.07.01 - MK - ClassServer was added, so the FileServer doesn't manage the file system factories anymore (only concrete file system instances) 11.10.01 - MK - Made singleton functionality more secure 20.11.01 - AF - added the priority of the file systems : LIFO - added the information of the file system id and its path to every mounted file system - prevented the odditity to mount a file system more than once - added GetFirstFileSystem and GetNextFileSystem to iterate through the mounted file systems 26.01.02 - MR - added ForEachFile 27.06.02 - MK - converted this to the Zeitgeist framework 09.07.02 - MK - converted this to the Kerosin framework 10.10.02 - MK - back to Zeitgeist framework TODO: TOFIX: */ #ifndef ZEITGEIST_FILESERVER_H #define ZEITGEIST_FILESERVER_H #include <list> #include <zeitgeist/node.h> #include "filesystem.h" namespace zeitgeist { /** FileServer - the global interface for file system access What the FileServer does: - Manage different file systems - Load files from a FileSystem The file server is an extremely useful subsystem, since it allows to access various implemented file systems. The regular file system is a standard directory-based implementation. The ZIP file system can load files from within ZIP-files. Before actually being able to open files, the FileServer is initialized with several FileSystems, which are associated with different paths. For each path, you have to pass in a file system. Now, when trying to open a file, each registered file system is asked to open the file. Filesystems are searched in the inverse order in wich they were registered- think of a filesystem stack. The first succesful opened file wins. This allows for some nice effects. File systems are associated with id strings like 'STD' or 'ZIP'. */ class FileServer : public Node { // // functions // public: typedef int THandle; protected: typedef std::map<THandle, boost::shared_ptr<salt::RFile> > TFileMap; public: /** constructs the fileserver */ FileServer(); ~FileServer(); /** searchs each registered file system for a file with this name. Filesystems are searched in the inverse order in which they are registered to the fileserve, i.e. a filesystem stack. The first succesful opened file is returned. */ boost::shared_ptr<salt::RFile> Open(const std::string& inName); /** tries to open the requested file and registers it. On success it returns a non 0 handle assiociated with the file object. */ THandle Register(const std::string& inName); /** returns the file corresponding to the given handle. */ boost::shared_ptr<salt::RFile> Get(THandle handle) const; /** closes the file corresponding to the given handle */ void Close(THandle handle); /** returns true if the file 'inName' exists. */ bool Exist(const std::string& inName); /** registers a filesystem to the fileserver. A file system may be registered only once, on each further try nothing is done and false returned \param inFileSysName is the class name of the File system \param inPath is the mount point in the virtual file system provided by the fileserver */ bool Mount(const std::string& inFileSysName, const std::string& inPath); /** unmounts a file system at the mount point inPath. if no file system id is given, for a first try FileSystemSTD is assumed, then the type is ignored. Returns true on success. */ bool Unmount(const std::string& inPath); /** unmounts a file system at the mount point inPath. Returns true on success. */ bool Unmount(const std::string& inClass, const std::string& inPath); /** iterates through files. 'directory', 'name' and * 'extension' give directory, name and extension a file must * match. directory,name and extension may be NULL, in wich * case every directory,extension and/or name matches. For * each match the function callback is called with the name * of the matched file and the additional user parameter * 'param'. param is just passed through to the callback and * has no meaning to the filesystem. */ int ForEachFile(const std::string& directory, const std::string& name, const std::string& extension, FileSystem::TCallback callback, void* param); protected: /** This rountine is called, before the FileServer hierarchy object is removed from the parent. */ virtual void OnUnlink(); private: FileServer(const FileServer&); FileServer& operator=(const FileServer&); protected: /** registry of opened files using the handle base system */ TFileMap mFileMap; /** the next free handle */ THandle mNextHandle; }; DECLARE_CLASS(FileServer) } //namespace zeitgeist #endif //ZEITGEIST_FILESERVER_H --- NEW FILE: fileserver_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: fileserver_c.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "fileserver.h" using namespace boost; using namespace zeitgeist; using namespace std; FUNCTION(FileServer,exist) { string inName; return ( (in.GetSize() == 1) && (in.GetValue(in.begin(),inName)) && (obj->Exist(inName.c_str())) ); } FUNCTION(FileServer,mount) { string inFsName; string inPath; return ( (in.GetSize() == 2) && (in.GetValue(in[0],inFsName)) && (in.GetValue(in[1],inPath)) && (obj->Mount(inFsName.c_str(),inPath.c_str())) ); } FUNCTION(FileServer,unmount) { bool ret = false; switch (in.GetSize()) { default: break; case 1: { string inPath; if (in.GetValue(in.begin(),inPath)) { ret = obj->Unmount(inPath.c_str()); } break; } case 2: { string inClass; string inPath; if ( (in.GetValue(in[0],inClass)) && (in.GetValue(in[1],inPath)) ) { ret = obj->Unmount(inClass.c_str(),inPath.c_str()); } break; } } return ret; } void CLASS(FileServer)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Node); DEFINE_FUNCTION(exist); DEFINE_FUNCTION(mount); DEFINE_FUNCTION(unmount); } --- NEW FILE: filesystem_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: filesystem_c.cpp,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "filesystem.h" using namespace boost; using namespace zeitgeist; using namespace std; FUNCTION(FileSystem,setPath) { string inPath; return( (in.GetSize() == 1) && (in.GetValue(in.begin(),inPath)) && (obj->SetPath(inPath.c_str()) != 0) ); } void CLASS(FileSystem)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Leaf); DEFINE_FUNCTION(setPath); } --- NEW FILE: filesystem.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: filesystem.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. FileSystem HISTORY: 27.06.2002 MK - initial version */ #ifndef ZEITGEIST_FILESYSTEM_H #define ZEITGEIST_FILESYSTEM_H #include <zeitgeist/class.h> #include <zeitgeist/leaf.h> #include <salt/fileclasses.h> namespace zeitgeist { /** this class defines the interface which derived filesystems must implement in order to be used with the fileserver. */ class FileSystem : public Leaf { // // types // public: /** this function defines an interface for a callback, used to iterate over files. It used in conjunction with ForEachFile(). */ typedef void (*TCallback) (char *filename, void *param); // // functions // public: /** constructs a filesystem */ FileSystem() : Leaf() {} virtual ~FileSystem() {} /** tries to open the file named inName. Returns an instance of a salt::RFile on success, NULL otherwise */ virtual boost::shared_ptr<salt::RFile> Open(const std::string& inName) = 0; /** sets the path all calls to Open are relative to. For a standard file system this call maps directly to a directory. For Filesystems providing access to an archive it is used to select the archive, i.e. it is the filename of an archive. Please refer to concrete Filesystems for an example implementation. */ virtual bool SetPath(const std::string& inPath) = 0; /** iterates over all files managed by this filesystem. * 'directory', 'name' and 'extension' give directory, name and * extension a file must match. directory,name and extension may * be NULL, in wich case every directory,extension and/or name * matches. For each match the function callback is called with * the name of the matched file and the additional user parameter * 'param'. param is just passed through to the callback and has * no meaning to the filesystem. */ virtual int ForEachFile(const std::string&, TCallback callback, void* param) = 0; private: FileSystem(const FileSystem& obj); FileSystem& operator=(const FileSystem& obj); }; DECLARE_ABSTRACTCLASS(FileSystem); } //namespace zeitgeist #endif //ZEITGEIST_FILESYSTEM_H |
Update of /cvsroot/simspark/simspark/spark/zeitgeist/telnetserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11684/telnetserver Added Files: telnetdaemon.cpp telnetdaemon.h telnetserver.cpp telnetserver.h telnetserver_c.cpp telnetsession.cpp telnetsession.h Log Message: --- NEW FILE: telnetsession.cpp --- #include "telnetsession.h" #include "telnetdaemon.h" #include "telnetserver.h" #include "../scriptserver/scriptserver.h" #include <iostream> using namespace zeitgeist; using namespace boost; TelnetSession::TelnetSession(TelnetDaemon &daemon) : mClientSocket(INVALID_SOCKET), mDaemon(daemon) { memset(&mClientAddr, 0, sizeof(mClientAddr)); // options mDoEcho = false; } TelnetSession::~TelnetSession() { } void TelnetSession::Init(SOCKET clientSocket, sockaddr_in clientAddr, boost::shared_ptr<ScriptServer> scriptServer) { mClientSocket = clientSocket; mClientAddr = clientAddr; mScriptServer = scriptServer; } void TelnetSession::operator()() { // attach ourselves to the daemon which created us mDaemon.Attach(this); bool done = false; while(!done) { Send(mDaemon.GetServer().GetHostName()+": "); std::string input; if (WaitForData(input) == false) { done = true; } else { if (input.compare("exit")==0) { Terminate(); } else { mScriptServer->Eval(input); //Send("Executing: '"+input+"'\r\n"); } } } // remove ourselves from the daemon mDaemon.Detach(this); closesocket(mClientSocket); } bool TelnetSession::Send(const std::string& data) { if ( send( mClientSocket , data.c_str() , data.size() , 0 ) != (int)data.size() ) { std::cout << "ERROR: Sending data to client failed" << std::endl; return false; } return true; } bool TelnetSession::WaitForData(std::string &data) { const unsigned char IAC = 255; // interpret as command // global would be faster.... std::string validChars = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~`!@#$%^&*()-_=+{[}]\\|;:'\"<,>.?/"; int sizeEchoBuf = 0; char echoBuf[4]; // empty the buffer memset( echoBuf , 0 , 4 ); unsigned char buf = 0; while ( buf != 13 ) { buf = 0; memset( echoBuf , 0 , 4 ); sizeEchoBuf = 0; if(recv( mClientSocket, (char*)&buf , 1 , 0) < 1) { //std::cout << "ERROR: Receiving data from client failed" << std::endl; return false; } switch((unsigned char)buf) { case 13: // return was pressed echoBuf[0] = 13; echoBuf[1] = 10; sizeEchoBuf = 2; break; case 8: // backspace was pressed case 127: // backspace was pressed if ( data.size() > 0 ) { // cut off one char data.resize(data.size()-1); echoBuf[0] = buf; echoBuf[1] = 32; echoBuf[2] = buf; sizeEchoBuf = 3; } else { continue; } break; case IAC: { recv( mClientSocket, (char*)&buf, 1 , 0); ProcessCommand(buf); } break; default: if (validChars.find(buf) != -1) { // add to result buffer data += buf; // echo the pressed char echoBuf[0] = buf; sizeEchoBuf = 1; } break; } // echo if ( mDoEcho == true && sizeEchoBuf>0) { if (send( mClientSocket , echoBuf , sizeEchoBuf , 0 ) != sizeEchoBuf) { std::cout << "ERROR: Sending data to client failed" << std::endl; return false; } } } return true; } void TelnetSession::Terminate() { shutdown(mClientSocket, 0x01); } void TelnetSession::ProcessCommand(unsigned char command) { unsigned char option = 0; std::cout << "Command: " << (unsigned int)command; if (command >= 251 && command <= 254) { // these commands need another byte from the client unsigned char buf; recv( mClientSocket, (char*)&buf, 1 , 0); option = buf; std::cout << " - " << (unsigned int)option; } std::cout << std::endl; switch (command) { case 253: // DO switch(option) { case 1: // do echo mDoEcho = true; break; } break; case 254: // DON'T switch(option) { case 1: // do echo mDoEcho = false; break; } break; }; } --- NEW FILE: telnetdaemon.cpp --- #include "telnetdaemon.h" #include "telnetserver.h" #include "telnetsession.h" #include <boost/thread/thread.hpp> #include <iostream> using namespace zeitgeist; using namespace std; using namespace boost; TelnetDaemon::TelnetDaemon(TelnetServer &server) : mServer(server) { mDaemonSocket = INVALID_SOCKET; } TelnetDaemon::~TelnetDaemon() { Terminate(); } /* The actual thread routine. */ void TelnetDaemon::operator()() { //tell the server that the daemon thread is running mServer.SetDaemon(this); // at this point the bidirectional connection between client/server is // established. Now we start the listening socket of the daemon if (Init(mServer.GetPort()) == false) return; std::cout << mServer.GetHostName() << ": Daemon started, listening for connections..." << std::endl; boost::thread_group sessionThreads; TelnetSession cc(*this); while (AcceptConnection(cc)) { sessionThreads.create_thread(cc); } // we wait for all session threads to finish, before we finish sessionThreads.join_all(); } bool TelnetDaemon::Init(int portNr) { // create socket mDaemonSocket = socket(AF_INET, SOCK_STREAM, 0); if (mDaemonSocket == INVALID_SOCKET) { std::cout << "ERROR: Could not create socket" << std::endl; return false; } int iOptval = 1; if ( setsockopt( mDaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &iOptval, sizeof(int)) ) { std::cout << "ERROR: Setsockopt failed" << std::endl; return false; } mDaemonAddr.sin_family = AF_INET; mDaemonAddr.sin_port = htons( USHORT(portNr) ); mDaemonAddr.sin_addr.s_addr = INADDR_ANY; // Bind to the given port if ( bind( mDaemonSocket, (struct sockaddr *) &mDaemonAddr, sizeof(mDaemonAddr) ) ) { std::cout << "ERROR: Bind failed" << std::endl; return false; } // change to passive socket if ( listen( mDaemonSocket , SOMAXCONN ) ) { std::cout << "ERROR: Listen failed" << std::endl; return false; } return true; } void TelnetDaemon::Terminate() { if (mDaemonSocket != INVALID_SOCKET) { closesocket(mDaemonSocket); mDaemonSocket = INVALID_SOCKET; } } bool TelnetDaemon::AcceptConnection(TelnetSession &cc) { sockaddr_in clientAddr; SOCKET clientSocket; // fill with zero terms memset( &clientAddr , 0 , sizeof(clientAddr) ); // wait for connetion int len = sizeof(clientAddr); clientSocket = accept( mDaemonSocket, (struct sockaddr *)&(clientAddr) , &len ); if ( clientSocket == INVALID_SOCKET ) { //std::cout << "ERROR: Accept failed" << std::endl; return false; } // get client ip address char szClientIp[255]; strncpy( szClientIp, inet_ntoa(clientAddr.sin_addr), 128); std::cout << "Incoming connection from: " << szClientIp << std::endl; // create a clientconnection cc.Init(clientSocket, clientAddr, mServer.GetScriptServer()); return true; } void TelnetDaemon::Attach(TelnetSession *session) { std::cout << "Attaching TelnetSession " << (void*) session << std::endl; mSessions.push_back(session); } void TelnetDaemon::Detach(TelnetSession *session) { std::cout << "Detaching TelnetSession " << (void*) session << std::endl; mSessions.remove(session); } void TelnetDaemon::Status() { std::cout << " Number of clients: " << mSessions.size() << std::endl; } --- NEW FILE: telnetdaemon.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: telnetdaemon.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. TelnetDaemon HISTORY: 19.06.2002 MK - initial version */ #ifndef ZEITGEIST_TELNETDAEMON_H #define ZEITGEIST_TELNETDAEMON_H #ifdef _WIN32 #include <winsock.h> #endif #include <list> namespace zeitgeist { class TelnetSession; class TelnetServer; /** the TelnetDaemon is responsible to listen for incoming connections. For each connection it creates a new thread with a TelnetSession object, managing the session. */ class TelnetDaemon { // // types // public: protected: private: typedef std::list<TelnetSession*> TSessionList; // // functions // public: /** constructs the TelnetDaemon \param server is a reference to the server constructing this daemon */ TelnetDaemon(TelnetServer &server); virtual ~TelnetDaemon(); /** contains the code run inside the thread for this Daemon, called from the boost thread library */ void operator()(); /** called from the server to shutdown the daemon. This method destroys all session objects */ void Terminate(); /** prints the status of the daemon to stdout */ void Status(); /** adds a session a object to the list of managed sessions */ void Attach(TelnetSession *session); /** removes a session object from the list of managed sessions */ void Detach(TelnetSession *session); /** return a reference to the TelnetServer object, called by the TelnetSession objects */ const TelnetServer& GetServer() const { return mServer; } protected: /** create the network socket and start the daemon */ bool Init(int portNr); /** accepts a pending connection request, creates a new socket and associates the TelnetSession cc with it*/ bool AcceptConnection(TelnetSession& cc); // // members // public: protected: private: /** the listen socket of the server */ SOCKET mDaemonSocket; /** the local adress the daemon is bound to */ sockaddr_in mDaemonAddr; /** the list of current active sessions */ TSessionList mSessions; /** a reference to the TelnetServer */ TelnetServer &mServer; }; } #endif // ZEITGEIST_TELNETDAEMON_H --- NEW FILE: telnetsession.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: telnetsession.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. TelnetSession HISTORY: 20.06.2002 MK - initial version */ #ifndef ZEITGEIST_TELNETSESSION_H #define ZEITGEIST_TELNETSESSION_H #include <winsock.h> #include <string> #include <boost/shared_ptr.hpp> namespace zeitgeist { class ScriptServer; class TelnetDaemon; /** TelnetSession is responsible for managing one connection to a remote client. It is created by a TelnetDaemon object and runs in its own thread context. It features basic telnet session setup and option negotiation with the client, like the used echo settings. TelnetSession display a simple prompt ':', waits for the user to enter a command, and executes it using the zeitgeist ScriptServer. !TODO!: the implemented ruby commands simply output to stdout. Therefore their output is not remotely visible. Steps to do: - extend the CoreContext to provide stream or printf semantics - alter all the commands to use these output functions - implement a CoreContext that forwards the output over the network */ class TelnetSession { // // functions // public: /** constructs a TelnetSession object */ TelnetSession(TelnetDaemon &daemon); virtual ~TelnetSession(); /** receives and remebers the socket, the local adress and a reference to the ScriptServer */ void Init(SOCKET clientSocket, sockaddr_in clientAddr, boost::shared_ptr<ScriptServer> scriptServer); /** contains the code run inside the thread for this Session, called from the boost thread library */ void operator()(); /** sends a string over the connected socket, returns true on success */ bool Send(const std::string& data); /** waits for data on the connected socket and interprets special characters like backspace and return. It further provides an echo mechanism, if the client enables it. The function returns true on success with data containing the received string */ */ bool WaitForData(std::string &data); /** closes the associated socket */ void Terminate(); protected: private: /** processes special telnet control characters like del and enter */ void ProcessCommand(unsigned char command); // // members // public: protected: private: /** the connected client socket */ SOCKET mClientSocket; /** the local adress of the socket */ sockaddr_in mClientAddr; /** true, if the client enabled the echo mechanism */ bool mDoEcho; /** a reference to the daemon which created this session */ TelnetDaemon &mDaemon; /** the core context associated with this session */ boost::shared_ptr<ScriptServer> mScriptServer; }; } #endif // ZEITGEIST_TELNETSESSION_H --- NEW FILE: telnetserver_c.cpp --- #include "telnetserver.h" using namespace zeitgeist; void CLASS(TelnetServer)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Node); } --- NEW FILE: telnetserver.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: telnetserver.h,v 1.1 2005/12/05 21:05:01 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. TelnetServer :TODO: Class description for TelnetServer HISTORY: 20.06.2002 MK - initial version 28.06.2003 MR - modified for inclusion into the zeitgeist library */ #ifndef ZEITGEIST_TELNETSERVER_H #define ZEITGEIST_TELNETSERVER_H #ifdef _WIN32 // the socket functions require the ws2_32 library #pragma comment(lib, "ws2_32.lib") // boost threads are used for thread creation #pragma comment(lib, "libboost_thread.lib") #endif #include <zeitgeist/node.h> #include <string> namespace zeitgeist { class TelnetDaemon; /** The TelnetServer provides remote access to the Zeitgeist framework using a telnet connection. The user can interact with the system using ruby statements. The TelnetServer starts a TelnetDaemon wich listens for incoming connections and creates a new TelnetSession object for each new connection. Each TelnetSession object runs in its own thread context. */ class TelnetServer : public Node { friend class TelnetDaemon; // // functions // public: /** constructs the TelnetServer and starts the TelnetDaemons, listening on the specified port, default 23 */ TelnetServer(unsigned int port = 23); virtual ~TelnetServer(); /** prints the current status to stdout */ void Status(); /** returns the port number the daemon listens on */ unsigned int GetPort() const { return mPort; }; /** returns the hostname of this machine */ const std::string& GetHostName() const { return mHostName; } private: TelnetServer(const TelnetServer& obj); TelnetServer& operator=(const TelnetServer& obj); /** called by the daemon to tell its instance */ void SetDaemon(TelnetDaemon *daemon) { mDaemon = daemon; } /** called by the daemon to get access to the scriptserver */ boost::shared_ptr<ScriptServer> GetScriptServer() { return GetScript(); } /** starts the telnetserver, creating the daemon */ bool Start(); /** shuts the telnetserver down, returns true on clean exit */ bool Shutdown(); // // members // protected: /** the port number the daemons listens on */ unsigned int mPort; /** the instance of then daemon */ TelnetDaemon *mDaemon; /** the hostname of this machine */ std::string mHostName; }; DECLARE_CLASS(TelnetServer); } #endif //ZEITGEIST_TELNETSERVER_H --- NEW FILE: telnetserver.cpp --- #include "telnetserver.h" #include <boost/thread/thread.hpp> #include <iostream> #include "telnetdaemon.h" #include "../logserver/logserver.h" using namespace zeitgeist; using namespace std; TelnetServer::TelnetServer(unsigned int port) : Node(), mPort(port) { mDaemon = NULL; #ifdef _WIN32 // Windows socket initialization WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(1, 1); // Find winsock version if ( WSAStartup(wVersionRequested, &wsaData) ) { GetLog()->Normal() << "TelnetServer: Incorrect winsock version\n" << endl; } #endif char buffer[512]; gethostname(buffer, 511); mHostName = buffer; Start(); } TelnetServer::~TelnetServer() { Shutdown(); #ifdef _WIN32 WSACleanup(); #endif } bool TelnetServer::Start() { if (mDaemon != NULL) { Shutdown(); } // here we start the actual worker thread TelnetDaemon daemon(*this); boost::thread daemonThread(daemon); return true; } bool TelnetServer::Shutdown() { if (mDaemon != NULL) { mDaemon->Terminate(); mDaemon = NULL; } return true; } void TelnetServer::Status() { std::cout << "TelnetServer::Status()\n"; if (mDaemon == NULL) { std::cout << " No daemon running...\n"; return; } std::cout << " Daemon running on port " << GetPort() << std::endl; mDaemon->Status(); std::cout << std::endl; } |
From: Markus R. <rol...@us...> - 2005-12-05 21:04:21
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/telnetserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11520/telnetserver Log Message: Directory /cvsroot/simspark/simspark/spark/zeitgeist/telnetserver added to the repository |
From: Markus R. <rol...@us...> - 2005-12-05 21:03:45
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/scriptserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11370/scriptserver Log Message: Directory /cvsroot/simspark/simspark/spark/zeitgeist/scriptserver added to the repository |
From: Markus R. <rol...@us...> - 2005-12-05 21:03:05
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/randomserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11213/randomserver Log Message: Directory /cvsroot/simspark/simspark/spark/zeitgeist/randomserver added to the repository |
From: Markus R. <rol...@us...> - 2005-12-05 21:01:53
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/logserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10883 Added Files: logserver.cpp logserver.h logserver_c.cpp logserverstreambuf.cpp logserverstreambuf.h Log Message: --- NEW FILE: logserverstreambuf.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: logserverstreambuf.h,v 1.1 2005/12/05 21:01:39 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ZEITGEIST_LOGSERVERSTREAMBUF_H #define ZEITGEIST_LOGSERVERSTREAMBUF_H /*! \class LogServerStreamBuf $Id: logserverstreambuf.h,v 1.1 2005/12/05 21:01:39 rollmark Exp $ ForwarderStreamBuf The ForwarderStreamBuf is a special std::streambuf derived class, which can stream to a list of streams. In addition to the multiplexing functionality this class also supports priorization of streamed data. Every registered stream is associated with a priority mask. This is a bitfield mask which tells the system which kind of messages should be muxed to a particular stream. The ForwarderStreamBuf also manages the current priority level to be used for incoming data. If the state is changed, the buffers are flushed! HISTORY: The forwarder subsystem was taken from a student project at the AI Research Group, Koblenz University. Original development by Marco Koegler <ko...@un...>, Marcus Rollmann <rol...@un...>, Alexander Fuchs <al...@un...>, et.al. It was built into the rcssserver3D, and then converted back into the diploma thesis of Marco Koegler, which was the base for rcssserver3D. */ #include <functional> #include <vector> #include <streambuf> namespace zeitgeist { class LogServerStreamBuf : public std::streambuf { // types // protected: typedef std::char_traits<char> TTraitsType; typedef traits_type::int_type TIntType; private: typedef std::pair<unsigned int, std::ostream*> TMaskStream; typedef std::vector<TMaskStream> TMaskStreams; // functions // public: LogServerStreamBuf(unsigned int size); virtual ~LogServerStreamBuf(); /*! Add a stream to the list of streams. First, it is checked if the stream is already in. If the stream is found, we only add a new priority mask to the existing ones, so no stream can be added twice. @param stream the stream to add @param mask the (new) priority mask for the stream */ void AddStream(std::ostream *stream, unsigned int mask); /*! Remove a stream from the list of streams. @param stream the stream to remove @return true if the stream was found (and thus removed) */ bool RemoveStream(const std::ostream *stream); /*! Set priority mask of a stream in the list. @param stream the stream for which we want to set the priority mask @param mask the new priority mask @return true if the stream was found */ bool SetPriorityMask(const std::ostream *stream, unsigned int mask); /*! Get priority mask of a stream in the list. @param stream the stream for which we want to set the priority mask @return the priority mask; 0 if stream was not found */ unsigned int GetPriorityMask(const std::ostream *stream) const; /*! Set the current priority level. All data which is streamed into the forwarder after this point will use the current priority level. Before the priority level is adjusted, all buffered data is flushed. @param priority current priority level (see EPriorityLevel) */ void SetCurrentPriority(unsigned int priority); protected: // these functions implement the streambuf interface ... handle with care TIntType overflow(TIntType c); int sync(); private: LogServerStreamBuf(const LogServerStreamBuf &obj); LogServerStreamBuf& operator=(const LogServerStreamBuf &obj); //! multiplex to all registered streams void Forward(const char *buffer, unsigned int length); //! stream out complete internal buffer void PutBuffer(); //! stream out a single character void PutChar(TIntType chr); //! A predicate to compare streams in a MaskStream list (or vector). class MaskStreamEQ : public std::unary_function<TMaskStream, bool> { private: const std::ostream *stream; public: explicit MaskStreamEQ(const std::ostream *str) : stream(str) {} bool operator ()(const TMaskStream &ms) { return ms.second == stream; } }; // members // private: //! size of the internal buffer to use unsigned int mSize; unsigned int mCurrentPriority; TMaskStreams mStreams; }; } //namespace #endif // ZEITGEIST_LOGSERVERSTREAMBUF_H --- NEW FILE: logserverstreambuf.cpp --- #include <algorithm> #include <iostream> #include "logserverstreambuf.h" using namespace std; using namespace zeitgeist; LogServerStreamBuf::LogServerStreamBuf(unsigned int size) : streambuf(), mSize(size), mCurrentPriority(0xffffffff) { // Here we set up the 'put' area, where data is streamed in if (mSize) { char* ptr = new char[mSize]; setp(ptr, ptr + mSize); } else { setp(0, 0); } // we don't support a 'get' area ... no istream support setg(0, 0, 0); } LogServerStreamBuf::~LogServerStreamBuf() { // flush buffer sync(); // delete mask-stream elements. The streams will not be deleted. while (mStreams.size() != 0) { if (mStreams.back().second != &std::cout && mStreams.back().second != &std::cerr) delete mStreams.back().second; mStreams.pop_back(); } // delete buffer delete[] pbase(); } void LogServerStreamBuf::AddStream(std::ostream *stream, unsigned int mask) { TMaskStreams::iterator i; i = find_if(mStreams.begin(), mStreams.end(), MaskStreamEQ(stream)); if (i == mStreams.end()) { TMaskStream pstream(mask, stream); mStreams.push_back(pstream); } else { i->first |= mask; } } bool LogServerStreamBuf::RemoveStream(const std::ostream *stream) { // flush buffer sync(); TMaskStreams::iterator i; i = find_if(mStreams.begin(), mStreams.end(), MaskStreamEQ(stream)); if (i != mStreams.end()) { mStreams.erase(i); return true; } return false; } bool LogServerStreamBuf::SetPriorityMask(const std::ostream *stream, unsigned int mask) { // flush buffer sync(); TMaskStreams::iterator i; i = find_if(mStreams.begin(), mStreams.end(), MaskStreamEQ(stream)); if (i != mStreams.end()) { i->first = mask; return true; } return false; } unsigned int LogServerStreamBuf::GetPriorityMask(const std::ostream *stream) const { TMaskStreams::const_iterator i; i = find_if(mStreams.begin(), mStreams.end(), MaskStreamEQ(stream)); if (i != mStreams.end()) { return i->first; } return 0; } void LogServerStreamBuf::SetCurrentPriority(unsigned int priority) { sync(); mCurrentPriority = priority; } /*! This routine is called by the iostream library if our internal buffer is overflowing (the put area is full). */ LogServerStreamBuf::TIntType LogServerStreamBuf::overflow(TIntType c) { // write out the buffered content PutBuffer(); // handle the extra character if it isn't eof if (c != TTraitsType::eof()) { // if we don't do buffering if (pbase() == epptr()) { // write out the character directly PutChar(c); } else { // buffer it sputc(c); } } return 0; } /*! This routine synchronizes the internal state with the external state. It is used to flush the streambuf object. */ int LogServerStreamBuf::sync() { PutBuffer(); return 0; } void LogServerStreamBuf::Forward(const char *buffer, unsigned int length) { TMaskStreams::iterator i; for (i=mStreams.begin(); i!= mStreams.end(); ++i) { if ((*i).first & mCurrentPriority) { (*i).second->write(buffer, length); } } } void LogServerStreamBuf::PutBuffer() { // if we have data to stream out if (pbase() != pptr()) { int len = (pptr() - pbase()); // pbase() = buffer address Forward(pbase(), len); // reset pointers == put area is empty setp(pbase(), epptr()); } } void LogServerStreamBuf::PutChar(TIntType chr) { char a[1]; a[0] = chr; Forward(a, 1); } --- NEW FILE: logserver.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: logserver.h,v 1.1 2005/12/05 21:01:39 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. LogServer HISTORY: 22.08.2002 MK - initial version - reclaimed from rcssserver3D :) */ #ifndef ZEITGEIST_LOGSERVER_H #define ZEITGEIST_LOGSERVER_H #include <iostream> #include "../node.h" namespace zeitgeist { class LogServerStreamBuf; /** The log server is responsible for holding a bunch of ostreams, which data can be streamed to. It is THE logging facility used within zeitgeist. */ class LogServer : public Node , public std::ostream { // types // public: /** defines different priority levels assigned to a log message. The values are designed as a bitmap and can be combined, to trigger different filters */ enum EPriorityLevel { eNone = 0, eDebug = 1, eNormal = 2, eWarning = 4, eError = 8, eAll = 0xffffffff }; // // functions // public: /** constructs a logserver with a an internal stream buffer of size */ LogServer(unsigned int size = 1024); virtual ~LogServer(); /** adds a stream to the list of streams. First, it is checked if the stream is already in. If the stream is found, we only install a new priority mask, so no stream can be added twice. @param stream the stream to add @param mask the (new) priority mask for the stream */ void AddStream(std::ostream *stream, unsigned int mask = eAll); /** removes a stream from the list of streams. @param stream the stream to remove @return true if the stream was found (and thus removed) */ bool RemoveStream(const std::ostream *stream); /** sets the priority mask of a stream in the list. @param stream the stream for which we want to set the priority mask @param mask the new priority mask @return true if the stream was found */ bool SetPriorityMask(const std::ostream *stream, unsigned int mask); /** gets priority mask of a stream in the list. @param stream the stream for which we want to set the priority mask @return the priority mask; 0 if stream was not found */ unsigned int GetPriorityMask(const std::ostream *stream) const; /** selects the priority for the messages to be written. It returns a reference to this logserver instance, allowing multiple priority changes in one stream expression, e.g. log << Priority(eNormal) << "normal msg" << Priority(eDbug) << "debug msg" */ LogServer& Priority(unsigned int prio); /** selects the debug priority and returns a reference to this logserver */ LogServer& Debug() { return Priority(eDebug); } /** selects the normal priority and returns a reference to this logserver */ LogServer& Normal() { return Priority(eNormal); } /** selects the warning priority and returns a reference to this logserver */ LogServer& Warning() { return Priority(eWarning); } /** selects the error priority and returns a reference to this logserver */ LogServer& Error() { return Priority(eError); } /** provides an printf-style interface. */ void Printf(const char *inFormat, ...); private: LogServer(const LogServer& obj); LogServer& operator=(const LogServer& obj); const LogServerStreamBuf& GetStreamBuf() const; LogServerStreamBuf& GetStreamBuf(); }; DECLARE_CLASS(LogServer); } //namespace zeitgeist #endif //ZEITGEIST_LOGSERVER_H --- NEW FILE: logserver.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: logserver.cpp,v 1.1 2005/12/05 21:01:39 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "logserver.h" #include "logserverstreambuf.h" #include <stdarg.h> using namespace std; using namespace zeitgeist; LogServer::LogServer(unsigned int size) : Node(), ostream(new LogServerStreamBuf(size)) { } LogServer::~LogServer() { flush(); // delete the created streambuf delete rdbuf(); } void LogServer::AddStream(std::ostream* stream, unsigned int mask) { GetStreamBuf().AddStream(stream, mask); } bool LogServer::RemoveStream(const std::ostream* stream) { return GetStreamBuf().RemoveStream(stream); } unsigned int LogServer::GetPriorityMask(const std::ostream* stream) const { return GetStreamBuf().GetPriorityMask(stream); } bool LogServer::SetPriorityMask(const std::ostream* stream, unsigned int mask) { return GetStreamBuf().SetPriorityMask(stream, mask); } LogServer& LogServer::Priority(unsigned int prio) { GetStreamBuf().SetCurrentPriority(prio); return *this; } void LogServer::Printf(const char *inFormat, ...) { const int size = 4096; char copyBuffer[size]; va_list args; va_start(args, inFormat); if (vsnprintf(copyBuffer, size, inFormat, args) == size) { copyBuffer[size-1] = 0; } va_end(args); (*this) << copyBuffer; this->flush(); } const LogServerStreamBuf& LogServer::GetStreamBuf() const { LogServerStreamBuf* streamBuf = (LogServerStreamBuf*)(rdbuf()); return *streamBuf; } LogServerStreamBuf& LogServer::GetStreamBuf() { LogServerStreamBuf* streamBuf = (LogServerStreamBuf*)(rdbuf()); return *streamBuf; } --- NEW FILE: logserver_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: logserver_c.cpp,v 1.1 2005/12/05 21:01:39 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "logserver.h" #include <fstream> using namespace boost; using namespace zeitgeist; FUNCTION(LogServer,addStream) { std::string inName; std::string inPriority; if ( (in.GetSize() != 2) || (! in.GetValue(in[0],inName)) || (! in.GetValue(in[1],inPriority)) ) { return false; } std::ostream *stream = NULL; if (inName == ":cout") { stream = &std::cout; } else if (inName == ":cerr") { stream = &std::cerr; } else { stream = new std::ofstream(inName.c_str()); } unsigned int pLevel = LogServer::eNone; do { if (inPriority == "eNone") { pLevel = LogServer::eNone; break; } if (inPriority == "eDebug") { pLevel = LogServer::eDebug; break; } if (inPriority == "eNormal") { pLevel = LogServer::eNormal; break; } if (inPriority == "eWarning") { pLevel = LogServer::eWarning; break; } if (inPriority == "eError") { pLevel = LogServer::eError; break; } if (inPriority == "eAll") { pLevel = LogServer::eAll; break; } // no match return false; } while(true); obj->AddStream(stream, pLevel); return true; } void CLASS(LogServer)::DefineClass() { DEFINE_BASECLASS(zeitgeist/Node); DEFINE_FUNCTION(addStream); } |
From: Markus R. <rol...@us...> - 2005-12-05 21:01:00
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/logserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10656/logserver Log Message: Directory /cvsroot/simspark/simspark/spark/zeitgeist/logserver added to the repository |
From: Markus R. <rol...@us...> - 2005-12-05 21:00:27
|
Update of /cvsroot/simspark/simspark/spark/zeitgeist/fileserver In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10501/fileserver Log Message: Directory /cvsroot/simspark/simspark/spark/zeitgeist/fileserver added to the repository |
Update of /cvsroot/simspark/simspark/spark/zeitgeist In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10095 Added Files: Makefile.am class.cpp class.h class_c.cpp core.cpp core.h corecontext.cpp corecontext.h leaf.cpp leaf.h leaf_c.cpp node.cpp node.h node_c.cpp object.cpp object.h object_c.cpp object_c.h parameterlist.cpp parameterlist.h zeitgeist.cpp zeitgeist.h Log Message: --- NEW FILE: zeitgeist.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: zeitgeist.h,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ZEITGEIST_ZEITGEIST_H #define ZEITGEIST_ZEITGEIST_H #include "core.h" #include "corecontext.h" #include "scriptserver/scriptserver.h" #include "logserver/logserver.h" #include <boost/shared_ptr.hpp> namespace zeitgeist { /** \class Zeitgeist is the main class, which initializes the Zeitgeist framework, manages the core and the main core context. It is the basic interface to the client code. */ class Zeitgeist { // // functions // public: /** constructs the main core and starts the zeitgeist framework. dotName gives the name of the directory in the user's home directory, where the default init scripts are searched. */ Zeitgeist(std::string dotName); /** constructs the main core as above but changes the relative path prefix used by the ScriptServer prior to running the zeitgeist init script. */ Zeitgeist(std::string dotName, std::string relPathPrefix); ~Zeitgeist(); /** creates a new corecontext */ boost::shared_ptr<CoreContext> CreateContext(); /** returns a pointer to the main core */ boost::shared_ptr<Core>& GetCore(); private: /** allocates and sets up the main core */ void ConstructCore(); /** runs the zeitgeist init script. dotName is the name of the users local directory, where the init scripts are searched */ void RunInitScript(std::string dotName); // // members // private: /** the main core */ boost::shared_ptr<Core> mCore; }; } //namespace zeitgeist #endif //ZEITGEIST_ZEITGEIST_H --- NEW FILE: leaf.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: leaf.h,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Leaf HISTORY: 04.06.2002 MK - initial version 13.06.2002 MK - reworked Base to use a quad-linked tree 15.06.2002 MK - split Base up into Base and Node classes 02.09.2002 MK - removed quad-link 22.02.2003 MK - renamed to Leaf */ #ifndef ZEITGEIST_LEAF_H #define ZEITGEIST_LEAF_H #include <list> #include <string> #include "object.h" namespace zeitgeist { /** Leaf defines the beginning of the hierarchy. A Leaf object can reside within the hierarchy, but cannot have children! */ class Leaf : public Object { friend class Node; // // types // public: typedef std::list< boost::shared_ptr<Leaf> > TLeafList; // // functions // public: /** constructs a leaf with the given name */ Leaf(const std::string &name = "<unnamed>"); virtual ~Leaf(); /** returns a reference to the name of the leaf */ std::string& GetName() { return mName; } /** returns a constant reference to the name of the leaf */ const std::string& GetName() const { return mName; } // hierarchy /** returns a pointer to the parent of the leaf */ boost::weak_ptr<Node>& GetParent(); /** returns a constant pointer to the parent of the leaf */ const boost::weak_ptr<Node>& GetParent() const; /** defines an interface to get a pointer to a child (i.e. node or leaf) with the given name, which can be searched recursively. The class Leaf will always return an empty reference */ virtual boost::shared_ptr<Leaf> GetChild(const std::string &name, bool recursive = false); /** defines an interface to get a pointer to child of the given class type, which can be searched recursively. The class Leaf will always return an empty reference */ virtual boost::shared_ptr<Leaf> GetChildOfClass(const std::string &name, bool recursive = false); /** defines an interface to get the fist child supporting the class 'name' (i.e. nodes of a type equal to or derived from the class 'name'), which can be searched recursively. The class Leaf will always return an empty reference */ virtual boost::shared_ptr<Leaf> GetChildSupportingClass(const std::string &name, bool recursive = false); /** defines an interface to get the fist child supporting the class 'name' (i.e. nodes of a type equal to or derived from the class 'name'), which can be searched recursively. The class Leaf will always return an empty reference. This implementation of FindChildSupportingClass does not rely on the associated zeitgeist class name but uses the c++ typeid system. */ template<class CLASS> boost::shared_ptr<CLASS> FindChildSupportingClass(bool recursive = false) { TLeafList::iterator lstEnd = end(); // avoid repeated virtual calls for (TLeafList::iterator i = begin(); i != lstEnd; ++i) { // check if we have found a match and return it boost::shared_ptr<CLASS> child = boost::shared_dynamic_cast<CLASS>(*i); if (child.get() != 0) { return child; } if (recursive) { return (*i)->FindChildSupportingClass<CLASS>(recursive); } } return boost::shared_ptr<CLASS>(); } /** defines an interface to get a list of children. The Leaf class will always return an empty list */ virtual void GetChildren(const std::string &name, TLeafList &baseList, bool recursive = false); /** defines an interface to get a list to all children of type 'name'. The Leaf class will always return an empty list */ virtual void GetChildrenOfClass(const std::string &name, TLeafList &baseList, bool recursive = false); /** defines an interface to get a list to all children supporting a class 'name' i.e. they are an instance of that class or are derived from it. The Leaf class will always return an empty list */ virtual void GetChildrenSupportingClass(const std::string &name, TLeafList &baseList, bool recursive = false); /** constructs a list of all children supporting a class 'name' i.e. they are an instance of that class or are derived from it. This implementation of GetChildrenSupportingClass does not rely on the associated zeitgeist class name but uses the c++ typeid system. */ template<class CLASS> void ListChildrenSupportingClass(TLeafList& list, bool recursive = false) { TLeafList::iterator lstEnd = end(); // avoid repeated virtual calls for (TLeafList::iterator i = begin(); i != lstEnd; ++i) { // check if we have found a match and add it boost::shared_ptr<CLASS> child = boost::shared_dynamic_cast<CLASS>(*i); if (child.get() != 0) { list.push_back(child); } if (recursive) { (*i)->ListChildrenSupportingClass<CLASS>(list,recursive); } } } /** defines an interface to get the first parent node on the way up the hierarchy that supports a class 'name', i.e. is an instance of that class or is derived from it. */ virtual boost::weak_ptr<Node> GetParentSupportingClass(const std::string &name) const; /** defines an interface to get the first parent node on the way up the hierarchy that supports a class 'name', i.e. is an instance of that class or is derived from it. This implementation of GetParentSupportingClass does not rely on the associated zeitgeist class name but uses the c++ typeid system. */ template<class CLASS> boost::weak_ptr<CLASS> FindParentSupportingClass() const; // { // boost::shared_ptr<Node> node // = boost::shared_static_cast<Node>(make_shared(GetParent())); // while (node.get() != 0) // { // boost::shared_ptr<CLASS> test = // boost::shared_dynamic_cast<CLASS>(node); // if (test.get() != 0) // { // return test; // } // node = boost::shared_static_cast<Node>(make_shared(node->GetParent())); // } // return boost::shared_ptr<CLASS>(); // } /** defines an interface to test if this node is a leaf. Only the TLeaf class will return true */ virtual bool IsLeaf() const; /** removes base from the set of children. */ virtual void RemoveChildReference(const boost::shared_ptr<Leaf> &base); /** adds base to the set of children and sets the parent of base to be this node */ virtual bool AddChildReference(const boost::shared_ptr<Leaf> &base); /** detaches this node and its hierarchy from its parent. */ void Unlink(); /** unlinks all child nodes */ virtual void UnlinkChildren(); /** writes debug data to stdout */ virtual void Dump() const; /** update variables from a script */ virtual void UpdateCached() {} /** constructs the full path of this node by walking up the tree. Cosecutive calls return a cached copy of the full path to avoid the expensive tree walk. */ const std::string& GetFullPath() const; /** clears any cached data (e.g. the cached full path and forces the node to recalculate all values */ void ClearCachedData() const; /** sets the name of this node */ void SetName(const std::string &name) { mName = name; ClearCachedData(); } // iterator helpers virtual TLeafList::iterator begin(); virtual TLeafList::const_iterator begin() const; virtual TLeafList::iterator end(); virtual TLeafList::const_iterator end() const; protected: /** called from within UpdatCached; override to perform node specific updates */ virtual void UpdateCachedInternal() {} /** Sets the parent of this node. It has to be implemented 'very carefully'. The parent object always holds a shared pointer reference to mSelf. What we have to do is 'get' the shared reference, remove it from the old parent. Insert it into the new parent and change the parent pointer. */ void SetParent(const boost::shared_ptr<Node> &parent); /** This method is called, when the hierarchy object has been linked to a parent. At that point, traversal can commence. It can be overridden to support custom 'link' behavior. */ virtual void OnLink(); /** This rountine is called, before the hierarchy object is removed from the parent. It can be overridden to support custom 'unlink' behavior. */ virtual void OnUnlink(); private: Leaf(const Leaf &obj); Leaf& operator=(const Leaf &obj); // // members // protected: /** This pointer holds a link to the parent of this node. It has to be at least a Node, as that is the first class, which can hold children. We use a weak pointer to break the cyclic dependency. */ boost::weak_ptr<Node> mParent; private: /** the name of the node */ std::string mName; /** temporary cached full path of this node in the hierarchy */ mutable std::string *mCachedFullPath; }; /** the class object declaration for Leaf has been moved to class.h to break * circular inclusion between class.h and leaf.h */ } //namespace zeitgeist; #endif //ZEITGEIST_LEAF_H --- NEW FILE: parameterlist.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2004 RoboCup Soccer Server 3D Maintenance Group $Id: parameterlist.h,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ZEITGEIST_PARAMETERLIST_H #define ZEITGEIST_PARAMETERLIST_H #include <boost/any.hpp> #include <vector> #include <string> #include <salt/vector.h> namespace zeitgeist { class ParameterList; /** \class ParameterList manages a list of values. Boost::Any is used as a typesafe container to realize a sequence of values of arbitrary types. */ class ParameterList { public: typedef std::vector<boost::any> TVector; protected: TVector mList; public: ParameterList(); virtual ~ParameterList(); /** inserts a value at the end of the managed sequence */ void AddValue(const boost::any& value); /** inserts an empty ParameterList as a new value at the end of the managed sequence and returns a reference to the new list. Using AddList instead of AddValue avoids copying a list on insertion. */ ParameterList& AddList(); /** returns the number of values contained in the managed sequence */ int GetSize() const; /** returns true if the managed sequence is empty */ bool IsEmpty() const; /** removes all elements from the managed sequence */ void Clear(); /** removes the first element from the managed sequence */ void Pop_Front(); /** removes the last element from the managed sequence */ void Pop_Back(); /** returns an iterator pointing at the begin of the managed sequence */ TVector::const_iterator begin() const; /** returns an iterator pointing at the end of the managed sequence */ TVector::const_iterator end() const; /** returns an iterator pointing at the nth element of the managed sequence */ TVector::const_iterator operator[] (int n) const; /** returns an iterator pointing at the nth element of the managed sequence */ TVector::iterator operator[] (int n); /** returns an iterator pointing at the begin of the managed sequence */ TVector::iterator begin(); /** returns an iterator pointing at the end of the managed sequence */ TVector::iterator end(); /** AdvanceAnyValue is a generic templated helper function for consumers of ParameterLists. It tries to cast the parameter at iter to a value of type T. If successful it returns true, assigns the casted parameter to value and increments the iterator iter. Otherwise false is returned and value and iter are unchanged. Note that AdvanceValue increments iter to transparently allow specialized functions for types that are represented by more than one entry in the ParameterList. An example is a three dimensional vector represented by a sequence of three floats. Note: the AdvanceAnyValue and AdvanceValue have distinct names, as C++ does not support partly specialized template function (currently only partly specialized classes) and would always call the generic template function instead of a partly specialized variant. \param iter position of the parameter \param value extracted value of the parameter \return true if extraction successful, false otherwise */ template<typename T> bool AdvanceAnyValue(TVector::const_iterator& iter, T& value) const { return GetValueInternal<T,T>(iter,value); } /** GetValue is a generic templated helper function for consumers of ParameterLists. It has the same semantics as it's corresponding AdvanceValue except that it takes a const reference to iter that it does not increment. */ template<typename T> f_inline bool GetValue(const TVector::const_iterator& iter, T& value) const { TVector::const_iterator tmp = iter; return AdvanceValue(tmp,value); } template<typename T> f_inline bool GetAnyValue(const TVector::const_iterator& iter, T& value) const { TVector::const_iterator tmp = iter; return AdvanceAnyValue(tmp,value); } /** Below are AdvanceValue helper functions spezialiced for a type */ bool AdvanceValue(TVector::const_iterator& iter, std::string& value) const; bool AdvanceValue(TVector::const_iterator& iter, float& value) const; bool AdvanceValue(TVector::const_iterator& iter, double& value) const; bool AdvanceValue(TVector::const_iterator& iter, int& value) const; bool AdvanceValue(TVector::const_iterator& iter, bool& value) const; bool AdvanceValue(TVector::const_iterator& iter, unsigned int& value) const; bool AdvanceValue(TVector::const_iterator& iter, salt::Vector3f& value) const; bool AdvanceValue(TVector::const_iterator& iter, salt::Vector2f& value) const; protected: /** This is a specialized GetValue helper to read any salt::TVector from a TParameterList. It first tries to interprete a single element of the TParameterList as a TVector. If this fails it tries to build a vector from a sequence of values in the ParameterList. Depending on the way the Vector is built iter is incremented either by one element or the number of scalar elements that make up a vector of the given type. Note: If GetVectorValue builds a vector from a sequence of scalars it uses the AdvanceValue function specialized for the scalar value type of that TVector. For example in the common case of a float vector this enables GetVectorValue to handle any mixture of float, int and string representation within the TParameterList. \param iter \param value a vector extracted from a parameter list \return true if extraction successful */ template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline bool GetVectorValue(TVector::const_iterator& iter, salt::TVector<DATATYPE,ELEMENTS,TYPE>& value) const { typedef salt::TVector<DATATYPE,ELEMENTS,TYPE> Vector; // try to cast to Vector from a single value if (GetValueInternal<Vector,Vector>(iter,value)) { return true; } // a direct cast faild. try to construct a vector from // three consecutive values TVector::const_iterator test = iter; Vector vec; int i=0; while ( (i<ELEMENTS) && (test != mList.end()) ) { if (! AdvanceValue(test,vec[i])) { break; } ++i; // iterator test is incremented within the // call to GetValue() } if (i != ELEMENTS) { // there were not enough components to build // the vector return false; } value = vec; iter = test; return true; } /** This is a specialized GetValue helper to read a scalar value from a TParameterList. It tries to generate the value from a string representation */ template<typename TYPE> f_inline bool ConvertStringValue(TVector::const_iterator& iter, TYPE& value) const { const boost::any& param = (*iter); try { std::string str; if (param.type() == typeid(std::string)) { str = boost::any_cast<std::string>(param); } else if (param.type() == typeid(char*)) { str = boost::any_cast<char*>(param); } else { return false; } value = static_cast<TYPE>(atof(str.c_str())); ++iter; } catch(const std::bad_cast&) { return false; } return true; } /** helper that tries to any_cast the TFrom value at iter to a TTo Value, on success it returns true and advances the iterator */ template<typename TFrom, typename TTo> f_inline bool GetValueInternal(TVector::const_iterator& iter, TTo& value) const { const boost::any& param = (*iter); if (param.type() != typeid(TFrom)) { return false; } try { value = static_cast<TTo>(boost::any_cast<TFrom>(*iter)); ++iter; return true; } catch(const std::bad_cast&) { return false; } } }; } #endif // ZEITGEIST_PARAMETERLIST_H --- NEW FILE: corecontext.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: corecontext.cpp,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "corecontext.h" #include <salt/path.h> #include "leaf.h" #include "node.h" #include "core.h" #include <iostream> using namespace boost; using namespace salt; using namespace std; using namespace zeitgeist; CoreContext::CoreContext(const boost::shared_ptr<Core> &core, const boost::shared_ptr<Leaf> &root) : mCore(core), mObject(root) { } CoreContext::~CoreContext() { //cout << "~CoreContext()" << endl; } boost::shared_ptr<Leaf> CoreContext::New(const std::string& className, const std::string& pathStr) { // first, we try to create the class with the core shared_ptr<Object> instance = mCore->New(className); if (instance.get()) { // now, we check the type by dynamic casting to leaf shared_ptr<Leaf> leaf = shared_static_cast<Leaf>(instance); if (leaf.get() != NULL) { // we have created the instance, now we install it at the location // stored in pathName if (Install(leaf, pathStr) == true) { mObject = leaf; return leaf; } } } // return default constructed 'NULL' object return shared_ptr<Leaf>(); } bool CoreContext::Delete (const std::string &name) { shared_ptr<Leaf> leaf = Get(name); if (leaf.get()) { leaf->Unlink(); return true; } return false; } boost::shared_ptr<Leaf> CoreContext::Select(const std::string &pathStr) { shared_ptr<Leaf> leaf = Get(pathStr); if (leaf.get()) { mObject = leaf; } return leaf; } bool CoreContext::Install(const boost::shared_ptr<Leaf> &leaf, const std::string &pathStr, bool isNamed) { //cout << "CoreContext(" << (void*) this << ") Install '" << pathStr << "'" << endl; Path path(pathStr); if(! isNamed) { // we need at least one token to 'name' the leaf class if (path.IsEmpty()) { return false; } leaf->SetName(path.Back()); path.PopBack(); // now, we have named the leaf object, so we can install it } shared_ptr<Leaf> current; // check if we have a relative or absolute path if (path.IsAbsolute()) { current = mCore->GetRoot(); } else { current = mObject; } if (! current.get()) { return false; } while (! path.IsEmpty()) { current = mCore->GetChild(current, path.Front()); if (! current.get()) { return false; } path.PopFront(); } return current->AddChildReference(leaf); } boost::shared_ptr<Leaf> CoreContext::Get(const std::string& pathStr) { return mCore->Get(pathStr, mObject); } bool CoreContext::Test(const std::string& pathStr) { return mCore->Test(pathStr, mObject); } void CoreContext::ListObjects() const { Leaf::TLeafList::iterator i; for (i = mObject->begin(); i != mObject->end(); ++i) { cout << (*i)->GetName(); if (!(*i)->IsLeaf()) { cout << "/"; } cout << endl; } } void CoreContext::Push() { if (mObject.get() != NULL) mObjectStack.push_front(mObject); } void CoreContext::Pop() { if (!mObjectStack.empty()) { mObject = mObjectStack.front(); mObjectStack.pop_front(); } } void CoreContext::Dir() const { for ( TObjectStack::const_iterator i = mObjectStack.begin(); i != mObjectStack.end(); ++i ) { cout << (*i)->GetName(); if (!(*i)->IsLeaf()) { cout << "/"; } cout << endl; } } --- NEW FILE: class.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: class.h,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Class HISTORY: 04.06.2002 MK - initial version */ #ifndef ZEITGEIST_CLASS_H #define ZEITGEIST_CLASS_H #include <zeitgeist/scriptserver/gcvalue.h> #ifdef HAVE_CONFIG_H #include <config.h> #endif #ifdef HAVE_HASH_MAP #include <hash_map> #else #include <map> #endif #include <string> #include <vector> #include <list> #include <salt/defines.h> #include <salt/sharedlibrary.h> #include "leaf.h" #include "parameterlist.h" namespace zeitgeist { #define CLASS(className) Class_##className #define DECLARE_CLASS(className)\ class CLASS(className) : public zeitgeist::Class\ {\ public:\ CLASS(className)() : zeitgeist::Class(#className) { DefineClass(); }\ zeitgeist::Object* CreateInstance() const\ {\ zeitgeist::Object *instance = new className();\ return instance;\ }\ private:\ void DefineClass();\ }; #define DECLARE_ABSTRACTCLASS(className)\ class CLASS(className) : public zeitgeist::Class\ {\ public:\ CLASS(className)() : zeitgeist::Class(#className) { DefineClass(); }\ private:\ void DefineClass();\ }; // note the 'unused' attribute suppresses compiler warnings if the // 'in' parameter is not accessed in the function implementation #define FUNCTION(className,functionName)\ static zeitgeist::GCValue functionName(className *obj, \ __attribute__((unused)) const zeitgeist::ParameterList &in) #define DEFINE_FUNCTION(functionName)\ mFunctions[#functionName] = (TCmdProc) &functionName; #define DEFINE_BASECLASS(baseClass)\ mBaseClasses.push_back(#baseClass); // // Export stuff // #define ZEITGEIST_EXPORT_BEGIN()\ using namespace boost;\ using namespace salt;\ using namespace zeitgeist;\ extern "C"{\ SHARED_LIB_EXPORT void Zeitgeist_RegisterBundle(std::list <shared_ptr<Class> > &classes){ #define ZEITGEIST_EXPORT_EX(className, path)\ classes.push_back(shared_ptr<Class>(new CLASS(className))); #define ZEITGEIST_EXPORT(className) ZEITGEIST_EXPORT_EX(className, "") #define ZEITGEIST_EXPORT_END()\ }} // forward declarations class Core; /** This class is quite essential for the Zeitgeist Core. Every class * which wants to be managed by Zeitgeist will have to derive a class * object from this class and override the factory method. Only * decendants from Object are able to use Class properly and the * factory method returns a Object pointer. * * A Class object is characterized by several parameters: * * - the name of the class * - the version of the class * * A version is stored as an unsigned 32-bit integer, with each byte * representing a version number. So ABCD would be A.B.C.D. That way a * simple integer comparison can be used for newer version queries. * * Class objects also are the key to providing Zeitgeist with a plugin * interface. The Core is responsible for managing all Class objects it * knows. It is possible to export Class objects from a shared library * through a unified interface, therefore enabling Class objects to be * added at runtime to the Core. */ class Class : public Leaf { // friends friend class Object; friend class Core; // // types // public: /** defines a signature for a function used as the c++ implementation of a member function exported to a script language. It receives a pointer to an instance of the class from which it is a member function along with a list of paramters. */ typedef GCValue (*TCmdProc)(Object* , const zeitgeist::ParameterList &in); typedef std::list<std::string> TStringList; private: /** defines a list of pointers to object instances */ typedef std::list< boost::weak_ptr<Object> > TObjectList; /** defines a mapping from member names to command procedures */ #ifdef HAVE_HASH_MAP typedef std::hash_map<std::string, TCmdProc> TCommandMap; #else typedef std::map<std::string, TCmdProc> TCommandMap; #endif // // functions // public: /** constructs a class object for the class 'name' */ Class(const std::string &name); virtual ~Class(); /** creates a new instance of the represented class */ boost::shared_ptr<Object> Create(); /** returns a pointer to the core this class is attached to */ boost::shared_ptr<Core> GetCore() const; /** sets the bundle, this class was loaded from */ void SetBundle(const boost::shared_ptr<salt::SharedLibrary> &bundle); /** the command procedure for a function */ TCmdProc GetCmdProc(const std::string &functionName) const; /** returns a list of base class names */ const TStringList& GetBaseClasses() const; /** returns true iff the class supports a given 'interface', * i.e. the base class hierarchy contains the class 'name' */ bool SupportsClass(const std::string &name) const; /** returns true iff the class supports a given command, i.e. to * this class or to one of its base classes the given command * procedure is registered */ bool SupportsCommand(const std::string &name) const; protected: /** adds an instance to the local list of instances */ void AttachInstance(const boost::weak_ptr<Object> &instance); /** removes an instance from the local list of instances */ void DetachInstance(const boost::weak_ptr<Object> &instance); private: Class(const Class &obj); Class& operator=(const Class &obj); /** pure virtual function which creates instances */ virtual Object* CreateInstance() const; /** pure virtual function which initializes the script callbacks and links to parent classes */ virtual void DefineClass() = 0; /** set the core, which this class belongs to */ void AttachTo(const boost::weak_ptr<Core>& core); // // members // protected: TCommandMap mFunctions; TStringList mBaseClasses; private: boost::weak_ptr<Core> mCore; /** a shared pointer to the bundle, this class object came * from. So, if all references to the class object are * deleted, the shared library will be freed. */ boost::shared_ptr<salt::SharedLibrary> mBundle; /** a list of instances, which were created by this class object */ TObjectList mInstances; }; /** this is the class object beloging to the class 'zeitgeist::Class'. */ class CLASS(Class) : public Class { public: CLASS(Class)() : Class("ClassClass") { DefineClass(); } private: void DefineClass(); }; /** declare the clss object for leaf. Put here to avoid a circular dependency between class inheriting from leaf and leaf needing class to inherit its corresponding class object */ DECLARE_CLASS(Leaf); } // namespace zeitgeist #endif //ZEITGEIST_CLASS_H --- NEW FILE: zeitgeist.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: zeitgeist.cpp,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "zeitgeist.h" #include <iostream> #include <sstream> using namespace std; using namespace zeitgeist; Zeitgeist::Zeitgeist(string dotName) { ConstructCore(); RunInitScript(dotName); } Zeitgeist::Zeitgeist(string dotName, string relPathPrefix) { ConstructCore(); if (mCore->GetScriptServer() == 0) { return; } mCore->GetScriptServer()->SetInitRelPathPrefix(relPathPrefix); RunInitScript(dotName); } Zeitgeist::~Zeitgeist() { // this Zeitgeist object owns the only shared_ptr to the // core. Class objects only own weak_ptrs to the core. Destructing // the core implicitly after this destructor finishes, invalidates // our shared_ptr prior to the call to Core::~Core() and all // instances are left without a valid core reference on shutdown // (calls to OnUnlink). Therefore we destruct the core and the hierarchy explicitly // with the mCore reference intact. mCore->Desctruct(); } void Zeitgeist::ConstructCore() { mCore = boost::shared_ptr<Core>(new Core()); mCore->Construct(mCore); } void Zeitgeist::RunInitScript(string dotName) { if (mCore->GetScriptServer() == 0) { return; } // setup the dot directory in the script server mCore->GetScriptServer()->SetDotName(dotName); // run the zeitgeist init script mCore->GetScriptServer()->RunInitScript ( "zeitgeist.rb", "lib/zeitgeist", ScriptServer::IS_COMMON ); } boost::shared_ptr<CoreContext> Zeitgeist::CreateContext() { return mCore->CreateContext(); } boost::shared_ptr<Core>& Zeitgeist::GetCore() { return mCore; } --- NEW FILE: corecontext.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: corecontext.h,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. CoreContext HISTORY: 05.07.2002 MK - initial version */ #ifndef ZEITGEIST_CORECONTEXT_H #define ZEITGEIST_CORECONTEXT_H #include <string> #include <list> #include <boost/weak_ptr.hpp> #include <boost/shared_ptr.hpp> namespace zeitgeist { class Core; class Leaf; /** This class is responsible for representing a browsing context * within the object hierarchy. It is usually created by the Core * object. * * Why was the browsing context separated from the Core? * * Well, the usage scenario of the framework envisions multiple clients * browsing the same object hierarchy. Therefore it was necessary to * place the current browsing context into a distinct object. */ class CoreContext { // // types // private: typedef std::list< boost::shared_ptr<Leaf> > TObjectStack; // // functions // public: /** constructs a core context * \param 'core' is the core this context belongs to * \param 'root' is the root of the core */ CoreContext(const boost::shared_ptr<Core> &core, const boost::shared_ptr<Leaf> &root); virtual ~CoreContext(); /** constructs a new class of type 'className' below the node * described by 'pathStr'. The function assumes that only * compatible classes are created this way. Compatible means * 'starting at Leaf' in the hierarchy. It returns a reference to * the constructed object. */ boost::shared_ptr<Leaf> New(const std::string& className, const std::string& pathStr); bool Delete(const std::string& name); /** selects the currenlty active object to be the one described the by path expression pathStr. It returns a reference to the selected object*/ boost::shared_ptr<Leaf> Select(const std::string& pathStr); /** inserts the object 'leaf' below the object described by the path expression 'pathStr' into the hierarchy and returns true on success */ bool Install(const boost::shared_ptr<Leaf>& leaf, const std::string& pathStr, bool isNamed = false); /** returns a reference to the object described by the path expression pathStr */ boost::shared_ptr<Leaf> Get(const std::string& pathStr); /** returns true if the object referenced by the path expression pathStr exists */ bool Test(const std::string& pathStr); /** returns the currently selected object */ boost::shared_ptr<Leaf> GetObject() const { return mObject; } /** returns the core this context belongs to */ boost::shared_ptr<Core> GetCore() const { return mCore; } /** prints the children of the currently selected object to stdout */ void ListObjects() const; /** pushs the current active object on the object stack */ void Push(); /** makes the top of the object stack the current object, no change if stack is empty */ void Pop(); /** prints the objects on the stack to stdout */ void Dir() const; private: CoreContext(const CoreContext& obj); CoreContext& operator=(const CoreContext& obj); // // members // private: /** pointer to the core object this context belongs to */ boost::shared_ptr<Core> mCore; /** the current active object */ boost::shared_ptr<Leaf> mObject; /** the current working path */ std::string mPath; /** the object stack */ TObjectStack mObjectStack; }; } // namespace zeitgeist #endif //ZEITGEIST_CORECONTEXT_H --- NEW FILE: class.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: class.cpp,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "class.h" #include "leaf.h" #include "core.h" #include <iostream> using namespace boost; using namespace std; using namespace zeitgeist; Class::Class(const std::string &name) : Leaf(name) { } Class::~Class() { if (mInstances.size() > 0) { cout << "(Class) Leaked " << mInstances.size() << " instances..." << endl; for ( TObjectList::iterator i = mInstances.begin(); i != mInstances.end(); ++i ) { if (shared_ptr<Object> j = i->lock()) { cout << " " << j.get() << endl; } else { cout << " " << "(expired)" << endl; } } } } boost::shared_ptr<Object> Class::Create() { shared_ptr<Object> obj(CreateInstance()); if (obj.get()) { if (obj->Construct(obj, shared_static_cast<Class> (make_shared(GetSelf()))) == true) { // successfully constructed AttachInstance(obj); } else { obj.reset(); } } return obj; } boost::shared_ptr<Core> Class::GetCore() const { if (mCore.expired()) { std::cerr << "(Class) ERROR: failed to get zeitgeist Core for class '" << GetName() << "'" << std::endl; } return make_shared(mCore); } void Class::AttachInstance(const boost::weak_ptr<Object> &instance) { mInstances.push_back(instance); } void Class::DetachInstance(const boost::weak_ptr<Object> &instance) { // mInstances.remove() doesn't work in this case because // operator== is not implemented for weak_ptr TObjectList::iterator first = mInstances.begin(); TObjectList::iterator last = mInstances.end(); while (first != last) { TObjectList::iterator next = first; ++next; boost::shared_ptr<Object> i = first->lock(); boost::shared_ptr<Object> j = instance.lock(); if (i.get() == j.get()) { mInstances.erase(first); } first = next; } } Object* Class::CreateInstance() const { return NULL; } void Class::AttachTo(const boost::weak_ptr<Core>& core) { mCore = core; } void Class::SetBundle(const boost::shared_ptr<salt::SharedLibrary> &bundle) { mBundle = bundle; } Class::TCmdProc Class::GetCmdProc(const std::string &functionName) const { TCommandMap::const_iterator cmd = mFunctions.find(functionName); if (cmd != mFunctions.end()) { return (*cmd).second; } // ok, we don't have the requested function, so we'll try the base // class objects shared_ptr<Leaf> classDir = GetCore()->Get("/classes"); for ( TStringList::const_iterator baseClass = mBaseClasses.begin(); baseClass != mBaseClasses.end(); ++baseClass ) { // this should get the base class object (it has to live on // the same level of the hierarchy as this class object) shared_ptr<Class> theClass = shared_static_cast<Class> (GetCore()->Get(*baseClass, classDir)); if (theClass) { // now, we ask the class object, if it knows the command // in question TCmdProc theCmd = theClass->GetCmdProc(functionName); //printf("theCmd: %s - %d\n", functionName.c_str(), theCmd); if (theCmd != NULL) { // here we have found the command and return it return theCmd; } } } return NULL; } const Class::TStringList& Class::GetBaseClasses() const { return mBaseClasses; } bool Class::SupportsCommand(const std::string & name) const { return (GetCmdProc(name) != 0); } bool Class::SupportsClass(const std::string &name) const { if (GetName().compare(name) == 0) { return true; } // check base-classes shared_ptr<Leaf> classDir = GetCore()->Get("/classes"); for ( TStringList::const_iterator i = mBaseClasses.begin(); i != mBaseClasses.end(); ++i ) { shared_ptr<Class> theClass = shared_static_cast<Class> (GetCore()->Get(*i, classDir)); if (theClass) { if (theClass->SupportsClass(name)) { return true; } } else { cout << "(Class) WARNING: Illegal BaseClass '" << (*i) << "' in Class '" << GetName() << "'" << endl; } } return false; } --- NEW FILE: object_c.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2004 RoboCup Soccer Server 3D Maintenance Group $Id: object_c.cpp,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "object_c.h" using namespace zeitgeist; void CLASS(Object)::DefineClass() { } --- NEW FILE: Makefile.am --- if DEBUG pkglib_LTLIBRARIES = libzeitgeist_debug.la libzeitgeist_debug_la_SOURCES = $(sources) libzeitgeist_debug_la_CXXFLAGS = -O -g -W -Wall libzeitgeist_debug_la_LIBADD = @RUBY_LDFLAGS@ @RUBY_LDADD@ libzeitgeist_debug_la_LDFLAGS = -version-info @zeitgeist_version_info@ else pkglib_LTLIBRARIES = libzeitgeist.la libzeitgeist_la_SOURCES = $(sources) libzeitgeist_la_CXXFLAGS = -O2 libzeitgeist_la_LIBADD = @RUBY_LDFLAGS@ @RUBY_LDADD@ libzeitgeist_la_LDFLAGS = -version-info @zeitgeist_version_info@ endif bin_SCRIPTS = zeitgeist-config AM_CPPFLAGS = -I${top_srcdir}/lib @RUBY_CPPFLAGS@ ## define include directory local to the pkgincludedir libpkgincludedir = $(includedir)/@PACKAGE@/zeitgeist ## architecture independent data (scripts) to be installed and distributed dist_pkgdata_DATA = zeitgeist.rb sources = \ class.cpp \ class_c.cpp \ core.cpp \ corecontext.cpp \ leaf.cpp \ leaf_c.cpp \ parameterlist.cpp \ node.cpp \ node_c.cpp \ object.cpp \ object_c.cpp \ zeitgeist.cpp \ fileserver/fileserver.cpp \ fileserver/fileserver_c.cpp \ fileserver/filesystem_c.cpp \ logserver/logserver.cpp \ logserver/logserver_c.cpp \ logserver/logserverstreambuf.cpp \ randomserver/randomserver.cpp \ randomserver/randomserver_c.cpp \ scriptserver/gcvalue.cpp \ scriptserver/rubywrapper.cpp \ scriptserver/scriptserver.cpp \ scriptserver/scriptserver_c.cpp #telnetserver/telnetdaemon.cpp \ #telnetserver/telnetserver.cpp \ #telnetserver/telnetserver_c.cpp \ #telnetserver/telnetsession.cpp nobase_libpkginclude_HEADERS = \ class.h \ core.h \ corecontext.h \ leaf.h \ parameterlist.h \ node.h \ object.h \ object_c.h \ zeitgeist.h \ fileserver/fileserver.h \ fileserver/filesystem.h \ logserver/logserver.h \ logserver/logserverstreambuf.h \ randomserver/randomserver.h \ scriptserver/gcvalue.h \ scriptserver/scriptserver.h \ scriptserver/rubywrapper.h #telnetserver/telnetdaemon.h \ #telnetserver/telnetserver.h \ #telnetserver/telnetsession.h --- NEW FILE: leaf.cpp --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: leaf.cpp,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "class.h" #include "node.h" #include <iostream> using namespace boost; using namespace std; using namespace zeitgeist; Leaf::Leaf(const std::string &name) : mName(name), mCachedFullPath(NULL) { } Leaf::~Leaf() { } boost::weak_ptr<Node>& Leaf::GetParent() { return mParent; } const boost::weak_ptr<Node>& Leaf::GetParent() const { return mParent; } boost::shared_ptr<Leaf> Leaf::GetChild(const std::string &name, bool /*recursive*/) { if (name.compare("..") == 0) { return make_shared(GetParent()); } if (name.compare(".") == 0) { return shared_static_cast<Leaf>(make_shared(GetSelf())); } return boost::shared_ptr<Leaf>(); } boost::shared_ptr<Leaf> Leaf::GetChildOfClass(const std::string &/*name*/, bool /*recursive*/) { return boost::shared_ptr<Leaf>(); } boost::shared_ptr<Leaf> Leaf::GetChildSupportingClass(const std::string &/*name*/, bool /*recursive*/) { return boost::shared_ptr<Leaf>(); } void Leaf::GetChildren(const std::string &name, TLeafList &baseList, bool /*recursive*/) { if (name.compare("..") == 0) { baseList.push_back(make_shared(GetParent())); } if (name.compare(".") == 0) { baseList.push_back(shared_static_cast<Leaf>(make_shared(GetSelf()))); } } void Leaf::GetChildrenOfClass(const std::string &/*name*/, TLeafList &/*baseList*/, bool /*recursive*/) { } void Leaf::GetChildrenSupportingClass(const std::string &/*name*/, TLeafList &/*baseList*/, bool /*recursive*/) { } boost::weak_ptr<Node> Leaf::GetParentSupportingClass(const std::string &name) const { shared_ptr<Node> node = shared_static_cast<Node>(make_shared(GetParent())); while ( (node.get() != 0) && (node->GetClass()) && (! node->GetClass()->SupportsClass(name)) ) { node = make_shared(node->GetParent()); } return weak_ptr<Node>(node); } bool Leaf::IsLeaf() const { return true; } void Leaf::RemoveChildReference(const boost::shared_ptr<Leaf> &/*base*/) { } bool Leaf::AddChildReference(const boost::shared_ptr<Leaf> &/*base*/) { return false; } void Leaf::Unlink() { // here we lose our reference to the parent SetParent(boost::shared_ptr<Node>()); } void Leaf::UnlinkChildren() { } void Leaf::Dump() const { Object::Dump(); cout << "Leaf: '" << GetName() << "'" << endl; } const std::string& Leaf::GetFullPath() const { //printf("this:getfullpath %x - %s - %x %x\n", this, GetName().c_str(), GetParent(), mCachedFullPath); if (mCachedFullPath == NULL) { std::string parentPath; if (shared_ptr<Leaf> p = GetParent().lock()) { if (p) { shared_ptr<Leaf> blah = make_shared(GetParent()); parentPath = blah->GetFullPath(); } } // no cached data available if (IsLeaf()) mCachedFullPath = new std::string(parentPath + mName); else mCachedFullPath = new std::string(parentPath + mName + "/"); } return *mCachedFullPath; } void Leaf::ClearCachedData() const { delete mCachedFullPath; mCachedFullPath = NULL; } Leaf::TLeafList gFakeChildren; Leaf::TLeafList::iterator Leaf::begin() { return gFakeChildren.begin(); } Leaf::TLeafList::const_iterator Leaf::begin() const { return gFakeChildren.begin(); } Leaf::TLeafList::iterator Leaf::end() { return gFakeChildren.end(); } Leaf::TLeafList::const_iterator Leaf::end() const { return gFakeChildren.end(); } void Leaf::SetParent(const boost::shared_ptr<Node> &newParent) { shared_ptr<Node> oldParent = make_shared(GetParent()); if (oldParent.get() != 0) { // we have a parent, so update our state shared_ptr<Leaf> self = shared_static_cast<Leaf>(make_shared(GetSelf())); // here reference count should be > 1 (at least one in the // parent, and one in this routine) assert(self.use_count() > 1); if (newParent.get() == 0) { // time to clean up OnUnlink(); ClearCachedData(); oldParent->RemoveChildReference(self); } // we remove ourself from the old parent's list of children oldParent->RemoveChildReference(self); // we add ourself to the new parent's list of children if (newParent.get() != 0) { newParent->AddChildReference(self); } } mParent = newParent; if (! mParent.expired()) { // we have been linked, so now we can do something :) OnLink(); } } void Leaf::OnLink() { } void Leaf::OnUnlink() { } --- NEW FILE: object.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: object.h,v 1.1 2005/12/05 20:59:18 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Object HISTORY: 31.08.2002 MK - initial version */ #ifndef ZEITGEIST_OBJECT_H #define ZEITGEIST_OBJECT_H #include <boost/weak_ptr.hpp> #include <boost/shared_ptr.hpp> #include "core.h" #include "parameterlist.h" namespace zeitgeist { class Class; class LogServer; class ScriptServer; /** Object is the base class of all objects in the Zeitgeist * framework. An object is characterized by a single thing, the class * which created it. The core it belongs to can be reached via the * class object. Every object holds a shared_ptr to the class object, * which created it. */ class Object { // // functions // public: /** constructs an object */ Object(); virtual ~Object(); /** sets up the internal state of the object, used by Class::Create(). * \param self is a pointer to the instance of the object, i.e. a smart this pointer * \param creator is a pointer to the class object that created this object */ bool Construct(const boost::shared_ptr<Object>& self, const boost::shared_ptr<Class>& creator); // class object /** returns the corresponding class object */ boost::shared_ptr<Class> GetClass() const; /** returns a pointer to the object */ boost::weak_ptr<Object>& GetSelf(); /** returns a constant pointer to the object */ const boost::weak_ptr<Object>& GetSelf() const; /** return a pointer to the core, this object belongs to */ boost::shared_ptr<Core> GetCore() const; /** helper function to get a reference to the FileServer */ const boost::shared_ptr<FileServer>& GetFile() const; /** helper function to get a reference to the LogServer */ ... [truncated message content] |
From: Markus R. <rol...@us...> - 2005-12-05 20:56:08
|
Update of /cvsroot/simspark/simspark/spark/salt In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9485 Added Files: Makefile.am bounds.cpp bounds.h defines.h fileclasses.cpp fileclasses.h frustum.cpp frustum.h gmath.h matrix.cpp matrix.h path.cpp path.h plane.cpp plane.h random.h rect.h salt.h sharedlibrary.cpp sharedlibrary.h tvector.h vector.h Log Message: --- NEW FILE: path.cpp --- /* -*- mode: c++ -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: path.cpp,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "path.h" #include <boost/tokenizer.hpp> using namespace std; using namespace salt; Path::Path(const std::string &path) { Set(path); } void Path::Set(const std::string &path) { if (path[0] == '/' || path[0] == '\\') { mIsAbsolute = true; } else { mIsAbsolute = false; } Tokenize(path); } std::string Path::GetCleanPath(const std::string &sep) const { string path; if (mIsAbsolute) { path += sep; } unsigned int count = 0; for (TStringList::const_iterator i = mPathComponents.begin(); i != mPathComponents.end(); ++i) { path += (*i); ++count; if ( count != mPathComponents.size() ) { path += sep; } } return path; } bool Path::IsAbsolute() const { return mIsAbsolute; } bool Path::IsEmpty() const { return mPathComponents.empty(); } const std::string& Path::Front() const { return mPathComponents.front(); } void Path::PopFront() { mIsAbsolute = false; mPathComponents.pop_front(); } const std::string& Path::Back() const { return mPathComponents.back(); } void Path::PopBack() { mPathComponents.pop_back(); } void Path::Tokenize(const std::string &path) { typedef boost::tokenizer<boost::char_separator<char> > TTokenizer; boost::char_separator<char> sep("/\\"); TTokenizer tokens(path, sep); for (TTokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i) { mPathComponents.push_back(*i); } } --- NEW FILE: fileclasses.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: fileclasses.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* this file defines two interfaces- RFile and WFile, that are used to * implement classes providing unified file semantics employing * different means. Two classes implementing these interfaces are * included: Memfile and StdFile. * Derived file classes providing access to .zip, .rar and other * archives have been implemented as plugins to the fileserver of the * zeitgeist library. */ #ifndef SALT_FILECLASSES_H #define SALT_FILECLASSES_H // #ifdef HAVE_CONFIG_H // #include <config.h> // #endif #include <cstdio> #include <cstdlib> namespace salt { /** RFile defines an interface and some basic support functions for * classes providing read only file services */ class RFile { public: virtual ~RFile() {}; // a bunch of pure virtual functions which a file must implement /** opens the file fn in the specified mode. The implementation of * the namespace and mode semantics ist up to derived classes */ virtual bool Open(const char*fn=NULL, char*mode="rb") = 0; /** closes a previously opened file */ virtual void Close() = 0; /** releases any occupied ressources used by the file. The * semantic is up to the derived classes */ virtual void Destroy() = 0; /** returns a non zero value if the file pointer is at the end of * the file */ virtual int Eof() = 0; /** returns the current file pointer position */ virtual long Tell() = 0; /** copies the current file pointer position to pos and returns * true on success */ virtual int GetPos(long *pos) = 0; /** sets the file pointer for the file. The new position, measured * in bytes, is obtained by adding offset bytes to the position * specified by origin. If origin is set to SEEK_SET, SEEK_CUR, or * SEEK_END, the offset is relative to the start of the file, the * current position indicator, or end-of-file, respectively. */ virtual int Seek(long offset, int origin) = 0; /** sets the file pointer to the beginning of the file */ virtual void Rewind() = 0; /** return the size of the file */ virtual long Size() = 0; /** reads in at most one less than n characters from the file and * stores them into buffer. A '\0' is stored after the last character in * the buffer. */ virtual char* Gets(char*buffer,int n) = 0; /** reads the next character from the file returns it as an int r * EOF on end of file or error. */ virtual int Getc() = 0; /** returns a handle identifying the file. The semantics of this * handle depends on the subclass, implementing this method */ virtual void* GetHandle() = 0; /** reads reads count elements of data, each size bytes long, * storing them in the specified buffer */ virtual size_t Read(void *buffer,size_t size,size_t count) = 0; /** reads count bytes of data, storing them in the specified buffer */ virtual size_t Read(void *buffer,size_t bytes) = 0; /** reads a 2 byte int from the file in Intel ordering */ int Igetw() { int b1, b2; if ((b1 = Getc()) != EOF) if ((b2 = Getc()) != EOF) return ((b2 << 8) | b1); return EOF; } /** reads a 4 byte int from the file in Intel ordering */ long Igetl() { int b1, b2, b3, b4; if ((b1 = Getc()) != EOF) if ((b2 = Getc()) != EOF) if ((b3 = Getc()) != EOF) if ((b4 = Getc()) != EOF) return (((long)b4<<24) | ((long)b3<<16) | ((long)b2<<8) | (long)b1); return EOF; } /** reads a 2 byte int from the file in Motorola ordering */ int Mgetw() { int b1, b2; if ((b1 = Getc()) != EOF) if ((b2 = Getc()) != EOF) return ((b1 << 8) | b2); return EOF; } /** reads a 4 byte int from the file in Motorola ordering */ long Mgetl() { int b1, b2, b3, b4; if ((b1 = Getc()) != EOF) if ((b2 = Getc()) != EOF) if ((b3 = Getc()) != EOF) if ((b4 = Getc()) != EOF) return (((long)b1<<24) | ((long)b2<<16) | ((long)b3<<8) | (long)b4); return EOF; } }; /** Memfile implements the RFile interface using an inmemory * buffer. On open() a file is completely read into the buffer and * from there on served from memory. */ class MemFile : public RFile { public: MemFile(const char*fn=NULL, char*mode="rb"); MemFile(FILE*f); MemFile(RFile *f); ~MemFile(); bool Open(const char*fn=NULL, char*mode="rb"); bool Open(void*buffer, long s); void Close(); void Destroy(); int Eof(); long Tell(); int GetPos(long *pos); int Seek(long offset, int origin); void Rewind(); long Size(); char* Gets(char*buffer,int n); int Getc(); void* GetHandle() { return mHandle; } size_t Read(void *buffer,size_t size,size_t count); size_t Read(void *buffer,size_t count) { return Read(buffer, 1,count); } private: /** the file handle */ void* mHandle; /** a pointer to the buffer holding the file */ unsigned char* mCharHandle; /** the size of the file in bytes */ long mSize; /** the current file pointer position */ long mPosition; }; /** WFile extends the RFile interface with methods for writing to a * file and related support funtions */ class WFile : public RFile { public: virtual ~WFile() {}; /** writes a string without the trailing '\0' */ virtual int Puts(const char*s) = 0; /** writes a single character */ virtual int Putc(int c) = 0; /** writes a 2 byte int in Intel ordering */ int Iputw(int w) { int b1, b2; b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if (Putc(b2)==b2) if (Putc(b1)==b1) return w; return EOF; } /** writes count elements of data from buffer, each size bytes long */ virtual size_t Write(void *buffer,size_t size,size_t count) = 0; /** writes count bytes of data from buffer */ virtual size_t Write(void *buffer,size_t count) = 0; /** writes a 4 byte int in Intel ordering */ long Iputl(long l) { int b1, b2, b3, b4; b1 = (int)((l & 0xFF000000L) >> 24); b2 = (int)((l & 0x00FF0000L) >> 16); b3 = (int)((l & 0x0000FF00L) >> 8); b4 = (int)l & 0x00FF; if (Putc(b4)==b4) if (Putc(b3)==b3) if (Putc(b2)==b2) if (Putc(b1)==b1) return l; return EOF; } /** writes a 2 byte int in Motorola ordering */ int Mputw(int w) { int b1, b2; b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if (Putc(b1)==b1) if (Putc(b2)==b2) return w; return EOF; } /** writes a 4 byte in in Motorola ordering */ long Mputl(long l) { int b1, b2, b3, b4; b1 = (int)((l & 0xFF000000L) >> 24); b2 = (int)((l & 0x00FF0000L) >> 16); b3 = (int)((l & 0x0000FF00L) >> 8); b4 = (int)l & 0x00FF; if (Putc(b1)==b1) if (Putc(b2)==b2) if (Putc(b3)==b3) if (Putc(b4)==b4) return l; return EOF; } }; /** StdFile implements the WFile interface using the standard file system */ class StdFile : public WFile { public: StdFile(FILE*f); StdFile(const char*fn=NULL, char*mode="rb"); virtual ~StdFile(); bool Open(const char*fn=NULL, char*mode="rb"); void Close(); void Destroy(); int Eof(); long Tell(); int GetPos(long *pos); int Seek(long offset, int origin); void Rewind(); long Size(); char* Gets(char*buffer,int n); int Getc(); int Puts(const char*s); int Putc(int c); size_t Read(void *buffer,size_t size,size_t count); size_t Read(void *buffer,size_t count) { return Read(buffer,1,count); } size_t Write(void *buffer,size_t size,size_t count); size_t Write(void *buffer,size_t count) { return Write(buffer,1,count); } void* GetHandle(); protected: /** the standard file handle */ FILE *mHandle; }; } //namespace salt #endif //FILECLASSES_H__ --- NEW FILE: matrix.cpp --- /* -*- mode: c++ -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: matrix.cpp,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "matrix.h" #include <cstdio> using namespace salt; float Matrix::mIdentity[16]= { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; void Matrix::Dump() const { printf("%f %f %f %f\n", m[0], m[4], m[8], m[12]); printf("%f %f %f %f\n", m[1], m[5], m[9], m[13]); printf("%f %f %f %f\n", m[2], m[6], m[10], m[14]); printf("%f %f %f %f\n", m[3], m[7], m[11], m[15]); } void Matrix::LookAt(const Vector3f & inEye, const Vector3f & inDirection, const Vector3f & inUp) { Vector3f forward = inDirection.Normalized(); Vector3f up = inUp.Normalized(); Vector3f right = forward.Cross(up); right.Normalize(); up = right.Cross(forward); // Make inverse rotation matrix using right, forward, up vectors Set( right.x(), right.y(), right.z(), 0.0f, up.x(), up.y(), up.z(), 0.0f, forward.x(), forward.y(), forward.z(), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); Pos() = Rotate(-inEye); } /*! Calculate an attenuation matrix. pos = world space position of light radius = radius of light (used for distance attenuation) */ void Matrix::CalcAttenuationNoRotation(const Vector3f &pos, float radius) { Matrix tmp1, tmp2; // translate to 'light space' ... no rotation needed tmp1.Translation(-pos); // create proper scaling matrix float invrad = 0.5f / radius; tmp2.Identity(); tmp2(0,0) = invrad; tmp2(1,1) = invrad; tmp2(2,2) = invrad; Identity (); Translation (Vector3f(0.5f, 0.5f, 0.5f)); *this *= tmp2 * tmp1; } void Matrix::CalcAttenuationWithRotation(const Matrix &lightWorldMatrix, float radius) { Matrix tmp1, tmp2; // translate to 'light space' ... this time with rotation tmp1 = lightWorldMatrix; tmp1.InvertRotationMatrix(); // create proper scaling matrix float invrad = 0.5f / radius; tmp2.Identity(); tmp2(0,0) = invrad; tmp2(1,1) = invrad; tmp2(2,2) = invrad; Identity (); Translation (Vector3f(0.5f, 0.5f, 0.5f)); *this *= tmp2 * tmp1; } void Matrix::CalcInfiniteProjection(float width, float height, float fov, float zNear) { const float halfWidth = zNear * (float)tan(gDegToRad(fov*0.5f)); const float halfHeight = halfWidth * (height/width); CalcInfiniteFrustum(-halfWidth, halfWidth, -halfHeight, halfHeight, zNear); } void Matrix::CalcInfiniteFrustum(float left, float right, float bottom, float top, float zNear) { Identity(); El(0,0) = (2*zNear) / (right - left); El(0,2) = (right + left) / (right - left); El(1,1) = (2*zNear) / (top - bottom); El(1,2) = (top + bottom) / (top - bottom); // nudge infinity in just slightly for lsb slop const float nudge = 1 - 1.0 / (1<<23); El(2,2) = -1 * nudge; El(2,3) = -2*zNear * nudge; El(3,2) = -1; El(3,3) = 0; } void Matrix::CalcSpotLight(const Matrix &lightWorldTransform, float fov, float width, float height, float zNear) { Matrix scale, proj, space; Vector3f halfVector(0.5f, 0.5f, 0.5f); Identity (); Translation (halfVector); scale.Identity (); scale.Scale (halfVector); // create projection matrix proj.CalcInfiniteProjection(width, height, fov, zNear); space = lightWorldTransform; space.InvertRotationMatrix(); // so, we transform first into light space, then project, then scale and // translate (this) *this *= scale * proj * space; } bool Matrix::IsEqual(const Matrix& matrix) const { for (int i=0; i<16; ++i) if (matrix.m[i] != m[i]) return false; return true; } --- NEW FILE: rect.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: rect.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SALT_RECT_H #define SALT_RECT_H #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "defines.h" namespace salt { /** this class provides rectangle in two dimensional space */ class Rect { public: /** constucts undefined Rect for performance reasons */ f_inline Rect() { } /** copy constructs a Rect from inOther */ f_inline Rect(const Rect &inOther) : mLeft(inOther.Left()), mTop(inOther.Top()), mRight(inOther.Right()), mBottom(inOther.Bottom()) { } /** constructs a Rect from the coordinates inLeft, inTop, inRight and inBottom */ f_inline Rect(int inLeft, int inTop, int inRight, int inBottom) : mLeft(inLeft), mTop(inTop), mRight(inRight), mBottom(inBottom) { } /** sets up a Rect from the coordinates inLeft, inTop, inRight and inBottom */ f_inline void Set(int inLeft, int inTop, int inRight, int inBottom) { mLeft=inLeft; mTop=inTop; mRight=inRight; mBottom=inBottom; } // member access /** returns the left boundary of the rectangle */ f_inline int Left() const { return mLeft; } /** return the right boundary of the rectangle */ f_inline int Right() const { return mRight; } /** return the top boundary of the rectangle */ f_inline int Top() const { return mTop; } /** return the bottom boundary of the rectangle */ f_inline int Bottom() const { return mBottom; } /** calculates the width of the rectangle */ f_inline int Width() const { return mRight-mLeft; } /** calculates the height of the rectangle */ f_inline int Height() const { return mBottom-mTop; } /// Actions /** normalizes the rectangle coordinates, i.e. assures that right>left and top>bottom. */ f_inline void Normalize() { if (mRight < mLeft) gSwap(mLeft, mRight); if (mBottom < mTop) gSwap(mTop, mBottom); } /** widens the rectangle about inDelta */ f_inline void Widen(int inDelta) { mLeft-=inDelta; mTop-=inDelta; mRight+=inDelta; mBottom+=inDelta; } /** widens the rectangle horizontally about inDeltaWidth and * vertically about inDeltaHeight */ f_inline void Widen(int inDeltaWidth, int inDeltaHeight) { mRight+=inDeltaWidth; mBottom+=inDeltaHeight; } /** widens the rectangles left boundary about inDeltaleft, the right * boundary about inDeltaRigt, the top boundary about inDeltaTop * and the bottom boundary about inDeltaBottom */ f_inline void Widen(int inDeltaLeft, int inDeltaTop, int inDeltaRight, int inDeltaBottom) { mLeft-=inDeltaLeft; mTop-=inDeltaTop; mRight+=inDeltaRight; mBottom+=inDeltaBottom; } /** shrinks the rectangle about inDelta */ f_inline void Shrink(int inDelta) { mLeft+=inDelta; mTop+=inDelta; mRight-=inDelta; mBottom-=inDelta; } /** shrinks the rectangle horizontally about inDeltaWidth and * vertically about inDeltaHeight */ f_inline void Shrink(int inDeltaWidth, int inDeltaHeight) { mRight-=inDeltaWidth; mBottom-=inDeltaHeight; } /** shrinks the rectangles left boundary about inDeltaleft, the right * boundary about inDeltaRigt, the top boundary about inDeltaTop * and the bottom boundary about inDeltaBottom */ f_inline void Shrink(int inDeltaLeft, int inDeltaTop, int inDeltaRight, int inDeltaBottom) { mLeft+=inDeltaLeft; mTop+=inDeltaTop; mRight-=inDeltaRight; mBottom-=inDeltaBottom; } /** moves the rectangle horizontally inDeltaX and vertically inDeltaY */ f_inline void Offset(int inDeltaX, int inDeltaY) { mLeft+=inDeltaX; mTop+=inDeltaY; mRight+=inDeltaX; mBottom+=inDeltaY; } /** returns true if this rectangle intersects with the rectangle b */ f_inline bool Intersects(const Rect &b) const { return !(mLeft > b.mRight || mRight < b.mLeft || mTop > b.mBottom || mBottom < b.mTop); } // assignment /** sets up the rectangle from inOther */ f_inline Rect& operator=(const Rect &inOther) { mLeft=inOther.Left(); mTop=inOther.Top(); mRight=inOther.Right(); mBottom=inOther.Bottom(); return *this; } // comparison /** returns true if inRhs is equal to this rectangle */ f_inline bool operator==(const Rect &inRHS) const { return (mLeft==inRHS.Left()) && (mTop==inRHS.Top()) && (mRight==inRHS.Right()) && (mBottom==inRHS.Bottom()); } /** returns true if inRhs differs from this rectangle */ f_inline bool operator!=(const Rect &inRHS) const { return (mLeft!=inRHS.Left()) || (mTop!=inRHS.Top()) || (mRight!=inRHS.Right()) || (mBottom!=inRHS.Bottom()); } private: /** the left boundary */ int mLeft; /** the top boundary */ int mTop; /** the right boundary */ int mRight; /** the bottom boundary */ int mBottom; }; } //namespace salt #endif //SALT_RECT_H --- NEW FILE: bounds.cpp --- /* -*- mode: c++ -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2003 Koblenz University $Id: bounds.cpp,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bounds.h" #include <cstdio> using namespace salt; void AABB3::TransformBy(Matrix& matrix) { AABB3 bb; Vector3f v(minVec); Vector3f w(maxVec); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),v.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),v.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),w.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),w.y(),v.z()))); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),v.y(),w.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),v.y(),w.z()))); bb.Encapsulate(matrix.Transform(Vector3f(v.x(),w.y(),w.z()))); bb.Encapsulate(matrix.Transform(Vector3f(w.x(),w.y(),w.z()))); minVec.Set(bb.minVec); maxVec.Set(bb.maxVec); } void BoundingSphere::Encapsulate(const Vector3f &v) { // TODO : check if this is correct Vector3f diff = v - center; float dist = diff.Dot(diff); if (dist > radiusSq) { Vector3f diff2 = diff.Normalized() * radius; Vector3f delta = 0.5f * (diff - diff2); center += delta; radius += delta.Length(); radiusSq = radius*radius; } } bool BoundingSphere::Intersects(const AABB3 &b) const { float distance = 0.0f; for (int t=0; t<3; t++) { if (center[t] < b.minVec[t]) { distance += (center[t] - b.minVec[t]) * (center[t] - b.minVec[t]); if (distance>radiusSq) return false; } else if (center[t]>b.maxVec[t]) { distance+=(center[t] - b.maxVec[t]) * (center[t] - b.maxVec[t]); if (distance>radiusSq) return false; } } return true; } bool BoundingSphere::Contains(const AABB3 &b) const { float distance = 0.0f; for (int t=0; t<3; t++) { if (center[t]<b.maxVec[t]) distance+=(center[t] - b.maxVec[t]) * (center[t] - b.maxVec[t]); else if (center[t]>b.minVec[t]) distance+=(center[t] - b.minVec[t]) * (center[t] - b.minVec[t]); if (distance>radiusSq) return false; } return true; } --- NEW FILE: Makefile.am --- if DEBUG pkglib_LTLIBRARIES = libsalt_debug.la libsalt_debug_la_SOURCES = $(sources) libsalt_debug_la_CXXFLAGS = -O -g -W -Wall libsalt_debug_la_LIBADD = @SALT_LIBADD@ ${top_srcdir}/utility/libobj/liblibobject.la libsalt_debug_la_LDFLAGS = -version-info @salt_version_info@ else pkglib_LTLIBRARIES = libsalt.la libsalt_la_SOURCES = $(sources) libsalt_la_CXXFLAGS = -O2 libsalt_la_LIBADD = @SALT_LIBADD@ ${top_srcdir}/utility/libobj/liblibobject.la libsalt_la_LDFLAGS = -version-info @salt_version_info@ endif bin_SCRIPTS = salt-config ## define include directory local to the pkgincludedir libpkgincludedir = $(includedir)/@PACKAGE@/salt sources = \ bounds.cpp \ fileclasses.cpp \ frustum.cpp \ matrix.cpp \ path.cpp \ plane.cpp \ gcc/sharedlibrary.cpp libpkginclude_HEADERS = \ bounds.h \ fileclasses.h \ gmath.h \ path.h \ random.h \ salt.h \ tvector.h \ defines.h \ frustum.h \ matrix.h \ plane.h \ rect.h \ sharedlibrary.h \ vector.h --- NEW FILE: tvector.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: tvector.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. TVector is a template class for vector implementations. It abstracts away the number of elements and their type. TVector2 is a 2D version TVector3 is a 3D version HISTORY: 12.08.2002 MK - initial version */ #ifndef SALT_TVECTOR_H #define SALT_TVECTOR_H // #ifdef HAVE_CONFIG_H // #include <config.h> // #endif #include "defines.h" #include "gmath.h" #include <iostream> namespace salt { /** TVector is a template class for vector implementations. It * abstracts away the number of elements and their type. */ template <typename DATATYPE, int ELEMENTS, typename TYPE> class TVector { // // functions // public: TVector() {} // accessors /** returns a reference to a row of the vector */ f_inline DATATYPE& operator[](int row) { return El(row); } /** returns a constant reference to a row of a vector */ f_inline const DATATYPE& operator[](int row) const { return El(row); } /** returns a reference to a row of a vector */ f_inline DATATYPE& Get(int row) { return El(row); } /** returns a constant reference to a row of a vector */ f_inline const DATATYPE& Get(int row) const { return El(row); } // Direct pointer access to the data member ... use with care!!! /** copies another vector 'copy' */ f_inline const TYPE& SetData(const DATATYPE *copy); /** return a pointer to the encapsulated vector */ f_inline DATATYPE* GetData() { return mData; } // Output /** prints the contents of vector to stdout */ void Dump() const; /** fills all components of the vector with value 'fill' */ f_inline const TYPE& Fill(const DATATYPE& fill); /** sets all components of the vector to 0 */ f_inline TYPE& Zero(); // operators /** calculates this VECTOR + VECTOR */ f_inline const TYPE operator+(const TYPE &v) const; /** calculates VECTOR - VECTOR*/ f_inline const TYPE operator-(const TYPE &v) const; /** calculates VECTOR * VECTOR */ f_inline const TYPE operator*(const DATATYPE &v) const; /** calculates VECTOR / SCALAR */ f_inline const TYPE operator/(const DATATYPE &v) const; /** add another vector */ f_inline TYPE& operator+=(const TYPE &v); /** substracts another vector */ f_inline TYPE& operator-=(const TYPE &v); /** multiplies another vector */ f_inline TYPE& operator*=(const DATATYPE &v); /** divides another vector */ f_inline TYPE& operator/=(const DATATYPE &v); /** returns the negate of this vector */ f_inline TYPE operator-() const; /** returns true if this vector and v are equal */ f_inline bool operator==(const TYPE& v)const; /** returns true if this vector and v are not equal */ f_inline bool operator!=(const TYPE& v)const; /** returns the dot product from this vector and v */ f_inline DATATYPE Dot(const TYPE& v) const; /** normalizes the vector */ f_inline const TYPE& Normalize(); /** calculates the normalized vector, not modifying the vector */ f_inline TYPE Normalized() const; /** calculates the squared length of the vector */ f_inline DATATYPE SquareLength() const; /** calculates the length of the vector */ f_inline DATATYPE Length() const { return gSqrt(SquareLength()); } /** returns the index of least significant axis */ f_inline int GetLeastSignificantAxis() const; /** returns the index of the most significant axis */ f_inline int GetMostSignificantAxis() const; /** lineary interpolates between this vector and to with an delta increment */ f_inline TYPE LinearInterpolate(const TYPE& to, float delta) const; /** lineary interpolates between this vector and to with an delta * increment, returning a normalized vector */ f_inline TYPE NormalizedLinearInterpolate(const TYPE& to, float delta) const { return LinearInterpolate(to, delta).Normalize(); } protected: // Copy constructor: TVector(const TYPE &v) { for (int i=0; i<ELEMENTS; i++) mData[i] = v[i]; } // Element accessor const DATATYPE& El(int index) const { return mData[index]; } DATATYPE& El(int index) { return mData[index]; } // // members // private: DATATYPE mData[ELEMENTS]; }; template <typename DATATYPE, int ELEMENTS, typename TYPE> std::ostream& operator <<(std::ostream& ost, const TVector<DATATYPE,ELEMENTS,TYPE>& v) { if (ELEMENTS < 1) return ost; ost << v[0]; for (int i=1; i<ELEMENTS; ++i) ost << " " << v[i]; return ost; } /** TVector2 is a two dimensional version of TVector */ template <typename DATATYPE, class TYPE> class TVector2 : public TVector<DATATYPE, 2, TYPE> { public: /** constructs an undefined TVector2 */ TVector2() : TVector<DATATYPE, 2, TYPE>() {}; /** constructs a TVector2 from x and y */ TVector2(DATATYPE x, DATATYPE y) : TVector<DATATYPE, 2, TYPE>() { Set(x, y); } // Element Access operators /** returns a reference to the first component */ f_inline DATATYPE& x() { return this->El(0); } /** returns a constant reference to the first component */ f_inline const DATATYPE& x() const { return this->El(0); } /** returns a reference to the second component */ f_inline DATATYPE& y() { return this->El(1); } /** returns a constant reference to the second component */ f_inline const DATATYPE& y() const { return this->El(1); } /** sets up the vector from x and y */ f_inline const TYPE& Set(const DATATYPE& x, const DATATYPE& y) { this->El(0) = x; this->El(1) = y; return *static_cast<TYPE*>(this); } }; /** TVector3 is a two dimensional version of TVector */ template <typename DATATYPE, class TYPE> class TVector3 : public TVector<DATATYPE, 3, TYPE> { public: /** constructs an undefined TVector3 */ TVector3() : TVector<DATATYPE, 3, TYPE>() {}; /** constructs a TVector3 from x,y and z */ TVector3(const DATATYPE& x, const DATATYPE& y, const DATATYPE& z) : TVector<DATATYPE, 3, TYPE>() { Set(x, y, z); } // Element Access operators /** returns a reference to the first component */ f_inline DATATYPE& x() { return this->El(0); } /** returns a constant reference to the first component */ f_inline const DATATYPE& x() const { return this->El(0); } /** returns a reference to the second component */ f_inline DATATYPE& y() { return this->El(1); } /** returns a constant reference to the second component */ f_inline const DATATYPE& y() const { return this->El(1); } /** returns a reference to the third component */ f_inline DATATYPE& z() { return this->El(2); } /** returns a constant reference to the third component */ f_inline const DATATYPE& z() const { return this->El(2); } /** calculates the cross product, returning a new TVector3 */ const TYPE Cross(const TVector<DATATYPE, 3, TYPE>& v) const { // Create a new one TYPE r; r[0] = this->El(1) * v[2] - this->El(2) * v[1]; r[1] = this->El(2) * v[0] - this->El(0) * v[2]; r[2] = this->El(0) * v[1] - this->El(1) * v[0]; return r; } // // Set operator // /** sets up the vector from x,y and z */ const TYPE& Set(const DATATYPE& x, const DATATYPE& y, const DATATYPE& z) { this->El(0) = x; this->El(1) = y; this->El(2) = z; return *static_cast<TYPE*>(this); } /** sets up the vector from another TVector3 v */ const TYPE& Set(const TYPE& v) { this->El(0) = v.x(); this->El(1) = v.y(); this->El(2) = v.z(); return *static_cast<TYPE*>(this); } }; // Set operator for any vector. Just with a pointer template <typename DATATYPE, int ELEMENTS, typename TYPE> inline const TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::SetData(const DATATYPE *copy) { for (int i=0; i<ELEMENTS; i++) mData[i] = copy[i]; return *static_cast<TYPE*>(this); } // Output template <typename DATATYPE, int ELEMENTS, typename TYPE> inline void TVector<DATATYPE, ELEMENTS, TYPE>::Dump() const { for (int i=0; i<ELEMENTS; i++) std::cout << mData[i] << " "; std::cout << "\n"; } // fill vector with value 'fill' template <typename DATATYPE, int ELEMENTS, class TYPE> f_inline const TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::Fill(const DATATYPE& fill) { for (int c=0; c < ELEMENTS; c++) mData[c] = fill; return *static_cast<TYPE*>(this); } // fill vector with zeros template <typename DATATYPE, int ELEMENTS, class TYPE> f_inline TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::Zero() { for (int c=0; c < ELEMENTS; c++) mData[c] = DATATYPE(0); return *static_cast<TYPE*>(this); } // DATATYPE * vector template <typename DATATYPE, int ELEMENTS, class TYPE> f_inline const TYPE operator*(const DATATYPE& f, const TVector<DATATYPE, ELEMENTS, TYPE>& vec) { return vec * f; } // vector addition // this + v return new Vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline const TYPE TVector<DATATYPE, ELEMENTS, TYPE>::operator+(const TYPE& v) const { TYPE r; for (int c=0; c < ELEMENTS; c++) r[c]=mData[c] + v[c]; return r; } // vector subtraction // this - v return new Vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline const TYPE TVector<DATATYPE, ELEMENTS, TYPE>::operator-(const TYPE& v) const { TYPE r; for (int c=0; c < ELEMENTS; c++) r[c]=mData[c] - v[c]; return r; } // scale // this * DATATYPE return new Vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline const TYPE TVector<DATATYPE, ELEMENTS, TYPE>::operator*(const DATATYPE& v) const { TYPE r; for (int c=0; c < ELEMENTS; c++) r[c]=mData[c] * v; return r; } // division // this / DATATYPE return new Vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline const TYPE TVector<DATATYPE, ELEMENTS, TYPE>::operator/(const DATATYPE& v) const { TYPE r; for (int c=0; c < ELEMENTS; c++) r[c]=mData[c] / v; return r; } // this += v returns reference to first vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::operator+=(const TYPE& v) { for (int c=0; c<ELEMENTS; c++) mData[c] += v[c]; return *static_cast<TYPE*>(this); } // this -= v returns reference to first vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::operator-=(const TYPE& v) { for (int c=0; c<ELEMENTS; c++) mData[c] -= v[c]; return *static_cast<TYPE*>(this); } // this *= DATATYPE returns reference to first vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::operator*=(const DATATYPE& v) { for (int c=0; c<ELEMENTS; c++) mData[c] *= v; return *static_cast<TYPE*>(this); } // this /= DATATYPE returns reference to first vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::operator/=(const DATATYPE& v) { for (int c=0; c<ELEMENTS; c++) mData[c] *= v; return *static_cast<TYPE*>(this); } // unary minus template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE TVector<DATATYPE, ELEMENTS, TYPE>::operator-() const { TYPE r; for (int c=0; c < ELEMENTS; c++) r[c] = -mData[c]; return r; } // equality template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline bool TVector<DATATYPE, ELEMENTS, TYPE>::operator==(const TYPE& v) const { return (0==memcmp(this,& v, sizeof(*this))); } // inequality template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline bool TVector<DATATYPE, ELEMENTS, TYPE>::operator!=(const TYPE& v) const { return (0!=memcmp(this,& v, sizeof(*this))); } // generic dot product template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline DATATYPE TVector<DATATYPE, ELEMENTS, TYPE>::Dot(const TYPE& v) const { DATATYPE r = mData[0] * v[0]; for (int c=1; c < ELEMENTS; c++) r += mData[c] * v[c]; return r; } // Normalize vector template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline const TYPE& TVector<DATATYPE, ELEMENTS, TYPE>::Normalize() { DATATYPE length = Length(); DATATYPE lengthInv = DATATYPE(DATATYPE(1) / length); for (int c=0; c<ELEMENTS; c++) mData[c] *= lengthInv; return *static_cast<TYPE*>(this); } template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE TVector<DATATYPE, ELEMENTS, TYPE>::Normalized() const { TYPE r; DATATYPE length = Length(); DATATYPE lengthInv = DATATYPE(DATATYPE(1) / length); for (int c=0; c<ELEMENTS; c++) r[c] = mData[c] * lengthInv; return r; } // Squared length determination: template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline DATATYPE TVector<DATATYPE, ELEMENTS, TYPE>::SquareLength() const { DATATYPE r = mData[0] * mData[0]; for (int c=1; c<ELEMENTS; c++) r += mData[c] * mData[c]; return r; } // Linear Interpolate. Interpolated from one vector to the other template <typename DATATYPE, int ELEMENTS, typename TYPE> f_inline TYPE TVector<DATATYPE, ELEMENTS, TYPE>::LinearInterpolate(const TYPE& to, float t) const { float it = 1.0f - t; TYPE r; for (int c=0; c<ELEMENTS; c++) r[c] = mData[c] * it + to[c] * t; return r; } } //namespace salt #endif //SALT_TVECTOR_H --- NEW FILE: path.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: path.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Path HISTORY: 13.06.2002 MK - initial version 31.08.2002 MK - moved to salt */ #ifndef SALT_PATH_H #define SALT_PATH_H #ifdef HAVE_CONFIG_H # ifdef PACKAGE_BUGREPORT # undef PACKAGE_BUGREPORT # endif # ifdef PACKAGE_NAME # undef PACKAGE_NAME # endif # ifdef PACKAGE_STRING # undef PACKAGE_STRING # endif # ifdef PACKAGE_TARNAME # undef PACKAGE_TARNAME # endif # ifdef PACKAGE_VERSION # undef PACKAGE_VERSION # endif #include "config.h" #endif #include <string> #include <list> namespace salt { /** This class serves as a helper for path strings within the object * hierarchy. It is capable of cleaning paths and separating a path * into path components. */ class Path { // // types // public: typedef std::list<std::string> TStringList; // // functions // public: /** constructs a path object from a string, using the Set * method */ Path(const std::string &path = ""); /** Sets the managed path expression. The path gets tokenized * and can be read element by element using Back(), Front(), * PopBack() and PopFront() */ void Set(const std::string &path); /** returns true if the managed path expression denotes an * absoulute path, i.e. has a leading slash */ bool IsAbsolute() const; /** returns the first path component */ const std::string& Front() const; /** returns and removes the first path component */ void PopFront(); /** returns the last path component */ const std::string& Back() const; /** returns and removes the last path component */ void PopBack(); /** returns true, if no path components remain, i.e. all path * components are popped */ bool IsEmpty() const; /** returns a cleaned path expression, removing superfluous * separators */ std::string GetCleanPath(const std::string &sep = "/") const; private: Path(const Path &obj); Path& operator=(const Path &obj); /** tokenizes the path components */ void Tokenize(const std::string &path); // // members // public: protected: /** the list of tokenized path components */ TStringList mPathComponents; /** indicates an absolute path expression */ bool mIsAbsolute; private: }; } //namespace salt #endif //SALT_PATH_H --- NEW FILE: bounds.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: bounds.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SALT_BOUNDS_H #define SALT_BOUNDS_H // #ifdef HAVE_CONFIG_H // #include <config.h> // #endif #include "defines.h" #include "matrix.h" #include "vector.h" #include <cfloat> namespace salt { /** AABB3 provides an axis aligned three dimensional bounding box */ class AABB3 { public: // constructors /** constructs an empty bounding box */ f_inline AABB3() { Init(); } /** constructs a bounding box encapsulating mn and mx */ f_inline AABB3(const Vector3f &mn, const Vector3f &mx) { Init(); Encapsulate(mn); Encapsulate(mx); } // inline functions /** sets minVec and maxVec to describe an empty bounding box */ f_inline void Init() { minVec.Set(FLT_MAX, FLT_MAX, FLT_MAX); maxVec.Set(-FLT_MAX, -FLT_MAX, -FLT_MAX); } /** encapsulates the Vector v, growing the box if necessary */ f_inline void Encapsulate(const Vector3f &v) { minVec.x() = gMin(minVec.x(), v.x()); minVec.y() = gMin(minVec.y(), v.y()); minVec.z() = gMin(minVec.z(), v.z()); maxVec.x() = gMax(maxVec.x(), v.x()); maxVec.y() = gMax(maxVec.y(), v.y()); maxVec.z() = gMax(maxVec.z(), v.z()); } /** encapsulates the Vector <x,y,z>, growing the box if necessary */ f_inline void Encapsulate(const float x, const float y, const float z) { minVec.x() = gMin(minVec.x(), x); minVec.y() = gMin(minVec.y(), y); minVec.z() = gMin(minVec.z(), z); maxVec.x() = gMax(maxVec.x(), x); maxVec.y() = gMax(maxVec.y(), y); maxVec.z() = gMax(maxVec.z(), z); } /** encapsulates another box, growing the box if necessary */ f_inline void Encapsulate(const AABB3 &box) { Encapsulate(box.minVec); Encapsulate(box.maxVec);} /** grows the box evenly with delta along all axis */ f_inline void Widen(float delta) { minVec.x()-=delta; minVec.y()-=delta; minVec.z()-=delta; maxVec.x()+=delta; maxVec.y()+=delta; maxVec.z()+=delta; } /** moves the box along the vector v */ f_inline void Translate(const Vector3f &v) { minVec+=v; maxVec+=v; } /** returns true if he box contains the vector v */ f_inline bool Contains(const Vector3f &v) const { return (gInRange(v.x(), minVec.x(), maxVec.x()) && gInRange(v.z(), minVec.z(), maxVec.z()) && gInRange(v.y(), minVec.y(), maxVec.y())); } /** returns true if the box contains the box b */ f_inline bool Contains(const AABB3 &b) const { return (Contains(b.minVec) && Contains(b.maxVec)); } /** returns true if this box and the box b have some space in common */ f_inline bool Intersects(const AABB3 &b) const { return !(minVec.x() > b.maxVec.x() || maxVec.x() < b.minVec.x() || minVec.y() > b.maxVec.y() || maxVec.y() < b.minVec.y() || minVec.z() > b.maxVec.z() || maxVec.z() < b.minVec.z()); } /** calculates the current width of the box */ f_inline float GetWidth() const { return gAbs(minVec.x()-maxVec.x()); } /** calculates the current height of the box */ f_inline float GetHeight() const { return gAbs(minVec.y()-maxVec.y()); } /** calculates the current depth of the box */ f_inline float GetDepth() const { return gAbs(minVec.z()-maxVec.z()); } /** calculates the center point of the box */ f_inline Vector3f GetMiddle() const { return Vector3f((minVec.x()+maxVec.x())*0.5f, (minVec.y()+maxVec.y())*0.5f, (minVec.z()+maxVec.z())*0.5f); } /** calculates the distance from the center point to one of the corners, * i.e the radius of the bounding sphere through the center. */ f_inline float GetRadius() const { return ((maxVec-minVec)*0.5).Length(); } // get distance from middle of bounding box to one of the corners // (i.e. radius of bounding sphere through Middle()). /* multiplies the box with the given matrix */ void TransformBy(Matrix& matrix); // attributes /** a vector describing the lower corner of the box */ Vector3f minVec; /** a vector describing the higher corner of the box */ Vector3f maxVec; }; /** AABB2 provides an axis aligned two dimensional bounding box */ class AABB2 { public: // constructors /** constructs an empty bounding box */ f_inline AABB2() { Init(); } /** constructs a bounding box encapsulating mn and mx */ f_inline AABB2(const Vector2f &mn, const Vector2f &mx) { Init(); Encapsulate(mn); Encapsulate(mx); } // inline functions /** sets minVec and maxVec to describe an empty bounding box */ f_inline void Init() { minVec.Set(FLT_MAX, FLT_MAX); maxVec.Set(-FLT_MAX, -FLT_MAX); } /** encapsulates the Vector v, growing the box if necessary */ f_inline void Encapsulate(const Vector2f &v) { minVec.x() = gMin(minVec.x(), v.x()); minVec.y() = gMin(minVec.y(), v.y()); maxVec.x() = gMax(maxVec.x(), v.x()); maxVec.y() = gMax(maxVec.y(), v.y()); } /** encapsulates another box, growing the box if necessary */ f_inline void Encapsulate(const AABB2 &box) { Encapsulate(box.minVec); Encapsulate(box.maxVec);} /** grows the box evenly with delta along both axis */ f_inline void Widen(float delta) { minVec.x()-=delta; minVec.y()-=delta; maxVec.x()+=delta; maxVec.y()+=delta; } /** moves the box along the vector v */ f_inline void Translate(const Vector2f &v) { minVec+=v; maxVec+=v; } /** returns true if he box contains the vector v */ f_inline bool Contains(const Vector2f &v) const { return (gInRange(v.x(), minVec.x(), maxVec.x()) && gInRange(v.y(), minVec.y(), maxVec.y())); } /** returns true if the box contains the box b */ f_inline bool Contains(const AABB2 &b) const { return (Contains(b.minVec) && Contains(b.maxVec)); } /** returns true if this box and the box b have some space in common */ f_inline bool Intersects(const AABB2 &b) const { return !(minVec.x() > b.maxVec.x() || maxVec.x() < b.minVec.x() || minVec.y() > b.maxVec.y() || maxVec.y() < b.minVec.y()); } /** calculates the current width of the box */ f_inline float GetWidth() const // get width of bounding box { return gAbs(minVec.x()-maxVec.x()); } /** calculates the current height of the box */ f_inline float GetHeight() const // get height of bounding box { return gAbs(minVec.y()-maxVec.y()); } /** calculates the center point of the box */ f_inline Vector2f GetMiddle() const { return Vector2f((minVec.x()+maxVec.x())*0.5f, (minVec.y()+maxVec.y())*0.5f); } /** calculates the distance from the center point to one of the corners, * i.e the radius of the bounding sphere through the center. */ f_inline float GetRadius() const { return ((maxVec-minVec)*0.5).Length(); } // attributes /** a vector describing the lower corner of the box */ Vector2f minVec; /** a vector describing the higher corner of the box */ Vector2f maxVec; }; /** BoundingSphere provides a three dimensional sphere */ class BoundingSphere { public: // constructors /** constructs an empty sphere */ f_inline BoundingSphere() : center(Vector3f(0,0,0)), radius(0.0f), radiusSq(0.0f) {} /** constructs a sphere around pos with the radius rad */ f_inline BoundingSphere(const Vector3f &pos, float rad) : center(pos), radius(rad), radiusSq(rad*rad) {} /** Constructs a bounding sphere * \param pos The position where the sphere is constructed * \param rad is the radius of the sphere * \param radSq is the user supplied square of rad */ f_inline BoundingSphere(const Vector3f &pos, float rad, float radSq) : center(pos), radius(rad), radiusSq(radSq) {} // inline functions /** encapsulates the vector v in the sphere, growing it if neccesary. * this method is fast but not accurate */ f_inline void EncapsulateFast(const Vector3f &v) { Vector3f diff=(center - v); float dist=diff.Dot(diff); // not accurate if (dist>radiusSq) { radiusSq=dist; radius=gSqrt(dist); }} /** returns true if the sphere contains the vector v */ f_inline bool Contains(const Vector3f &v) { return ((center - v).SquareLength() < radiusSq); } /** returns true if the sphere contains the sphere s */ f_inline bool Contains(const BoundingSphere &s) const { return (radius >= s.radius) && ((center - s.center).SquareLength() < (radius - s.radius) * (radius - s.radius)); } /** returns true if this sphere and the sphere s intersect */ f_inline bool Intersects(const BoundingSphere &s) const { return ((center - s.center).SquareLength() < (radius + s.radius) * (radius + s.radius)); } // non-inline functions /** encapsulates the vector v in the sphere, growing it if neccesary. * this method is accurate but slower than EncapsulateFast */ void Encapsulate(const Vector3f &v); /** returns true, if the sphere contains the axis aligned bounding box b */ bool Contains(const AABB3 &b) const; /** returns true, if the sphere and the axis aligned bounding box b intersect */ bool Intersects(const AABB3 &b) const; // attributes /** describes the center of the sphere */ Vector3f center; /** describes the radius of the sphere */ float radius; /** the square of the sphere radius. The value ist either accuratly calculated * in the constructor or user supplied and may be inaccurate. */ float radiusSq; }; } // namespace salt #endif // SALT_BOUNDS_H --- NEW FILE: vector.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: vector.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Here we define/complete the vector definitions of TVector into specific vector types (2d float, 3d float, etc...). HISTORY: 12.08.2002 MK - initial version */ #ifndef SALT_VECTOR_H #define SALT_VECTOR_H // #ifdef HAVE_CONFIG_H // #include <config.h> // #endif #include "tvector.h" #include <cstdlib> #include <climits> namespace salt { class Vector2f : public TVector2<float, Vector2f> { // // Methods // public: /// Construction/Destruction/Assignment f_inline Vector2f() : TVector2<float, Vector2f>() { } f_inline Vector2f(float x, float y) : TVector2<float, Vector2f>(x, y) { } explicit Vector2f(const float *f) : TVector2<float, Vector2f>() { SetData(f); } f_inline Vector2f(const Vector2f &v) : TVector2<float, Vector2f>(v) { } explicit Vector2f(float f) : TVector2<float, Vector2f>() { Fill(f); } float GetAngleRad() const { const double length = Length(); if (length == 0) { return 0.0; } double rad = gArcCos(Get(0) / length); if (Get(1) < 0) { rad = 2*M_PI - rad; } return rad; } float GetAngleDeg() const { return gRadToDeg(GetAngleRad()); } }; class Vector3f : public TVector3<float, Vector3f> { // // Methods // public: /// Construction/Destruction/Assignment f_inline Vector3f() : TVector3<float, Vector3f>() { } f_inline Vector3f(float x, float y, float z) : TVector3<float, Vector3f>(x, y, z) { } explicit Vector3f(const float *f) : TVector3<float, Vector3f>() { SetData(f); } f_inline Vector3f(const Vector3f &v) : TVector3<float, Vector3f>(v) { } explicit Vector3f(float f) : TVector3<float, Vector3f>() { Fill(f); } f_inline Vector3f Reflect(const Vector3f &normal) { float fac = 2.0f * (normal.x() * x() + normal.y() * y() + normal.z() * z()); return Vector3f(fac * normal.x()-x(), fac * normal.y()-y(), fac * normal.z()-z()); } f_inline void RandomUnitVector() { x() = 1.0f - 2.0f*rand()/(float)RAND_MAX; y() = 1.0f - 2.0f*rand()/(float)RAND_MAX; z() = 1.0f - 2.0f*rand()/(float)RAND_MAX; Normalize(); } }; } //namespace salt #endif //SALT_VECTOR_H --- NEW FILE: matrix.h --- /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: matrix.h,v 1.1 2005/12/05 20:56:00 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef SALT_MATRIX_H #define SALT_MATRIX_H // #ifdef HAVE_CONFIG_H // #include <config.h> // #endif #include "defines.h" #include "vector.h" #include <memory.h> namespace salt { #if 0 } #endif /** Matrix ... [truncated message content] |
From: Oliver O. <fr...@us...> - 2005-11-19 23:19:20
|
Update of /cvsroot/simspark/simspark/web/cgi-bin In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26909 Modified Files: printenv.cgi Log Message: Index: printenv.cgi =================================================================== RCS file: /cvsroot/simspark/simspark/web/cgi-bin/printenv.cgi,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** printenv.cgi 19 Nov 2005 23:08:50 -0000 1.1 --- printenv.cgi 19 Nov 2005 23:19:12 -0000 1.2 *************** *** 2,5 **** --- 2,6 ---- print "Content-type: text/html\n\n"; + print "printenv.cgi script<BR>"; while (($key, $val) = each %ENV) { print "$key = $val<BR>\n"; |