From: Harishankar Date: Thu, 21 May 2020 09:39:03 +0000 (+0530) Subject: Refactored template loading to its own class for performance X-Git-Url: https://harishankar.org/repos/?p=biaweb2.git;a=commitdiff_plain;h=eda0b06c5328e232e12e0535528a528493caa90a Refactored template loading to its own class for performance Refactored template string loading to its own class to avoid reading the template directory for every call to to_html() or output_to_html () --- diff --git a/biaweb.cpp b/biaweb.cpp index 22e4121..2ed34fb 100644 --- a/biaweb.cpp +++ b/biaweb.cpp @@ -36,11 +36,16 @@ int main (int argc, char *argv[]) { // // else { // // std::cout << "Usage: " << argv[0] << "
" << std::endl; + std::chrono::steady_clock::time_point t1 (std::chrono::steady_clock::now()); DocumentTree tree (""); tree.document_tree_builder ("Test/Reviews"); tree.visualize_tree (); - tree.create_tree_html ("templates", - "Test/Out"); + Template tpl ("templates"); + tree.create_tree_html (&tpl, "Test/Out"); + std::chrono::steady_clock::time_point t2 (std::chrono::steady_clock::now()); + std::chrono::duration dur (t2 - t1); + std::cout << dur.count () << std::endl; + // // } // Document doc; diff --git a/biawebdoclist.hpp b/biawebdoclist.hpp index 547664a..8a92cdd 100644 --- a/biawebdoclist.hpp +++ b/biawebdoclist.hpp @@ -10,6 +10,7 @@ #include #include "biawebstrings.hpp" #include "biawebdocument.hpp" +#include "biawebtemplate.hpp" // to implement a list of items (documents) with creation/modified date/time display namespace biaweb { @@ -59,16 +60,12 @@ namespace biaweb { } // output to HTML vide the template - std::string to_html (std::string templatedir); + std::string to_html (Template *t); }; // output to HTML vide the template - std::string DocListItem::to_html (std::string templatedir) { - std::ifstream templ (templatedir + "/doclistitem.tpl.html"); - std::string templstr ((std::istreambuf_iterator (templ)), - (std::istreambuf_iterator ()) ); - templ.close (); - + std::string DocListItem::to_html (Template *t) { + std::string templstr = t->get_doclistitem_tpl (); std::tm c, m; c = *std::localtime (&this->ctime); m = *std::localtime (&this->mtime); @@ -95,22 +92,18 @@ namespace biaweb { this->items.insert (this->items.cend(), docitem); } // render to HTML from a template - std::string to_html (std::string templatedir); + std::string to_html (Template *t); }; - std::string DocList::to_html (std::string templatedir) { - std::ifstream templ (templatedir + "/doclist.tpl.html"); - std::string templstr ( (std::istreambuf_iterator (templ) ), - (std::istreambuf_iterator ())); - - templ.close (); + std::string DocList::to_html (Template *t) { + std::string templstr = t->get_doclist_tpl (); std::string outputhtml = ""; // if the number of elements is non zero if (this->items.size () != 0) { std::string docitems = ""; for (DocListItem item : this->items) - docitems += item.to_html (templatedir); + docitems += item.to_html (t); outputhtml = fmt::format (templstr, fmt::arg ("title", this->title), diff --git a/biawebdocument.hpp b/biawebdocument.hpp index 65005dd..3972107 100644 --- a/biawebdocument.hpp +++ b/biawebdocument.hpp @@ -8,11 +8,11 @@ #include #include #include -#include #include "biawebutil.hpp" #include "biawebsidebar.hpp" #include "biawebstrings.hpp" #include "biawebnavigationbit.hpp" +#include "biawebtemplate.hpp" // class to represent a biaweb document which can have a file name, title, description, // keywords, content and sidebar items @@ -101,8 +101,8 @@ namespace biaweb { return this->cdate; } - // output the document to HTML using the templates in templatedir - void output_to_html (std::string templatedir, std::string path); + // output the document to HTML using the template specified + void output_to_html (Template *t, std::string path); // set the content portion of document as raw HTML content void set_content (std::string content) { @@ -194,26 +194,20 @@ namespace biaweb { } // output the document using the provided template - void Document::output_to_html (std::string templatedir, std::string path) + void Document::output_to_html (Template *t, std::string path) { - // read the main template file - std::ifstream tpl (templatedir + "/main.tpl.html"); - std::string templstr ( (std::istreambuf_iterator (tpl)), - (std::istreambuf_iterator ()) ); - tpl.close (); + std::string templstr = t->get_main_tpl (); + // read the style template file - std::ifstream style (templatedir + "/style.tpl.css"); - std::string stylesheet ( (std::istreambuf_iterator (style)), - (std::istreambuf_iterator ())); - style.close (); + std::string stylesheet = t->get_style_tpl (); // first render the sidebars std::string sidebartext; for (SideBar bar : sidebars) { - sidebartext += bar.to_html (templatedir); + sidebartext += bar.to_html (t); } // render the navigation bit - std::string navbit_str = this->navbit.to_html (templatedir); + std::string navbit_str = this->navbit.to_html (t); // time of creation and modification struct std::tm c, m; diff --git a/biawebdocumenttree.hpp b/biawebdocumenttree.hpp index 9122feb..e1e6401 100644 --- a/biawebdocumenttree.hpp +++ b/biawebdocumenttree.hpp @@ -11,6 +11,7 @@ #include "biawebstrings.hpp" #include "biawebutil.hpp" #include "biawebdoclist.hpp" +#include "biawebtemplate.hpp" // class to implement a document tree - both with or without subtrees namespace biaweb { @@ -29,17 +30,12 @@ namespace biaweb { std::string stub; // list of documents in this tree std::list docs; - // common strings used for template generation - std::array doc_strings; // set the parent - protected function as this has to be // called only by add_child void set_parent (DocumentTree *parent) { this->parent = parent; } - // load document generation strings from file stringbits.txt from template dir - void load_doc_strings (std::string templatedir); - public: // method to build a document tree from a path void document_tree_builder (std::string srcpath); @@ -77,7 +73,7 @@ namespace biaweb { } // create the document index for this tree - void create_tree_html (std::string templatedir, std::string destdir); + void create_tree_html (Template *t, std::string destdir); // set the title void set_title (std::string title) { @@ -136,22 +132,6 @@ namespace biaweb { return lev; } - // load document generation strings from file stringbits.txt from template dir - void DocumentTree::load_doc_strings (std::string templatedir) { - // load the template file - std::ifstream stringsfile (templatedir + "/stringbits.txt"); - - std::string line; - // read line by line and append it to doc_strings - int i = 0; - while (! stringsfile.eof () && i < this->doc_strings.size ()) { - std::getline (stringsfile, line); - this->doc_strings[i] = line; - i ++; - } - stringsfile.close (); - } - // get the stub hierarchy for this tree std::string DocumentTree::stub_hierarchy () { std::list levels; @@ -185,9 +165,7 @@ namespace biaweb { // create the tree - the index file for this tree and all the documents and // the child trees recursively - using the template specified - void DocumentTree::create_tree_html (std::string templatedir, std::string destdir) { - // load the document string bits to be used in templates - this->load_doc_strings (templatedir); + void DocumentTree::create_tree_html (Template *tpl, std::string destdir) { // create a document to represent the index of the tree. std::unique_ptr index (new Document (this->title)); @@ -208,13 +186,13 @@ namespace biaweb { // If this tree has a parent, create a sidebar link to the level up std::unique_ptr bar1 (new SideBar()); GenericLinkItem item0; - bar1.get()->set_title (this->doc_strings [NAVIGATION]); - item0.set_item_text (this->doc_strings[INDEX]); + bar1.get()->set_title (tpl->get_stringbit (NAVIGATION)); + item0.set_item_text (tpl->get_stringbit (INDEX)); item0.set_item_url (urlpath + "index.html"); bar1.get()->add_sidebar_item (item0); if (this->get_parent() != nullptr) { GenericLinkItem item1; - item1.set_item_text (this->doc_strings[GO_UP]); + item1.set_item_text (tpl->get_stringbit(GO_UP)); item1.set_item_url (this->stub_hierarchy() + "index.html"); bar1.get()->add_sidebar_item (item1); } @@ -222,7 +200,7 @@ namespace biaweb { // create a sidebar for the child levels if there are children std::unique_ptr bar2 (new SideBar ()); - bar2.get()->set_title (this->doc_strings[SUB_CAT] + this->title); + bar2.get()->set_title (tpl->get_stringbit (SUB_CAT) + this->title); for (DocumentTree tree : this->children) { // we use site relative URLs that rely on the base href tag // so for biaweb generated sites, the base href tag should be @@ -238,7 +216,7 @@ namespace biaweb { // Create the list of documents in this tree with links std::unique_ptr article_list (new DocList ()); - article_list.get()->set_title (this->title + ": " + this->doc_strings[ARTICLES_LIST]); + article_list.get()->set_title (this->title + ": " + tpl->get_stringbit (ARTICLES_LIST)); // sort the documents as per creation time and then add the document // links - newest documents should appear above older ones. sort_documents_creation_time (); @@ -253,7 +231,7 @@ namespace biaweb { navbit.get()->add_link_item (GenericLinkItem(par1->stub, par1->stub_hierarchy() + par1->stub + "/index.html")); else - navbit.get()->add_link_item (GenericLinkItem(this->doc_strings[HOME], "index.html")); + navbit.get()->add_link_item (GenericLinkItem(tpl->get_stringbit(HOME), "index.html")); par1 = par1->parent; } @@ -267,20 +245,20 @@ namespace biaweb { doc.set_navigation_bit (*navbit.get()); doc.add_side_bar (*bar1.get()); doc.add_side_bar (*bar2.get()); - doc.output_to_html (templatedir, filepath); + doc.output_to_html (tpl, filepath); } // add the navigation bit index.get()->set_navigation_bit (*navbit.get()); // index should contain the summary followed by the article list - index.get()->set_content (this->summary + article_list.get()->to_html(templatedir)); + index.get()->set_content (this->summary + article_list.get()->to_html(tpl)); // output the index file - index.get()->output_to_html (templatedir, filepath); + index.get()->output_to_html (tpl, filepath); // recursively create index for children for (DocumentTree tree : this->children) - tree.create_tree_html (templatedir, destdir); + tree.create_tree_html (tpl, destdir); } // build a document tree from a filesystem path recursively @@ -307,9 +285,7 @@ namespace biaweb { // the contents to the summary of the Doctree if (fsitem.path().stem().string() == "index") { - std::ifstream infile (fsitem.path()); - std::string infilestr ( (std::istreambuf_iterator (infile)), - (std::istreambuf_iterator ()) ); + std::string infilestr = load_from_file (fsitem.path ()); this->set_markdown_summary (infilestr); } // else it is a non-index file- diff --git a/biawebnavigationbit.hpp b/biawebnavigationbit.hpp index 6be5b40..08a2cc5 100644 --- a/biawebnavigationbit.hpp +++ b/biawebnavigationbit.hpp @@ -6,6 +6,7 @@ #include #include "biawebutil.hpp" #include "biawebsidebar.hpp" +#include "biawebtemplate.hpp" namespace biaweb { // class to represent a navigation bit like this in html @@ -21,20 +22,17 @@ namespace biaweb { } // render using the given template directory - std::string to_html (std::string templatedir) ; + std::string to_html (Template *t) ; }; // render using the given template - std::string NavigationBit::to_html (std::string templatedir) { - std::ifstream templ (templatedir + "/navigationbit.tpl.html"); - std::string templ_str ((std::istreambuf_iterator (templ)), - (std::istreambuf_iterator ())); - + std::string NavigationBit::to_html (Template *t) { + std::string templ_str = t->get_navigationbit_tpl (); std::string output_html = ""; std::string items_str = ""; for (GenericLinkItem item : this->items) - items_str += item.to_html (templatedir); + items_str += item.to_html (t); if (this->items.size () > 0) output_html = fmt::format (templ_str, fmt::arg ("items", items_str)); diff --git a/biawebsidebar.hpp b/biawebsidebar.hpp index 6f419fa..226f51a 100644 --- a/biawebsidebar.hpp +++ b/biawebsidebar.hpp @@ -6,6 +6,7 @@ #include #include #include "biawebutil.hpp" +#include "biawebtemplate.hpp" // classes to describe the a list of (link) items and sidebar containers which form part of // main document @@ -30,8 +31,8 @@ namespace biaweb { void set_item_url (std::string url) { this->itemurl = escape_html (url); } - // output to HTML using a template directory specified - std::string to_html (std::string templatedir); + // output to HTML using a template specified + std::string to_html (Template *t); GenericLinkItem (std::string text = "", std::string url = "") { this->itemtext = escape_html (text); @@ -39,17 +40,13 @@ namespace biaweb { } }; - std::string GenericLinkItem::to_html (std::string templatedir) { + std::string GenericLinkItem::to_html (Template *t) { std::string html = ""; // if url is not empty it is a link item so load the sidebar link template if (! this->itemurl.empty ()) { if (!this->itemtext.empty ()) { - std::ifstream tpl_linkitem (templatedir + "/genericlinklistitem.tpl.html"); - - std::string tpl_linkitem_str ( (std::istreambuf_iterator (tpl_linkitem)), - (std::istreambuf_iterator ())); - tpl_linkitem.close (); + std::string tpl_linkitem_str = t->get_genericlinklistitem_tpl (); html = fmt::format (tpl_linkitem_str, fmt::arg ("itemurl", this->itemurl), fmt::arg ("itemtext", this->itemtext)); @@ -58,11 +55,7 @@ namespace biaweb { // Non link item. Load the normal sidebar item template. else if (! this->itemtext.empty ()) { - std::ifstream tpl_item (templatedir + "/genericlistitem.tpl.html"); - - std::string tpl_item_str ( (std::istreambuf_iterator (tpl_item)), - (std::istreambuf_iterator ())); - tpl_item.close (); + std::string tpl_item_str = t->get_genericlistitem_tpl (); html = fmt::format (tpl_item_str, fmt::arg ("itemtext", this->itemtext) ); } return html; @@ -84,20 +77,18 @@ namespace biaweb { this->items.insert (this->items.cend(), item); } - // render the sidebar using the template directory specified - std::string to_html (std::string templatedir) ; + // render the sidebar using the template specified + std::string to_html (Template *t) ; }; // render the sidebar to HTML representation from the template. - std::string SideBar::to_html (std::string templatedir) { - std::ifstream sidetpl (templatedir + "/sidebar.tpl.html"); - std::string sidetpl_str ( ( std::istreambuf_iterator (sidetpl)) , - (std::istreambuf_iterator ())); - sidetpl.close (); + std::string SideBar::to_html (Template *t) { + std::string sidetpl_str = t->get_sidebar_tpl (); + std::string listitems; // first get the sidebar items and render them to HTML for (GenericLinkItem item : this->items) { - listitems += item.to_html (templatedir); + listitems += item.to_html (t); } std::string html = ""; diff --git a/biawebtemplate.hpp b/biawebtemplate.hpp new file mode 100644 index 0000000..604cb26 --- /dev/null +++ b/biawebtemplate.hpp @@ -0,0 +1,67 @@ +#ifndef __BIAWEBTEMPLATE__ +#define __BIAWEBTEMPLATE__ + +#include +#include +#include "biawebutil.hpp" + +namespace biaweb { + // class to load template from a directory for use with classes requiring to output + // via templates + class Template { + protected: + // all the template bits stored as strings + std::string main_tpl; + std::string doclist_tpl; + std::string doclistitem_tpl; + std::string genericlinklistitem_tpl; + std::string genericlistitem_tpl; + std::string navigationbit_tpl; + std::string sidebar_tpl; + std::string style_tpl; + std::array stringbits; + public: + // constructor: generate the template bits from a template directory + Template (std::string templatedir) ; + + // getters; + std::string get_main_tpl () { return this->main_tpl; } + std::string get_doclist_tpl () { return this->doclist_tpl; } + std::string get_doclistitem_tpl () { return this->doclistitem_tpl; } + std::string get_genericlistitem_tpl () { return this->genericlistitem_tpl; } + std::string get_genericlinklistitem_tpl () { return this->genericlinklistitem_tpl; } + std::string get_navigationbit_tpl () { return this->navigationbit_tpl; } + std::string get_sidebar_tpl () { return this->sidebar_tpl; } + std::string get_style_tpl () { return this->style_tpl; } + std::string get_stringbit (unsigned int id) { return this->stringbits[id]; } + }; + + // construct a template from a source directory + Template::Template (std::string templatedir) { + // read the templates + this->main_tpl = load_from_file (templatedir + "/main.tpl.html"); + this->doclist_tpl = load_from_file (templatedir + "/doclist.tpl.html"); + this->doclistitem_tpl = load_from_file (templatedir + "/doclistitem.tpl.html"); + this->genericlinklistitem_tpl = load_from_file + (templatedir + "/genericlinklistitem.tpl.html"); + this->genericlistitem_tpl = load_from_file (templatedir + "/genericlistitem.tpl.html"); + this->navigationbit_tpl = load_from_file (templatedir + "/navigationbit.tpl.html"); + this->sidebar_tpl = load_from_file (templatedir + "/sidebar.tpl.html"); + this->style_tpl = load_from_file (templatedir + "/style.tpl.css"); + + + // read the stringbits into the array + std::ifstream f (templatedir + "/stringbits.txt"); + unsigned int i = 0; + std::string line; + while (! f.eof () && i < this->stringbits.size ()) { + std::getline (f, line); + this->stringbits[i] = line; + i ++; + } + f.close (); + } + +} + +#endif \ No newline at end of file diff --git a/biawebutil.hpp b/biawebutil.hpp index c8603ea..279d394 100644 --- a/biawebutil.hpp +++ b/biawebutil.hpp @@ -1,6 +1,7 @@ #ifndef __BIAWEBUTIL__ #define __BIAWEBUTIL__ #include +#include // "discount" markdown library is a C library and hence requires to be wrapped in // extern "C" @@ -11,6 +12,13 @@ extern "C" { // utility functions for Biaweb that don't fit into any class and can be used by // any class namespace biaweb { + // load a string from file + std::string load_from_file (std::string filename) { + std::ifstream f (filename); + std::string r ((std::istreambuf_iterator (f)), + (std::istreambuf_iterator ())); + return r; + } // convert markdown std::string convert_to_markdown (std::string str) { @@ -29,11 +37,7 @@ namespace biaweb { FILE *f = fdopen (fd, "w"); markdown (doc, f, 0); fclose (f); - std::ifstream ftmp (tempfile); - std::string tmpl ( (std::istreambuf_iterator (ftmp)), - (std::istreambuf_iterator ()) - ); - ftmp.close (); + std::string tmpl = load_from_file (tempfile); mkd_cleanup (doc); remove (tempfile); return tmpl; diff --git a/templates/main.tpl.html b/templates/main.tpl.html index 198a3c5..c57f20c 100644 --- a/templates/main.tpl.html +++ b/templates/main.tpl.html @@ -1,9 +1,10 @@ + My Site - {title} - - + + -
+ +

My Site

Created on: {cdate:%d %b %Y, %H:%M %Z}, last modified: {mdate:%d %b %Y, %H:%M %Z}
@@ -22,6 +24,7 @@ {sidebar} diff --git a/templates/style.tpl.css b/templates/style.tpl.css index 3b3358e..d1688ca 100644 --- a/templates/style.tpl.css +++ b/templates/style.tpl.css @@ -13,8 +13,8 @@ header { width: 100%; color: white; background-color:#a1a0c0; - height: 50px; float: left; + text-align: center; } .inlinelist {