• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDevelop Platform Libraries
  • Sitemap
  • Contact Us
 

language/duchain

identifier.cpp

00001 /* This file is part of KDevelop
00002     Copyright 2006 Hamish Rodda <rodda@kde.org>
00003     Copyright 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "identifier.h"
00021 
00022 #include <QtCore/QHash>
00023 #include "stringhelpers.h"
00024 #include "indexedstring.h"
00025 #include "appendedlist_static.h"
00026 #include "repositories/itemrepository.h"
00027 
00028 #define ifDebug(x)
00029 
00030 namespace KDevelop
00031 {
00032 template<bool dynamic = false>
00033 class IdentifierPrivate
00034 {
00035 public:
00036   IdentifierPrivate() : m_unique(0), m_refCount(0), m_hash(0) {
00037   }
00038   
00039   template<bool rhsDynamic>
00040   IdentifierPrivate(const IdentifierPrivate<rhsDynamic>& rhs) : m_unique(rhs.m_unique), m_identifier(rhs.m_identifier), m_refCount(0), m_hash(rhs.m_hash) {
00041     copyListsFrom(rhs);
00042   }
00043   
00044   ~IdentifierPrivate() {
00045     templateIdentifiersList.free(const_cast<IndexedTypeIdentifier*>(templateIdentifiers()));
00046   }
00047 
00048   //Flags the stored hash-value invalid
00049   void clearHash() { //This is always called on an object private to an Identifier, so there is no threading-problem.
00050     Q_ASSERT(dynamic);
00051     m_hash = 0;
00052   }
00053 
00054   uint hash() const { //Since this only needs reading and the data needs not to be private, this may be called by multiple threads simultaneously, so computeHash() must be thread-safe.
00055     if( !m_hash && dynamic )
00056       computeHash();
00057     return m_hash;
00058   }
00059 
00060   int m_unique;
00061   IndexedString m_identifier;
00062   uint m_refCount;
00063 
00064   START_APPENDED_LISTS(IdentifierPrivate)
00065 
00066   APPENDED_LIST_FIRST(IndexedTypeIdentifier, templateIdentifiers)
00067 
00068   END_APPENDED_LISTS(templateIdentifiers)
00069 
00070   unsigned int itemSize() const {
00071     return sizeof(IdentifierPrivate<false>) + lastOffsetBehind();
00072   }
00073 
00074     void computeHash() const {
00075       Q_ASSERT(dynamic);
00076       //this must stay thread-safe(may be called by multiple threads at a time)
00077       //The thread-safety is given because all threads will have the same result, and it will only be written once at the end.
00078       uint hash = m_identifier.hash();
00079       FOREACH_FUNCTION(IndexedTypeIdentifier templateIdentifier, templateIdentifiers)
00080         hash = hash * 13 + IndexedTypeIdentifier(templateIdentifier).hash();
00081       hash += m_unique;
00082       m_hash = hash;
00083     }
00084 
00085     mutable uint m_hash;
00086 };
00087 
00088 typedef IdentifierPrivate<true> DynamicIdentifierPrivate;
00089 typedef IdentifierPrivate<false> ConstantIdentifierPrivate;
00090 
00091 struct IdentifierItemRequest {
00092   IdentifierItemRequest(const DynamicIdentifierPrivate& identifier) : m_identifier(identifier) {
00093     identifier.hash(); //Make sure the hash is valid by calling this
00094   }
00095 
00096   enum {
00097     AverageSize = sizeof(IdentifierPrivate<false>)+4
00098   };
00099 
00100   //Should return the hash-value associated with this request(For example the hash of a string)
00101   unsigned int hash() const {
00102     return m_identifier.hash();
00103   }
00104 
00105   //Should return the size of an item created with createItem
00106   unsigned int itemSize() const {
00107       return m_identifier.itemSize();
00108   }
00109   //Should create an item where the information of the requested item is permanently stored. The pointer
00110   //@param item equals an allocated range with the size of itemSize().
00111   void createItem(ConstantIdentifierPrivate* item) const {
00112     new (item) ConstantIdentifierPrivate(m_identifier);
00113   }
00114   
00115   static bool persistent(const ConstantIdentifierPrivate* item) {
00116     return (bool)item->m_refCount;
00117   }
00118   
00119   static void destroy(ConstantIdentifierPrivate* item, KDevelop::AbstractItemRepository&) {
00120     item->~ConstantIdentifierPrivate();
00121   }
00122 
00123   //Should return whether the here requested item equals the given item
00124   bool equals(const ConstantIdentifierPrivate* item) const {
00125     return item->m_hash == m_identifier.m_hash && item->m_unique == m_identifier.m_unique && item->m_identifier == m_identifier.m_identifier && m_identifier.listsEqual(*item);
00126   }
00127 
00128   const DynamicIdentifierPrivate& m_identifier;
00129 };
00130 
00131 RepositoryManager< ItemRepository<ConstantIdentifierPrivate, IdentifierItemRequest>, false> identifierRepository("Identifier Repository");
00132 
00134 uint emptyConstantIdentifierPrivateIndex() {
00135   static uint index = identifierRepository->index(DynamicIdentifierPrivate());
00136   
00137   if(index == 0) 
00138     identifierRepository->deleteItem(0);
00139   
00140   return index;
00141 }
00142 
00143 const ConstantIdentifierPrivate* emptyConstantIdentifierPrivate() {
00144   return identifierRepository->itemFromIndex(emptyConstantIdentifierPrivateIndex());
00145 }
00146 
00147 bool IndexedIdentifier::isEmpty() const {
00148   return index == emptyConstantIdentifierPrivateIndex();
00149 }
00150 
00151 
00153 template<bool dynamic>
00154 class QualifiedIdentifierPrivate
00155 {
00156 public:
00157   QualifiedIdentifierPrivate() : m_explicitlyGlobal(false), m_isExpression(false), m_hash(0), m_refCount(0) {
00158   }
00159   
00160   template<bool rhsDynamic>
00161   QualifiedIdentifierPrivate(const QualifiedIdentifierPrivate<rhsDynamic>& rhs)
00162     : m_explicitlyGlobal(rhs.m_explicitlyGlobal)
00163     , m_isExpression(rhs.m_isExpression)
00164     , m_hash(rhs.m_hash)
00165     , m_refCount(0)
00166   {
00167     copyListsFrom(rhs);
00168   }
00169   
00170   ~QualifiedIdentifierPrivate() {
00171     identifiersList.free(const_cast<IndexedIdentifier*>(identifiers()));
00172   }
00173   
00174   bool m_explicitlyGlobal:1;
00175   bool m_isExpression:1;
00176   mutable uint m_hash;
00177   uint m_refCount;
00178 
00179   START_APPENDED_LISTS(QualifiedIdentifierPrivate)
00180 
00181   APPENDED_LIST_FIRST(IndexedIdentifier, identifiers)
00182 
00183   END_APPENDED_LISTS(identifiers)
00184 
00185   unsigned int itemSize() const {
00186     return sizeof(QualifiedIdentifierPrivate<false>) + lastOffsetBehind();
00187   }
00188 
00189   //Constructs m_identifiers
00190   void splitIdentifiers( const QString& str, int start )
00191   {
00192     Q_ASSERT(dynamic);
00193     uint currentStart = start;
00194 
00195     while( currentStart < (uint)str.length() ) {
00196       identifiersList.append(IndexedIdentifier(Identifier( str, currentStart, &currentStart )));
00197       while( currentStart < (uint)str.length() && (str[currentStart] == ' ' ) )
00198         ++currentStart;
00199       currentStart += 2; //Skip "::"
00200     }
00201   }
00202 
00203   inline void clearHash() const {
00204     m_hash = 0;
00205   }
00206 
00207   uint hash() const
00208   {
00209     if( m_hash == 0 )
00210     {
00211       uint mhash = 0;
00212       FOREACH_FUNCTION( IndexedIdentifier identifier, identifiers )
00213         mhash = 11*mhash + Identifier(identifier).hash();
00214 
00215       if(mhash != m_hash)
00216         m_hash = mhash;//The local class may be in read-only memory, so only  change m_hash if it's actually a change
00217     }
00218     return m_hash;
00219   }
00220 };
00221 
00222 typedef QualifiedIdentifierPrivate<true> DynamicQualifiedIdentifierPrivate;
00223 typedef QualifiedIdentifierPrivate<false> ConstantQualifiedIdentifierPrivate;
00224 
00225 struct QualifiedIdentifierItemRequest {
00226   QualifiedIdentifierItemRequest(const DynamicQualifiedIdentifierPrivate& identifier) : m_identifier(identifier) {
00227     identifier.hash(); //Make sure the hash is valid by calling this
00228   }
00229 
00230   enum {
00231     AverageSize = sizeof(QualifiedIdentifierPrivate<false>)+8
00232   };
00233 
00234   //Should return the hash-value associated with this request(For example the hash of a string)
00235   unsigned int hash() const {
00236     return m_identifier.hash();
00237   }
00238 
00239   //Should return the size of an item created with createItem
00240   unsigned int itemSize() const {
00241       return m_identifier.itemSize();
00242   }
00243   //Should create an item where the information of the requested item is permanently stored. The pointer
00244   //@param item equals an allocated range with the size of itemSize().
00245   void createItem(ConstantQualifiedIdentifierPrivate* item) const {
00246     Q_ASSERT(shouldDoDUChainReferenceCounting(item));
00247     Q_ASSERT(shouldDoDUChainReferenceCounting(((char*)item) + (itemSize()-1)));
00248     new (item) ConstantQualifiedIdentifierPrivate(m_identifier);
00249   }
00250   
00251   static bool persistent(const ConstantQualifiedIdentifierPrivate* item) {
00252     return (bool)item->m_refCount;
00253   }
00254   
00255   static void destroy(ConstantQualifiedIdentifierPrivate* item, KDevelop::AbstractItemRepository&) {
00256     Q_ASSERT(shouldDoDUChainReferenceCounting(item));
00257     item->~ConstantQualifiedIdentifierPrivate();
00258   }
00259 
00260   //Should return whether the here requested item equals the given item
00261   bool equals(const ConstantQualifiedIdentifierPrivate* item) const {
00262     return item->m_explicitlyGlobal == m_identifier.m_explicitlyGlobal &&
00263     item->m_isExpression == m_identifier.m_isExpression &&
00264     item->m_hash == m_identifier.m_hash &&
00265     m_identifier.listsEqual(*item);
00266   }
00267 
00268   const DynamicQualifiedIdentifierPrivate& m_identifier;
00269 };
00270 
00271 AbstractRepositoryManager* returnIdentifierRepository() {
00272   return &identifierRepository;
00273 }
00274 
00275 RepositoryManager< ItemRepository<ConstantQualifiedIdentifierPrivate, QualifiedIdentifierItemRequest>, false> qualifiedidentifierRepository("Qualified Identifier Repository", 1, &returnIdentifierRepository);
00276 
00277 uint emptyConstantQualifiedIdentifierPrivateIndex() {
00278    static uint index = qualifiedidentifierRepository->index(DynamicQualifiedIdentifierPrivate());
00279     if(index == 0) 
00280       identifierRepository->deleteItem(0);
00281    return index;
00282 }
00283 
00284 const ConstantQualifiedIdentifierPrivate* emptyConstantQualifiedIdentifierPrivate() {
00285   return qualifiedidentifierRepository->itemFromIndex(emptyConstantQualifiedIdentifierPrivateIndex());
00286 }
00287 
00288 // uint QualifiedIdentifier::combineHash(uint leftHash, uint /*leftSize*/, Identifier appendIdentifier) {
00289 //   return 11*leftHash + appendIdentifier.hash();
00290 // }
00291 
00292 Identifier::Identifier(const Identifier& rhs) {
00293   rhs.makeConstant();
00294   cd = rhs.cd;
00295   m_index = rhs.m_index;
00296 }
00297 
00298 Identifier::Identifier(uint index) : m_index(index) {
00299   Q_ASSERT(m_index);
00300   cd = identifierRepository->itemFromIndex(index);
00301 }
00302 
00303 Identifier::~Identifier() {
00304   if(!m_index)
00305     delete dd;
00306 }
00307 
00308 bool Identifier::nameEquals(const Identifier& rhs) const {
00309   return identifier() == rhs.identifier();
00310 }
00311 
00312 uint Identifier::hash() const {
00313   if(!m_index)
00314     return dd->hash();
00315   else
00316     return cd->hash();
00317 }
00318 
00319 bool Identifier::isEmpty() const {
00320   if(!m_index)
00321     return dd->m_identifier.isEmpty() && dd->m_unique == 0 && dd->templateIdentifiersSize() == 0;
00322   else
00323     return cd->m_identifier.isEmpty() && cd->m_unique == 0 && cd->templateIdentifiersSize() == 0;
00324 }
00325 
00326 Identifier::Identifier(const IndexedString& str)
00327   : m_index(0), dd(new IdentifierPrivate<true>)
00328 {
00329   dd->m_identifier = str;
00330 }
00331 
00332 
00333 Identifier::Identifier(const QString& id, uint start, uint* takenRange)
00334   : m_index(0), dd(new IdentifierPrivate<true>)
00335 {
00337   ParamIterator paramIt("<>:", id, start);
00338   dd->m_identifier = IndexedString(paramIt.prefix().trimmed());
00339   while( paramIt ) {
00340     appendTemplateIdentifier( IndexedTypeIdentifier(IndexedQualifiedIdentifier(QualifiedIdentifier(*paramIt))) );
00341     ++paramIt;
00342   }
00343 
00344   if( takenRange )
00345     *takenRange = paramIt.position();
00346 }
00347 
00348 Identifier::Identifier()
00349   : m_index(emptyConstantIdentifierPrivateIndex()), cd(emptyConstantIdentifierPrivate())
00350 {
00351 }
00352 
00353 Identifier Identifier::unique(int token)
00354 {
00355   Identifier ret;
00356   ret.setUnique(token);
00357   return ret;
00358 }
00359 
00360 bool Identifier::isUnique() const
00361 {
00362   if(!m_index)
00363     return dd->m_unique;
00364   else
00365     return cd->m_unique;
00366 }
00367 
00368 int Identifier::uniqueToken() const
00369 {
00370   if(!m_index)
00371     return dd->m_unique;
00372   else
00373     return cd->m_unique;
00374 }
00375 
00376 void Identifier::setUnique(int token)
00377 {
00378   prepareWrite();
00379   dd->m_unique = token;
00380 }
00381 
00382 const IndexedString Identifier::identifier() const
00383 {
00384   if(!m_index)
00385     return dd->m_identifier;
00386   else
00387     return cd->m_identifier;
00388 }
00389 
00390 void Identifier::setIdentifier(const QString& identifier)
00391 {
00392   prepareWrite();
00393   dd->m_identifier = IndexedString(identifier);
00394 }
00395 
00396 void Identifier::setIdentifier(const IndexedString& identifier)
00397 {
00398   prepareWrite();
00399   dd->m_identifier = identifier;
00400 }
00401 
00402 IndexedTypeIdentifier Identifier::templateIdentifier(int num) const
00403 {
00404   if(!m_index)
00405     return dd->templateIdentifiers()[num];
00406   else
00407     return cd->templateIdentifiers()[num];
00408 }
00409 
00410 uint Identifier::templateIdentifiersCount() const
00411 {
00412   if(!m_index)
00413     return dd->templateIdentifiersSize();
00414   else
00415     return cd->templateIdentifiersSize();
00416 }
00417 
00418 void Identifier::appendTemplateIdentifier(const IndexedTypeIdentifier& identifier)
00419 {
00420   prepareWrite();
00421   dd->templateIdentifiersList.append(identifier);
00422 }
00423 
00424 void Identifier::clearTemplateIdentifiers()
00425 {
00426   prepareWrite();
00427   dd->templateIdentifiersList.clear();
00428 }
00429 
00430 uint Identifier::index() const
00431 {
00432   makeConstant();
00433   Q_ASSERT(m_index);
00434   return m_index;
00435 }
00436 
00437 void Identifier::setTemplateIdentifiers(const QList<IndexedTypeIdentifier>& templateIdentifiers)
00438 {
00439   prepareWrite();
00440   dd->templateIdentifiersList.clear();
00441   foreach(const IndexedTypeIdentifier& id, templateIdentifiers)
00442     dd->templateIdentifiersList.append(id);
00443 }
00444 
00445 QString Identifier::toString() const
00446 {
00447   if (!this) {
00448     return "(null identifier)";
00449   }
00450 
00451   QString ret = identifier().str();
00452 
00453 /*  if(isUnique())
00454     ret += "unique";*/
00455 
00456   if (templateIdentifiersCount()) {
00457     ret.append("< ");
00458     for (uint i = 0; i < templateIdentifiersCount(); ++i) {
00459       ret.append(templateIdentifier(i).toString());
00460       if (i != templateIdentifiersCount() - 1)
00461         ret.append(", ");
00462     }
00463     ret.append(" >");
00464   }
00465 
00466   return ret;
00467 }
00468 
00469 bool Identifier::operator==(const Identifier& rhs) const
00470 {
00471   return index() == rhs.index();
00472 }
00473 
00474 bool Identifier::operator!=(const Identifier& rhs) const
00475 {
00476   return !operator==(rhs);
00477 }
00478 
00479 Identifier& Identifier::operator=(const Identifier& rhs)
00480 {
00481   if(dd == rhs.dd && cd == rhs.cd)
00482     return *this;
00483 
00484   if(!m_index)
00485     delete dd;
00486   dd = 0;
00487 
00488   rhs.makeConstant();
00489   cd = rhs.cd;
00490   m_index = rhs.m_index;
00491   Q_ASSERT(cd);
00492   return *this;
00493 }
00494 
00495 uint QualifiedIdentifier::index() const {
00496   makeConstant();
00497   Q_ASSERT(m_index);
00498   return m_index;
00499 }
00500 
00501 void Identifier::makeConstant() const {
00502   if(m_index)
00503     return;
00504   m_index = identifierRepository->index( IdentifierItemRequest(*dd) );
00505   delete dd;
00506   cd = identifierRepository->itemFromIndex( m_index );
00507 }
00508 
00509 void Identifier::prepareWrite() {
00510 
00511   if(m_index) {
00512     const IdentifierPrivate<false>* oldCc = cd;
00513     dd = new IdentifierPrivate<true>;
00514     dd->m_hash = oldCc->m_hash;
00515     dd->m_unique = oldCc->m_unique;
00516     dd->m_identifier = oldCc->m_identifier;
00517     dd->copyListsFrom(*oldCc);
00518     m_index = 0;
00519   }
00520 
00521   dd->clearHash();
00522 }
00523 
00524 bool QualifiedIdentifier::inRepository() const {
00525   if(m_index)
00526     return true;
00527   else
00528     return (bool)qualifiedidentifierRepository->findIndex( QualifiedIdentifierItemRequest(*dd) );
00529 }
00530 
00531 QualifiedIdentifier::QualifiedIdentifier(uint index) : m_index(index), cd( qualifiedidentifierRepository->itemFromIndex(index) ) {
00532 }
00533 
00534 QualifiedIdentifier::QualifiedIdentifier(const QString& id, bool isExpression)
00535   : m_index(0), dd(new DynamicQualifiedIdentifierPrivate)
00536 {
00537   if(isExpression) {
00538     setIsExpression(true);
00539     if(!id.isEmpty()) {
00540       //Prevent tokenization, since we may lose information there
00541       Identifier finishedId;
00542       finishedId.setIdentifier(id);
00543       push(finishedId);
00544     }
00545   }else{
00546     if (id.startsWith("::")) {
00547       dd->m_explicitlyGlobal = true;
00548       dd->splitIdentifiers(id, 2);
00549     } else {
00550       dd->m_explicitlyGlobal = false;
00551       dd->splitIdentifiers(id, 0);
00552     }
00553   }
00554 }
00555 
00556 QualifiedIdentifier::QualifiedIdentifier(const Identifier& id)
00557   : m_index(0), dd(new DynamicQualifiedIdentifierPrivate)
00558 {
00559   if (id.dd->m_identifier.str().isEmpty()) {
00560     dd->m_explicitlyGlobal = true;
00561   } else {
00562     dd->m_explicitlyGlobal = false;
00563     dd->identifiersList.append(IndexedIdentifier(id));
00564   }
00565 }
00566 
00567 QualifiedIdentifier::QualifiedIdentifier()
00568   : m_index(emptyConstantQualifiedIdentifierPrivateIndex()), cd(emptyConstantQualifiedIdentifierPrivate())
00569 {
00570 }
00571 
00572 QualifiedIdentifier::~QualifiedIdentifier() {
00573   if(!m_index)
00574     delete dd;
00575 }
00576 
00577 QualifiedIdentifier::QualifiedIdentifier(const QualifiedIdentifier& id)
00578 {
00579   if(id.m_index) {
00580     m_index = id.m_index;
00581     cd = id.cd;
00582   }else{
00583     m_index = 0;
00584     dd = new QualifiedIdentifierPrivate<true>(*id.dd);
00585   }
00586 }
00587 
00588 QStringList QualifiedIdentifier::toStringList() const
00589 {
00590   QStringList ret;
00591   if (explicitlyGlobal())
00592     ret.append(QString());
00593 
00594   if(m_index) {
00595     FOREACH_FUNCTION(IndexedIdentifier index, cd->identifiers)
00596       ret << index.identifier().toString();
00597   }else{
00598     FOREACH_FUNCTION(IndexedIdentifier index, dd->identifiers)
00599       ret << index.identifier().toString();
00600   }
00601 
00602   return ret;
00603 }
00604 
00605 QString QualifiedIdentifier::toString(bool ignoreExplicitlyGlobal) const
00606 {
00607   QString ret;
00608   if( !ignoreExplicitlyGlobal && explicitlyGlobal() )
00609     ret = "::";
00610 
00611   bool first = true;
00612   if(m_index) {
00613     FOREACH_FUNCTION(IndexedIdentifier index, cd->identifiers)
00614     {
00615       if( !first )
00616         ret += "::";
00617       else
00618         first = false;
00619 
00620       ret += index.identifier().toString();
00621     }
00622   }else{
00623     FOREACH_FUNCTION(IndexedIdentifier index, dd->identifiers)
00624     {
00625       if( !first )
00626         ret += "::";
00627       else
00628         first = false;
00629 
00630       ret += index.identifier().toString();
00631     }
00632   }
00633 
00634   return ret;
00635 }
00636 
00637 QualifiedIdentifier QualifiedIdentifier::merge(const QualifiedIdentifier& base) const
00638 {
00639   QualifiedIdentifier ret(base);
00640   ret.prepareWrite();
00641 
00642   if(m_index)
00643     ret.dd->identifiersList.append(cd->identifiers(), cd->identifiersSize());
00644   else
00645     ret.dd->identifiersList.append(dd->identifiers(), dd->identifiersSize());
00646 
00647   if( explicitlyGlobal() )
00648     ret.setExplicitlyGlobal(true);
00649 
00650   return ret;
00651 }
00652 
00653 QualifiedIdentifier QualifiedIdentifier::operator+(const QualifiedIdentifier& rhs) const {
00654   return rhs.merge(*this);
00655 }
00656 
00657 QualifiedIdentifier& QualifiedIdentifier::operator+=(const QualifiedIdentifier& rhs) {
00658   push(rhs);
00659   return *this;
00660 }
00661 
00662 QualifiedIdentifier QualifiedIdentifier::operator+(const Identifier& rhs) const {
00663   QualifiedIdentifier ret(*this);
00664   ret.push(rhs);
00665   return ret;
00666 }
00667 
00668 QualifiedIdentifier& QualifiedIdentifier::operator+=(const Identifier& rhs) {
00669   push(rhs);
00670   return *this;
00671 }
00672 
00673 // QualifiedIdentifier QualifiedIdentifier::strip(const QualifiedIdentifier & unwantedBase) const
00674 // {
00675 //   // Don't strip the top identifier
00676 //   if (count() <= unwantedBase.count())
00677 //     return *this;
00678 //
00679 //   //Make sure this one starts with unwantedBase
00680 //   for( int a = 0; a < unwantedBase.count(); a++ )
00681 //     if( d->m_identifiers[a] != unwantedBase.d->m_identifiers[a] )
00682 //       return *this;
00683 //
00684 //
00685 //   QualifiedIdentifier ret;
00686 //   ret.setExplicitlyGlobal(false);
00687 //   ret.prepareWrite();
00688 //
00689 //   int remove = unwantedBase.d->m_identifiers.count();
00690 //
00691 //   ret.d->m_identifiers.append(&d->m_identifiers[remove], d->m_identifiers.size() - remove);
00692 //
00693 //   return ret;
00694 // }
00695 
00696 bool QualifiedIdentifier::isExpression() const
00697 {
00698   if(m_index)
00699     return cd->m_isExpression;
00700   else
00701     return dd->m_isExpression;
00702 }
00703 
00704 void QualifiedIdentifier::setIsExpression(bool is)
00705 {
00706   prepareWrite();
00707   dd->m_isExpression = is;
00708 }
00709 
00710 bool QualifiedIdentifier::explicitlyGlobal() const
00711 {
00712   // True if started with "::"
00713   if(m_index)
00714     return cd->m_explicitlyGlobal;
00715   else
00716     return dd->m_explicitlyGlobal;
00717 }
00718 
00719 void QualifiedIdentifier::setExplicitlyGlobal(bool eg)
00720 {
00721   prepareWrite();
00722   dd->m_explicitlyGlobal = eg;
00723 }
00724 
00725 bool QualifiedIdentifier::sameIdentifiers(const QualifiedIdentifier& rhs) const
00726 {
00727   if(m_index && rhs.m_index)
00728     return cd->listsEqual(*rhs.cd);
00729   else if(m_index && !rhs.m_index)
00730     return cd->listsEqual(*rhs.dd);
00731   else if(!m_index && !rhs.m_index)
00732     return dd->listsEqual(*rhs.dd);
00733   else
00734     return dd->listsEqual(*rhs.cd);
00735 }
00736 
00737 // bool QualifiedIdentifier::isSame(const QualifiedIdentifier& rhs, bool ignoreExplicitlyGlobal) const
00738 // {
00739 //   if( cd == rhs.cd )
00740 //     return true;
00741 // 
00742 //   if (!ignoreExplicitlyGlobal && (explicitlyGlobal() != rhs.explicitlyGlobal()))
00743 //     return false;
00744 // 
00745 //   if( isExpression() != rhs.isExpression() )
00746 //     return false;
00747 // 
00748 //   if( hash() != rhs.hash() )
00749 //     return false;
00750 // 
00751 //   return sameIdentifiers(rhs);
00752 // }
00753 
00754 bool QualifiedIdentifier::operator==(const QualifiedIdentifier& rhs) const
00755 {
00756   if( cd == rhs.cd )
00757     return true;
00758   return hash() == rhs.hash() && sameIdentifiers(rhs);
00759 }
00760 
00761 bool QualifiedIdentifier::operator!=(const QualifiedIdentifier& rhs) const
00762 {
00763   return !operator==(rhs);
00764 }
00765 
00766 QualifiedIdentifier& QualifiedIdentifier::operator=(const QualifiedIdentifier& rhs)
00767 {
00768   if(!m_index)
00769     delete dd;
00770   rhs.makeConstant();
00771   cd = rhs.cd;
00772   m_index = rhs.m_index;
00773   return *this;
00774 }
00775 
00776 bool QualifiedIdentifier::beginsWith(const QualifiedIdentifier& other) const
00777 {
00778   uint c = count();
00779   uint oc = other.count();
00780 
00781   for (uint i = 0; i < c && i < oc; ++i)
00782     if (at(i) == other.at(i)) {
00783       continue;
00784     } else {
00785       return false;
00786     }
00787 
00788   return true;
00789 }
00790 
00791 struct Visitor {
00792   Visitor(KDevVarLengthArray<QualifiedIdentifier>& _target, uint _hash) : target(_target), hash(_hash) {
00793   }
00794 
00795   bool operator()(const ConstantQualifiedIdentifierPrivate* item, uint index) const {
00796     if(item->m_hash == hash)
00797       target.append(QualifiedIdentifier(index));
00798     return true;
00799   }
00800   KDevVarLengthArray<QualifiedIdentifier>& target;
00801   uint hash;
00802 };
00803 
00804 void QualifiedIdentifier::findByHash(HashType hash, KDevVarLengthArray<QualifiedIdentifier>& target)
00805 {
00806   Visitor v(target, hash);
00807   qualifiedidentifierRepository->visitItemsWithHash<Visitor>(v, hash);
00808 }
00809 
00810 uint QualifiedIdentifier::hash() const {
00811   if(m_index)
00812     return cd->hash();
00813   else
00814     return dd->hash();
00815 }
00816 
00817 uint qHash(const IndexedTypeIdentifier& id)
00818 {
00819   return id.hash();
00820 }
00821 
00822 uint qHash(const QualifiedIdentifier& id)
00823 {
00824   return id.hash();
00825 }
00826 
00827 uint qHash(const Identifier& id)
00828 {
00829   return id.hash();
00830 }
00831 
00832 bool QualifiedIdentifier::isQualified() const
00833 {
00834   return count() > 1 || explicitlyGlobal();
00835 }
00836 
00837 void QualifiedIdentifier::push(const Identifier& id)
00838 {
00839   if(id.isEmpty())
00840     return;
00841   
00842   prepareWrite();
00843 
00844   dd->identifiersList.append(IndexedIdentifier(id));
00845 }
00846 
00847 void QualifiedIdentifier::push(const QualifiedIdentifier& id)
00848 {
00849   if(id.isEmpty())
00850     return;
00851   
00852   prepareWrite();
00853   id.makeConstant();
00854 
00855   dd->identifiersList.append(id.cd->identifiers(), id.cd->identifiersSize());
00856 }
00857 
00858 void QualifiedIdentifier::pop()
00859 {
00860   prepareWrite();
00861   if(!dd->identifiersSize())
00862     return;
00863   dd->identifiersList.resize(dd->identifiersList.size()-1);
00864 }
00865 
00866 void QualifiedIdentifier::clear()
00867 {
00868   prepareWrite();
00869   dd->identifiersList.clear();
00870   dd->m_explicitlyGlobal = false;
00871   dd->m_isExpression = false;
00872 }
00873 
00874 
00875 bool QualifiedIdentifier::isEmpty() const
00876 {
00877   if(m_index)
00878     return cd->identifiersSize() == 0;
00879   else
00880     return dd->identifiersSize() == 0;
00881 }
00882 
00883 int QualifiedIdentifier::count() const
00884 {
00885   if(m_index)
00886     return cd->identifiersSize();
00887   else
00888     return dd->identifiersSize();
00889 }
00890 
00891 Identifier QualifiedIdentifier::first() const
00892 {
00893   if( (m_index && cd->identifiersSize() == 0) || (!m_index && dd->identifiersSize() == 0) )
00894     return Identifier();
00895   else
00896     return at(0);
00897 }
00898 
00899 Identifier QualifiedIdentifier::last() const
00900 {
00901   uint c = count();
00902   if(c)
00903     return at(c-1);
00904   else
00905     return Identifier();
00906 }
00907 
00908 Identifier QualifiedIdentifier::top() const
00909 {
00910   return last();
00911 }
00912 
00913 QualifiedIdentifier QualifiedIdentifier::mid(int pos, int len) const {
00914   QualifiedIdentifier ret;
00915   if( pos == 0 )
00916     ret.setExplicitlyGlobal(explicitlyGlobal());
00917 
00918   int cnt = (int)count();
00919 
00920   if( len == -1 )
00921     len = cnt - pos;
00922 
00923   if( pos+len > cnt )
00924     len -= cnt - (pos+len);
00925 
00926   for( int a = pos; a < pos+len; a++ )
00927     ret.push(at(a));
00928 
00929   return ret;
00930 }
00931 
00932 const Identifier QualifiedIdentifier::at(int i) const
00933 {
00934   if(m_index) {
00935     Q_ASSERT(i >= 0 && i < (int)cd->identifiersSize());
00936     return cd->identifiers()[i];
00937   }else{
00938     Q_ASSERT(i >= 0 && i < (int)dd->identifiersSize());
00939     return dd->identifiers()[i];
00940   }
00941 }
00942 
00943 void QualifiedIdentifier::makeConstant() const {
00944   if(m_index)
00945     return;
00946   m_index = qualifiedidentifierRepository->index( QualifiedIdentifierItemRequest(*dd) );
00947   delete dd;
00948   cd = qualifiedidentifierRepository->itemFromIndex( m_index );
00949 }
00950 
00951 void QualifiedIdentifier::prepareWrite() {
00952 
00953   if(m_index) {
00954     const QualifiedIdentifierPrivate<false>* oldCc = cd;
00955     dd = new QualifiedIdentifierPrivate<true>;
00956     dd->m_explicitlyGlobal = oldCc->m_explicitlyGlobal;
00957     dd->m_isExpression = oldCc->m_isExpression;
00958     dd->m_hash = oldCc->m_hash;
00959 
00960     dd->copyListsFrom(*oldCc);
00961     m_index = 0;
00962   }
00963 
00964   dd->clearHash();
00965 }
00966 
00967 uint IndexedTypeIdentifier::hash() const {
00968     return m_identifier.getIndex() * 13 + (m_isConstant ? 17 : 0) + (m_isReference ? 12371 : 0) + m_pointerConstMask * 89321 + m_pointerDepth * 1023;
00969 }
00970 
00971 bool IndexedTypeIdentifier::operator==(const IndexedTypeIdentifier& rhs) const {
00972     return m_identifier == rhs.m_identifier && m_isConstant == rhs.m_isConstant && m_isReference == rhs.m_isReference && m_pointerConstMask == rhs.m_pointerConstMask && m_pointerDepth == rhs.m_pointerDepth;
00973 }
00974 
00975 bool IndexedTypeIdentifier::operator!=(const IndexedTypeIdentifier& rhs) const {
00976   return !operator==(rhs);
00977 }
00978 
00979 bool IndexedTypeIdentifier::isReference() const {
00980   return m_isReference;
00981 }
00982 
00983 void IndexedTypeIdentifier::setIsReference(bool isRef) {
00984   m_isReference = isRef;
00985 }
00986 
00987 bool IndexedTypeIdentifier::isConstant() const {
00988   return m_isConstant;
00989 }
00990 
00991 void IndexedTypeIdentifier::setIsConstant(bool isConst) {
00992   m_isConstant = isConst;
00993 }
00994 
00996 int IndexedTypeIdentifier::pointerDepth() const {
00997   return m_pointerDepth;
00998 }
00999 
01002 void IndexedTypeIdentifier::setPointerDepth(int depth) {
01004   for(int s = depth; s < (int)m_pointerDepth; ++s)
01005     setIsConstPointer(s, false);
01006 
01007   m_pointerDepth = depth;
01008 }
01009 
01010 bool IndexedTypeIdentifier::isConstPointer(int depthNumber) const {
01011   return m_pointerConstMask & (1 << depthNumber);
01012 }
01013 
01014 void IndexedTypeIdentifier::setIsConstPointer(int depthNumber, bool constant) {
01015   if(constant)
01016     m_pointerConstMask |= (1 << depthNumber);
01017   else
01018     m_pointerConstMask &= (~(1 << depthNumber));
01019 }
01020 
01021 QString IndexedTypeIdentifier::toString(bool ignoreExplicitlyGlobal) const {
01022   QString ret;
01023   if(isConstant())
01024     ret += "const ";
01025   ret += m_identifier.identifier().toString(ignoreExplicitlyGlobal);
01026   for(int a = 0; a < pointerDepth(); ++a) {
01027     ret += '*';
01028     if( isConstPointer(a) )
01029       ret += "const";
01030   }
01031 
01032   if(isReference())
01033     ret += '&';
01034   return ret;
01035 }
01036 
01037 IndexedTypeIdentifier::IndexedTypeIdentifier(KDevelop::IndexedQualifiedIdentifier identifier) : m_identifier(identifier), m_isConstant(false), m_isReference(false), m_pointerDepth(0), m_pointerConstMask(0) {
01038 }
01039 
01040 IndexedTypeIdentifier::IndexedTypeIdentifier(const QString& identifier, bool isExpression) : m_identifier(QualifiedIdentifier(identifier, isExpression)), m_isConstant(false), m_isReference(false), m_pointerDepth(0), m_pointerConstMask(0) {
01041 }
01042 
01043 IndexedIdentifier::IndexedIdentifier() : index(emptyConstantIdentifierPrivateIndex()) {
01044   if(shouldDoDUChainReferenceCounting(this)) {
01045     QMutexLocker lock(identifierRepository->mutex());
01046     increase(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01047   }
01048 }
01049 
01050 IndexedIdentifier::IndexedIdentifier(const Identifier& id) : index(id.index()) {
01051   if(shouldDoDUChainReferenceCounting(this)) {
01052     QMutexLocker lock(identifierRepository->mutex());
01053     increase(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01054   }
01055 }
01056 
01057 IndexedIdentifier::IndexedIdentifier(const IndexedIdentifier& rhs) : index(rhs.index) {
01058   if(shouldDoDUChainReferenceCounting(this)) {
01059     QMutexLocker lock(identifierRepository->mutex());
01060     increase(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01061   }
01062 }
01063 
01064 IndexedIdentifier::~IndexedIdentifier() {
01065   if(shouldDoDUChainReferenceCounting(this)) {
01066     QMutexLocker lock(identifierRepository->mutex());
01067     decrease(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01068   }
01069 }
01070 
01071 IndexedIdentifier& IndexedIdentifier::operator=(const Identifier& id) {
01072   if(shouldDoDUChainReferenceCounting(this)) {
01073     QMutexLocker lock(identifierRepository->mutex());
01074     decrease(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01075   }
01076 
01077   index = id.index();
01078 
01079   if(shouldDoDUChainReferenceCounting(this)) {
01080     QMutexLocker lock(identifierRepository->mutex());
01081     increase(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01082   }
01083   return *this;
01084 }
01085 
01086 IndexedIdentifier& IndexedIdentifier::operator=(const IndexedIdentifier& id) {
01087   if(shouldDoDUChainReferenceCounting(this)) {
01088     QMutexLocker lock(identifierRepository->mutex());
01089     decrease(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01090   }
01091 
01092   index = id.index;
01093 
01094   if(shouldDoDUChainReferenceCounting(this)) {
01095     QMutexLocker lock(identifierRepository->mutex());
01096     increase(identifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01097   }
01098   return *this;
01099 }
01100 
01101 bool IndexedIdentifier::operator==(const IndexedIdentifier& rhs) const {
01102   return index == rhs.index;
01103 }
01104 
01105 bool IndexedIdentifier::operator!=(const IndexedIdentifier& rhs) const {
01106   return index != rhs.index;
01107 }
01108 
01109 bool IndexedIdentifier::operator==(const Identifier& id) const {
01110   return index == id.index();
01111 }
01112 
01113 Identifier IndexedIdentifier::identifier() const {
01114   return Identifier(index);
01115 }
01116 
01117 IndexedIdentifier::operator Identifier() const {
01118   return Identifier(index);
01119 }
01120 
01121 bool IndexedQualifiedIdentifier::isValid() const {
01122   return index != emptyConstantQualifiedIdentifierPrivateIndex();
01123 }
01124 
01125 int cnt = 0;
01126 
01127 IndexedQualifiedIdentifier IndexedTypeIdentifier::identifier() const
01128 {
01129   return m_identifier;
01130 }
01131 
01132 
01133 void IndexedTypeIdentifier::setIdentifier(KDevelop::IndexedQualifiedIdentifier id)
01134 {
01135   m_identifier = id;
01136 }
01137 
01138 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier() : index(emptyConstantQualifiedIdentifierPrivateIndex()) {
01139   ifDebug( kDebug() << "(" << ++cnt << ")" << m_id << identifier().toString() << index; )
01140   
01141   if(shouldDoDUChainReferenceCounting(this)) {
01142     ifDebug( kDebug() << "increasing"; )
01143     
01144     //kDebug() << "(" << ++cnt << ")" << this << identifier().toString() << "inc" << index;
01145     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01146     increase(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01147   }
01148 }
01149 
01150 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(const QualifiedIdentifier& id) : index(id.index()) {
01151   ifDebug( kDebug() << "(" << ++cnt << ")" << m_id << identifier().toString() << index; )
01152   
01153   if(shouldDoDUChainReferenceCounting(this)) {
01154     ifDebug( kDebug() << "increasing"; )
01155     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01156     increase(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01157   }
01158 }
01159 
01160 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(const IndexedQualifiedIdentifier& id) : index(id.index) {
01161   ifDebug( kDebug() << "(" << ++cnt << ")" << m_id << identifier().toString() << index; )
01162   
01163   if(shouldDoDUChainReferenceCounting(this)) {
01164     ifDebug( kDebug() << "increasing"; )
01165     
01166     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01167     increase(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01168   }
01169 }
01170 
01171 IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(const QualifiedIdentifier& id) {
01172   ifDebug( kDebug() << "(" << ++cnt << ")" << m_id << identifier().toString() << index; )
01173   
01174   if(shouldDoDUChainReferenceCounting(this)) {
01175     ifDebug( kDebug() << "decreasing"; )
01176     
01177     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01178     decrease(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01179   }
01180   
01181   index = id.index();
01182   
01183   if(shouldDoDUChainReferenceCounting(this)) {
01184     ifDebug( kDebug() << index << "increasing"; )
01185     
01186     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01187     increase(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01188   }
01189   
01190   return *this;
01191 }
01192 
01193 IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(const IndexedQualifiedIdentifier& rhs) {
01194   
01195   ifDebug( kDebug() << "(" << ++cnt << ")" << m_id << identifier().toString() << index; )
01196   
01197   if(shouldDoDUChainReferenceCounting(this)) {
01198     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01199     ifDebug( kDebug() << "decreasing"; )
01200     
01201     decrease(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01202   }
01203   
01204   index = rhs.index;
01205   
01206   if(shouldDoDUChainReferenceCounting(this)) {
01207     ifDebug( kDebug() << index << "increasing"; )
01208     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01209     increase(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01210   }
01211   
01212   return *this;
01213 }
01214 
01215 IndexedQualifiedIdentifier::~IndexedQualifiedIdentifier() {
01216   ifDebug( kDebug() << "(" << ++cnt << ")" << m_id << identifier().toString() << index; )
01217   if(shouldDoDUChainReferenceCounting(this)) {
01218     ifDebug( kDebug() << index << "decreasing"; )
01219     QMutexLocker lock(qualifiedidentifierRepository->mutex());
01220     decrease(qualifiedidentifierRepository->dynamicItemFromIndexSimple(index)->m_refCount, index);
01221   }
01222 }
01223 
01224 bool IndexedQualifiedIdentifier::operator==(const IndexedQualifiedIdentifier& rhs) const {
01225   return index == rhs.index;
01226 }
01227 
01228 bool IndexedQualifiedIdentifier::operator==(const QualifiedIdentifier& id) const {
01229   return index == id.index();
01230 }
01231 
01232 QualifiedIdentifier IndexedQualifiedIdentifier::identifier() const {
01233   return QualifiedIdentifier(index);
01234 }
01235 
01236 IndexedQualifiedIdentifier::operator QualifiedIdentifier() const {
01237   return QualifiedIdentifier(index);
01238 }
01239 
01240 }
01241 
01242 // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on

language/duchain

Skip menu "language/duchain"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDevelop Platform Libraries

Skip menu "KDevelop Platform Libraries"
  • interfaces
  • language
  •   codegen
  •   duchain
  •   editor
  • outputview
  • project
  • shell
  • sublime
  • util
  • vcs
Generated for KDevelop Platform Libraries by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal