00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00049 void clearHash() {
00050 Q_ASSERT(dynamic);
00051 m_hash = 0;
00052 }
00053
00054 uint hash() const {
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
00077
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();
00094 }
00095
00096 enum {
00097 AverageSize = sizeof(IdentifierPrivate<false>)+4
00098 };
00099
00100
00101 unsigned int hash() const {
00102 return m_identifier.hash();
00103 }
00104
00105
00106 unsigned int itemSize() const {
00107 return m_identifier.itemSize();
00108 }
00109
00110
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
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
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, ¤tStart )));
00197 while( currentStart < (uint)str.length() && (str[currentStart] == ' ' ) )
00198 ++currentStart;
00199 currentStart += 2;
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;
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();
00228 }
00229
00230 enum {
00231 AverageSize = sizeof(QualifiedIdentifierPrivate<false>)+8
00232 };
00233
00234
00235 unsigned int hash() const {
00236 return m_identifier.hash();
00237 }
00238
00239
00240 unsigned int itemSize() const {
00241 return m_identifier.itemSize();
00242 }
00243
00244
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
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
00289
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
00454
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
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
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
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
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
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
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
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