From d272b0b28fbb30d71d8b7f7b6b86bd2297cdb0be Mon Sep 17 00:00:00 2001 From: Melroy van den Berg Date: Mon, 14 Dec 2020 19:40:08 +0100 Subject: [PATCH] Some refactoring --- src/file.cc | 29 +++++------- src/file.h | 14 ++---- src/ipfs.cc | 57 +++++++++++++++------- src/ipfs.h | 4 +- src/main.cc | 40 ++++++++-------- src/mainwindow.cc | 34 +++++++------ src/mainwindow.h | 68 +++++++++++++------------- src/md-parser.cc | 56 +++++++--------------- src/md-parser.h | 18 ++++--- src/network.h | 2 +- src/render-area.h | 118 +++++++++++++++++++++++----------------------- suppressions.txt | 3 +- 12 files changed, 218 insertions(+), 225 deletions(-) diff --git a/src/file.cc b/src/file.cc index eb2382f..b876355 100644 --- a/src/file.cc +++ b/src/file.cc @@ -1,7 +1,8 @@ #include "file.h" -#include #include +#include +#include #include File::File() {} @@ -11,9 +12,14 @@ File::File() {} * \param path File path * \return AST model of markdown file (cmark_node) */ -cmark_node * File::read(const std::string& path) +std::string const File::read(const std::string& path) { - return parser.parseFile(path); + std::ifstream inFile; + inFile.open(path, std::ifstream::in); + + std::stringstream strStream; + strStream << inFile.rdbuf(); + return strStream.str(); } /** @@ -22,22 +28,9 @@ cmark_node * File::read(const std::string& path) * \throw runtime error when something goes wrong * \return AST model of markdown file (cmark_node) */ -cmark_node * File::fetch(const std::string& path) +std::string const File::fetch(const std::string& path) { std::stringstream contents; network.fetchFile(path, &contents); - return parser.parseStream(contents); -} - -std::string const File::getSource(cmark_node *node) -{ - return parser.getSource(node); -} - -/** - * Free AST cmark_node memory, to avoid memory leaks - */ -void File::free(cmark_node *node) -{ - cmark_node_free(node); + return contents.str(); } diff --git a/src/file.h b/src/file.h index ba958ba..234fc4e 100644 --- a/src/file.h +++ b/src/file.h @@ -1,26 +1,22 @@ #ifndef FILE_H #define FILE_H -#include "md-parser.h" #include "network.h" #include /** * \class File - * \brief Fetch markdown file from disk or IPFS network and parse to AST + * \brief Fetch markdown file from disk or IPFS network */ class File { public: - File(); + File(); - cmark_node * read(const std::string& path); /*!< Read file from disk */ - cmark_node * fetch(const std::string& path); /*!< Fetch file from IPFS network */ - std::string const getSource(cmark_node *node); /*!< Get source code from AST */ - void free(cmark_node *node); /*!< Free pointer */ + std::string const read(const std::string& path); /*!< Read file from disk */ + std::string const fetch(const std::string& path); /*!< Fetch file from IPFS network */ private: - Parser parser; - Network network; + Network network; }; #endif \ No newline at end of file diff --git a/src/ipfs.cc b/src/ipfs.cc index b702c2d..a549b61 100644 --- a/src/ipfs.cc +++ b/src/ipfs.cc @@ -2,26 +2,49 @@ #include #include #include +#include +#include +#include + +#ifdef LEGACY_CXX +#include +namespace n_fs = ::std::experimental::filesystem; +#else +#include +namespace n_fs = ::std::filesystem; +#endif int IPFS::startIPFSDaemon() { - // Be sure to kill any running daemons - std::system("killall -q ipfs"); + // Be sure to kill any running daemons + std::system("killall -q ipfs"); - /// open /dev/null for writing - int fd = open("/dev/null", O_WRONLY); + /// open /dev/null for writing + int fd = open("/dev/null", O_WRONLY); - dup2(fd, 1); // make stdout a copy of fd (> /dev/null) - dup2(fd, 2); // ..and same with stderr - close(fd); // close fd + dup2(fd, 1); // make stdout a copy of fd (> /dev/null) + dup2(fd, 2); // ..and same with stderr + close(fd); // close fd - // Ignore ISO C++ forbids converting a string constant to ‘char*’ - // This is valid in C. - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wwrite-strings" - // stdout and stderr now write to /dev/null - // Ready to call exec to start IPFS Daemon - constexpr char *proc[] = { "../../go-ipfs/ipfs", "daemon", "--init", "--migrate", NULL}; - #pragma GCC diagnostic pop - return execv(proc[0], proc); -} \ No newline at end of file + // stdout and stderr now write to /dev/null + // Ready to call exec to start IPFS Daemon + std::string currentPath = n_fs::current_path().string(); + std::string executable = currentPath.append("/../../go-ipfs/ipfs"); + const char* exe = executable.c_str(); + std::cout << "Info: Starting IPFS Daemon from: " << exe << std::endl; + char *proc[] = { strdup(exe), strdup("daemon"), strdup("--init"), strdup("--migrate"), NULL}; + return execv(exe, proc); +} + +/* +std::string IPFS::getExecutablePath() { + char buff[PATH_MAX]; + ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1); + if (len != -1) { + buff[len] = '\0'; + return std::string(buff); + } + else { + return ""; + } +}*/ diff --git a/src/ipfs.h b/src/ipfs.h index 59898b5..2dc9742 100644 --- a/src/ipfs.h +++ b/src/ipfs.h @@ -1,6 +1,8 @@ #ifndef IPFS_H #define IPFS_H +#include + /** * \class IPFS * \brief Helper class to start/stop IPFS deamon @@ -8,6 +10,6 @@ class IPFS { public: - static int startIPFSDaemon(); + static int startIPFSDaemon(); }; #endif \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index 7072d7d..63e6b6e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -4,25 +4,25 @@ int main(int argc, char *argv[]) { - pid_t child_pid = fork(); - if (child_pid == 0) - { - // Run by child process - return IPFS::startIPFSDaemon(); - } - else if (child_pid > 0 ) - { - // Parent process (child_pid is PID of child) - auto app = Gtk::Application::create(argc, argv, "org.melroy.browser"); + pid_t child_pid = fork(); + if (child_pid == 0) + { + // Run by child process + return IPFS::startIPFSDaemon(); + } + else if (child_pid > 0 ) + { + // Parent process (child_pid is PID of child) + auto app = Gtk::Application::create(argc, argv, "org.melroy.browser"); - MainWindow window; - int exitCode = app->run(window); - // Kill also the child - kill(child_pid, SIGTERM); - return exitCode; - } - else // PID < 0, error - { - printf("ERROR: fork failed.\n"); - } + MainWindow window; + int exitCode = app->run(window); + // Kill also the child + kill(child_pid, SIGTERM); + return exitCode; + } + else // PID < 0, error + { + printf("ERROR: fork failed.\n"); + } } diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 76f67c0..bd23e48 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -2,6 +2,8 @@ #include #include +#include +#include "md-parser.h" #ifdef LEGACY_CXX #include @@ -16,7 +18,7 @@ MainWindow::MainWindow() m_hbox_bar(Gtk::ORIENTATION_HORIZONTAL, 0), requestPath(""), finalRequestPath(""), - currentSourceCode("") + currentContent("") { set_title("DBrowser"); set_default_size(1000, 800); @@ -34,10 +36,6 @@ MainWindow::MainWindow() m_vbox.pack_start(m_menu, false, false, 0); - - m_sourceCodeDialog.setText("Hallo!?"); - m_sourceCodeDialog.setText("123"); - // Horizontal bar auto styleBack = m_backButton.get_style_context(); styleBack->add_class("circular"); @@ -86,7 +84,7 @@ void MainWindow::go_home() { this->requestPath = ""; this->finalRequestPath = ""; - this->currentSourceCode = ""; + this->currentContent = ""; this->m_inputField.set_text(""); m_renderArea.showStartPage(); } @@ -99,12 +97,12 @@ void MainWindow::input_activate() void MainWindow::doRequest(const std::string &path) { - currentSourceCode = ""; + currentContent = ""; if (!path.empty()) { requestPath = path; } if (requestPath.empty()) { - std::cerr << "Empty request path." << std::endl; + std::cerr << "Info: Empty request path." << std::endl; } else { // Check if CID if (requestPath.rfind("ipfs://", 0) == 0) { @@ -143,12 +141,12 @@ void MainWindow::fetchFromIPFS() // TODO: In a seperate thread/process? // Since otherwise this may block the UI. try { - cmark_node *fetchDoc = m_file.fetch(finalRequestPath); - m_renderArea.processDocument(fetchDoc); - currentSourceCode = m_file.getSource(fetchDoc); - m_file.free(fetchDoc); + currentContent = m_file.fetch(finalRequestPath); + cmark_node* doc = Parser::parseContent(currentContent); + m_renderArea.processDocument(doc); + cmark_node_free(doc); } catch (const std::runtime_error &error) { - std::cerr << "IPFS Deamon is most likely down: " << error.what() << std::endl; + std::cerr << "Error: IPFS Deamon is most likely down: " << error.what() << std::endl; // Not found (or any other issue) m_renderArea.showMessage("Page not found!", "Detailed error message: " + std::string(error.what())); } @@ -162,10 +160,10 @@ void MainWindow::openFromDisk() // std::string exePath = n_fs::current_path().string(); // std::string filePath = exePath.append("/../../test.md"); try { - cmark_node *readDoc = m_file.read(finalRequestPath); - m_renderArea.processDocument(readDoc); - currentSourceCode = m_file.getSource(readDoc); - m_file.free(readDoc); + currentContent = m_file.read(finalRequestPath); + cmark_node *doc = Parser::parseContent(currentContent); + m_renderArea.processDocument(doc); + cmark_node_free(doc); } catch (const std::runtime_error &error) { m_renderArea.showMessage("Page not found!", "Detailed error message: " + std::string(error.what())); } @@ -173,6 +171,6 @@ void MainWindow::openFromDisk() void MainWindow::show_source_code_dialog() { - m_sourceCodeDialog.setText(currentSourceCode); + m_sourceCodeDialog.setText(currentContent); m_sourceCodeDialog.run(); } \ No newline at end of file diff --git a/src/mainwindow.h b/src/mainwindow.h index 8529feb..3e18a0d 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -16,45 +16,45 @@ class MainWindow : public Gtk::Window { public: - MainWindow(); + MainWindow(); protected: - // Signal handlers: - // Our new improved on_button_clicked(). (see below) - void go_home(); - void input_activate(); - void on_button_clicked(Glib::ustring data); - void show_about(); - void hide_about(int response); - void show_source_code_dialog(); + // Signal handlers: + // Our new improved on_button_clicked(). (see below) + void go_home(); + void input_activate(); + void on_button_clicked(Glib::ustring data); + void show_about(); + void hide_about(int response); + void show_source_code_dialog(); - // Child widgets - Menu m_menu; - Gtk::Box m_vbox; - Gtk::Box m_hbox_bar; - Gtk::Button m_backButton; - Gtk::Button m_forwardButton; - Gtk::Button m_refreshButton; - Gtk::Button m_homeButton; - Gtk::Entry m_inputField; - Gtk::Image backIcon; - Gtk::Image forwardIcon; - Gtk::Image refreshIcon; - Gtk::Image homeIcon; - Gtk::ScrolledWindow m_scrolledWindow; - RenderArea m_renderArea; - SourceCodeDialog m_sourceCodeDialog; - About m_about; + // Child widgets + Menu m_menu; + Gtk::Box m_vbox; + Gtk::Box m_hbox_bar; + Gtk::Button m_backButton; + Gtk::Button m_forwardButton; + Gtk::Button m_refreshButton; + Gtk::Button m_homeButton; + Gtk::Entry m_inputField; + Gtk::Image backIcon; + Gtk::Image forwardIcon; + Gtk::Image refreshIcon; + Gtk::Image homeIcon; + Gtk::ScrolledWindow m_scrolledWindow; + RenderArea m_renderArea; + SourceCodeDialog m_sourceCodeDialog; + About m_about; private: - File m_file; - std::string requestPath; - std::string finalRequestPath; - std::string currentSourceCode; + File m_file; + std::string requestPath; + std::string finalRequestPath; + std::string currentContent; - void doRequest(const std::string &path = ""); - void refresh(); - void fetchFromIPFS(); - void openFromDisk(); + void doRequest(const std::string &path = ""); + void refresh(); + void fetchFromIPFS(); + void openFromDisk(); }; #endif \ No newline at end of file diff --git a/src/md-parser.cc b/src/md-parser.cc index 9ca22b3..0cdfd12 100644 --- a/src/md-parser.cc +++ b/src/md-parser.cc @@ -7,50 +7,39 @@ #include #include -Parser::Parser(): options(CMARK_OPT_DEFAULT) {} +static const int OPTIONS = CMARK_OPT_DEFAULT; + +/// Meyers Singleton +Parser::Parser()= default; +/// Destructor +Parser::~Parser()= default; /** - * Parse markdown by file path - * @return AST structure (of type cmark_node) + * \brief Get singleton instance + * \return Helper reference (singleton) */ -cmark_node * Parser::parseFile(const std::string &filePath) -{ - // Parse to AST with cmark - FILE *file; - if (!std::filesystem::exists(filePath.c_str())) { - throw std::runtime_error("File not found."); - } - - if( ( file = fopen(filePath.c_str(), "r" ) ) != NULL ) - { - cmark_node *doc; - // TODO: Copy/paste cmark_parse_file() content to here, allowing me to add extensions to the parser. - doc = cmark_parse_file(file, options); - fclose(file); - return doc; - } else { - throw std::runtime_error("File open failed."); - } +Parser& Parser::getInstance() { + static Parser instance; + return instance; } /** - * Parse markdown file by stringstream + * Parse markdown file from string content * @return AST structure (of type cmark_node) */ -cmark_node * Parser::parseStream(const std::stringstream &stream) +cmark_node * Parser::parseContent(const std::string &content) { //cmark_node *doc; // Parse to AST with cmark - // mark_parser *parser = cmark_parser_new(options); + // mark_parser *parser = cmark_parser_new(OPTIONS); // Add extensions //addMarkdownExtension(parser, "strikethrough"); //addMarkdownExtension(parser, "table"); - const std::string tmp = stream.str(); - const char *data = tmp.c_str(); + const char *data = content.c_str(); // TODO: Copy cmark_parse_document() to be able to add extensions to the parser - return cmark_parse_document(data, strlen(data), options); + return cmark_parse_document(data, strlen(data), OPTIONS); } /** @@ -58,18 +47,7 @@ cmark_node * Parser::parseStream(const std::stringstream &stream) */ std::string const Parser::renderHTML(cmark_node *node) { - char *tmp = cmark_render_html(node, options, NULL); - std::string output = std::string(tmp); - free(tmp); - return output; -} - -/** - * Get just the plain text - */ -std::string const Parser::getSource(cmark_node *node) -{ - char *tmp = cmark_render_commonmark(node, options, 0); + char *tmp = cmark_render_html(node, OPTIONS, NULL); std::string output = std::string(tmp); free(tmp); return output; diff --git a/src/md-parser.h b/src/md-parser.h index 8b750f5..207471e 100644 --- a/src/md-parser.h +++ b/src/md-parser.h @@ -11,14 +11,18 @@ class Parser { public: - Parser(); - cmark_node * parseFile(const std::string &filePath); - cmark_node * parseStream(const std::stringstream &stream); - std::string const renderHTML(cmark_node *node); - std::string const getSource(cmark_node *node); + // Singleton + static Parser& getInstance(); + + static cmark_node * parseContent(const std::string &content); + static std::string const renderHTML(cmark_node *node); private: - int options; - void addMarkdownExtension(cmark_parser *parser, const char *extName); + Parser(); + ~Parser(); + Parser(const Parser&)= delete; + Parser& operator=(const Parser&)= delete; + + static void addMarkdownExtension(cmark_parser *parser, const char *extName); }; #endif diff --git a/src/network.h b/src/network.h index 0e7caed..f181a3b 100644 --- a/src/network.h +++ b/src/network.h @@ -16,6 +16,6 @@ public: void fetchFile(const std::string& path, std::iostream* response); private: - ipfs::Client m_client; + ipfs::Client m_client; }; #endif \ No newline at end of file diff --git a/src/render-area.h b/src/render-area.h index 5e405d5..60d0d17 100644 --- a/src/render-area.h +++ b/src/render-area.h @@ -6,81 +6,81 @@ #include struct text_struct { - int x; - int y; - Glib::RefPtr layout; + int x; + int y; + Glib::RefPtr layout; }; struct line_struct { - int start_x; - int start_y; - int end_x; // -1 means auto-size - int end_y; - int margin_end_x; - double height; - std::string hex_color; - Cairo::LineCap cap; + int start_x; + int start_y; + int end_x; // -1 means auto-size + int end_y; + int margin_end_x; + double height; + std::string hex_color; + Cairo::LineCap cap; }; class RenderArea : public Gtk::DrawingArea { public: - RenderArea(); - virtual ~RenderArea(); + RenderArea(); + virtual ~RenderArea(); - void processDocument(cmark_node *root_node); - void showMessage(const std::string &message, const std::string &detailed_info = ""); - void showStartPage(); + void processDocument(cmark_node *root_node); + void showMessage(const std::string &message, const std::string &detailed_info = ""); + void showStartPage(); protected: - std::list m_textList; - std::list m_lines; + std::list m_textList; + std::list m_lines; - // Override default signal handler: - bool on_draw(const Cairo::RefPtr& cr) override; + // Override default signal handler: + bool on_draw(const Cairo::RefPtr& cr) override; private: - int currentX; - int currentY; - int sceneMarginX; - int sceneMarginY; - int currentXList; - int headingLevel; - int listLevel; - int wordSpacing; - int highestWidth; - int highestHeight; - int paragraphMargin; - int headingMargin; - int listMargin; - int horizontalLineMargin; - int listXOffset; - bool isBold; - bool isItalic; - int bulletListLevel; - int orderedListLevel; - bool isOrderedList; - std::map orderedListCounters; - int fontSize; - std::string fontFamily; - int pageWidth; - int pageHeight; + int currentX; + int currentY; + int sceneMarginX; + int sceneMarginY; + int currentXList; + int headingLevel; + int listLevel; + int wordSpacing; + int highestWidth; + int highestHeight; + int paragraphMargin; + int headingMargin; + int listMargin; + int horizontalLineMargin; + int listXOffset; + bool isBold; + bool isItalic; + int bulletListLevel; + int orderedListLevel; + bool isOrderedList; + std::map orderedListCounters; + int fontSize; + std::string fontFamily; + int pageWidth; + int pageHeight; - Pango::FontDescription defaultFont; - Pango::FontDescription boldFont; - Pango::FontDescription italicFont; - Pango::FontDescription boldItalicFont; - Pango::FontDescription heading1Font; - Pango::FontDescription heading2Font; - Pango::FontDescription heading3Font; - Pango::FontDescription heading4Font; + Pango::FontDescription defaultFont; + Pango::FontDescription boldFont; + Pango::FontDescription italicFont; + Pango::FontDescription boldItalicFont; + Pango::FontDescription heading1Font; + Pango::FontDescription heading2Font; + Pango::FontDescription heading3Font; + Pango::FontDescription heading4Font; - void createPangoContexts(); - void clear(); - void processNode(cmark_node *node, cmark_event_type ev_type); - void redraw(); - std::string const intToRoman(int num); - void hexToRGB(const std::string& hex, double &r, double &g, double &b); + void createPangoContexts(); + void clear(); + void processNode(cmark_node *node, cmark_event_type ev_type); + void redraw(); + std::string const intToRoman(int num); + void hexToRGB(const std::string& hex, double &r, double &g, double &b); }; #endif \ No newline at end of file diff --git a/suppressions.txt b/suppressions.txt index f946042..5633e78 100644 --- a/suppressions.txt +++ b/suppressions.txt @@ -1,4 +1,3 @@ missingIncludeSystem missingInclude:lib/* -unusedFunction -unusedPrivateFunction \ No newline at end of file +unusedFunction \ No newline at end of file