summaryrefslogtreecommitdiffstats
path: root/lib/catalog
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch)
treeacaf47eb0fa12142d3896416a69e74cbf5a72242 /lib/catalog
downloadtdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz
tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/catalog')
-rw-r--r--lib/catalog/Mainpage.dox10
-rw-r--r--lib/catalog/Makefile.am13
-rw-r--r--lib/catalog/catalog.cpp462
-rw-r--r--lib/catalog/catalog.h80
-rw-r--r--lib/catalog/tag.cpp127
-rw-r--r--lib/catalog/tag.h309
6 files changed, 1001 insertions, 0 deletions
diff --git a/lib/catalog/Mainpage.dox b/lib/catalog/Mainpage.dox
new file mode 100644
index 00000000..f18b8ced
--- /dev/null
+++ b/lib/catalog/Mainpage.dox
@@ -0,0 +1,10 @@
+/**
+@mainpage The KDevelop Catalog Library
+
+This is the persistant symbol store library working with BerkeleyDb backend.
+
+<b>Link with</b>: -lkdevcatalog \$(KDEDIR)/kdevbdb/libdb.a
+
+<b>Include path</b>: -I\$(kde_includes)/kdevelop/catalog -I\$(KDEDIR)/kdevbdb/include
+*/
+
diff --git a/lib/catalog/Makefile.am b/lib/catalog/Makefile.am
new file mode 100644
index 00000000..ff01a6f6
--- /dev/null
+++ b/lib/catalog/Makefile.am
@@ -0,0 +1,13 @@
+INCLUDES = $(all_includes) $(DB3INCLUDES)
+lib_LTLIBRARIES = libkdevcatalog.la
+libkdevcatalog_la_SOURCES = tag.cpp catalog.cpp
+libkdevcatalog_la_LDFLAGS = -no-undefined $(all_libraries) $(DB3LDFLAGS)
+libkdevcatalog_la_LIBADD = -l$(DB3LIB) $(LIB_KDECORE) $(LIB_QT)
+
+kdevcatalogincludedir = $(includedir)/kdevelop/catalog
+kdevcataloginclude_HEADERS = catalog.h tag.h
+
+DOXYGEN_REFERENCES = dcop interfaces kdecore kdefx kdeui khtml kmdi kio kjs kparts kutils
+DOXYGEN_PROJECTNAME = KDevelop Catalog Library
+DOXYGEN_DOCDIRPREFIX = kdev
+include ../../Doxyfile.am
diff --git a/lib/catalog/catalog.cpp b/lib/catalog/catalog.cpp
new file mode 100644
index 00000000..b3438f1e
--- /dev/null
+++ b/lib/catalog/catalog.cpp
@@ -0,0 +1,462 @@
+/* This file is part of KDevelop
+ Copyright (C) 2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "catalog.h"
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdatastream.h>
+
+#include <krandomsequence.h>
+#include <kdebug.h>
+
+
+#include <cstring>
+#include <cstdlib>
+#include <db.h>
+
+#include <config.h>
+
+struct _Catalog_Private
+{
+ QString dbName;
+
+ DB* dbp;
+ QMap<QCString, DB*> indexList;
+ KRandomSequence rnd;
+ bool enabled;
+
+ _Catalog_Private()
+ : dbp( 0 ), enabled( true )
+ {
+ }
+
+ bool hasIndex( const QCString& name ) const
+ {
+ return indexList.contains( name );
+ }
+
+ DB* index( const QCString& name )
+ {
+ return indexList[ name ];
+ }
+
+ bool addItem( DB* dbp, const QCString& id, const Tag& tag )
+ {
+ Q_ASSERT( dbp != 0 );
+
+ DBT key, data;
+ int ret;
+
+ std::memset( &key, 0, sizeof(key) );
+ std::memset( &data, 0, sizeof(data) );
+
+ QByteArray a1;
+ {
+ QDataStream stream( a1, IO_WriteOnly );
+ stream << id;
+ key.data = a1.data();
+ key.size = a1.size();
+ }
+
+ QByteArray a2;
+ {
+ QDataStream stream( a2, IO_WriteOnly );
+ tag.store( stream );
+ data.data = a2.data();
+ data.size = a2.size();
+ }
+
+ ret = dbp->put( dbp, 0, &key, &data, 0 );
+
+ return ret == 0;
+ }
+
+ bool addItem( DB* dbp, const QVariant& id, const QCString& v )
+ {
+ Q_ASSERT( dbp != 0 );
+
+ DBT key, data;
+ int ret;
+
+ std::memset( &key, 0, sizeof(key) );
+ std::memset( &data, 0, sizeof(data) );
+
+ QByteArray a1;
+ {
+ QDataStream stream( a1, IO_WriteOnly );
+ stream << id;
+ key.data = a1.data();
+ key.size = a1.size();
+ }
+
+ QByteArray a2;
+ {
+ QDataStream stream( a2, IO_WriteOnly );
+ stream << v;
+ data.data = a2.data();
+ data.size = a2.size();
+ }
+
+ ret = dbp->put( dbp, 0, &key, &data, 0 );
+
+ return ret == 0;
+ }
+
+};
+
+
+/*!
+ \fn Catalog::Catalog
+ */
+ Catalog::Catalog()
+ : d( new _Catalog_Private() )
+{
+}
+
+/*!
+ \fn Catalog::~Catalog
+ */
+ Catalog::~Catalog()
+{
+ close();
+ delete( d );
+ d = 0;
+}
+
+/*!
+ \fn Catalog::indexList() const
+ */
+ QValueList<QCString> Catalog::indexList() const
+{
+ QValueList<QCString> l;
+ QMap<QCString, DB*>::Iterator it = d->indexList.begin();
+ while( it != d->indexList.end() ){
+ l << it.key();
+ ++it;
+ }
+
+ return l;
+}
+
+bool Catalog::enabled() const
+{
+ return d->enabled;
+}
+
+void Catalog::setEnabled( bool isEnabled )
+{
+ d->enabled = isEnabled;
+}
+
+/*!
+ \fn Catalog::addIndex( const QString& name )
+ @todo document these functions
+ */
+ void Catalog::addIndex( const QCString& name )
+{
+ Q_ASSERT( d->dbp != 0 );
+
+ QMap<QCString, DB*>::Iterator it = d->indexList.find( name );
+ if( it == d->indexList.end() ){
+ DB* dbp = 0;
+
+ int ret;
+
+ if ((ret = db_create(&dbp, 0, 0)) != 0) {
+ kdDebug() << "db_create: " << db_strerror(ret) << endl;
+ return /*false*/;
+ }
+
+ if ((ret = dbp->set_flags(dbp, DB_DUP | DB_DUPSORT)) != 0) {
+ dbp->err(dbp, ret, "set_flags: DB_DUP | DB_DUPSORT");
+ dbp->close( dbp, 0 );
+ return;
+ }
+
+ QFileInfo fileInfo( d->dbName );
+ QString indexName = fileInfo.dirPath(true) + "/" + fileInfo.baseName(true) + "." + QString(name) + ".idx";
+
+ if( (ret = dbp->set_cachesize( dbp, 0, 2 * 1024 * 1024, 0 )) != 0 ){
+ kdDebug() << "set_cachesize: " << db_strerror(ret) << endl;
+ }
+
+ if ((ret = dbp->open(
+ dbp, NULL, QFile::encodeName( indexName ).data(), 0, DB_BTREE, DB_CREATE, 0664)) != 0) {
+ kdDebug() << "db_open: " << db_strerror(ret) << endl;
+ dbp->close( dbp, 0 );
+ return;
+ }
+
+ d->indexList[ name ] = dbp;
+ }
+}
+
+/*!
+ \fn Catalog::close()
+ */
+
+ void Catalog::close()
+{
+ d->dbName = QString::null;
+
+ QMap<QCString, DB*>::Iterator it = d->indexList.begin();
+ while( it != d->indexList.end() ){
+ if( it.data() ){
+ it.data()->close( it.data(), 0 );
+ }
+ ++it;
+ }
+ d->indexList.clear();
+
+ if( d->dbp != 0 ){
+ d->dbp->close( d->dbp, 0 );
+ d->dbp = 0;
+ }
+}
+
+/*!
+ \fn Catalog::open( const QString& dbName )
+ */
+
+ void Catalog::open( const QString& dbName )
+{
+ Q_ASSERT( d->dbp == 0 );
+
+ d->dbName = dbName;
+
+ int ret;
+
+ if ((ret = db_create(&d->dbp, 0, 0)) != 0) {
+ kdDebug() << "db_create: " << db_strerror(ret) << endl;
+ return /*false*/;
+ }
+
+ if ((ret = d->dbp->set_flags(d->dbp, DB_RECNUM)) != 0) {
+ d->dbp->err(d->dbp, ret, "set_flags: DB_RECNUM");
+ close();
+ return;
+ }
+
+ if( (ret = d->dbp->set_cachesize( d->dbp, 0, 2 * 1024 * 1024, 0 )) != 0 ){
+ kdDebug() << "set_cachesize: " << db_strerror(ret) << endl;
+ }
+
+ if ((ret = d->dbp->open(
+ d->dbp, NULL, d->dbName.local8Bit(), 0, DB_BTREE, DB_CREATE, 0664)) != 0) {
+ kdDebug() << "db_open: " << db_strerror(ret) << endl;
+ close();
+ return;
+ }
+}
+
+/*!
+ \fn Catalog::dbName() const
+ */
+
+ QString Catalog::dbName() const
+{
+ return d->dbName;
+}
+
+/*!
+ \fn Catalog::isValid() const
+ */
+
+ bool Catalog::isValid() const
+{
+ return d->dbp != 0;
+}
+
+/*!
+ \fn Catalog::addItem( Tag& tag )
+ */
+
+ void Catalog::addItem( Tag& tag )
+{
+ if( tag.name().isEmpty() )
+ return;
+
+ QCString id = generateId();
+
+ tag.setId( id );
+ if( d->addItem(d->dbp, id, tag) ){
+ QMap<QCString, DB*>::Iterator it = d->indexList.begin();
+ while( it != d->indexList.end() ){
+ if( tag.hasAttribute(it.key()) )
+ d->addItem( it.data(), tag.attribute(it.key()), id );
+ ++it;
+ }
+ }
+}
+
+/*!
+ \fn Catalog::getItemById( const QString& id )
+ */
+
+ Tag Catalog::getItemById( const QCString& id )
+{
+ Q_ASSERT( d->dbp != 0 );
+
+ DBT key, data;
+ std::memset( &key, 0, sizeof(key) );
+ std::memset( &data, 0, sizeof(data) );
+
+ QByteArray a1;
+ {
+ QDataStream stream( a1, IO_WriteOnly );
+ stream << id;
+ key.data = a1.data();
+ key.size = a1.size();
+ }
+
+ int ret = d->dbp->get( d->dbp, 0, &key, &data, 0 );
+ Q_ASSERT( ret == 0 );
+
+ Tag tag;
+
+ if( ret == 0 ){
+ QByteArray a;
+ a.setRawData( (const char*) data.data, data.size );
+ QDataStream stream( a, IO_ReadOnly );
+ tag.load( stream );
+ a.resetRawData( (const char*) data.data, data.size );
+ }
+
+ return tag;
+}
+
+/*!
+ \fn Catalog::sync()
+*/
+
+ void Catalog::sync()
+{
+ Q_ASSERT( d->dbp != 0 );
+ d->dbp->sync( d->dbp, 0 );
+
+ QMap<QCString, DB*>::Iterator it = d->indexList.begin();
+ while( it != d->indexList.end() ){
+ it.data()->sync( it.data(), 0 );
+ ++it;
+ }
+}
+
+/*!
+ \fn Catalog::query( const QValueList<QueryArgument>& args )
+*/
+
+ QValueList<Tag> Catalog::query( const QValueList<QueryArgument>& args )
+{
+ QValueList<Tag> tags;
+
+ DBT key, data;
+
+ DBC** cursors = new DBC* [ args.size() + 1 ];
+
+ QValueList< QPair<QCString,QVariant> >::ConstIterator it = args.begin();
+ int current = 0;
+ while( it != args.end() ){
+ QCString indexName = (*it).first;
+ QVariant value = (*it).second;
+
+ if( d->hasIndex(indexName) ) {
+ DB* dbp = d->index( indexName );
+ Q_ASSERT( dbp != 0 );
+
+ std::memset( &key, 0, sizeof(key) );
+ std::memset( &data, 0, sizeof(data) );
+
+ QByteArray a1;
+ {
+ QDataStream stream( a1, IO_WriteOnly );
+ stream << value;
+ key.data = a1.data();
+ key.size = a1.size();
+ }
+
+ DBC* cursor = 0;
+ int rtn = dbp->cursor( dbp, 0, &cursor, 0 );
+
+ if ( rtn == 0 ) {
+
+ rtn = cursor->c_get( cursor, &key, &data, DB_SET );
+
+ if ( rtn == 0 ) {
+ cursors[ current++ ] = cursor;
+ }
+ else if ( rtn != DB_NOTFOUND) {
+ kdDebug() << "fetching cursor failed: " << db_strerror(rtn) << endl;
+ cursor->c_close(cursor);
+ }
+ }
+ else {
+ kdDebug() << "creating cursor failed: " << db_strerror(rtn) << endl;
+ }
+ }
+ ++it;
+ }
+
+ cursors[ current ] = 0;
+
+ if( current == args.size() ) {
+
+ DBC* join_curs = 0;
+ int rtn = d->dbp->join( d->dbp, cursors, &join_curs, 0 );
+
+ if ( rtn == 0 ) {
+
+ std::memset( &key, 0, sizeof(key) );
+ std::memset( &data, 0, sizeof(data) );
+
+ while( join_curs->c_get(join_curs, &key, &data, 0) == 0 ) {
+
+ QByteArray a2;
+ a2.setRawData( (const char*) data.data, data.size );
+ QDataStream s( a2, IO_ReadOnly );
+ Tag tag;
+ tag.load( s );
+ a2.resetRawData( (const char*) data.data, data.size );
+ tags << tag;
+ }
+
+ join_curs->c_close( join_curs );
+ }
+ else {
+ kdDebug() << "joining results failed: " << db_strerror(rtn) << endl;
+ }
+ }
+
+ DBC** c = cursors;
+ while( *c != 0 ){
+ (*c)->c_close( *c );
+ ++c;
+ }
+ delete[] cursors;
+
+ return tags;
+}
+
+ QCString Catalog::generateId()
+{
+ static int n = 1;
+ QCString asStr;
+ asStr.sprintf( "%05d", n++ );
+ return asStr;
+}
+
diff --git a/lib/catalog/catalog.h b/lib/catalog/catalog.h
new file mode 100644
index 00000000..8183acaf
--- /dev/null
+++ b/lib/catalog/catalog.h
@@ -0,0 +1,80 @@
+/* This file is part of KDevelop
+ Copyright (C) 2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef CATALOG_H
+#define CATALOG_H
+
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qvariant.h>
+
+
+#include "tag.h"
+/**
+@file catalog.h
+Catalog database - the persistent symbol store database.
+*/
+
+/**
+Catalog objects represent separate symbol databases.
+Catalogs can be created/loaded/unloaded dynamically.
+To find a symbol in the repository each catalog should be queried.
+
+Persistent symbol store is useful to keep information about code that
+never or rarely changes. System libraries are perfect examples of such code.
+*/
+class Catalog
+{
+public:
+ typedef QPair<QCString, QVariant> QueryArgument;
+
+public:
+ Catalog();
+ virtual ~Catalog();
+
+ bool isValid() const;
+ QString dbName() const;
+
+ bool enabled() const;
+ void setEnabled( bool en );
+
+ virtual void open( const QString& dbName );
+ virtual void close();
+ virtual void sync();
+
+ QValueList<QCString> indexList() const;
+ void addIndex( const QCString& name );
+
+ void addItem( Tag& tag );
+
+ Tag getItemById( const QCString& id );
+ QValueList<Tag> query( const QValueList<QueryArgument>& args );
+
+ QCString generateId();
+
+private:
+ class _Catalog_Private* d;
+
+private:
+ Catalog( const Catalog& source );
+ void operator = ( const Catalog& source );
+};
+
+
+#endif
diff --git a/lib/catalog/tag.cpp b/lib/catalog/tag.cpp
new file mode 100644
index 00000000..f4dbda67
--- /dev/null
+++ b/lib/catalog/tag.cpp
@@ -0,0 +1,127 @@
+/* This file is part of KDevelop
+ Copyright (C) 2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "tag.h"
+#include <qdatastream.h>
+
+Tag::Tag()
+{
+ data = new TagData();
+ data->kind = 0;
+ data->flags = 0;
+ data->startLine = 0;
+ data->startColumn = 0;
+ data->endLine = 0;
+ data->endColumn = 0;
+}
+
+Tag::Tag( const Tag& source )
+{
+ data = source.data;
+ data->ref();
+}
+
+Tag::~Tag()
+{
+ if( data->deref() ){
+ delete( data );
+ data = 0;
+ }
+}
+
+void Tag::detach()
+{
+ if( data->count != 1 )
+ *this = copy();
+}
+
+Tag Tag::copy()
+{
+ Tag t;
+
+ t.data->id = data->id;
+ t.data->kind = data->kind;
+ t.data->flags = data->flags;
+ t.data->name = data->name;
+ t.data->scope = data->scope;
+ t.data->fileName = data->fileName;
+ t.data->startLine = data->startLine;
+ t.data->startColumn = data->startColumn;
+ t.data->endLine = data->endLine;
+ t.data->endColumn = data->endColumn;
+ t.data->attributes = data->attributes;
+
+ return t;
+}
+
+Tag& Tag::operator = ( const Tag& source )
+{
+ source.data->ref();
+ if ( data->deref() ){
+ delete data;
+ }
+ data = source.data;
+
+ return( *this );
+}
+
+void Tag::load( QDataStream& stream )
+{
+ stream
+ >> data->id
+ >> data->kind
+ >> data->flags
+ >> data->name
+ >> data->scope
+ >> data->fileName
+ >> data->startLine
+ >> data->startColumn
+ >> data->endLine
+ >> data->endColumn
+ >> data->attributes;
+}
+
+void Tag::store( QDataStream& stream ) const
+{
+ stream
+ << data->id
+ << data->kind
+ << data->flags
+ << data->name
+ << data->scope
+ << data->fileName
+ << data->startLine
+ << data->startColumn
+ << data->endLine
+ << data->endColumn
+ << data->attributes;
+}
+
+QDataStream& operator << ( QDataStream& s, const Tag& t)
+{
+ t.store( s );
+ return s;
+}
+
+QDataStream& operator >> ( QDataStream& s, Tag& t )
+{
+ t.load( s );
+ return s;
+}
+
diff --git a/lib/catalog/tag.h b/lib/catalog/tag.h
new file mode 100644
index 00000000..af5879a6
--- /dev/null
+++ b/lib/catalog/tag.h
@@ -0,0 +1,309 @@
+/* This file is part of KDevelop
+ Copyright (C) 2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef TAG_H
+#define TAG_H
+
+#include <qmap.h>
+#include <qvariant.h>
+#include <qshared.h>
+
+class QDataStream;
+
+union TagFlags
+{
+ unsigned long flags;
+ struct
+ {
+ unsigned long access:
+ 3;
+ unsigned long isVirtual:
+ 1;
+ }
+ data;
+} ;
+
+class Tag
+{
+public:
+ enum Kind
+ {
+ Kind_Unknown,
+
+ Kind_Typedef = 1000,
+ Kind_Namespace,
+ Kind_UsingDirective,
+ Kind_Base_class,
+ Kind_Enum,
+ Kind_Enumerator,
+ Kind_Class,
+ Kind_Struct,
+ Kind_Union,
+ Kind_VariableDeclaration,
+ Kind_Variable,
+ Kind_FunctionDeclaration,
+ Kind_Function,
+ Kind_NamespaceAlias,
+ Kind_TranslationUnit,
+
+ // ...
+
+ Kind_Custom = 2000
+ };
+
+public:
+ Tag();
+ Tag( const Tag& source );
+ ~Tag();
+
+ operator bool() const {
+ return kind() != Kind_Unknown && kind() != 0;
+ }
+
+ Tag& operator = ( const Tag& source );
+
+ QCString id() const
+ {
+ return data->id;
+ }
+
+ void setId( const QCString& id )
+ {
+ detach();
+ data->id = id;
+ }
+
+ int kind() const
+ {
+ return data->kind;
+ }
+
+ void setKind( int kind )
+ {
+ detach();
+ data->kind = kind;
+ }
+
+ unsigned long flags() const
+ {
+ return data->flags;
+ }
+
+ void setFlags( unsigned long flags )
+ {
+ detach();
+ data->flags = flags;
+ }
+
+ QString fileName() const
+ {
+ return data->fileName;
+ }
+
+ void setFileName( const QString& fileName )
+ {
+ detach();
+ data->fileName = fileName;
+ }
+
+ QString path( const QString& sep = QString::fromLatin1("::") ) const
+ {
+ QString s = scope().join( sep );
+ if( s.isNull() )
+ return name();
+ return s + sep + name();
+ }
+
+ QString name() const
+ {
+ return data->name;
+ }
+
+ QString comment() const {
+ if( hasAttribute( "cmt" ) ) {
+ return attribute( "cmt" ).asString();
+ } else {
+ return "";
+ }
+ }
+
+ void setComment( const QString& comment ) {
+ setAttribute( "cmt", comment );
+ }
+
+ void setName( const QString& name )
+ {
+ detach();
+ data->name = name;
+ }
+
+ QStringList scope() const
+ {
+ return data->scope;
+ }
+
+ void setScope( const QStringList& scope )
+ {
+ detach();
+ data->scope = scope;
+ }
+
+ void getStartPosition( int* line, int* column ) const
+ {
+ if( line ) *line = data->startLine;
+ if( column ) *column = data->startColumn;
+ }
+
+ void setStartPosition( int line, int column )
+ {
+ detach();
+ data->startLine = line;
+ data->startColumn = column;
+ }
+
+ void getEndPosition( int* line, int* column ) const
+ {
+ if( line ) *line = data->endLine;
+ if( column ) *column = data->endColumn;
+ }
+
+ void setEndPosition( int line, int column )
+ {
+ detach();
+ data->endLine = line;
+ data->endColumn = column;
+ }
+
+ QString getSpecializationDeclaration() const {
+ if( hasAttribute( "spc" ) )
+ return data->attributes["spc"].asString();
+ else
+ return QString::null;
+ }
+
+ bool hasSpecializationDeclaration() const {
+ return data->attributes.contains( "spc" );
+ }
+
+ void setSpecializationDeclaration( const QString& str ) {
+ data->attributes["spc"] = str;
+ }
+
+ bool hasAttribute( const QCString& name ) const
+ {
+ if( name == "kind" ||
+ name == "name" ||
+ name == "scope" ||
+ name == "fileName" ||
+ name == "startLine" ||
+ name == "startColumn" ||
+ name == "endLine" ||
+ name == "endColumn" )
+ return true;
+ return data->attributes.contains( name );
+ }
+
+ QVariant attribute( const QCString& name ) const
+ {
+ if( name == "id" )
+ return data->id;
+ else if( name == "kind" )
+ return data->kind;
+ else if( name == "name" )
+ return data->name;
+ else if( name == "scope" )
+ return data->scope;
+ else if( name == "fileName" )
+ return data->fileName;
+ else if( name == "startLine" )
+ return data->startLine;
+ else if( name == "startColumn" )
+ return data->startColumn;
+ else if( name == "endLine" )
+ return data->endLine;
+ else if( name == "endColumn" )
+ return data->endColumn;
+ else if( name == "prefix" )
+ return data->name.left( 2 );
+ return data->attributes[ name ];
+ }
+
+ void setAttribute( const QCString& name, const QVariant& value )
+ {
+ detach();
+ if( name == "id" )
+ data->id = value.toCString();
+ else if( name == "kind" )
+ data->kind = value.toInt();
+ else if( name == "name" )
+ data->name = value.toString();
+ else if( name == "scope" )
+ data->scope = value.toStringList();
+ else if( name == "fileName" )
+ data->fileName = value.toString();
+ else if( name == "startLine" )
+ data->startLine = value.toInt();
+ else if( name == "startColumn" )
+ data->startColumn = value.toInt();
+ else if( name == "endLine" )
+ data->endLine = value.toInt();
+ else if( name == "endColumn" )
+ data->endColumn = value.toInt();
+ else
+ data->attributes[ name ] = value;
+ }
+
+ void addTemplateParam( const QString& param , const QString& def = "" ) {
+ QMap<QCString, QVariant>::iterator it = data->attributes.find( "tpl" );
+ if( it != data->attributes.end() && (*it).type() == QVariant::StringList ) {
+ }else{
+ it = data->attributes.insert( "tpl", QVariant( QStringList() ) );
+ }
+
+ QStringList& l( (*it).asStringList() );
+ l << param;
+ l << def;
+ }
+
+ void load( QDataStream& stream );
+ void store( QDataStream& stream ) const;
+
+private:
+ Tag copy();
+ void detach();
+
+private:
+ struct TagData: public QShared
+ {
+ QCString id;
+ int kind;
+ unsigned long flags;
+ QString name;
+ QStringList scope;
+ QString fileName;
+ int startLine, startColumn;
+ int endLine, endColumn;
+ QMap<QCString, QVariant> attributes;
+ } *data;
+};
+
+QDataStream& operator << ( QDataStream&, const Tag& );
+QDataStream& operator >> ( QDataStream&, Tag& );
+
+#endif