Skip to main content
Bounty Awarded with 50 reputation awarded by John
added 187 characters in body
Source Link
G. Sliepen
  • 69.3k
  • 3
  • 75
  • 180

Using a single std::string to store the contents of a document is a very naive design for a text editor. While it might be good enough for small documents, the problem is that the time most operations will take more timenow linearly scale with the longersize of the document is, so for large documents everything becomes very slow. A slightly less naive way to store the document would be to store the lines of the document in a std::vector<std::string>, as that at least makes navigation very quickfast, and edits within a line will also be quickfast (assuming you don't have extremely long lines). But there are data structures designed to make almost all operations fast, likeregardless of the number of lines or the length of the lines. Have a look at rope or aand gap bufferbuffers, although these are not the only ones.

Using a single std::string to store the contents of a document is a very naive design for a text editor. While it might be good enough for small documents, the problem is that most operations will take more time the longer the document is. A slightly less naive way to store the document would be to store the lines of the document in a std::vector<std::string>, as that at least makes navigation very quick, and edits within a line will also be quick (assuming you don't have extremely long lines). But there are data structures designed to make all operations fast, like a rope or a gap buffer.

Using a single std::string to store the contents of a document is a very naive design for a text editor. While it might be good enough for small documents, the problem is that the time most operations will take now linearly scale with the size of the document, so for large documents everything becomes very slow. A slightly less naive way to store the document would be to store the lines of the document in a std::vector<std::string>, as that at least makes navigation very fast, and edits within a line will also be fast (assuming you don't have extremely long lines). But there are data structures designed to make almost all operations fast, regardless of the number of lines or the length of the lines. Have a look at rope and gap buffers, although these are not the only ones.

added 6 characters in body
Source Link
G. Sliepen
  • 69.3k
  • 3
  • 75
  • 180
class DocumentEditor {
    …
    template<typename T, typename... Args>
    int execute(Args&&... args) {
        m_history.emplace_back(new T(std::forward<Args>(args)...));
        m_history.back()->execute(m_document);
        …
    }

    int undo() {
        …
        m_history.back()->unexecute();
        m_redo_list.push_back(std::move(m_history.back());
        m_history.pop_back();
        …
    }
    …
private:
    Document m_document;
    std::deque<std::unique_ptr<ICommand>> m_history;
    std::deque<std::unique_ptr<ICommand>> m_redo_list;
}
class DocumentEditor {
    …
    template<typename T, typename... Args>
    int execute(Args&&... args) {
        m_history.emplace_back(new T(std::forward<Args>(args)...));
        m_history.back()->execute(m_document);
        …
    }

    int undo() {
        …
        m_history.back()->unexecute();
        m_redo_list.push_back(std::move(m_history.back());
        m_history.pop_back();
        …
    }
    …
private:
    Document m_document;
    
}
class DocumentEditor {
    …
    template<typename T, typename... Args>
    int execute(Args&&... args) {
        m_history.emplace_back(new T(std::forward<Args>(args)...));
        m_history.back()->execute(m_document);
        …
    }

    int undo() {
        …
        m_history.back()->unexecute();
        m_redo_list.push_back(std::move(m_history.back());
        m_history.pop_back();
        …
    }
    …
private:
    Document m_document;
    std::deque<std::unique_ptr<ICommand>> m_history;
    std::deque<std::unique_ptr<ICommand>> m_redo_list;
}
added 6 characters in body
Source Link
G. Sliepen
  • 69.3k
  • 3
  • 75
  • 180
class Invoker {
public:
    Invoker(std::shared_ptr<Document> document_ptr): m_document_ptr(document_ptr) {}

    template<typename T, typename... Args>
    int execute(Args&&... args) {
        auto cmd = std::make_shared<T>(documentm_document_ptr, std::forward<Args>(args)...);
        cmd->execute();
        …
    }
    …
private:
    std::shared_ptr<Document> m_document_ptr;
    …
};

int main() {
    auto diary_ptr = std::make_shared<Document>();
    …
    auto diary_editor = Invoker(diary_ptr);
    …
    diary_editor.execute<Append>("5/2/2024 ");
    diary_editor.execute<Append>("thursday");
    diary_editor.execute<Append>("\n");
    diary_editor.execute<Insert>(1, 10, "rainy ");
    …
}

class DocumentEditor { … template<typename T, typename... Args> int execute(Args&&... args) { m_history.emplace_back(new T(std::forward(args)...)); m_history.back()->execute(m_document); … }

class DocumentEditor {
    …
    template<typename T, typename... Args>
    int execute(Args&&... args) {
        m_history.emplace_back(new T(std::forward<Args>(args)...));
        m_history.back()->execute(m_document);
        …
    }

    int undo() {
            m_history.back()->unexecute();
        m_redo_list.push_back(std::move(m_history.back());
        m_history.pop_back();
        }
    …
private:
    Document m_document;
    
}

private: Document m_document; … }

class Invoker {
public:
    Invoker(std::shared_ptr<Document> document_ptr): m_document_ptr(document_ptr) {}

    template<typename T, typename... Args>
    int execute(Args&&... args) {
        auto cmd = std::make_shared<T>(document, std::forward<Args>(args)...);
        cmd->execute();
        …
    }
    …
private:
    std::shared_ptr<Document> m_document_ptr;
    …
};

int main() {
    auto diary_ptr = std::make_shared<Document>();
    …
    auto diary_editor = Invoker(diary_ptr);
    …
    diary_editor.execute<Append>("5/2/2024 ");
    diary_editor.execute<Append>("thursday");
    diary_editor.execute<Append>("\n");
    diary_editor.execute<Insert>(1, 10, "rainy ");
    …
}

class DocumentEditor { … template<typename T, typename... Args> int execute(Args&&... args) { m_history.emplace_back(new T(std::forward(args)...)); m_history.back()->execute(m_document); … }

int undo() {
    …
    m_history.back()->unexecute();
    m_redo_list.push_back(std::move(m_history.back());
    m_history.pop_back();
    …
}
…

private: Document m_document; … }

class Invoker {
public:
    Invoker(std::shared_ptr<Document> document_ptr): m_document_ptr(document_ptr) {}

    template<typename T, typename... Args>
    int execute(Args&&... args) {
        auto cmd = std::make_shared<T>(m_document_ptr, std::forward<Args>(args)...);
        cmd->execute();
        …
    }
    …
private:
    std::shared_ptr<Document> m_document_ptr;
    …
};

int main() {
    auto diary_ptr = std::make_shared<Document>();
    …
    auto diary_editor = Invoker(diary_ptr);
    …
    diary_editor.execute<Append>("5/2/2024 ");
    diary_editor.execute<Append>("thursday");
    diary_editor.execute<Append>("\n");
    diary_editor.execute<Insert>(1, 10, "rainy ");
    …
}
class DocumentEditor {
    …
    template<typename T, typename... Args>
    int execute(Args&&... args) {
        m_history.emplace_back(new T(std::forward<Args>(args)...));
        m_history.back()->execute(m_document);
        …
    }

    int undo() {
            m_history.back()->unexecute();
        m_redo_list.push_back(std::move(m_history.back());
        m_history.pop_back();
        }
    …
private:
    Document m_document;
    
}
Source Link
G. Sliepen
  • 69.3k
  • 3
  • 75
  • 180
Loading