summaryrefslogtreecommitdiffstats
path: root/kig/misc/argsparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kig/misc/argsparser.cpp')
-rw-r--r--kig/misc/argsparser.cpp267
1 files changed, 267 insertions, 0 deletions
diff --git a/kig/misc/argsparser.cpp b/kig/misc/argsparser.cpp
new file mode 100644
index 00000000..c2387970
--- /dev/null
+++ b/kig/misc/argsparser.cpp
@@ -0,0 +1,267 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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; either version 2
+// of the License, or (at your option) any later version.
+
+// 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., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301, USA.
+
+#include "argsparser.h"
+
+#include "../objects/object_imp.h"
+#include "../objects/object_holder.h"
+
+#include <cassert>
+#include <algorithm>
+#include <kdebug.h>
+
+void ArgsParser::initialize( const struct spec* args, int n )
+{
+ std::vector<spec> vect( args, args + n );
+ initialize( vect );
+}
+
+ArgsParser::ArgsParser()
+{
+}
+
+ArgsParser::ArgsParser( const std::vector<spec>& args )
+{
+ initialize( args );
+}
+
+void ArgsParser::initialize( const std::vector<spec>& args )
+{
+ margs = args;
+}
+
+ArgsParser::ArgsParser( const spec* args, int n )
+{
+ initialize( args, n );
+}
+
+static bool hasimp( const ObjectCalcer& o, const ObjectImpType* imptype )
+{
+ return o.imp()->inherits( imptype );
+}
+
+static bool hasimp( const ObjectImp& o, const ObjectImpType* imptype )
+{
+ return o.inherits( imptype );
+}
+
+static bool isvalid( const ObjectImp& o )
+{
+ return o.valid();
+}
+
+static bool isvalid( const ObjectCalcer& o )
+{
+ return o.imp()->valid();
+}
+
+// we use a template method that is used for both Objects and Args to
+// not have to write the same thing twice..
+template <class Collection>
+static int check( const Collection& c, const std::vector<ArgsParser::spec>& margs )
+{
+ std::vector<bool> found( margs.size() );
+
+ for ( typename Collection::const_iterator o = c.begin(); o != c.end(); ++o )
+ {
+ for ( uint i = 0; i < margs.size(); ++i )
+ {
+ if ( hasimp( **o, margs[i].type ) && !found[i] )
+ {
+ // object o is of a type that we're looking for
+ found[i] = true;
+ goto matched;
+ };
+ };
+ return ArgsParser::Invalid;
+ matched:
+ ;
+ };
+ for( uint i = 0; i < margs.size(); ++i )
+ if ( !found[i] ) return ArgsParser::Valid;
+ return ArgsParser::Complete;
+}
+
+int ArgsParser::check( const Args& os ) const
+{
+ return ::check( os, margs );
+}
+
+int ArgsParser::check( const std::vector<ObjectCalcer*>& os ) const
+{
+ return ::check( os, margs );
+}
+
+template <typename Collection>
+static Collection parse( const Collection& os,
+ const std::vector<ArgsParser::spec> margs )
+{
+ Collection ret( margs.size(), static_cast<typename Collection::value_type>( 0 ) );
+
+ for ( typename Collection::const_iterator o = os.begin(); o != os.end(); ++o )
+ {
+ for( uint i = 0; i < margs.size(); ++i )
+ if ( hasimp( **o, margs[i].type ) && ret[i] == 0 )
+ {
+ // object o is of a type that we're looking for
+ ret[i] = *o;
+ goto added;
+ }
+ added:
+ ;
+ };
+ // remove 0's from the output..
+ ret.erase(
+ std::remove( ret.begin(), ret.end(),
+ static_cast<typename Collection::value_type>( 0 ) ),
+ ret.end() );
+ return ret;
+}
+
+Args ArgsParser::parse( const Args& os ) const
+{
+ return ::parse( os, margs );
+}
+
+std::vector<ObjectCalcer*> ArgsParser::parse( const std::vector<ObjectCalcer*>& os ) const
+{
+ return ::parse( os, margs );
+}
+
+ArgsParser ArgsParser::without( const ObjectImpType* type ) const
+{
+ std::vector<spec> ret;
+ ret.reserve( margs.size() - 1 );
+ for ( uint i = 0; i < margs.size(); ++i )
+ if ( margs[i].type != type )
+ ret.push_back( margs[i] );
+ return ArgsParser( ret );
+}
+
+ArgsParser::spec ArgsParser::findSpec( const ObjectImp* obj, const Args& parents ) const
+{
+ spec ret;
+ ret.type = 0;
+
+ std::vector<bool> found( margs.size(), false );
+
+ for ( Args::const_iterator o = parents.begin();
+ o != parents.end(); ++o )
+ {
+ for ( uint i = 0; i < margs.size(); ++i )
+ {
+ if ( (*o)->inherits( margs[i].type ) && !found[i] )
+ {
+ // object o is of a type that we're looking for
+ found[i] = true;
+ if ( *o == obj ) return margs[i];
+ // i know that "goto's are *evil*", but they're very useful
+ // and completely harmless if you use them as better "break;"
+ // statements.. trust me ;)
+ goto matched;
+ };
+ };
+ matched:
+ ;
+ };
+ kdDebug() << k_funcinfo << "no proper spec found :(" << endl;
+ return ret;
+}
+
+const ObjectImpType* ArgsParser::impRequirement(
+ const ObjectImp* o, const Args& parents ) const
+{
+ spec s = findSpec( o, parents );
+ return s.type;
+}
+
+std::string ArgsParser::usetext( const ObjectImp* obj, const Args& sel ) const
+{
+ spec s = findSpec( obj, sel );
+ return s.usetext;
+}
+
+template<typename Collection>
+static bool checkArgs( const Collection& os, uint min, const std::vector<ArgsParser::spec>& argsspec )
+{
+ assert( os.size() <= argsspec.size() );
+ if( os.size() < min ) return false;
+ uint checknum = os.size();
+ for ( uint i = 0; i < checknum; ++i )
+ {
+ if( !isvalid( *os[i] ) ) return false;
+ if( !hasimp( *os[i], argsspec[i].type ) ) return false;
+ }
+ return true;
+}
+
+bool ArgsParser::checkArgs( const Args& os ) const
+{
+ return checkArgs( os, margs.size() );
+}
+
+bool ArgsParser::checkArgs( const Args& os, uint min ) const
+{
+ return ::checkArgs( os, min, margs );
+}
+
+bool ArgsParser::checkArgs( const std::vector<ObjectCalcer*>& os ) const
+{
+ return checkArgs( os, margs.size() );
+}
+
+bool ArgsParser::checkArgs( const std::vector<ObjectCalcer*>& os, uint minobjects ) const
+{
+ return ::checkArgs( os, minobjects, margs );
+}
+
+ArgsParser::~ArgsParser()
+{
+}
+
+bool ArgsParser::isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const
+{
+ spec s = findSpec( o, parents );
+ return s.onOrThrough;
+}
+
+std::string ArgsParser::selectStatement( const Args& selection ) const
+{
+ std::vector<bool> found( margs.size(), false );
+
+ for ( Args::const_iterator o = selection.begin();
+ o != selection.end(); ++o )
+ {
+ for ( uint i = 0; i < margs.size(); ++i )
+ {
+ if ( (*o)->inherits( margs[i].type ) && !found[i] )
+ {
+ // object o is of a type that we're looking for
+ found[i] = true;
+ break;
+ }
+ }
+ }
+ for ( uint i = 0; i < margs.size(); ++i )
+ {
+ if ( !found[i] )
+ return margs[i].selectstat;
+ }
+ kdDebug() << k_funcinfo << "no proper select statement found :(" << endl;
+ return 0;
+}
+