PageRenderTime 61ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/xalanc/Include/XalanDeque.hpp

https://github.com/apache/xalan-c
C++ Header | 543 lines | 385 code | 114 blank | 44 comment | 22 complexity | 4ea29cdde2a408e3657fcb65558768a8 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #if !defined(XALANDEQUE_HEADER_GUARD_1357924680)
  19. #define XALANDEQUE_HEADER_GUARD_1357924680
  20. // Base include file. Must be first.
  21. #include <xalanc/Include/PlatformDefinitions.hpp>
  22. #include <xalanc/Include/XalanVector.hpp>
  23. #include <xalanc/Include/XalanMemoryManagement.hpp>
  24. namespace XALAN_CPP_NAMESPACE {
  25. template <class Value>
  26. struct XalanDequeIteratorTraits
  27. {
  28. typedef Value value_type;
  29. typedef Value& reference;
  30. typedef Value* pointer;
  31. typedef const Value& const_reference;
  32. };
  33. template <class Value>
  34. struct XalanDequeConstIteratorTraits
  35. {
  36. typedef Value value_type;
  37. typedef const Value& reference;
  38. typedef const Value* pointer;
  39. typedef const Value& const_reference;
  40. };
  41. template <class Traits, class XalanDeque>
  42. class XalanDequeIterator
  43. {
  44. public:
  45. typedef size_t size_type;
  46. typedef typename Traits::value_type value_type;
  47. typedef typename Traits::reference reference;
  48. typedef typename Traits::pointer pointer;
  49. typedef typename Traits::const_reference const_reference;
  50. typedef ptrdiff_t difference_type;
  51. typedef std::random_access_iterator_tag iterator_category;
  52. // The non-const iterator type. In the case of the non-const instatiation, this
  53. // is the same type.
  54. typedef XalanDequeIterator<XalanDequeIteratorTraits<value_type>, XalanDeque> Iterator;
  55. // The const version needs access to our private data members for copy construction and
  56. // assignment. For the const instantiation, this is a superfluous friend declaration,
  57. // since it's the same type as the class itself.
  58. friend class XalanDequeIterator<XalanDequeConstIteratorTraits<value_type>, XalanDeque>;
  59. XalanDequeIterator(
  60. XalanDeque* deque,
  61. size_type pos) :
  62. m_deque(deque),
  63. m_pos(pos)
  64. {
  65. }
  66. // This is standard copy-construction for the non-const iterator type. For the
  67. // const iterator type, this is copy construction from the non-const type, and the
  68. // compiler will generate the standard copy constructor.
  69. XalanDequeIterator(const Iterator& iterator) :
  70. m_deque(iterator.m_deque),
  71. m_pos(iterator.m_pos)
  72. {
  73. }
  74. // This is the standard assignment operator for the non-const iterator type.
  75. // For the const iterator type, this is the assignment operator from the
  76. // non-const type, and the compiler will generate the standard assignment
  77. // operator.
  78. XalanDequeIterator&
  79. operator=(const Iterator& iterator)
  80. {
  81. m_deque = iterator.m_deque;
  82. m_pos = iterator.m_pos;
  83. return *this;
  84. }
  85. XalanDequeIterator&
  86. operator++()
  87. {
  88. ++m_pos;
  89. return *this;
  90. }
  91. XalanDequeIterator
  92. operator++(int)
  93. {
  94. XalanDequeIterator temp = *this;
  95. ++m_pos;
  96. return temp;
  97. }
  98. XalanDequeIterator&
  99. operator--()
  100. {
  101. --m_pos;
  102. return *this;
  103. }
  104. pointer
  105. operator->()
  106. {
  107. return &(*m_deque[m_pos]);
  108. }
  109. reference
  110. operator*()
  111. {
  112. return (*m_deque)[m_pos];
  113. }
  114. const_reference
  115. operator*() const
  116. {
  117. return (*m_deque)[m_pos];
  118. }
  119. XalanDequeIterator
  120. operator+(difference_type difference) const
  121. {
  122. return XalanDequeIterator(m_deque, m_pos + difference);
  123. }
  124. XalanDequeIterator
  125. operator-(difference_type difference) const
  126. {
  127. return XalanDequeIterator(m_deque, m_pos - difference);
  128. }
  129. difference_type
  130. operator-(const XalanDequeIterator& theRHS) const
  131. {
  132. return m_pos - theRHS.m_pos;
  133. }
  134. bool
  135. operator==(const XalanDequeIterator& theRHS) const
  136. {
  137. return theRHS.m_deque == m_deque &&
  138. theRHS.m_pos == m_pos;
  139. }
  140. bool
  141. operator!=(const XalanDequeIterator& theRHS) const
  142. {
  143. return !(theRHS == *this);
  144. }
  145. bool
  146. operator<(const XalanDequeIterator& theRHS) const
  147. {
  148. return m_pos < theRHS.m_pos;
  149. }
  150. private:
  151. XalanDeque* m_deque;
  152. size_type m_pos;
  153. };
  154. /**
  155. * Xalan implementation of deque
  156. */
  157. template <class Type, class ConstructionTraits = MemoryManagedConstructionTraits<Type> >
  158. class XalanDeque
  159. {
  160. public:
  161. typedef size_t size_type;
  162. typedef Type value_type;
  163. typedef Type& reference;
  164. typedef const Type& const_reference;
  165. typedef XalanVector<Type, ConstructionTraits> BlockType;
  166. typedef XalanVector<BlockType*> BlockIndexType;
  167. typedef XalanDeque<Type, ConstructionTraits> ThisType;
  168. typedef XalanDequeIterator<XalanDequeIteratorTraits<value_type>, ThisType> iterator;
  169. typedef XalanDequeIterator<XalanDequeConstIteratorTraits<value_type>, ThisType> const_iterator;
  170. typedef std::reverse_iterator<iterator> reverse_iterator_;
  171. typedef std::reverse_iterator<const_iterator> const_reverse_iterator_;
  172. typedef reverse_iterator_ reverse_iterator;
  173. typedef const_reverse_iterator_ const_reverse_iterator;
  174. typedef typename ConstructionTraits::Constructor Constructor;
  175. typedef typename Constructor::ConstructableType ConstructableType;
  176. XalanDeque(
  177. MemoryManager& memoryManager,
  178. size_type initialSize = 0,
  179. size_type blockSize = 10) :
  180. m_memoryManager(&memoryManager),
  181. m_blockSize(blockSize),
  182. m_blockIndex(memoryManager,
  183. initialSize / blockSize + (initialSize % blockSize == 0 ? 0 : 1)),
  184. m_freeBlockVector(memoryManager)
  185. {
  186. const ConstructableType defaultValue(*m_memoryManager);
  187. using std::fill_n;
  188. using std::back_inserter;
  189. fill_n(
  190. back_inserter(*this),
  191. initialSize,
  192. defaultValue.value);
  193. }
  194. XalanDeque(
  195. const XalanDeque& theRHS,
  196. MemoryManager& theMemoryManager) :
  197. m_memoryManager(&theMemoryManager),
  198. m_blockSize(theRHS.m_blockSize),
  199. m_blockIndex(*theRHS.m_memoryManager,
  200. theRHS.size() / theRHS.m_blockSize + (theRHS.size() % theRHS.m_blockSize == 0 ? 0 : 1)),
  201. m_freeBlockVector(theMemoryManager)
  202. {
  203. using std::copy;
  204. using std::back_inserter;
  205. copy(
  206. theRHS.begin(),
  207. theRHS.end(),
  208. back_inserter(*this));
  209. }
  210. static XalanDeque*
  211. create(
  212. MemoryManager& theManager,
  213. size_type initialSize = 0,
  214. size_type blockSize = 10)
  215. {
  216. XalanAllocationGuard theGuard(theManager, theManager.allocate(sizeof(ThisType)));
  217. ThisType* const theResult =
  218. new (theGuard.get()) ThisType(theManager, initialSize, blockSize);
  219. theGuard.release();
  220. return theResult;
  221. }
  222. ~XalanDeque()
  223. {
  224. destroyBlockList(m_freeBlockVector);
  225. destroyBlockList(m_blockIndex);
  226. }
  227. iterator
  228. begin()
  229. {
  230. return iterator(this, 0);
  231. }
  232. const_iterator
  233. begin() const
  234. {
  235. return const_iterator(const_cast<XalanDeque*>(this), 0);
  236. }
  237. iterator
  238. end()
  239. {
  240. return iterator(this, size());
  241. }
  242. const_iterator
  243. end() const
  244. {
  245. return const_iterator(const_cast<XalanDeque*>(this), size());
  246. }
  247. const_reverse_iterator
  248. rbegin() const
  249. {
  250. return const_reverse_iterator(end());
  251. }
  252. const_reverse_iterator
  253. rend() const
  254. {
  255. return const_reverse_iterator(begin());
  256. }
  257. bool
  258. empty() const
  259. {
  260. return m_blockIndex.empty();
  261. }
  262. size_type
  263. size() const
  264. {
  265. if (m_blockIndex.empty())
  266. {
  267. return 0;
  268. }
  269. else
  270. {
  271. return (m_blockIndex.size() - 1) * m_blockSize
  272. + m_blockIndex.back()->size();
  273. }
  274. }
  275. value_type&
  276. back()
  277. {
  278. return m_blockIndex.back()->back();
  279. }
  280. value_type&
  281. operator[](size_type index)
  282. {
  283. BlockType& block = *m_blockIndex[index / m_blockSize];
  284. return block[index % m_blockSize];
  285. }
  286. const value_type&
  287. operator[](size_type index) const
  288. {
  289. BlockType& block = *m_blockIndex[index / m_blockSize];
  290. return block[index % m_blockSize];
  291. }
  292. void
  293. clear()
  294. {
  295. typename BlockIndexType::iterator iter = m_blockIndex.begin();
  296. m_freeBlockVector.reserve(m_freeBlockVector.size() + m_blockIndex.size());
  297. while (iter != m_blockIndex.end())
  298. {
  299. (*iter)->clear();
  300. m_freeBlockVector.push_back(*iter);
  301. ++iter;
  302. }
  303. m_blockIndex.clear();
  304. }
  305. void
  306. push_back(const value_type& value)
  307. {
  308. if (m_blockIndex.empty() ||
  309. m_blockIndex.back()->size() >= m_blockSize)
  310. {
  311. pushNewIndexBlock();
  312. }
  313. m_blockIndex.back()->push_back(value);
  314. }
  315. void
  316. pop_back()
  317. {
  318. assert(!empty());
  319. BlockType& lastBlock = *m_blockIndex.back();
  320. lastBlock.pop_back();
  321. if (lastBlock.empty())
  322. {
  323. m_freeBlockVector.push_back(&lastBlock);
  324. m_blockIndex.pop_back();
  325. }
  326. }
  327. void
  328. resize(size_type newSize)
  329. {
  330. const ConstructableType defaultValue(*m_memoryManager);
  331. if (newSize > size())
  332. {
  333. for (size_type i = 0; i < newSize - size(); ++i)
  334. {
  335. push_back(defaultValue.value);
  336. }
  337. }
  338. else
  339. {
  340. for (size_type i = 0; i < size() - newSize; ++i)
  341. {
  342. pop_back();
  343. }
  344. }
  345. }
  346. void
  347. swap(XalanDeque& theRHS)
  348. {
  349. MemoryManager* const temp = m_memoryManager;
  350. m_memoryManager = theRHS.m_memoryManager;
  351. theRHS.m_memoryManager = temp;
  352. theRHS.m_blockIndex.swap(m_blockIndex);
  353. theRHS.m_freeBlockVector.swap(m_freeBlockVector);
  354. }
  355. XalanDeque&
  356. operator=(const XalanDeque& theRHS)
  357. {
  358. if (this != &theRHS)
  359. {
  360. using std::copy;
  361. using std::back_inserter;
  362. clear();
  363. copy(
  364. theRHS.begin(),
  365. theRHS.end(),
  366. back_inserter(*this));
  367. }
  368. return *this;
  369. }
  370. MemoryManager&
  371. getMemoryManager()
  372. {
  373. assert (m_memoryManager != 0);
  374. return *m_memoryManager;
  375. }
  376. private:
  377. void
  378. pushNewIndexBlock()
  379. {
  380. // Allocate space first, so we don't have to worry
  381. // about an out-of-memory error once we've constructed
  382. // the new block.
  383. m_blockIndex.push_back(0);
  384. if (m_freeBlockVector.empty())
  385. {
  386. XalanConstruct(
  387. *m_memoryManager,
  388. m_blockIndex.back(),
  389. *m_memoryManager,
  390. m_blockSize);
  391. }
  392. else
  393. {
  394. m_blockIndex.back() = m_freeBlockVector.back();
  395. // Now that ownership has been transfered, pop
  396. // it off the free list.
  397. m_freeBlockVector.pop_back();
  398. }
  399. assert(m_blockIndex.back() != 0);
  400. }
  401. void
  402. destroyBlockList(BlockIndexType& theBlockIndex)
  403. {
  404. typename BlockIndexType::iterator iter =
  405. theBlockIndex.begin();
  406. while (iter != theBlockIndex.end())
  407. {
  408. // Normally, we should be able to just call
  409. // the version of XalanDestroy() that accepts
  410. // a pointer, but Visual Studio 6 has issues
  411. // with partial ordering, so we're stuck with
  412. // this for now.
  413. if (*iter != 0)
  414. {
  415. XalanDestroy(*m_memoryManager, **iter);
  416. }
  417. ++iter;
  418. }
  419. }
  420. MemoryManager* m_memoryManager;
  421. const size_type m_blockSize;
  422. BlockIndexType m_blockIndex;
  423. BlockIndexType m_freeBlockVector;
  424. // These are not implemented
  425. XalanDeque();
  426. XalanDeque(const XalanDeque&);
  427. };
  428. }
  429. #endif // XALANDEQUE_HEADER_GUARD_1357924680