6 #ifndef CNOID_UTIL_DEQUE_2D_H
7 #define CNOID_UTIL_DEQUE_2D_H
14 template <
typename ElementType,
typename Allocator = std::allocator<ElementType>>
23 class const_iterator :
public std::iterator<std::random_access_iterator_tag, ElementType> {
25 friend class Deque2D<ElementType, Allocator>;
139 return iterator(*
this, buf + offset);
143 return const_iterator(*
this, buf + offset);
165 size_ = owner.colSize_;
167 if(owner.capacity_ > 0){
168 top += (owner.offset + rowIndex * owner.colSize_) % owner.capacity_;
211 offset = owner.offset;
212 colSize = owner.colSize_;
213 capacity = owner.capacity_;
214 rowSize = owner.rowSize_;
215 end_ =
iterator(*
this, top + ((owner.capacity_ > 0) ? ((offset + owner.size_) % owner.capacity_) : 0));
219 return (rowSize == 0);
227 return top[(offset + rowIndex * colSize) % capacity];
231 return top[(offset + rowIndex * colSize) % capacity];
235 return top[index * colSize];
238 class iterator :
public std::iterator<std::bidirectional_iterator_tag, ElementType, int> {
240 ElementType* current;
252 term = top +
column.capacity;
266 current = term - colSize;
272 return (current == rhs.current);
275 return (current != rhs.current);
280 return iterator(*
this, top + offset);
317 : allocator(org.allocator) {
320 rowSize_ = org.rowSize_;
321 colSize_ = org.colSize_;
322 capacity_ = size_ + colSize_;
326 buf = allocator.allocate(capacity_);
328 ElementType* p = buf;
329 ElementType* pend = buf + size_;
330 ElementType* q = org.buf + org.offset;
331 ElementType* qterm = org.buf + org.capacity_;
333 allocator.construct(p++, *q++);
339 end_ = iterator(*
this, buf + ((capacity_ > 0) ? ((offset + size_) % capacity_) : 0));
344 resizeMain(rhs.rowSize_, rhs.colSize_,
false);
345 iterator p =
begin();
346 const_iterator q = rhs.
cbegin();
347 const_iterator qend = rhs.
cend();
359 ElementType* p = buf + offset;
360 const ElementType* pend = buf + (offset + size_) % capacity_;
364 allocator.destroy(p++);
367 for(ElementType* q = buf; q != pend; ++q){
368 allocator.destroy(q);
370 const ElementType* pterm = buf + capacity_;
371 for(ElementType* q = p; q != pterm; ++q){
372 allocator.destroy(q);
375 allocator.deallocate(buf, capacity_);
380 return !rowSize_ || !colSize_;
384 void reallocMemory(
int newColSize,
int newSize,
int newCapacity,
bool doCopy) {
388 newBuf = allocator.allocate(newCapacity);
392 ElementType* p = newBuf;
393 ElementType* pend = newBuf + newSize;
396 ElementType* qend = buf + (offset + size_) % capacity_;
399 if(newCapacity > 0 && newColSize == colSize_ && doCopy){
400 ElementType* q = buf + offset;
402 while(q != qend && p != pend){
403 allocator.construct(p++, *q++);
406 for(ElementType* r = buf; r != qend && p != pend; ++r){
407 allocator.construct(p++, *r);
409 ElementType* qterm = buf + capacity_;
410 for(ElementType* r = q; r != qterm && p != pend; ++r){
411 allocator.construct(p++, *r);
416 ElementType* q = buf + offset;
419 allocator.destroy(q++);
422 for(ElementType* r = buf; r != qend; ++r){
423 allocator.destroy(r);
425 ElementType* qterm = buf + capacity_;
426 for(ElementType* r = q; r != qterm; ++r){
427 allocator.destroy(r);
434 allocator.construct(p++, ElementType());
438 allocator.deallocate(buf, capacity_);
441 capacity_ = newCapacity;
445 void resizeMain(
int newRowSize,
int newColSize,
bool doCopy) {
447 const int newSize = newRowSize * newColSize;
450 reallocMemory(newColSize, newSize, 0,
false);
454 const int minCapacity = newSize + newColSize;
456 if(capacity_ > 0 && minCapacity <= capacity_){
457 if(newColSize != colSize_ && (capacity_ % newColSize > 0)){
458 reallocMemory(newColSize, newSize, capacity_ - (capacity_ % newColSize), doCopy);
460 }
else if(newSize > size_){
461 ElementType* p = buf + (offset + size_) % capacity_;
462 const ElementType* pend = buf + (offset + newSize) % capacity_;
465 allocator.construct(p++, ElementType());
468 for(ElementType* r = buf; r != pend; ++r){
469 allocator.construct(r, ElementType());
471 const ElementType* pterm = buf + capacity_;
472 for(ElementType* r = p; r != pterm; ++r){
473 allocator.construct(r, ElementType());
476 }
else if(newSize < size_){
477 ElementType* p = buf + (offset + newSize) % capacity_;
478 ElementType* pend = buf + (offset + size_) % capacity_;
481 allocator.destroy(p++);
484 for(ElementType* r = buf; r != pend; ++r){
485 allocator.destroy(r);
487 const ElementType* pterm = buf + capacity_;
488 for(ElementType* r = p; r != pterm; ++r){
489 allocator.destroy(r);
495 capacity_ = minCapacity;
497 buf = allocator.allocate(minCapacity);
498 ElementType* p = buf;
499 ElementType* pend = buf + newSize;
502 allocator.construct(p++, ElementType());
507 const int expandedSize = size_ * 3 / 2;
508 if(expandedSize > newSize){
509 newCapacity = expandedSize - (expandedSize % newColSize) + newColSize;
511 newCapacity = minCapacity;
513 reallocMemory(newColSize, newSize, newCapacity, doCopy);
518 rowSize_ = newRowSize;
519 colSize_ = newColSize;
521 end_ = iterator(*
this, buf + ((capacity_ > 0) ? ((offset + size_) % capacity_) : 0));
525 void resize(
int newRowSize,
int newColSize) {
526 resizeMain(newRowSize, newColSize,
true);
530 resize(rowSize_, newColSize);
541 resize(newRowSize, colSize_);
553 return buf[(offset + (rowIndex * colSize_)) % capacity_ + colIndex];
557 return buf[(offset + (rowIndex * colSize_)) % capacity_ + colIndex];
561 return buf[(offset + (rowIndex * colSize_)) % capacity_ + colIndex];
565 return buf[(offset + (rowIndex * colSize_)) % capacity_ + colIndex];
569 return Row(*
this, rowIndex);
573 return Row(*
this, rowIndex);
577 return Row(*
this, rowIndex);
580 const Row
row(
int rowIndex)
const {
581 return Row(*
this, rowIndex);
585 return Row(*
this, rowSize_ - 1);
589 return Row(*
this, rowSize_ - 1);
593 return Column(*
this, colIndex);
596 const Column
column(
int colIndex)
const {
597 return Column(*
this, colIndex);
601 resize(rowSize_ + 1, colSize_);
602 return Row(*
this, rowSize_ - 1);
606 resize(rowSize_ - 1, colSize_);
613 if(numRows > rowSize_){
616 const size_t popSize = numRows * colSize_;
617 ElementType* p = buf + offset;
618 const ElementType* pend = buf + (offset + popSize) % capacity_;
622 allocator.destroy(p++);
625 for(ElementType* r = buf; r != pend; ++r){
626 allocator.destroy(r);
628 const ElementType* pterm = buf + capacity_;
629 for(ElementType* r = p; r != pterm; ++r){
630 allocator.destroy(r);
633 offset = (offset + popSize) % capacity_;