• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdevelop API Reference
  • KDE Home
  • Contact Us
 

kdevplatform/language/util

  • sources
  • kfour-appscomplete
  • kdevelop
  • kdevplatform
  • language
  • util
setrepository.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  Copyright 2007 David Nolden <[email protected]>
3 ***************************************************************************/
4 
5 /***************************************************************************
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 ***************************************************************************/
13 
14 #include "setrepository.h"
15 #include <debug.h>
16 #include <list>
17 #include <util/kdevvarlengtharray.h>
18 #include <iostream>
19 #include <limits>
20 #include <serialization/itemrepository.h>
21 #include <serialization/indexedstring.h>
22 #include <QString>
23 #include <QMutex>
24 #include <algorithm>
25 
26 //#define DEBUG_SETREPOSITORY
27 
28 #ifdef DEBUG_SETREPOSITORY
29 #define ifDebug(X) X
30 #else
31 #define ifDebug(x)
32 #undef Q_ASSERT
33 #define Q_ASSERT(x)
34 #endif
35 
36 #ifndef DEBUG_SETREPOSITORY
37 #define CHECK_SPLIT_POSITION(Node)
38 #else
39 #define CHECK_SPLIT_POSITION(node) Q_ASSERT(!(node).leftNode || \
40  (getLeftNode(&node)->end() <= \
41  splitPositionForRange((node).start, \
42  (node).end) && \
43  getRightNode(&node)->start() >= \
44  splitPositionForRange((node).start, (node).end)))
45 #endif
46 
47 namespace Utils {
61 using Index = BasicSetRepository::Index;
62 
66 uint splitPositionForRange(uint start, uint end, uchar& splitBit)
67 {
68  if (end - start == 1) {
69  splitBit = 0;
70  return 0;
71  }
72 
73  while (true) {
74  uint position = ((end - 1) >> splitBit) << splitBit; //Round to the split-position in this interval that is smaller than end
75  if (position > start && position < end)
76  return position;
77  Q_ASSERT(splitBit != 0);
78  --splitBit;
79  }
80 
81  return 0;
82 }
83 
84 uint splitPositionForRange(uint start, uint end)
85 {
86  uchar splitBit = 31;
87  return splitPositionForRange(start, end, splitBit);
88 }
89 
90 class SetNodeDataRequest;
91 
92  #define getLeftNode(node) repository.itemFromIndex(node->leftNode())
93  #define getRightNode(node) repository.itemFromIndex(node->rightNode())
94  #define nodeFromIndex(index) repository.itemFromIndex(index)
95 struct SetRepositoryAlgorithms
96 {
97  SetRepositoryAlgorithms(SetDataRepository& _repository,
98  BasicSetRepository* _setRepository) : repository(_repository)
99  , setRepository(_setRepository)
100  {
101  }
102 
104  Index count(const SetNodeData* node) const;
105 
106  void localCheck(const SetNodeData* node);
107 
108  void check(uint node);
109 
110  void check(const SetNodeData* node);
111 
112  QString shortLabel(const SetNodeData& node) const;
113 
114  uint set_union(uint firstNode, uint secondNode, const SetNodeData* first, const SetNodeData* second,
115  uchar splitBit = 31);
116  uint createSetFromNodes(uint leftNode, uint rightNode, const SetNodeData* left = nullptr,
117  const SetNodeData* right = nullptr);
118  uint computeSetFromNodes(uint leftNode, uint rightNode, const SetNodeData* left, const SetNodeData* right,
119  uchar splitBit);
120  uint set_intersect(uint firstNode, uint secondNode, const SetNodeData* first, const SetNodeData* second,
121  uchar splitBit = 31);
122  bool set_contains(const SetNodeData* node, Index index);
123  uint set_subtract(uint firstNode, uint secondNode, const SetNodeData* first, const SetNodeData* second,
124  uchar splitBit = 31);
125 
126  //Required both nodes to be split correctly
127  bool set_equals(const SetNodeData* lhs, const SetNodeData* rhs);
128 
129  QString dumpDotGraph(uint node) const;
130 
132  uint setForIndices(std::vector<uint>::const_iterator begin, std::vector<uint>::const_iterator end,
133  uchar splitBit = 31)
134  {
135  Q_ASSERT(begin != end);
136 
137  uint startIndex = *begin;
138  uint endIndex = *(end - 1) + 1;
139 
140  if (endIndex == startIndex + 1) {
141  SetNodeData data(startIndex, endIndex);
142 
143  return repository.index(SetNodeDataRequest(&data, repository, setRepository));
144  }
145 
146  uint split = splitPositionForRange(startIndex, endIndex, splitBit);
147  Q_ASSERT(split);
148 
149  auto splitIterator = std::lower_bound(begin, end, split);
150  Q_ASSERT(*splitIterator >= split);
151  Q_ASSERT(splitIterator > begin);
152  Q_ASSERT(*(splitIterator - 1) < split);
153 
154  return createSetFromNodes(setForIndices(begin, splitIterator, splitBit),
155  setForIndices(splitIterator, end, splitBit));
156  }
157 
158 private:
159  QString dumpDotGraphInternal(uint node, bool master = false) const;
160 
161  SetDataRepository& repository;
162  BasicSetRepository* setRepository;
163 };
164 
165 void SetNodeDataRequest::destroy(SetNodeData* data, KDevelop::AbstractItemRepository& _repository)
166 {
167  auto& repository(static_cast<SetDataRepository&>(_repository));
168 
169  if (repository.setRepository->delayedDeletion()) {
170  if (data->leftNode()) {
171  SetDataRepositoryBase::MyDynamicItem left = repository.dynamicItemFromIndex(data->leftNode());
172  SetDataRepositoryBase::MyDynamicItem right = repository.dynamicItemFromIndex(data->rightNode());
173  Q_ASSERT(left->m_refCount > 0);
174  --left->m_refCount;
175  Q_ASSERT(right->m_refCount > 0);
176  --right->m_refCount;
177  } else {
178  //Deleting a leaf
179  Q_ASSERT(data->end() - data->start() == 1);
180  repository.setRepository->itemRemovedFromSets(data->start());
181  }
182  }
183 }
184 
185 SetNodeDataRequest::SetNodeDataRequest(const SetNodeData* _data, SetDataRepository& _repository,
186  BasicSetRepository* _setRepository) : data(*_data)
187  , m_hash(_data->hash())
188  , repository(_repository)
189  , setRepository(_setRepository)
190  , m_created(false)
191 {
192  ifDebug(SetRepositoryAlgorithms alg(repository); alg.check(_data));
193 }
194 
195 SetNodeDataRequest::~SetNodeDataRequest()
196 {
197  //Eventually increase the reference-count of direct children
198  if (m_created) {
199  if (data.leftNode())
200  ++repository.dynamicItemFromIndex(data.leftNode())->m_refCount;
201  if (data.rightNode())
202  ++repository.dynamicItemFromIndex(data.rightNode())->m_refCount;
203  }
204 }
205 
206 //Should create an item where the information of the requested item is permanently stored. The pointer
207 //@param item equals an allocated range with the size of itemSize().
208 void SetNodeDataRequest::createItem(SetNodeData* item) const
209 {
210  Q_ASSERT((data.rightNode() && data.leftNode()) || (!data.rightNode() && !data.leftNode()));
211 
212  m_created = true;
213 
214  *item = data;
215 
216  Q_ASSERT((item->rightNode() && item->leftNode()) || (!item->rightNode() && !item->leftNode()));
217 
218 #ifdef DEBUG_SETREPOSITORY
219  //Make sure we split at the correct split position
220  if (item->hasSlaves()) {
221  uint split = splitPositionForRange(data.start, data.end);
222  const SetNodeData* left = repository.itemFromIndex(item->leftNode());
223  const SetNodeData* right = repository.itemFromIndex(item->rightNode());
224  Q_ASSERT(split >= left->end() && split <= right->start());
225  }
226 #endif
227  if (!data.leftNode() && setRepository) {
228  for (uint a = item->start(); a < item->end(); ++a)
229  setRepository->itemAddedToSets(a);
230  }
231 }
232 
233 bool SetNodeDataRequest::equals(const SetNodeData* item) const
234 {
235  Q_ASSERT((item->rightNode() && item->leftNode()) || (!item->rightNode() && !item->leftNode()));
236  //Just compare child nodes, since data must be correctly split, this is perfectly ok
237  //Since this happens in very tight loops, we don't call an additional function here, but just do the check.
238  return item->leftNode() == data.leftNode() && item->rightNode() == data.rightNode() &&
239  item->start() == data.start() && item->end() == data.end();
240 }
241 
242 Set::Set()
243 {
244 }
245 
246 Set::~Set()
247 {
248 }
249 
250 unsigned int Set::count() const
251 {
252  if (!m_repository || !m_tree)
253  return 0;
254  QMutexLocker lock(m_repository->m_mutex);
255 
256  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
257  return alg.count(m_repository->m_dataRepository.itemFromIndex(m_tree));
258 }
259 
260 Set::Set(uint treeNode, BasicSetRepository* repository) : m_tree(treeNode)
261  , m_repository(repository)
262 {
263 }
264 
265 Set::Set(const Set& rhs)
266 {
267  m_repository = rhs.m_repository;
268  m_tree = rhs.m_tree;
269 }
270 
271 Set& Set::operator=(const Set& rhs)
272 {
273  m_repository = rhs.m_repository;
274  m_tree = rhs.m_tree;
275  return *this;
276 }
277 
278 QString Set::dumpDotGraph() const
279 {
280  if (!m_repository || !m_tree)
281  return QString();
282 
283  QMutexLocker lock(m_repository->m_mutex);
284 
285  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
286  return alg.dumpDotGraph(m_tree);
287 }
288 
289 Index SetRepositoryAlgorithms::count(const SetNodeData* node) const
290 {
291  if (node->leftNode() && node->rightNode())
292  return count(getLeftNode(node)) + count(getRightNode(node));
293  else
294  return node->end() - node->start();
295 }
296 
297 void SetRepositoryAlgorithms::localCheck(const SetNodeData* ifDebug(node))
298 {
299 // Q_ASSERT(node->start() > 0);
300  Q_ASSERT(node->start() < node->end());
301  Q_ASSERT((node->leftNode() && node->rightNode()) || (!node->leftNode() && !node->rightNode()));
302  Q_ASSERT(!node->leftNode() ||
303  (getLeftNode(node())->start() == node->start() && getRightNode(node)->end() == node->end()));
304  Q_ASSERT(!node->leftNode() || (getLeftNode(node())->end() <= getRightNode(node)->start()));
305 }
306 
307 void SetRepositoryAlgorithms::check(uint node)
308 {
309  if (!node)
310  return;
311 
312  check(nodeFromIndex(node));
313 }
314 
315 void SetRepositoryAlgorithms::check(const SetNodeData* node)
316 {
317  localCheck(node);
318  if (node->leftNode())
319  check(getLeftNode(node));
320  if (node->rightNode())
321  check(getRightNode(node));
322 // CHECK_SPLIT_POSITION(*node); Re-enable this
323 }
324 
325 QString SetRepositoryAlgorithms::shortLabel(const SetNodeData& node) const
326 {
327  return QStringLiteral("n%1_%2").arg(node.start()).arg(node.end());
328 }
329 
330 QString SetRepositoryAlgorithms::dumpDotGraphInternal(uint nodeIndex, bool master) const
331 {
332  if (!nodeIndex)
333  return QStringLiteral("empty node");
334 
335  const SetNodeData& node(*repository.itemFromIndex(nodeIndex));
336 
337  QString color = QStringLiteral("blue");
338  if (master)
339  color = QStringLiteral("red");
340 
341  QString label = QStringLiteral("%1 -> %2").arg(node.start()).arg(node.end());
342  if (!node.contiguous())
343  label += QLatin1String(", with gaps");
344 
345  QString ret = QStringLiteral("%1[label=\"%2\", color=\"%3\"];\n").arg(shortLabel(node), label, color);
346 
347  if (node.leftNode()) {
348  const SetNodeData& left(*repository.itemFromIndex(node.leftNode()));
349  const SetNodeData& right(*repository.itemFromIndex(node.rightNode()));
350  Q_ASSERT(node.rightNode());
351  ret += QStringLiteral("%1 -> %2;\n").arg(shortLabel(node), shortLabel(left));
352  ret += QStringLiteral("%1 -> %2;\n").arg(shortLabel(node), shortLabel(right));
353  ret += dumpDotGraphInternal(node.leftNode());
354  ret += dumpDotGraphInternal(node.rightNode());
355  }
356 
357  return ret;
358 }
359 
360 QString SetRepositoryAlgorithms::dumpDotGraph(uint nodeIndex) const
361 {
362  QString ret = QStringLiteral("digraph Repository {\n");
363  ret += dumpDotGraphInternal(nodeIndex, true);
364  ret += QLatin1String("}\n");
365  return ret;
366 }
367 
368 const int nodeStackAlloc = 500;
369 
370 class Set::IteratorPrivate
371 {
372 public:
373  IteratorPrivate()
374  {
375  nodeStackData.resize(nodeStackAlloc);
376  nodeStack = nodeStackData.data();
377  }
378 
379  IteratorPrivate(const Set::IteratorPrivate& rhs)
380  : nodeStackData(rhs.nodeStackData)
381  , nodeStackSize(rhs.nodeStackSize)
382  , currentIndex(rhs.currentIndex)
383  , repository(rhs.repository)
384  {
385  nodeStack = nodeStackData.data();
386  }
387 
388  Set::IteratorPrivate& operator=(const Set::IteratorPrivate& rhs)
389  {
390  nodeStackData = rhs.nodeStackData;
391  nodeStackSize = rhs.nodeStackSize;
392  currentIndex = rhs.currentIndex;
393  repository = rhs.repository;
394  nodeStack = nodeStackData.data();
395 
396  return *this;
397  }
398 
399  void resizeNodeStack()
400  {
401  nodeStackData.resize(nodeStackSize + 1);
402  nodeStack = nodeStackData.data();
403  }
404 
405  KDevVarLengthArray<const SetNodeData*, nodeStackAlloc> nodeStackData;
406  const SetNodeData** nodeStack;
407  int nodeStackSize = 0;
408  Index currentIndex = 0;
409  BasicSetRepository* repository = nullptr;
410 
414  void startAtNode(const SetNodeData* node)
415  {
416  Q_ASSERT(node->start() != node->end());
417  currentIndex = node->start();
418 
419  do {
420  nodeStack[nodeStackSize++] = node;
421 
422  if (nodeStackSize >= nodeStackAlloc)
423  resizeNodeStack();
424 
425  if (node->contiguous())
426  break; //We need no finer granularity, because the range is contiguous
427  node = Set::Iterator::getDataRepository(repository).itemFromIndex(node->leftNode());
428  } while (node);
429  Q_ASSERT(currentIndex >= nodeStack[0]->start());
430  }
431 };
432 
433 std::set<Index> Set::stdSet() const
434 {
435  Set::Iterator it = iterator();
436  std::set<Index> ret;
437 
438  while (it) {
439  Q_ASSERT(ret.find(*it) == ret.end());
440  ret.insert(*it);
441  ++it;
442  }
443 
444  return ret;
445 }
446 
447 Set::Iterator::Iterator(const Iterator& rhs)
448  : d_ptr(new Set::IteratorPrivate(*rhs.d_ptr))
449 {
450 }
451 
452 Set::Iterator& Set::Iterator::operator=(const Iterator& rhs)
453 {
454  *d_ptr = *rhs.d_ptr;
455  return *this;
456 }
457 
458 Set::Iterator::Iterator()
459  : d_ptr(new Set::IteratorPrivate)
460 {
461 }
462 
463 Set::Iterator::~Iterator() = default;
464 
465 Set::Iterator::operator bool() const
466 {
467  Q_D(const Iterator);
468 
469  return d->nodeStackSize;
470 }
471 
472 Set::Iterator& Set::Iterator::operator++()
473 {
474  Q_D(Iterator);
475 
476  Q_ASSERT(d->nodeStackSize);
477 
478  if (d->repository->m_mutex)
479  d->repository->m_mutex->lock();
480 
481  ++d->currentIndex;
482 
483  //const SetNodeData** currentNode = &d->nodeStack[d->nodeStackSize - 1];
484  if (d->currentIndex >= d->nodeStack[d->nodeStackSize - 1]->end()) {
485  //Advance to the next node
486  while (d->nodeStackSize && d->currentIndex >= d->nodeStack[d->nodeStackSize - 1]->end()) {
487  --d->nodeStackSize;
488  }
489 
490  if (!d->nodeStackSize) {
491  //ready
492  } else {
493  //++d->nodeStackSize;
494  //We were iterating the left slave of the node, now continue with the right.
495  ifDebug(const SetNodeData& left =
496  *d->repository->m_dataRepository.itemFromIndex(
497  d->nodeStack[d->nodeStackSize - 1]->leftNode()); Q_ASSERT(left.end == d->currentIndex); )
498 
499  const SetNodeData& right = *d->repository->m_dataRepository.itemFromIndex(
500  d->nodeStack[d->nodeStackSize - 1]->rightNode());
501 
502  d->startAtNode(&right);
503  }
504  }
505 
506  Q_ASSERT(d->nodeStackSize == 0 || d->currentIndex < d->nodeStack[0]->end());
507 
508  if (d->repository->m_mutex)
509  d->repository->m_mutex->unlock();
510 
511  return *this;
512 }
513 
514 BasicSetRepository::Index Set::Iterator::operator*() const
515 {
516  Q_D(const Iterator);
517 
518  return d->currentIndex;
519 }
520 
521 Set::Iterator Set::iterator() const
522 {
523  if (!m_tree || !m_repository)
524  return Iterator();
525 
526  QMutexLocker lock(m_repository->m_mutex);
527 
528  Iterator ret;
529  ret.d_ptr->repository = m_repository;
530 
531  if (m_tree)
532  ret.d_ptr->startAtNode(m_repository->m_dataRepository.itemFromIndex(m_tree));
533  return ret;
534 }
535 
536 //Creates a set item with the given children., they must be valid, and they must be split around their split-position.
537 uint SetRepositoryAlgorithms::createSetFromNodes(uint leftNode, uint rightNode, const SetNodeData* left,
538  const SetNodeData* right)
539 {
540  if (!left)
541  left = nodeFromIndex(leftNode);
542  if (!right)
543  right = nodeFromIndex(rightNode);
544 
545  Q_ASSERT(left->end() <= right->start());
546 
547  SetNodeData set(left->start(), right->end(), leftNode, rightNode);
548 
549  Q_ASSERT(set.start() < set.end());
550 
551  uint ret = repository.index(SetNodeDataRequest(&set, repository, setRepository));
552  Q_ASSERT(set.leftNode() >= 0x10000);
553  Q_ASSERT(set.rightNode() >= 0x10000);
554  Q_ASSERT(ret == repository.findIndex(SetNodeDataRequest(&set, repository, setRepository)));
555  ifDebug(check(ret));
556  return ret;
557 }
558 
559 //Constructs a set node from the given two sub-nodes. Those must be valid, they must not intersect, and they must have a correct split-hierarchy.
560 //The do not need to be split around their computed split-position.
561 uint SetRepositoryAlgorithms::computeSetFromNodes(uint leftNode, uint rightNode, const SetNodeData* left,
562  const SetNodeData* right, uchar splitBit)
563 {
564  Q_ASSERT(left->end() <= right->start());
565  uint splitPosition = splitPositionForRange(left->start(), right->end(), splitBit);
566 
567  Q_ASSERT(splitPosition);
568 
569  if (splitPosition < left->end()) {
570  //The split-position intersects the left node
571  uint leftLeftNode = left->leftNode();
572  uint leftRightNode = left->rightNode();
573 
574  const SetNodeData* leftLeft = this->getLeftNode(left);
575  const SetNodeData* leftRight = this->getRightNode(left);
576 
577  Q_ASSERT(splitPosition >= leftLeft->end() && splitPosition <= leftRight->start());
578 
579  //Create a new set from leftLeft, and from leftRight + right. That set will have the correct split-position.
580  uint newRightNode = computeSetFromNodes(leftRightNode, rightNode, leftRight, right, splitBit);
581 
582  return createSetFromNodes(leftLeftNode, newRightNode, leftLeft);
583  } else if (splitPosition > right->start()) {
584  //The split-position intersects the right node
585  uint rightLeftNode = right->leftNode();
586  uint rightRightNode = right->rightNode();
587 
588  const SetNodeData* rightLeft = this->getLeftNode(right);
589  const SetNodeData* rightRight = this->getRightNode(right);
590 
591  Q_ASSERT(splitPosition >= rightLeft->end() && splitPosition <= rightRight->start());
592 
593  //Create a new set from left + rightLeft, and from rightRight. That set will have the correct split-position.
594  uint newLeftNode = computeSetFromNodes(leftNode, rightLeftNode, left, rightLeft, splitBit);
595 
596  return createSetFromNodes(newLeftNode, rightRightNode, nullptr, rightRight);
597  } else {
598  return createSetFromNodes(leftNode, rightNode, left, right);
599  }
600 }
601 
602 uint SetRepositoryAlgorithms::set_union(uint firstNode, uint secondNode, const SetNodeData* first,
603  const SetNodeData* second, uchar splitBit)
604 {
605  if (firstNode == secondNode)
606  return firstNode;
607 
608  uint firstStart = first->start(), secondEnd = second->end();
609 
610  if (firstStart >= secondEnd)
611  return computeSetFromNodes(secondNode, firstNode, second, first, splitBit);
612 
613  uint firstEnd = first->end(), secondStart = second->start();
614 
615  if (secondStart >= firstEnd)
616  return computeSetFromNodes(firstNode, secondNode, first, second, splitBit);
617 
618  //The ranges of first and second do intersect
619 
620  uint newStart = firstStart < secondStart ? firstStart : secondStart;
621  uint newEnd = firstEnd > secondEnd ? firstEnd : secondEnd;
622 
623  //Compute the split-position for the resulting merged node
624  uint splitPosition = splitPositionForRange(newStart, newEnd, splitBit);
625 
626  //Since the ranges overlap, we can be sure that either first or second contain splitPosition.
627  //The node that contains it, will also be split by it.
628 
629  if (splitPosition > firstStart && splitPosition < firstEnd && splitPosition > secondStart &&
630  splitPosition < secondEnd) {
631  //The split-position intersect with both first and second. Continue the union on both sides of the split-position, and merge it.
632 
633  uint firstLeftNode = first->leftNode();
634  uint firstRightNode = first->rightNode();
635  uint secondLeftNode = second->leftNode();
636  uint secondRightNode = second->rightNode();
637 
638  const SetNodeData* firstLeft = repository.itemFromIndex(firstLeftNode);
639  const SetNodeData* firstRight = repository.itemFromIndex(firstRightNode);
640  const SetNodeData* secondLeft = repository.itemFromIndex(secondLeftNode);
641  const SetNodeData* secondRight = repository.itemFromIndex(secondRightNode);
642 
643  Q_ASSERT(splitPosition >= firstLeft->end() && splitPosition <= firstRight->start());
644  Q_ASSERT(splitPosition >= secondLeft->end() && splitPosition <= secondRight->start());
645 
646  return createSetFromNodes(set_union(firstLeftNode, secondLeftNode, firstLeft, secondLeft, splitBit),
647  set_union(firstRightNode, secondRightNode, firstRight, secondRight, splitBit));
648  } else if (splitPosition > firstStart && splitPosition < firstEnd) {
649  uint firstLeftNode = first->leftNode();
650  uint firstRightNode = first->rightNode();
651 
652  const SetNodeData* firstLeft = repository.itemFromIndex(firstLeftNode);
653  const SetNodeData* firstRight = repository.itemFromIndex(firstRightNode);
654 
655  Q_ASSERT(splitPosition >= firstLeft->end() && splitPosition <= firstRight->start());
656 
657  //splitPosition does not intersect second. That means that second is completely on one side of it.
658  //So we only need to union that side of first with second.
659 
660  if (secondEnd <= splitPosition) {
661  return createSetFromNodes(set_union(firstLeftNode, secondNode, firstLeft, second,
662  splitBit), firstRightNode, nullptr, firstRight);
663  } else {
664  Q_ASSERT(secondStart >= splitPosition);
665  return createSetFromNodes(firstLeftNode, set_union(firstRightNode, secondNode, firstRight, second,
666  splitBit), firstLeft);
667  }
668  } else if (splitPosition > secondStart && splitPosition < secondEnd) {
669  uint secondLeftNode = second->leftNode();
670  uint secondRightNode = second->rightNode();
671 
672  const SetNodeData* secondLeft = repository.itemFromIndex(secondLeftNode);
673  const SetNodeData* secondRight = repository.itemFromIndex(secondRightNode);
674 
675  Q_ASSERT(splitPosition >= secondLeft->end() && splitPosition <= secondRight->start());
676 
677  if (firstEnd <= splitPosition) {
678  return createSetFromNodes(set_union(secondLeftNode, firstNode, secondLeft, first,
679  splitBit), secondRightNode, nullptr, secondRight);
680  } else {
681  Q_ASSERT(firstStart >= splitPosition);
682  return createSetFromNodes(secondLeftNode, set_union(secondRightNode, firstNode, secondRight, first,
683  splitBit), secondLeft);
684  }
685  } else {
686  //We would have stopped earlier of first and second don't intersect
687  ifDebug(uint test = repository.findIndex(SetNodeDataRequest(first, repository, setRepository)); qCDebug(
688  LANGUAGE) << "found index:" << test; )
689  Q_ASSERT(0);
690  return 0;
691  }
692 }
693 
694 bool SetRepositoryAlgorithms::set_equals(const SetNodeData* lhs, const SetNodeData* rhs)
695 {
696  if (lhs->leftNode() != rhs->leftNode() || lhs->rightNode() != rhs->rightNode())
697  return false;
698  else
699  return true;
700 }
701 
702 uint SetRepositoryAlgorithms::set_intersect(uint firstNode, uint secondNode, const SetNodeData* first,
703  const SetNodeData* second, uchar splitBit)
704 {
705  if (firstNode == secondNode)
706  return firstNode;
707 
708  if (first->start() >= second->end())
709  return 0;
710 
711  if (second->start() >= first->end())
712  return 0;
713 
714  //The ranges of first and second do intersect
715  uint firstStart = first->start(), firstEnd = first->end(), secondStart = second->start(), secondEnd = second->end();
716 
717  uint newStart = firstStart < secondStart ? firstStart : secondStart;
718  uint newEnd = firstEnd > secondEnd ? firstEnd : secondEnd;
719 
720  //Compute the split-position for the resulting merged node
721  uint splitPosition = splitPositionForRange(newStart, newEnd, splitBit);
722 
723  //Since the ranges overlap, we can be sure that either first or second contain splitPosition.
724  //The node that contains it, will also be split by it.
725 
726  if (splitPosition > firstStart && splitPosition < firstEnd && splitPosition > secondStart &&
727  splitPosition < secondEnd) {
728  //The split-position intersect with both first and second. Continue the intersection on both sides
729 
730  uint firstLeftNode = first->leftNode();
731  uint firstRightNode = first->rightNode();
732 
733  uint secondLeftNode = second->leftNode();
734  uint secondRightNode = second->rightNode();
735 
736  const SetNodeData* firstLeft = repository.itemFromIndex(firstLeftNode);
737  const SetNodeData* firstRight = repository.itemFromIndex(firstRightNode);
738  const SetNodeData* secondLeft = repository.itemFromIndex(secondLeftNode);
739  const SetNodeData* secondRight = repository.itemFromIndex(secondRightNode);
740 
741  Q_ASSERT(splitPosition >= firstLeft->end() && splitPosition <= firstRight->start());
742  Q_ASSERT(splitPosition >= secondLeft->end() && splitPosition <= secondRight->start());
743 
744  uint newLeftNode = set_intersect(firstLeftNode, secondLeftNode, firstLeft, secondLeft, splitBit);
745  uint newRightNode = set_intersect(firstRightNode, secondRightNode, firstRight, secondRight, splitBit);
746 
747  if (newLeftNode && newRightNode)
748  return createSetFromNodes(newLeftNode, newRightNode);
749  else if (newLeftNode)
750  return newLeftNode;
751  else
752  return newRightNode;
753  } else if (splitPosition > firstStart && splitPosition < firstEnd) {
754  uint firstLeftNode = first->leftNode();
755  uint firstRightNode = first->rightNode();
756 
757  const SetNodeData* firstLeft = repository.itemFromIndex(firstLeftNode);
758  const SetNodeData* firstRight = repository.itemFromIndex(firstRightNode);
759 
760  Q_ASSERT(splitPosition >= firstLeft->end() && splitPosition <= firstRight->start());
761 
762  //splitPosition does not intersect second. That means that second is completely on one side of it.
763  //So we can completely ignore the other side of first.
764 
765  if (secondEnd <= splitPosition) {
766  return set_intersect(firstLeftNode, secondNode, firstLeft, second, splitBit);
767  } else {
768  Q_ASSERT(secondStart >= splitPosition);
769  return set_intersect(firstRightNode, secondNode, firstRight, second, splitBit);
770  }
771  } else if (splitPosition > secondStart && splitPosition < secondEnd) {
772  uint secondLeftNode = second->leftNode();
773  uint secondRightNode = second->rightNode();
774 
775  const SetNodeData* secondLeft = repository.itemFromIndex(secondLeftNode);
776  const SetNodeData* secondRight = repository.itemFromIndex(secondRightNode);
777 
778  Q_ASSERT(splitPosition >= secondLeft->end() && splitPosition <= secondRight->start());
779 
780  if (firstEnd <= splitPosition) {
781  return set_intersect(secondLeftNode, firstNode, secondLeft, first, splitBit);
782  } else {
783  Q_ASSERT(firstStart >= splitPosition);
784  return set_intersect(secondRightNode, firstNode, secondRight, first, splitBit);
785  }
786  } else {
787  //We would have stopped earlier of first and second don't intersect
788  Q_ASSERT(0);
789  return 0;
790  }
791  Q_ASSERT(0);
792 }
793 
794 bool SetRepositoryAlgorithms::set_contains(const SetNodeData* node, Index index)
795 {
796  while (true) {
797  if (node->start() > index || node->end() <= index)
798  return false;
799 
800  if (node->contiguous())
801  return true;
802 
803  const SetNodeData* leftNode = nodeFromIndex(node->leftNode());
804 
805  if (index < leftNode->end())
806  node = leftNode;
807  else {
808  const SetNodeData* rightNode = nodeFromIndex(node->rightNode());
809  node = rightNode;
810  }
811  }
812 
813  return false;
814 }
815 
816 uint SetRepositoryAlgorithms::set_subtract(uint firstNode, uint secondNode, const SetNodeData* first,
817  const SetNodeData* second, uchar splitBit)
818 {
819  if (firstNode == secondNode)
820  return 0;
821 
822  if (first->start() >= second->end() || second->start() >= first->end())
823  return firstNode;
824 
825  //The ranges of first and second do intersect
826  uint firstStart = first->start(), firstEnd = first->end(), secondStart = second->start(), secondEnd = second->end();
827 
828  uint newStart = firstStart < secondStart ? firstStart : secondStart;
829  uint newEnd = firstEnd > secondEnd ? firstEnd : secondEnd;
830 
831  //Compute the split-position for the resulting merged node
832  uint splitPosition = splitPositionForRange(newStart, newEnd, splitBit);
833 
834  //Since the ranges overlap, we can be sure that either first or second contain splitPosition.
835  //The node that contains it, will also be split by it.
836 
837  if (splitPosition > firstStart && splitPosition < firstEnd && splitPosition > secondStart &&
838  splitPosition < secondEnd) {
839  //The split-position intersect with both first and second. Continue the subtract on both sides of the split-position, and merge it.
840 
841  uint firstLeftNode = first->leftNode();
842  uint firstRightNode = first->rightNode();
843 
844  uint secondLeftNode = second->leftNode();
845  uint secondRightNode = second->rightNode();
846 
847  const SetNodeData* firstLeft = repository.itemFromIndex(firstLeftNode);
848  const SetNodeData* firstRight = repository.itemFromIndex(firstRightNode);
849  const SetNodeData* secondLeft = repository.itemFromIndex(secondLeftNode);
850  const SetNodeData* secondRight = repository.itemFromIndex(secondRightNode);
851 
852  Q_ASSERT(splitPosition >= firstLeft->end() && splitPosition <= firstRight->start());
853  Q_ASSERT(splitPosition >= secondLeft->end() && splitPosition <= secondRight->start());
854 
855  uint newLeftNode = set_subtract(firstLeftNode, secondLeftNode, firstLeft, secondLeft, splitBit);
856  uint newRightNode = set_subtract(firstRightNode, secondRightNode, firstRight, secondRight, splitBit);
857 
858  if (newLeftNode && newRightNode)
859  return createSetFromNodes(newLeftNode, newRightNode);
860  else if (newLeftNode)
861  return newLeftNode;
862  else
863  return newRightNode;
864  } else if (splitPosition > firstStart && splitPosition < firstEnd) {
865 // Q_ASSERT(splitPosition >= firstLeft->end() && splitPosition <= firstRight->start());
866 
867  uint firstLeftNode = first->leftNode();
868  uint firstRightNode = first->rightNode();
869 
870  const SetNodeData* firstLeft = repository.itemFromIndex(firstLeftNode);
871  const SetNodeData* firstRight = repository.itemFromIndex(firstRightNode);
872 
873  //splitPosition does not intersect second. That means that second is completely on one side of it.
874  //So we only need to subtract that side of first with second.
875 
876  uint newLeftNode = firstLeftNode, newRightNode = firstRightNode;
877 
878  if (secondEnd <= splitPosition) {
879  newLeftNode = set_subtract(firstLeftNode, secondNode, firstLeft, second, splitBit);
880  } else {
881  Q_ASSERT(secondStart >= splitPosition);
882  newRightNode = set_subtract(firstRightNode, secondNode, firstRight, second, splitBit);
883  }
884 
885  if (newLeftNode && newRightNode)
886  return createSetFromNodes(newLeftNode, newRightNode);
887  else if (newLeftNode)
888  return newLeftNode;
889  else
890  return newRightNode;
891  } else if (splitPosition > secondStart && splitPosition < secondEnd) {
892  uint secondLeftNode = second->leftNode();
893  uint secondRightNode = second->rightNode();
894 
895  const SetNodeData* secondLeft = repository.itemFromIndex(secondLeftNode);
896  const SetNodeData* secondRight = repository.itemFromIndex(secondRightNode);
897 
898  Q_ASSERT(splitPosition >= secondLeft->end() && splitPosition <= secondRight->start());
899 
900  if (firstEnd <= splitPosition) {
901  return set_subtract(firstNode, secondLeftNode, first, secondLeft, splitBit);
902  } else {
903  Q_ASSERT(firstStart >= splitPosition);
904  return set_subtract(firstNode, secondRightNode, first, secondRight, splitBit);
905  }
906  } else {
907  //We would have stopped earlier of first and second don't intersect
908  Q_ASSERT(0);
909  return 0;
910  }
911  Q_ASSERT(0);
912 }
913 
914 Set BasicSetRepository::createSetFromIndices(const std::vector<Index>& indices)
915 {
916  QMutexLocker lock(m_mutex);
917 
918  if (indices.empty())
919  return Set();
920 
921  SetRepositoryAlgorithms alg(m_dataRepository, this);
922 
923  return Set(alg.setForIndices(indices.begin(), indices.end()), this);
924 }
925 
926 Set BasicSetRepository::createSet(Index i)
927 {
928  QMutexLocker lock(m_mutex);
929  SetNodeData data(i, i + 1);
930 
931  return Set(m_dataRepository.index(SetNodeDataRequest(&data, m_dataRepository, this)), this);
932 }
933 
934 Set BasicSetRepository::createSet(const std::set<Index>& indices)
935 {
936  if (indices.empty())
937  return Set();
938 
939  QMutexLocker lock(m_mutex);
940 
941  std::vector<Index> indicesVector;
942  indicesVector.reserve(indices.size());
943 
944  for (unsigned int index : indices) {
945  indicesVector.push_back(index);
946  }
947 
948  return createSetFromIndices(indicesVector);
949 }
950 
951 BasicSetRepository::BasicSetRepository(const QString& name, KDevelop::ItemRepositoryRegistry* registry,
952  bool delayedDeletion)
953  : m_dataRepository(this, name, registry)
954  , m_mutex(nullptr)
955  , m_delayedDeletion(delayedDeletion)
956 {
957  m_mutex = m_dataRepository.mutex();
958 }
959 
960 struct StatisticsVisitor
961 {
962  explicit StatisticsVisitor(const SetDataRepository& _rep) : nodeCount(0)
963  , badSplitNodeCount(0)
964  , zeroRefCountNodes(0)
965  , rep(_rep)
966  {
967  }
968  bool operator()(const SetNodeData* item)
969  {
970  if (item->m_refCount == 0)
971  ++zeroRefCountNodes;
972  ++nodeCount;
973  uint split = splitPositionForRange(item->start(), item->end());
974  if (item->hasSlaves())
975  if (split < rep.itemFromIndex(item->leftNode())->end() ||
976  split > rep.itemFromIndex(item->rightNode())->start())
977  ++badSplitNodeCount;
978  return true;
979  }
980  uint nodeCount;
981  uint badSplitNodeCount;
982  uint zeroRefCountNodes;
983  const SetDataRepository& rep;
984 };
985 
986 void BasicSetRepository::printStatistics() const
987 {
988  StatisticsVisitor stats(m_dataRepository);
989  m_dataRepository.visitAllItems<StatisticsVisitor>(stats);
990  qCDebug(LANGUAGE) << "count of nodes:" << stats.nodeCount << "count of nodes with bad split:" <<
991  stats.badSplitNodeCount << "count of nodes with zero reference-count:" << stats.zeroRefCountNodes;
992 }
993 
994 BasicSetRepository::~BasicSetRepository() = default;
995 
996 void BasicSetRepository::itemRemovedFromSets(uint /*index*/)
997 {
998 }
999 
1000 void BasicSetRepository::itemAddedToSets(uint /*index*/)
1001 {
1002 }
1003 
1005 
1006 bool Set::contains(Index index) const
1007 {
1008  if (!m_tree || !m_repository)
1009  return false;
1010 
1011  QMutexLocker lock(m_repository->m_mutex);
1012 
1013  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1014  return alg.set_contains(m_repository->m_dataRepository.itemFromIndex(m_tree), index);
1015 }
1016 
1017 Set Set::operator +(const Set& first) const
1018 {
1019  if (!first.m_tree)
1020  return *this;
1021  else if (!m_tree || !m_repository)
1022  return first;
1023 
1024  Q_ASSERT(m_repository == first.m_repository);
1025 
1026  QMutexLocker lock(m_repository->m_mutex);
1027 
1028  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1029 
1030  uint retNode = alg.set_union(m_tree, first.m_tree, m_repository->m_dataRepository.itemFromIndex(
1031  m_tree), m_repository->m_dataRepository.itemFromIndex(first.m_tree));
1032 
1033  ifDebug(alg.check(retNode));
1034 
1035  return Set(retNode, m_repository);
1036 }
1037 
1038 Set& Set::operator +=(const Set& first)
1039 {
1040  if (!first.m_tree)
1041  return *this;
1042  else if (!m_tree || !m_repository) {
1043  m_tree = first.m_tree;
1044  m_repository = first.m_repository;
1045  return *this;
1046  }
1047 
1048  QMutexLocker lock(m_repository->m_mutex);
1049 
1050  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1051 
1052  m_tree = alg.set_union(m_tree, first.m_tree, m_repository->m_dataRepository.itemFromIndex(
1053  m_tree), m_repository->m_dataRepository.itemFromIndex(first.m_tree));
1054 
1055  ifDebug(alg.check(m_tree));
1056  return *this;
1057 }
1058 
1059 Set Set::operator &(const Set& first) const
1060 {
1061  if (!first.m_tree || !m_tree)
1062  return Set();
1063 
1064  Q_ASSERT(m_repository);
1065 
1066  QMutexLocker lock(m_repository->m_mutex);
1067 
1068  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1069 
1070  Set ret(alg.set_intersect(m_tree, first.m_tree, m_repository->m_dataRepository.itemFromIndex(
1071  m_tree), m_repository->m_dataRepository.itemFromIndex(first.m_tree)), m_repository);
1072 
1073  ifDebug(alg.check(ret.m_tree));
1074 
1075  return ret;
1076 }
1077 
1078 Set& Set::operator &=(const Set& first)
1079 {
1080  if (!first.m_tree || !m_tree) {
1081  m_tree = 0;
1082  return *this;
1083  }
1084 
1085  Q_ASSERT(m_repository);
1086 
1087  QMutexLocker lock(m_repository->m_mutex);
1088 
1089  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1090 
1091  m_tree = alg.set_intersect(m_tree, first.m_tree, m_repository->m_dataRepository.itemFromIndex(
1092  m_tree), m_repository->m_dataRepository.itemFromIndex(first.m_tree));
1093  ifDebug(alg.check(m_tree));
1094  return *this;
1095 }
1096 
1097 Set Set::operator -(const Set& rhs) const
1098 {
1099  if (!m_tree || !rhs.m_tree)
1100  return *this;
1101 
1102  Q_ASSERT(m_repository);
1103 
1104  QMutexLocker lock(m_repository->m_mutex);
1105 
1106  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1107 
1108  Set ret(alg.set_subtract(m_tree, rhs.m_tree, m_repository->m_dataRepository.itemFromIndex(
1109  m_tree), m_repository->m_dataRepository.itemFromIndex(rhs.m_tree)), m_repository);
1110  ifDebug(alg.check(ret.m_tree));
1111  return ret;
1112 }
1113 
1114 Set& Set::operator -=(const Set& rhs)
1115 {
1116  if (!m_tree || !rhs.m_tree)
1117  return *this;
1118 
1119  Q_ASSERT(m_repository);
1120 
1121  QMutexLocker lock(m_repository->m_mutex);
1122 
1123  SetRepositoryAlgorithms alg(m_repository->m_dataRepository, m_repository);
1124 
1125  m_tree = alg.set_subtract(m_tree, rhs.m_tree, m_repository->m_dataRepository.itemFromIndex(
1126  m_tree), m_repository->m_dataRepository.itemFromIndex(rhs.m_tree));
1127 
1128  ifDebug(alg.check(m_tree));
1129  return *this;
1130 }
1131 
1132 BasicSetRepository* Set::repository() const
1133 {
1134  return m_repository;
1135 }
1136 
1137 void Set::staticRef()
1138 {
1139  if (!m_tree)
1140  return;
1141 
1142  QMutexLocker lock(m_repository->m_mutex);
1143  SetNodeData* data = m_repository->m_dataRepository.dynamicItemFromIndexSimple(m_tree);
1144  ++data->m_refCount;
1145 }
1146 
1148 void Set::unrefNode(uint current)
1149 {
1150  SetNodeData* data = m_repository->m_dataRepository.dynamicItemFromIndexSimple(current);
1151  Q_ASSERT(data->m_refCount);
1152  --data->m_refCount;
1153  if (!m_repository->delayedDeletion()) {
1154  if (data->m_refCount == 0) {
1155  if (data->leftNode()) {
1156  Q_ASSERT(data->rightNode());
1157  unrefNode(data->rightNode());
1158  unrefNode(data->leftNode());
1159  } else {
1160  //Deleting a leaf
1161  Q_ASSERT(data->end() - data->start() == 1);
1162  m_repository->itemRemovedFromSets(data->start());
1163  }
1164 
1165  m_repository->m_dataRepository.deleteItem(current);
1166  }
1167  }
1168 }
1169 
1173 void Set::staticUnref()
1174 {
1175  if (!m_tree)
1176  return;
1177 
1178  QMutexLocker lock(m_repository->m_mutex);
1179 
1180  unrefNode(m_tree);
1181 }
1182 
1183 StringSetRepository::StringSetRepository(const QString& name) : Utils::BasicSetRepository(name)
1184 {
1185 }
1186 
1187 void StringSetRepository::itemRemovedFromSets(uint index)
1188 {
1190  KDevelop::IndexedString string = KDevelop::IndexedString::fromIndex(index);
1191 
1192  const KDevelop::DUChainReferenceCountingEnabler rcEnabler(&string, sizeof(KDevelop::IndexedString));
1193  string.~IndexedString(); //Call destructor with enabled reference-counting
1194 }
1195 
1196 void StringSetRepository::itemAddedToSets(uint index)
1197 {
1199 
1200  KDevelop::IndexedString string = KDevelop::IndexedString::fromIndex(index);
1201 
1202  char data[sizeof(KDevelop::IndexedString)];
1203 
1204  const KDevelop::DUChainReferenceCountingEnabler rcEnabler(data, sizeof(KDevelop::IndexedString));
1205  new (data) KDevelop::IndexedString(string); //Call constructor with enabled reference-counting
1206 }
1207 }
Utils::BasicSetRepository::BasicSetRepository
BasicSetRepository(const QString &name, KDevelop::ItemRepositoryRegistry *registry=&KDevelop::globalItemRepositoryRegistry(), bool delayedDeletion=delayedDeletionByDefault)
Definition: setrepository.cpp:951
Utils::Set::operator&
Set operator&(const Set &rhs) const
Set intersection.
Definition: setrepository.cpp:1059
Utils::SetNodeData::leftNode
uint leftNode() const
Definition: basicsetrepository.h:118
Utils::SetNodeDataRequest::data
SetNodeData data
Definition: basicsetrepository.h:175
Utils::BasicSetRepository::itemRemovedFromSets
virtual void itemRemovedFromSets(uint index)
Is called when this index is not part of any set any more.
Definition: setrepository.cpp:996
Utils::SetNodeDataRequest::repository
SetDataRepository & repository
Definition: basicsetrepository.h:178
Utils::SetNodeDataRequest::createItem
void createItem(SetNodeData *item) const
Definition: setrepository.cpp:208
Utils::Set::operator-=
Set & operator-=(const Set &rhs)
Definition: setrepository.cpp:1114
Utils::SetNodeDataRequest::m_created
bool m_created
Definition: basicsetrepository.h:180
Utils::Set::Index
unsigned int Index
Definition: basicsetrepository.h:203
Utils::Set::contains
bool contains(Index index) const
Definition: setrepository.cpp:1006
Utils::BasicSetRepository::createSetFromIndices
Set createSetFromIndices(const std::vector< Index > &indices)
Takes a sorted list indices, returns a set representing them.
Definition: setrepository.cpp:914
Utils::SetNodeData
Internal node representation, exported here for performance reason.
Definition: basicsetrepository.h:58
Utils::Set::Set
Set()
Utils::SetNodeData::end
uint end() const
Definition: basicsetrepository.h:114
Utils::BasicSetRepository::~BasicSetRepository
virtual ~BasicSetRepository()
Utils::SetNodeData::m_refCount
uint m_refCount
Definition: basicsetrepository.h:74
Utils::SetNodeDataRequest::equals
bool equals(const SetNodeData *item) const
Definition: setrepository.cpp:233
Utils::BasicSetRepository
This is a repository that can be used to efficiently manage generic sets that are represented by inte...
Definition: basicsetrepository.h:274
Utils::SetNodeData::rightNode
uint rightNode() const
Definition: basicsetrepository.h:122
Utils::StringSetRepository::itemRemovedFromSets
void itemRemovedFromSets(uint index) override
Is called when this index is not part of any set any more.
Definition: setrepository.cpp:1187
Utils::Set
This object is copyable.
Definition: basicsetrepository.h:198
setrepository.h
Utils::Set::operator&=
Set & operator&=(const Set &rhs)
Definition: setrepository.cpp:1078
getLeftNode
#define getLeftNode(node)
Definition: setrepository.cpp:92
Utils::Set::IteratorPrivate
friend class IteratorPrivate
Definition: basicsetrepository.h:369
Utils::Set::operator=
Set & operator=(const Set &rhs)
Definition: setrepository.cpp:271
Utils::StringSetRepository::itemAddedToSets
void itemAddedToSets(uint index) override
Is called when this index is added to one of the contained sets for the first time.
Definition: setrepository.cpp:1196
Q_ASSERT
#define Q_ASSERT(x)
Definition: setrepository.cpp:33
Utils::SetNodeDataRequest
Definition: basicsetrepository.h:133
Utils::SetNodeDataRequest::setRepository
BasicSetRepository * setRepository
Definition: basicsetrepository.h:179
Utils::Set::~Set
~Set()
Definition: setrepository.cpp:246
Utils::BasicSetRepository::Index
unsigned int Index
Definition: basicsetrepository.h:283
Utils::SetDataRepository::setRepository
BasicSetRepository * setRepository
Definition: basicsetrepository.h:192
QString
Utils::splitPositionForRange
uint splitPositionForRange(uint start, uint end, uchar &splitBit)
The returned split position shall be the end of the first sub-range, and the start of the second.
Definition: setrepository.cpp:66
Utils::Set::stdSet
std::set< unsigned int > stdSet() const
Definition: setrepository.cpp:433
Utils::SetNodeData::start
uint start() const
Definition: basicsetrepository.h:110
Utils::BasicSetRepository::createSet
Set createSet(const std::set< Index > &indices)
Takes a simple set of indices.
Definition: setrepository.cpp:934
Utils::Set::count
unsigned int count() const
Returns the count of items in the set.
Definition: setrepository.cpp:250
Utils::Set::repository
BasicSetRepository * repository() const
Returns a pointer to the repository this set belongs to. Returns zero when this set is not initialize...
Definition: setrepository.cpp:1132
Utils::BasicSetRepository::itemAddedToSets
virtual void itemAddedToSets(uint index)
Is called when this index is added to one of the contained sets for the first time.
Definition: setrepository.cpp:1000
Utils::SetNodeData::contiguous
bool contiguous() const
Definition: basicsetrepository.h:100
Utils::Set::operator-
Set operator-(const Set &rhs) const
Set subtraction.
Definition: setrepository.cpp:1097
QLatin1String
Utils::SetNodeDataRequest::~SetNodeDataRequest
~SetNodeDataRequest()
Definition: setrepository.cpp:195
Utils::BasicSetRepository::delayedDeletion
bool delayedDeletion() const
Definition: basicsetrepository.h:337
Utils::Index
BasicSetRepository::Index Index
To achieve a maximum re-usage of nodes, we make sure that sub-nodes of a node always split at specifi...
Definition: setrepository.cpp:61
Utils::BasicSetRepository::Set
friend class Set
Definition: basicsetrepository.h:343
Utils::Set::Iterator
Iterator()
Utils::SetDataRepository
Definition: basicsetrepository.h:183
Utils::SetNodeDataRequest::destroy
static void destroy(SetNodeData *data, KDevelop::AbstractItemRepository &_repository)
Definition: setrepository.cpp:165
Utils::StringSetRepository::StringSetRepository
StringSetRepository(const QString &name)
Definition: setrepository.cpp:1183
Utils::BasicSetRepository::printStatistics
void printStatistics() const
Definition: setrepository.cpp:986
nodeFromIndex
#define nodeFromIndex(index)
Definition: setrepository.cpp:94
QMutexLocker
ifDebug
#define ifDebug(x)
Definition: setrepository.cpp:31
Utils::Set::dumpDotGraph
QString dumpDotGraph() const
Definition: setrepository.cpp:278
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Utils::Set::staticRef
void staticRef()
Increase the static reference-count of this set by one. The initial reference-count of newly created ...
Definition: setrepository.cpp:1137
Utils::Set::operator+=
Set & operator+=(const Set &rhs)
Definition: setrepository.cpp:1038
Utils::Set::staticUnref
void staticUnref()
Decrease the static reference-count of this set by one.
Definition: setrepository.cpp:1173
Utils
This header defines convenience-class that allow handling set-repositories using the represented high...
Definition: basicsetrepository.h:48
Utils::SetNodeData::hasSlaves
bool hasSlaves() const
Definition: basicsetrepository.h:105
Utils::nodeStackAlloc
const int nodeStackAlloc
Definition: setrepository.cpp:368
getRightNode
#define getRightNode(node)
Definition: setrepository.cpp:93
Utils::SetNodeDataRequest::SetNodeDataRequest
SetNodeDataRequest(const SetNodeData *_data, SetDataRepository &_repository, BasicSetRepository *_setRepository)
Definition: setrepository.cpp:185
Utils::Set::operator+
Set operator+(const Set &rhs) const
Set union.
Definition: setrepository.cpp:1017
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Jan 27 2021 23:31:01 by doxygen 1.8.16 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kdevplatform/language/util

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

kdevelop API Reference

Skip menu "kdevelop API Reference"
  • kdevplatform
  •   debugger
  •   documentation
  •   interfaces
  •   language
  •     assistant
  •     backgroundparser
  •     checks
  •     classmodel
  •     codecompletion
  •     codegen
  •     duchain
  •     editor
  •     highlighting
  •     interfaces
  •     util
  •   outputview
  •   project
  •   serialization
  •   shell
  •   sublime
  •   tests
  •   util
  •   vcs

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal