From b7560534c1d89afe82ddaa304a7303b04d972265 Mon Sep 17 00:00:00 2001 From: IlushaShurupov Date: Sat, 15 Jul 2023 10:03:16 +0300 Subject: [PATCH] Removing TextEditor from strings for now --- Containers/public/Buffer.hpp | 6 + Strings/private/Logging.cpp | 19 +- Strings/private/TextEditor.cpp | 554 --------------------------------- Strings/public/Logging.hpp | 2 +- Strings/public/StringLogic.hpp | 19 ++ Strings/public/Strings.hpp | 132 +++----- Strings/public/TextEditor.hpp | 382 ----------------------- 7 files changed, 65 insertions(+), 1049 deletions(-) delete mode 100644 Strings/private/TextEditor.cpp delete mode 100644 Strings/public/TextEditor.hpp diff --git a/Containers/public/Buffer.hpp b/Containers/public/Buffer.hpp index 1c9d3bf..3a62be5 100644 --- a/Containers/public/Buffer.hpp +++ b/Containers/public/Buffer.hpp @@ -175,6 +175,12 @@ namespace tp { if (prevSize > mLoad) resizeBuffer(prevSize); } + void reserve(ualni aSize) { + for (ualni i = 0; i < mLoad; i++) mBuff[i].~tType(); + mBuff = (tType*) mAllocator.allocate(sizeof(tType) * aSize); + mSize = aSize; + mLoad = 0; + } private: void resizeBuffer(ualni newSize) { diff --git a/Strings/private/Logging.cpp b/Strings/private/Logging.cpp index 443de68..17c3c21 100644 --- a/Strings/private/Logging.cpp +++ b/Strings/private/Logging.cpp @@ -1,7 +1,6 @@ #include "Logging.hpp" #include "Allocators.hpp" -#include "TextEditor.hpp" #include @@ -18,8 +17,7 @@ namespace tp { } void Logger::Report::calcLineCount() { - Input input = { mData.raw(), (ualni) mData.size() }; - input.getLineOffsets(mLineOffsets); + mData.calcLineOffsets(mLineOffsets); } Logger::Report::Report() { @@ -35,19 +33,10 @@ namespace tp { } void Logger::write(const String& in, bool post, Report::Type type) { - StringTemplate copy = in; - copy.capture(); - mBuff.pushBack(Report(copy, type)); - + mBuff.pushBack(Report(in, type)); mLineCount += mBuff.last()->data.getLineCount(); - - if (!mCursor) { - mCursor = mBuff.last(); - } - - if (post) { - printf("%s", in.raw()); - } + if (!mCursor) mCursor = mBuff.last(); + if (post) printf("%s", in.read()); } String Logger::read() { diff --git a/Strings/private/TextEditor.cpp b/Strings/private/TextEditor.cpp deleted file mode 100644 index 1493f76..0000000 --- a/Strings/private/TextEditor.cpp +++ /dev/null @@ -1,554 +0,0 @@ - -#include "TextEditor.hpp" - -using namespace tp; -using namespace str; - -bool tp::str::PiecesDS::Node::mInsertionOperation = false; - -bool tp::str::isNewLineChar(Char character) { - return (character == '\n') || (character == '\r'); -} - -void Input::getLineOffsets(Buffer& out) { - halni lines = 0; - for (auto idx : Range(mLen)) { - if (isNewLineChar(mInput[idx])) { - lines++; - } - } - out.reserve(lines + 2); // plust start and end offsets - lines = 0; - for (auto idx : Range(mLen)) { - if (isNewLineChar(mInput[idx])) { - out[lines + 1] = Index(idx + 1); - lines++; - } - } - out[0] = 0; - out[lines + 1] = mLen; -} - - // ---------------------- Pointer ---------------------- // - -Pointer::Pointer() { - mCol = 0; mLine = 0; -} - -Pointer::Pointer(LineId aLine, ColumnId aCol) { - mLine = aLine; - mCol = aCol; -} - -Pointer::Pointer(const Input& aInput) { - halni lines = 0; - halni col = 0; - for (auto idx : Range(aInput.mLen)) { - if (isNewLineChar(aInput.mInput[idx])) { - lines++; - col = 0; - } - else { - col++; - } - } - mLine = lines; - mCol = col; -} - -void Pointer::operator+=(Char achar) { - if (isNewLineChar(achar)) { - mLine += 1; - mCol = 0; - } - else { - mCol += 1; - } -} - -void Pointer::operator+=(const Pointer& ap) { - *this = operator+(ap); -} - -Pointer Pointer::operator-(const Pointer in) const { - if (mLine == in.mLine) { - return { 0, mCol - in.mCol }; - } - return { mLine - in.mLine, mCol }; -} - -Pointer Pointer::operator+(const Pointer& ap) const { - if (ap.mLine == 0) { - return { mLine, mCol + ap.mCol }; - } - return { mLine + ap.mLine, ap.mCol }; -} - -bool Pointer::operator==(const Pointer& in) const { - return in.mCol == mCol && in.mLine == mLine; -} - -bool Pointer::operator>(const Pointer& in) const { - if (mLine > in.mLine) { - return true; - } - else if (mLine < in.mLine) { - return false; - } - - return mCol > in.mCol; -} - -bool Pointer::operator>=(const Pointer& in) const { - return operator>(in) || in == *this; -} - -Pointer Piece::diffPtr() const { - return mEnd - mStart; -} - -LineId Piece::nLines() const { - return { mEnd.mLine - mStart.mLine }; -} - -// ---------------------- Add Buff ---------------------- // - -AddBuff::AddBuff() { - Input input = { "", 0 }; - Buffer lineoffsets; - input.getLineOffsets(lineoffsets); - mLineOffsets.append(lineoffsets.mBuff(), (Index)lineoffsets.length()); -} - -void AddBuff::append(Input aInput) { - - // TODO : errors here - - Buffer lineoffsets; - aInput.getLineOffsets(lineoffsets); - - if (lineoffsets.length() == 2) { - mLineOffsets[mLineOffsets.len() - 1] += lineoffsets[1] - lineoffsets[0]; - } - else { - - auto last_line_offset = mLineOffsets[mLineOffsets.len() - 1]; - - // offset last line ptr - mLineOffsets[mLineOffsets.len() - 1] += lineoffsets[1]; - - // offset all lines by mLineOffsets.mLast ptr - for (auto offset : lineoffsets) { - offset.data() += last_line_offset; - } - - mLineOffsets.append(&lineoffsets[2], (Index)(lineoffsets.length() - 2)); - } - - mBuff.append(aInput.mInput, aInput.mLen); -} - -Pointer AddBuff::endPtr() { - return { mLineOffsets.len() - 2, mLineOffsets[mLineOffsets.len() - 1] - mLineOffsets[mLineOffsets.len() - 2] }; -} - -// ---------------------- Orig Buff ---------------------- // - -OrigBuff::OrigBuff(Input aOriginal) { - mOriginal = aOriginal; - mOriginal.getLineOffsets(mLineOffsets); - - mPtrStart = { 0, 0 }; - mPtrEnd = mOriginal; -} - -void OrigBuff::makeOwnOriginalInput() { - if (mOwnsInput) { - return; - } - - auto input_copy = new Char[mOriginal.mLen + 1]; - DEBUG_ASSERT(sizeof(Char) == sizeof(uint1)); - memcp(input_copy, mOriginal.mInput, mOriginal.mLen); - input_copy[mOriginal.mLen] = '\0'; - mOriginal.mInput = input_copy; - mOwnsInput = true; -} - -OrigBuff::~OrigBuff() { - if (mOwnsInput) { - delete[] mOriginal.mInput; - } -} - -// ---------------------- Editor ---------------------- // - -PieceCrs TextEditor::findPiece(Pointer ptr) const { - PieceCrs out; - if (!mPieces.nPieces()) { - return out; - } - - if (mPieces.ptrSum() == ptr) { - out.piece = mPieces.maxNode(mPieces.head()); - } else { - out.piece = mPieces.find(ptr); - } - - DBG_BREAK(!out.piece); - out.piece_ptr = out.piece->getFindKey(); - out.ptr = ptr; - out.offset = out.ptr - out.piece_ptr; - return out; -} - -void TextEditor::clampPtr(Pointer& ptr) const { - if (!mPieces.nPieces()) { - ptr = { 0, 0 }; - return; - } - - CLAMP(ptr.mLine, 0, mNLines()); - - auto crs = findPiece(Pointer{ ptr.mLine, 0 }); - Index line_len = getPieceLineLen(crs.piece->mPiece, crs.offset.mLine); - - auto next_piece_ptr = nextPiecePtr(crs.piece, crs.piece_ptr); - auto piece = crs.piece; - while (piece->mNext && ptr.mLine == next_piece_ptr.mLine) { - piece = piece->mNext; - next_piece_ptr = nextPiecePtr(piece, next_piece_ptr); - line_len += getPieceLineLen(piece->mPiece, 0); - } - - if (ptr.mLine != mNLines()) { - line_len -= 1; - } - - CLAMP(ptr.mCol, 0, line_len); -} - -void TextEditor::setCursor(Pointer ptr) { - clampPtr(ptr); - mCursor = ptr; -} - -void TextEditor::setCursorEnd(Pointer ptr) { - clampPtr(ptr); - mCursorEnd = ptr; - mCursor = mCursorEnd; -} - -const Char* TextEditor::getPieceLine(const Piece* piece, LineId offset) const { - const Char* buff; - if (piece->mAddedBuff) { - if (offset == 0) { - buff = &mAddBuff.mBuff[mAddBuff.mLineOffsets[piece->mStart.mLine]] + piece->mStart.mCol; - } - else if (offset > piece->nLines()) { - buff = &mAddBuff.mBuff[mAddBuff.mLineOffsets[piece->mEnd.mLine]] + piece->mEnd.mCol; - } - else { - buff = &mAddBuff.mBuff[mAddBuff.mLineOffsets[piece->mStart.mLine + offset]]; - } - } - else { - if (offset == 0) { - buff = &mOrigBuff.mOriginal.mInput[mOrigBuff.mLineOffsets[piece->mStart.mLine]] + piece->mStart.mCol; - } - else if (offset > piece->nLines()) { - buff = &mOrigBuff.mOriginal.mInput[mOrigBuff.mLineOffsets[piece->mEnd.mLine]] + piece->mEnd.mCol; - } - else { - buff = &mOrigBuff.mOriginal.mInput[mOrigBuff.mLineOffsets[piece->mStart.mLine + offset]]; - } - } - return buff; -} - -const Char* TextEditor::getBuffLine(const Piece* piece, LineId offset) const { - const Char* buff; - if (piece->mAddedBuff) { - buff = &mAddBuff.mBuff[mAddBuff.mLineOffsets[piece->mStart.mLine + offset]]; - } - else { - buff = &mOrigBuff.mOriginal.mInput[mOrigBuff.mLineOffsets[piece->mStart.mLine + offset]]; - } - return buff; -} - -Pointer TextEditor::prevPiecePtr(PiecesDS::Node* piece_node, Pointer aPtr) const { - if (!piece_node->mPrev) { - return { 0, 0 }; - } - - return piece_node->mPrev->getFindKey(); -} - -Pointer TextEditor::nextPiecePtr(PiecesDS::Node* aPiece, Pointer aPtr) const { - if (!aPiece) return { -1, -1 }; - - if (aPiece->mNext) { - return aPiece->mNext->getFindKey(); - } - return aPiece->getFindKey() + aPiece->mDiff; -} - -LineId TextEditor::getPieceLineLen(Piece* aPiece, LineId line) const { - return LineId(getPieceLine(aPiece, line + 1) - getPieceLine(aPiece, line)); -} - -TextEditor::TextEditor(Input original) : mOrigBuff(original) { - DEBUG_ASSERT(original.mLen); - auto new_node = mPieces.insertAfter(0, { false, mOrigBuff.mPtrStart, mOrigBuff.mPtrEnd }); - mPieces.pushUndoPoint(); -} - -TextEditor::TextEditor() : mOrigBuff({ 0, 0 }) { -} - -Index TextEditor::mNLines() const { - return mPieces.ptrSum().mLine; -} - -Pointer TextEditor::getCursor() const { - return mCursor; -} - -Pointer TextEditor::getCursorEnd() const { - return mCursorEnd; -} - -void TextEditor::insert(Input aInput) { - // handle selectiom - remove(true); - - // save input to addbuff - auto start_ref = mAddBuff.endPtr(); - mAddBuff.append(aInput); - auto end_ref = mAddBuff.endPtr(); - auto input_diff = end_ref - start_ref; - - PiecesDS::Node* prev_node = nullptr; - PiecesDS::Node* new_node = nullptr; - - auto crs = findPiece(mCursor); - - if (crs.piece && crs.piece->mPrev && crs.offset == Pointer{ 0, 0 }) { - crs.piece_ptr = prevPiecePtr(crs.piece, crs.piece_ptr); - crs.offset = crs.ptr - crs.piece_ptr; - crs.piece = crs.piece->mPrev; - } - - if (crs.piece) { - if (crs.ptr == crs.piece_ptr) { // start - prev_node = crs.piece->mPrev; - } - else if (crs.offset == crs.piece->mPiece->diffPtr()) { // end - if (mLastInsertionCrs == crs.ptr && crs.piece->mPiece->mAddedBuff && crs.piece->mPiece->mEnd == start_ref) { - crs.piece->mPiece->mEnd += input_diff; - mPieces.update_cache(crs.piece); - goto END; - } - else { - prev_node = crs.piece; - } - } - else { // middle - prev_node = splitPiece(crs.piece, crs.offset); - } - } - - // create the new node - new_node = mPieces.insertAfter(prev_node, { true, start_ref, end_ref }); - - END: - mCursor = mCursor + input_diff; - mCursorEnd = mCursor; - mLastInsertionCrs = mCursor; - mPieces.pushUndoPoint(); -} - -PiecesDS::Node* TextEditor::splitPiece(PiecesDS::Node* piece, Pointer split_ptr) { - auto span = piece->mPiece->diffPtr(); - - if (span == split_ptr || split_ptr == Pointer{ 0, 0 }) { - return nullptr; - } - - // save temp data - auto end_ptr = piece->mPiece->mEnd; - auto left_piece = Piece{ piece->mPiece->mAddedBuff, piece->mPiece->mStart, piece->mPiece->mStart + split_ptr }; - auto left_node = mPieces.insertAfter(piece->mPrev, left_piece); - - // create right half - auto right_node = mPieces.insertAfter(left_node, { left_node->mPiece->mAddedBuff, left_node->mPiece->mEnd, end_ptr }); - - auto line_len = halni(getBuffLine(right_node->mPiece, 1) - getBuffLine(right_node->mPiece, 0)); - if (line_len == right_node->mPiece->mStart.mCol) { - DBG_BREAK(1); - right_node->mPiece->mStart = { right_node->mPiece->mStart.mLine + 1, 0 }; - } - - // remove current node - mPieces.remove(right_node->mNext); - - return left_node; -} - -void TextEditor::remove(bool only_selection, Dir dir, DirUnit unit) { - if (!mPieces.nPieces()) { - return; - } - - if (mCursor == mCursorEnd) { - if (only_selection) { - return; - } - - if (dir == LEFT) { - if (mCursor == Pointer(0, 0)) { - return; - } - - PieceCrs crs; - if (mCursor.mCol == nullptr) { - auto new_ptr = Pointer{ mCursor.mLine - 1, ENV_HALNI_MAX }; - clampPtr(new_ptr); - crs = findPiece(new_ptr); - //crs = findPiece({ crs.ptr.mLine, crs.ptr.mCol - 1 }); - } - else { - crs = findPiece({ mCursor.mLine, mCursor.mCol - 1 }); - } - - mCursorEnd = mCursor; - mCursor = crs.ptr; - } - else if (dir == RIGHT) { - auto crs = findPiece(Pointer{ mCursor.mLine, mCursor.mCol + 1 }); - mCursorEnd = mCursor; - mCursor = crs.ptr; - - if (mCursor == mCursorEnd) { - return; - } - } - else { - return; - } - } - - if (mCursor > mCursorEnd) { - swap(mCursor, mCursorEnd); - } - - auto crs = findPiece(mCursor); - - // first and last pieces to be deleted - PiecesDS::Node* del_start = nullptr, *del_end = nullptr; - - // find left - if (crs.offset == Pointer{ 0, 0 }) { - del_start = crs.piece; - } - else if (crs.piece->mPiece->diffPtr() == crs.offset) { - del_start = crs.piece->mNext; - } - else { - del_start = splitPiece(crs.piece, crs.offset)->mNext; - } - - auto crs_end = findPiece(mCursorEnd); - - // find right - if (crs_end.offset == Pointer{ 0, 0 }) { - del_end = crs_end.piece->mPrev; - } - else if (crs_end.piece->mPiece->diffPtr() == crs_end.offset) { - del_end = crs_end.piece; - } - else { - bool intersect = crs_end.piece == del_start; - del_end = splitPiece(crs_end.piece, crs_end.offset); - if (intersect) { - del_start = del_end; - } - } - - DEBUG_ASSERT(del_start && del_end); - auto end_piece = del_end->mNext ? del_end->mNext->mPiece : nullptr; - - while (del_start && del_start->mPiece != end_piece) { - auto del = del_start; - - // del_start will be reused by the avl-tree after deletion otherwise - // works as we go from left to right - if (!del_start->mNext || del_start->mHeight <= del_start->mNext->mHeight) { - del_start = del_start->mNext; - } - - mPieces.remove(del); - } - mCursorEnd = mCursor; - - mPieces.pushUndoPoint(); -} - -void TextEditor::undo() { - mPieces.undo(); -} - -void TextEditor::redo() { - mPieces.redo(); -} - -TextEditor::~TextEditor() { -} - -// ------------------------------ ITERATOR ------------------------------ // - -Iterator TextEditor::begin() { return Iterator(this); } -alni TextEditor::end() { return nullptr; } - -Iterator::Iterator(const TextEditor* aSelf) { - mSelf = aSelf; - mNode = mSelf->mPieces.first(); - mVal = mSelf->getPieceLine(mNode->mPiece, 0)[0]; -} - -bool Iterator::inputLeft() { - return mNode; -} - -Char Iterator::character() { - return mVal; -} - -void Iterator::operator++() { - auto nl = isNewLineChar(mVal); - auto diff = Pointer{ nl, !nl }; - mPtr += diff; - mOffset += diff; - - if (mOffset == mNode->mPiece->diffPtr()) { - mNode = mNode->mNext; - mOffset = { 0, 0 }; - if (!mNode) { - return; - } - } - - mVal = mSelf->getPieceLine(mNode->mPiece, mOffset.mLine)[mOffset.mCol]; -} - -bool Iterator::operator!=(alni const& iter) { - return inputLeft(); -} - -bool Iterator::operator==(alni const& iter) { - return !inputLeft(); -} - -Char Iterator::operator->() { return mVal; } -const Iterator& Iterator::operator*() { return *this; } diff --git a/Strings/public/Logging.hpp b/Strings/public/Logging.hpp index 6616e72..dbe9977 100644 --- a/Strings/public/Logging.hpp +++ b/Strings/public/Logging.hpp @@ -12,7 +12,7 @@ namespace tp { class Report { String mData; - Buffer mLineOffsets; + Buffer mLineOffsets; public: enum Type { INFO, ERR, WARN, SUC } mType = INFO; diff --git a/Strings/public/StringLogic.hpp b/Strings/public/StringLogic.hpp index 488349a..84d6557 100644 --- a/Strings/public/StringLogic.hpp +++ b/Strings/public/StringLogic.hpp @@ -170,5 +170,24 @@ namespace tp { } return true; } + + static void calcLineOffsets(const tChar* aBuff, Index aLength, Buffer& aOut) { + halni lines = 0; + for (auto idx : Range(aLength)) { + if (isNewLineChar(aBuff[idx])) { + lines++; + } + } + aOut.reserve(lines + 2); // plus start and end offsets + lines = 0; + for (auto idx : Range(aLength)) { + if (isNewLineChar(aBuff[idx])) { + aOut[lines + 1] = Index(idx + 1); + lines++; + } + } + aOut[0] = 0; + aOut[lines + 1] = aLength; + } }; } \ No newline at end of file diff --git a/Strings/public/Strings.hpp b/Strings/public/Strings.hpp index 3fdb5a4..1718f30 100644 --- a/Strings/public/Strings.hpp +++ b/Strings/public/Strings.hpp @@ -2,7 +2,7 @@ #include "PoolAllocator.hpp" #include "StringLogic.hpp" -#include "TextEditor.hpp" +#include "Buffer.hpp" namespace tp { @@ -11,48 +11,23 @@ namespace tp { template class StringTemplate; - using String = StringTemplate; + using String = StringTemplate; - template + template class StringTemplate { - typedef StringLogic StringLogic; + public: + typedef StringLogic Logic; + typedef Logic::Index Index; + private: // Hidden slave class class StringData { - - // allows to edit each string with text editor inplace - class TextEditors { - enum { MAX_EDITED_STRINGS = 65536 }; // 2^16 - do not change mindlessly - typedef uint2 Address; - ChunkAlloc mEditorsPool; - - public: - TextEditors() : mEditorsPool() {} - - TextEditor* get(Address address) { return mEditorsPool.getBuff() + address; } - - Address createTextEditor(const tChar* originalBuffer) { - auto entry = (TextEditor**) mEditorsPool.allocate(0); - *entry = new TextEditor( originalBuffer ); - return Address(entry - mEditorsPool.getBuff()); - } - - void destroyTextEditor(Address address) { - auto entry = mEditorsPool.getBuff() + address; - mEditorsPool.deallocate(entry); - delete entry; - } - }; - - static TextEditors sTextEditors; - public: uint2 mIsConst; // source is non-modifiable uint2 mEditedIdx; // editor id uint4 mReferenceCount; // number of users of this tChar* mBuff; // actual string data - public: StringData() { MODULE_SANITY_CHECK(gModuleStrings) mBuff = (tChar*) "*"; @@ -73,7 +48,7 @@ namespace tp { explicit StringData(const tChar* aBuff) { MODULE_SANITY_CHECK(gModuleStrings) DEBUG_ASSERT(aBuff) - auto const len = StringLogic::calcLength(aBuff); + auto const len = Logic::calcLength(aBuff); resize(len); memCopy(mBuff, aBuff, len); mReferenceCount = 0; @@ -82,52 +57,18 @@ namespace tp { } [[nodiscard]] tChar* getBuffer() { - DEBUG_ASSERT(!isEditorMode()) - if (isEditorMode()) return nullptr; return mBuff; } ~StringData() { if (!mIsConst) delete[] mBuff; - if (isEditorMode()) sTextEditors.destroyTextEditor(mEditedIdx); } - public: void resize(ualni size) { - DEBUG_ASSERT(!isEditorMode() && mReferenceCount == 1 && !mIsConst) + DEBUG_ASSERT(mReferenceCount == 1 && !mIsConst) delete[] mBuff; mBuff = new tChar[size + 1]; - mBuff[size] = StringLogic::getEndChar(); - } - - public: - [[nodiscard]] bool isEditorMode() const { return mEditedIdx; } - - void createEditor() { - DEBUG_ASSERT(!isEditorMode()) - if (isEditorMode()) mEditedIdx = sTextEditors.createTextEditor(mBuff); - } - - [[nodiscard]] TextEditor* getEditor() const { - DEBUG_ASSERT(isEditorMode()) - if (!isEditorMode()) return nullptr; - return sTextEditors.get(mEditedIdx); - } - - void applyEditor() { - DEBUG_ASSERT(isEditorMode() && mReferenceCount == 1 && !mIsConst) - if (!isEditorMode()) return; - auto editor = sTextEditors.get(mEditedIdx); - resize(editor.textSize()); - for ( auto character : *editor) { - mBuff[character.idx] = character; - } - } - - void destroyEditor() { - DEBUG_ASSERT(isEditorMode()) - if (!isEditorMode()) return; - sTextEditors.destroyTextEditor(mEditedIdx); + mBuff[size] = Logic::getEndChar(); } }; @@ -149,14 +90,8 @@ namespace tp { // References existing string data StringTemplate(const StringTemplate& in) { - if (in.isEditorMode()) { - // Copies raw data and claims ownership over it - mStringData = new (sStringPool->allocate(0)) StringData(in.mStringData->mBuff); - incReference(mStringData); - } else { - mStringData = in.mStringData; - incReference(mStringData); - } + mStringData = in.mStringData; + incReference(mStringData); } // Creates new string data from raw data pointer. @@ -177,11 +112,6 @@ namespace tp { } private: - - [[nodiscard]] bool isEditorMode() const { - return mStringData->isEditorMode(); - } - static void incReference(StringData* dp) { dp->mReferenceCount++; } @@ -213,21 +143,7 @@ namespace tp { return mStringData->getBuffer(); } - public: // TextEditor Mode - // Enters TextEditor Mode - void createEditor() { mStringData->createEdited(); } - - // Access to TextEditor Context & Interface - [[nodiscard]] TextEditor* getEditor() { return mStringData->getEdited(); } - [[nodiscard]] const TextEditor* getEditor() const { return mStringData->getEdited(); } - - // Applies TextEditor Mode To Current buffer - void applyEditor() { mStringData->applyEditor(); } - - // Leaves TextEditor Mode - void destroyEditor() { mStringData->destroyEditor(); } - - private: + public: void makeModifiable() { // We have no rights to modify if someone references that memory too // So we need to create new copy of StringData @@ -244,5 +160,27 @@ namespace tp { incReference(mStringData); } } + + public: // Syntax sugars + Index size() const { + return Logic::calcLength(read()); + } + + void calcLineOffsets(Buffer& aOut) const { + Logic::calcLineOffsets(read(), size(), aOut); + } + + StringTemplate& operator=(const tChar* in) { + this->~StringTemplate(); + new (this) StringTemplate(in); + return *this; + } + + StringTemplate& operator=(const StringTemplate& in) { + if (&in == this) return *this; + ~StringTemplate(); + new (this) StringTemplate(in); + return *this; + } }; } \ No newline at end of file diff --git a/Strings/public/TextEditor.hpp b/Strings/public/TextEditor.hpp deleted file mode 100644 index e1b1dc1..0000000 --- a/Strings/public/TextEditor.hpp +++ /dev/null @@ -1,382 +0,0 @@ - -#pragma once - -#include "Strings.hpp" -#include "Buffer.hpp" -#include "Tree.hpp" - -namespace tp { - - class PiecesDS { - - struct Input { - const Char* mInput = nullptr; - Index mLen = 0; - void getLineOffsets(Buffer& out); - }; - - struct Pointer { - LineId mLine; - ColumnId mCol; - - Pointer(); - Pointer(LineId aLine, ColumnId aCol); - Pointer(const Input& aInput); - void operator+=(Char achar); - void operator+=(const Pointer& ap); - Pointer operator-(const Pointer in) const; - Pointer operator+(const Pointer& ap) const; - bool operator==(const Pointer& in) const; - bool operator>(const Pointer& in) const; - bool operator>=(const Pointer& in) const; - }; - - struct Piece { - bool mAddedBuff = false; - Pointer mStart; - Pointer mEnd; - - Pointer diffPtr() const; - LineId nLines() const; - }; - - public: - - // Tree Node : Based on AvlNodeBlueprint - struct Node { - - Node* mLeft = nullptr; - Node* mRight = nullptr; - Node* mParent = nullptr; - halni mHeight = 0; - - Pointer mPtrLeft; - Pointer mPtrRight; - Pointer mDiff; - - Node* mNext = nullptr; - Node* mPrev = nullptr; - Piece* mPiece = nullptr; - - static bool mInsertionOperation; - - Node() {} - Node(Pointer aKey) { - //mVal = aKey; - } - - bool disentRight(Pointer aKey) const { - return aKey > mPtrLeft; - } - - bool disentLeft(Pointer aKey) const { - return mPtrLeft > aKey; - } - - bool exactNode(Pointer aKey) const { - if (mInsertionOperation) { - return aKey > mPtrLeft && mPtrLeft + mDiff > aKey; - } - return aKey >= mPtrLeft && mPtrLeft + mDiff > aKey; - } - - Pointer getFindKey(Node* node = nullptr) const { - // node must be ancestor of this node - - Pointer out = mPtrLeft; - - if (node == this) { - return out; - } - - auto iter = this; - while (iter->mParent != node) { - if (iter == iter->mParent->mRight) { - auto left_sub_tree = iter->mParent->mPtrLeft + iter->mParent->mDiff; - out = left_sub_tree + out; - } - iter = iter->mParent; - } - - if (node) { - if (iter == iter->mParent->mRight) { - auto left_sub_tree = iter->mParent->mPtrLeft + iter->mParent->mDiff; - out = left_sub_tree + out; - } - } - return out; - } - - void copyData(const Node& in) { - mPiece = in.mPiece; - mNext = in.mNext; - mPrev = in.mPrev; - - if (mPrev) { - mPrev->mNext = this; - } - - if (mNext) { - mNext->mPrev = this; - } - } - - Pointer keyInRightSubtree(Pointer key) const { return key - (mPtrLeft + mDiff); } - Pointer keyInLeftSubtree(Pointer key) const { return key; } - - void updateTreeCahceCallBack() { - DEBUG_ASSERT(mPiece); - mDiff = mPiece->diffPtr(); - if (mLeft) { - mPtrLeft = mLeft->sum(); - } - else { - mPtrLeft = { 0, 0 }; - } - - if (mRight) { - mPtrRight = mRight->sum(); - } - else { - mPtrRight = { 0, 0 }; - } - } - - Pointer sum() const { - return (mPtrLeft + mDiff) + mPtrRight; - } - }; - - private: - - AvlTree mTree; - - public: - - PiecesDS() { - } - - Node* find(Pointer ptr) const { - return mTree.find(ptr); - } - - Node* minNode(Node* node) const { - return mTree.minNode(node); - } - - Node* maxNode(Node* node) const { - return mTree.maxNode(node); - } - - Node* head() const { - return mTree.head(); - } - - void insert(const Node& node, Pointer ptr) { - Node::mInsertionOperation = true; - mTree.insert(ptr, node); - Node::mInsertionOperation = false; - } - - Node* insertAfter(Node* node, Piece piece) { - auto key = node ? (node->getFindKey() + node->mDiff) : Pointer{ 0, 0 }; - auto new_node = Node(); - new_node.mPiece = new Piece(piece); - - insert(new_node, key); - -#ifdef _DEBUG - auto err_node = mTree.isInvalid(mTree.head()); - DBG_BREAK(err_node); -#endif - - auto out = mTree.find(key); - - Node* next = out->mRight; - Node* prev = out->mLeft; - - if (!(next || prev) && out->mParent) { - if (out->mParent->mLeft == out) { - next = out->mParent; - } - else { - prev = out->mParent; - } - } - - if (next) { - out->mNext = next; - out->mPrev = next->mPrev; - next->mPrev = out; - if (out->mPrev) out->mPrev->mNext = out; - } - else if (prev) { - out->mPrev = prev; - out->mNext = prev->mNext; - prev->mNext = out; - if (out->mNext) out->mNext->mPrev = out; - } - - return out; - } - - void remove(Node* aNode) { - auto key = aNode->getFindKey(); - - if (aNode->mPrev) { - aNode->mPrev->mNext = aNode->mNext; - } - - if (aNode->mNext) { - aNode->mNext->mPrev = aNode->mPrev; - } - - auto del = aNode->mPiece; - mTree.remove(key); - delete del; - -#ifdef _DEBUG - auto err_node = mTree.isInvalid(mTree.head()); - DBG_BREAK(err_node); -#endif - } - - Node* first() const { - return mTree.minNode(mTree.head()); - } - - Pointer ptrSum() const { - if (mTree.head()) { - return mTree.head()->sum(); - } - return { 0, 0 }; - } - - halni nPieces() const { - return mTree.size(); - } - - void update_cache(Node* node) { - if (node) { - node->updateTreeCahceCallBack(); - update_cache(node->mParent); - } - } - - void undo() {} - void redo() {} - void pushUndoPoint() {} - }; - - struct AddBuff { - Buffer mBuff; - Buffer mLineOffsets; - Index mColumn = 0; - - AddBuff(); - void append(Input aInput); - Pointer endPtr(); - }; - - struct OrigBuff { - bool mOwnsInput = false; - Input mOriginal; - Buffer mLineOffsets; - - Pointer mPtrStart; - Pointer mPtrEnd; - - // does not owns the original input by default - OrigBuff(Input aOriginal); - - void makeOwnOriginalInput(); - - ~OrigBuff(); - }; - - struct PieceCrs { - Pointer piece_ptr; - Pointer offset; - Pointer ptr; - PiecesDS::Node* piece = nullptr; - }; - - class TextEditor { - friend class Iterator; - - class Iterator { - friend TextEditor; - - const TextEditor* mSelf; - PiecesDS::Node* mNode = nullptr; - Pointer mOffset = { 0, 0 }; - Pointer mPtr = { 0, 0 }; - Char mVal = 0; - - Iterator(const TextEditor* mSelf); - bool inputLeft(); - - public: - - Char character(); - void operator++(); - bool operator!=(alni const& iter); - bool operator==(alni const& iter); - Char operator->(); - const Iterator& operator*(); - }; - - public: - - // pieces of strings that construct the text - PiecesDS mPieces; - - // string buffers to wich pieces can reffer - OrigBuff mOrigBuff; - AddBuff mAddBuff; - - // active position on the text - Pointer mCursor; - Pointer mCursorEnd; - - Pointer mLastInsertionCrs; - //private: - - [[nodiscard]] PieceCrs findPiece(Pointer ptr) const; - [[nodiscard]] Pointer prevPiecePtr(PiecesDS::Node* piece_node, Pointer piece_pointer) const; - [[nodiscard]] Pointer nextPiecePtr(PiecesDS::Node* piece_node, Pointer piece_pointer) const; - - [[nodiscard]] const Char* getBuffLine(const Piece*, LineId) const; - [[nodiscard]] const Char* getPieceLine(const Piece*, LineId) const; - [[nodiscard]] PiecesDS::Node* splitPiece(PiecesDS::Node* piece, Pointer split_ptr); - [[nodiscard]] LineId getPieceLineLen(Piece* aPiece, LineId line) const; - - public: - enum Dir : uint1 { LEFT, RIGHT, UP, DOWN }; - enum DirUnit : uint1 { CHAR, WORD, TOK, LINE_END, LINE_START }; - - public: - - TextEditor(); - explicit TextEditor(Input original); - - [[nodiscard]] Index mNLines() const; - void clampPtr(Pointer& ptr) const; - [[nodiscard]] Pointer getCursor() const; - [[nodiscard]] Pointer getCursorEnd() const; - void setCursor(Pointer ptr); - void setCursorEnd(Pointer ptr); - - void insert(Input aInput); - - void remove(bool only_selection = false, Dir dir = LEFT, DirUnit unit = CHAR); - - void undo(); - void redo(); - - Iterator begin(); - alni end(); - - ~TextEditor(); - }; -} \ No newline at end of file