3 #include <utils/messageException.h>
4 #include <memory/memoryStructure.h>
12 template <
typename T>
class TapeObserver;
13 template <
typename T>
class TapeModifier;
86 constexpr
Tape(
const T& blank);
125 constexpr
void left();
135 constexpr
void right();
154 [[nodiscard]] constexpr
const T&
read()
const;
161 constexpr
void write(
const T& symbol);
167 constexpr
void erase();
176 template<
typename CharT =
char,
typename Trait = std::
char_traits<CharT>>
177 friend std::basic_ostream<CharT, Trait>&
operator<<(std::basic_ostream<CharT, Trait>& os,
const Movement& movement) {
182 os <<
"RIGHT";
break;
192 constexpr
void allocateLeft();
193 constexpr
void allocateRight();
194 constexpr
void allocate();
195 constexpr
void allocateLeft(
size_t);
196 constexpr
void allocateRight(
size_t);
197 constexpr
void allocate(
size_t);
198 void setSizeFactor(
size_t);
199 constexpr
void shrink();
200 constexpr
void shrink(std::vector<T>&,
size_t);
205 std::vector<T>* currentTape;
209 size_t sizeFactor = 2;
213 template <
typename T>
216 currentTape(&rightTape)
219 template <
typename T>
222 currentTape(&rightTape)
225 template <
typename T>
228 leftTape(other.leftTape),
229 rightTape(other.rightTape),
230 currentTape(other.currentTape),
231 position(other.position),
232 onRight(other.onRight),
233 sizeFactor(other.sizeFactor)
236 template <
typename T>
238 blank(std::move(other.blank)),
239 leftTape(std::move(other.leftTape)),
240 rightTape(std::move(other.rightTape)),
241 currentTape(other.onRight ? &leftTape : &rightTape),
242 position(std::move(other.position)),
243 onRight(std::move(other.onRight)),
244 sizeFactor(std::move(other.sizeFactor))
247 template <
typename T>
252 leftTape = other.leftTape;
253 rightTape = other.rightTape;
254 currentTape = other.currentTape;
255 position = other.position;
256 onRight = other.onRight;
257 sizeFactor = other.sizeFactor;
262 template <
typename T>
266 blank = std::move(other.blank);
267 leftTape = std::move(other.leftTape);
268 rightTape = std::move(other.rightTape);
269 currentTape = other.onRight ? &leftTape : &rightTape;
270 position = std::move(other.position);
271 onRight = std::move(other.onRight);
272 sizeFactor = std::move(other.sizeFactor);
278 template <
typename T>
287 currentTape = &leftTape;
292 if(position >= leftTape.size()) {
298 template <
typename T>
301 leftTape.resize(leftTape.size()*sizeFactor, blank);
304 template <
typename T>
305 constexpr
void Tape<T>::allocateLeft(
size_t e)
307 leftTape.resize(leftTape.size() + e, blank);
310 template <
typename T>
315 if(position >= rightTape.size()) {
325 currentTape = &rightTape;
330 template <
typename T>
333 rightTape.resize(rightTape.size()*sizeFactor, blank);
336 template <
typename T>
337 constexpr
void Tape<T>::allocateRight(
size_t e)
339 rightTape.resize(rightTape.size() + e, blank);
342 template <
typename T>
350 case Movement::RIGHT:
359 template <
typename T>
366 template <
typename T>
367 constexpr
void Tape<T>::allocate(
size_t e)
373 template <
typename T>
376 return (*currentTape)[position];
379 template <
typename T>
382 (*currentTape)[position] = e;
385 template <
typename T>
388 (*currentTape)[position] = blank;
391 template <
typename T>
395 throw InvalidFactorException(
"Size factor is too small in Tape<T>::setSizeFactor(size_t). Must be > 1.", e);
400 template <
typename T>
401 constexpr
void Tape<T>::shrink()
403 shrink(leftTape, onRight ? 0 : position);
404 shrink(rightTape, onRight ? position : 0);
407 template <
typename T>
410 size_t idxOfLastNonBlank = tape.size()-1;
412 for(; idxOfLastNonBlank > MinAllocatedTapeSize-1 && tape[idxOfLastNonBlank] == blank; --idxOfLastNonBlank){
415 tape.resize(std::max(idxOfLastNonBlank, inf) + 1);
425 template <
typename T>
446 [[nodiscard]] constexpr
size_t getRightSize()
const {
return this->memory->rightTape.size(); }
455 [[nodiscard]] constexpr
size_t getLeftSize()
const {
return this->memory->leftTape.size(); }
464 [[nodiscard]] constexpr
const std::vector<T>&
getRightTape()
const {
return this->memory->rightTape; }
473 [[nodiscard]] constexpr
const std::vector<T>&
getLeftTape()
const {
return this->memory->leftTape; }
478 [[nodiscard]] constexpr
const std::vector<T>*
getCurrentTape()
const {
return this->memory->currentTape; }
488 [[nodiscard]] constexpr
size_t getSizeFactor()
const {
return this->memory->sizeFactor; }
495 [[nodiscard]] constexpr
const T&
getBlank()
const {
return this->memory->blank; }
502 [[nodiscard]] constexpr
bool isOnRight()
const {
return this->memory->onRight; }
519 [[nodiscard]] constexpr
long long int getPosition()
const {
return this->memory->onRight ?
520 static_cast<long long int>(this->memory->position) :
521 -
static_cast<long long int>(this->memory->position)-1; }
529 [[nodiscard]] constexpr
const T&
operator[](
long long int position)
const {
531 typename std::vector<T>::size_type i =
static_cast<typename std::vector<T>::size_type
>(position);
532 if (i < this->memory->rightTape.size()) {
533 return this->memory->rightTape[i];
535 return this->memory->blank;
537 typename std::vector<T>::size_type i =
static_cast<typename std::vector<T>::size_type
>(-position - 1);
538 if (i < this->memory->leftTape.size()) {
539 return this->memory->leftTape[i];
541 return this->memory->blank;
557 template <
typename T>
591 constexpr
void allocate()
const { this->memory->allocate(); }
599 constexpr
void allocateRight(
size_t additionalSize)
const { this->memory->allocateRight(additionalSize); }
607 constexpr
void allocateLeft(
size_t additionalSize)
const { this->memory->allocateLeft(additionalSize); }
616 constexpr
void allocate(
size_t additionalSize)
const { this->memory->allocate(additionalSize); }
624 constexpr
void shrink()
const { this->memory->shrink(); }
632 constexpr
void setSizeFactor(
size_t newSizeFactor)
const { this->memory->setSizeFactor(newSizeFactor); }
639 size_t position_u =
static_cast<size_t>(position);
640 this->memory->position = position_u;
641 this->memory->onRight =
true;
642 size_t rSize = this->memory->rightTape.size();
643 if(position_u >= rSize) {
644 this->memory->allocateRight(position_u - rSize + 1);
646 this->memory->currentTape = &this->memory->rightTape;
649 size_t position_u =
static_cast<size_t>(- position - 1);
650 this->memory->position = position_u;
651 this->memory->onRight =
false;
652 size_t lSize = this->memory->leftTape.size();
653 if(position_u >= lSize) {
654 this->memory->allocateLeft(position_u - lSize + 1);
656 this->memory->currentTape = &this->memory->leftTape;
668 typename std::vector<T>::size_type i =
static_cast<typename std::vector<T>::size_type
>(position);
669 size_t rSize = this->memory->rightTape.size();
671 this->memory->allocateRight(i - rSize + 1);
673 return this->memory->rightTape[i];
676 typename std::vector<T>::size_type i =
static_cast<typename std::vector<T>::size_type
>(- position - 1);
677 size_t lSize = this->memory->leftTape.size();
679 this->memory->allocateRight(i - lSize + 1);
681 return this->memory->leftTape[i];