From d531418ad2300463bd975829f0a0f4eec7a86e2f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 5 May 2023 23:20:03 +0200 Subject: [PATCH] Layout statistics form - caching, refactoring, printing statistics for 'all' shapes --- src/layui/layui/layLayoutStatisticsForm.cc | 563 ++++++++++++--------- src/tl/tl/tlUri.cc | 9 +- 2 files changed, 331 insertions(+), 241 deletions(-) diff --git a/src/layui/layui/layLayoutStatisticsForm.cc b/src/layui/layui/layLayoutStatisticsForm.cc index b5d8af8cb..77c883bd2 100644 --- a/src/layui/layui/layLayoutStatisticsForm.cc +++ b/src/layui/layui/layLayoutStatisticsForm.cc @@ -28,6 +28,8 @@ #include "tlString.h" #include "tlExpression.h" #include "tlTimer.h" +#include "tlUri.h" +#include "tlFileUtils.h" #include "dbLayoutQuery.h" #include "dbCellGraphUtils.h" @@ -135,10 +137,10 @@ static std::string format_tech_name (const std::string &s) class StatisticsTemplateProcessor { public: - StatisticsTemplateProcessor (const QUrl &url, const db::Layout *layout) + StatisticsTemplateProcessor (const tl::URI &url, const db::Layout *layout) : mp_layout (layout) { - QResource res (QString::fromUtf8 (":/st/") + url.path ()); + QResource res (QString::fromUtf8 (":/st/") + QString::fromUtf8 (url.path ().c_str ())); #if QT_VERSION >= 0x60000 if (res.compressionAlgorithm () == QResource::ZlibCompression) { #else @@ -149,13 +151,9 @@ public: m_temp = QByteArray ((const char *)res.data (), (int)res.size ()); } -#if QT_VERSION >= 0x050000 - QList > queryItems = QUrlQuery (url.query ()).queryItems (); -#else - QList > queryItems = url.queryItems (); -#endif - for (QList >::const_iterator q = queryItems.begin (); q != queryItems.end (); ++q) { - m_top_eval.set_var (tl::to_string (q->first), tl::to_string (q->second)); + auto query_items = url.query (); + for (auto q = query_items.begin (); q != query_items.end (); ++q) { + m_top_eval.set_var (q->first, q->second); } } @@ -496,11 +494,27 @@ public: return count (db::Shape::Edge); } + size_t edge_pair_total () const + { + return count (db::Shape::EdgePair); + } + size_t user_total () const { return count (db::Shape::UserObject); } + size_t all_total () const + { + return box_total () + + polygon_total () + + path_total () + + text_total () + + edge_total () + + edge_pair_total () + + user_total (); + } + private: std::map m_count; }; @@ -517,278 +531,357 @@ public: // .. nothing yet .. } - std::string get (const std::string &url); + std::string get (const std::string &url) + { + auto p = m_page_cache.find (url); + if (p != m_page_cache.end ()) { + return p->second; + } else { + std::string t = get_impl (url); + m_page_cache [url] = t; + return t; + } + } + + void clear_cache () + { + m_page_cache.clear (); + } private: const lay::LayoutHandleRef m_h; + std::map m_page_cache; + + std::string index_page (const tl::URI &uri) const; + std::string per_layer_stat_page (const tl::URI &uri) const; + std::string get_impl (const std::string &url); }; +static std::string s_per_layer_stat_path_ld = "per-layer-stat-ld"; +static std::string s_per_layer_stat_path_name = "per-layer-stat-name"; + std::string -StatisticsSource::get (const std::string &url) +StatisticsSource::per_layer_stat_page (const tl::URI &uri) const { - static QString s_per_layer_stat_path_ld = QString::fromUtf8 ("per-layer-stat-ld"); - static QString s_per_layer_stat_path_name = QString::fromUtf8 ("per-layer-stat-name"); + // This is the default top level page + // TODO: handle other input as well - QUrl qurl (tl::to_qstring (url)); - QFileInfo fi (qurl.path ()); + const db::Layout &layout = m_h->layout (); - if (fi.suffix () == QString::fromUtf8 ("stxml")) { + std::ostringstream os; + os.imbue (std::locale ("C")); - StatisticsTemplateProcessor tp (qurl, &m_h->layout ()); - tp.process (); - std::string r = tp.get ().constData (); - return r; + std::vector layers; + for (unsigned int i = 0; i < layout.layers (); ++i) { + if (layout.is_valid_layer (i)) { + layers.push_back (i); + } + } - } else if (fi.baseName () == s_per_layer_stat_path_ld || fi.baseName () == s_per_layer_stat_path_name) { + if (tl::basename (uri.path ()) == s_per_layer_stat_path_ld) { + std::sort (layers.begin (), layers.end (), CompareLDName (layout)); + } else { + std::sort (layers.begin (), layers.end (), CompareNameLD (layout)); + } - // This is the default top level page - // TODO: handle other input as well + os << "" << std::endl + << "" << std::endl + << "

" << tl::to_string (QObject::tr ("Detailed Layer Statistics for '")) << m_h->name () << "'

" << std::endl - const db::Layout &layout = m_h->layout (); + << "

" << std::endl + << "" << std::endl - std::ostringstream os; - os.imbue (std::locale ("C")); + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + << "" << std::endl + ; + + db::CellCounter cc (&layout); + + tl::RelativeProgress progress (tl::to_string (QObject::tr ("Collecting statistics")), layers.size () * layout.cells (), 100000); + for (std::vector ::const_iterator l = layers.begin (); l != layers.end (); ++l) { + + ShapeStatistics st_hier; + ShapeStatistics st_flat; + + for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) { + + ShapeStatistics st; + st.compute (layout.cell (*c).shapes (*l)); + + st_hier += st; + st *= cc.weight (*c); + st_flat += st; + + ++progress; - std::vector layers; - for (unsigned int i = 0; i < layout.layers (); ++i) { - if (layout.is_valid_layer (i)) { - layers.push_back (i); - } } - if (fi.baseName () == s_per_layer_stat_path_ld) { - std::sort (layers.begin (), layers.end (), CompareLDName (layout)); - } else { - std::sort (layers.begin (), layers.end (), CompareNameLD (layout)); - } - - os << "" << std::endl - << "" << std::endl - << "

" << tl::to_string (QObject::tr ("Detailed Layer Statistics for '")) << m_h->name () << "'

" << std::endl - - << "

" << std::endl - << "

" << tl::to_string (QObject::tr ("Layer")) << "" << tl::to_string (QObject::tr ("All")) << "" << tl::to_string (QObject::tr ("Boxes")) << "" << tl::to_string (QObject::tr ("Polygons")) << "" << tl::to_string (QObject::tr ("Paths")) << "" << tl::to_string (QObject::tr ("Texts")) << "" << tl::to_string (QObject::tr ("Edges")) << "" << tl::to_string (QObject::tr ("Edge Pairs")) << "" << tl::to_string (QObject::tr ("User objects")) << "
" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(total)")) << "
" << std::endl - - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl + os << "" << std::endl + << "" << std::endl + << "" << std::endl + // Boxes (total, single, array) + << "" << std::endl + << "" << std::endl + << "" << std::endl + // Polygons (total, single, array) + << "" << std::endl + << "" << std::endl + << "" << std::endl + // Paths (total, single, array) + << "" << std::endl + << "" << std::endl + << "" << std::endl + // Texts (total, single, array) + << "" << std::endl + << "" << std::endl + << "" << std::endl + // Edges (total) + << "" << std::endl + // EdgePairs (total) + << "" << std::endl + // User objects (total) + << "" << std::endl + // ... + << "" << std::endl << "" << std::endl ; - db::CellCounter cc (&layout); + } - tl::RelativeProgress progress (tl::to_string (QObject::tr ("Collecting statistics")), layers.size () * layout.cells (), 100000); - for (std::vector ::const_iterator l = layers.begin (); l != layers.end (); ++l) { + os << "
" << tl::to_string (QObject::tr ("Layer")) << "" << tl::to_string (QObject::tr ("Boxes")) << "" << tl::to_string (QObject::tr ("Polygons")) << "" << tl::to_string (QObject::tr ("Paths")) << "" << tl::to_string (QObject::tr ("Texts")) << "" << tl::to_string (QObject::tr ("Edges")) << "" << tl::to_string (QObject::tr ("User objects")) << "
" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(single)")) << "" << tl::to_string (QObject::tr ("(arrays)")) << "" << tl::to_string (QObject::tr ("(total)")) << "" << tl::to_string (QObject::tr ("(total)")) << "
" << tl::escaped_to_html (layout.get_properties (*l).to_string (), true) << "" << st_hier.all_total () << "

" << st_flat.all_total () << "
" << st_hier.box_total () << "

" << st_flat.box_total () << "
" << st_hier.box_single () << "

" << st_flat.box_single () << "
" << st_hier.box_array () << "

" << st_flat.box_array () << "
" << st_hier.polygon_total () << "

" << st_flat.polygon_total () << "
" << st_hier.polygon_single () << "

" << st_flat.polygon_single () << "
" << st_hier.polygon_array () << "

" << st_flat.polygon_array () << "
" << st_hier.path_total () << "

" << st_flat.path_total () << "
" << st_hier.path_single () << "

" << st_flat.path_single () << "
" << st_hier.path_array () << "

" << st_flat.path_array () << "
" << st_hier.text_total () << "

" << st_flat.text_total () << "
" << st_hier.text_single () << "

" << st_flat.text_single () << "
" << st_hier.text_array () << "

" << st_flat.text_array () << "
" << st_hier.edge_total () << "

" << st_flat.edge_total () << "
" << st_hier.edge_pair_total () << "

" << st_flat.edge_pair_total () << "
" << st_hier.user_total () << "

" << st_flat.user_total () << "
" << tl::to_string (QObject::tr ("(hier)")) << "

" << tl::to_string (QObject::tr ("(flat)")) << "
" << std::endl + << "

" << std::endl + << tl::to_string (QObject::tr ("

Note

" + "

" + "\"(hier)\" is the object count where each cell counts once. " + "\"(flat)\" is the \"as if flat\" count where the cells count as many times as they are seen from the top cells." + "

" + "

" + "\"(total)\" is the effective number of shapes. \"(single)\" are the single shapes. " + "\"(arrays)\" is the number of shape arrays where each array counts as one, but contributes many individual shapes to \"(total)\"." + "

" + )) + << "" << std::endl + << ""; + + return os.str (); +} + +std::string +StatisticsSource::index_page (const tl::URI & /*uri*/) const +{ + // maybe later ... + bool with_shape_statistics = false; + + // This is the default top level page + // TODO: handle other input as well + + const db::Layout &layout = m_h->layout (); + + std::ostringstream os; + os.imbue (std::locale ("C")); + + size_t num_cells = layout.cells (); + + size_t num_layers = 0; + for (unsigned int i = 0; i < layout.layers (); ++i) { + if (layout.is_valid_layer (i)) { + ++num_layers; + } + } + + db::CellCounter cc (&layout); + + os << "" << std::endl + << "" << std::endl + << "

" << tl::to_string (QObject::tr ("Common Statistics For '")) << tl::escaped_to_html (m_h->name (), true) << "'

" << std::endl + << "

" << std::endl + << "" << std::endl + << "" + << "" + << "" << std::endl; + if (! m_h->save_options ().format ().empty ()) { + os << "" + << "" + << "" << std::endl; + } + os << "" + << "" + << "" << std::endl + << "" + << "" + << "" << std::endl + << "" + << "" + << "" << std::endl + << "" + << "" + << "" << std::endl; + for (db::Layout::meta_info_iterator meta = layout.begin_meta (); meta != layout.end_meta (); ++meta) { + std::string d = meta->second.description; + if (!d.empty ()) { + d = layout.meta_info_name (meta->first); + } + os << "" << std::endl; + } + os << "
" << tl::to_string (QObject::tr ("Path")) << ": " << tl::escaped_to_html (m_h->filename (), true) << "
" << tl::to_string (QObject::tr ("Format")) << ": " << tl::escaped_to_html (m_h->save_options ().format (), true) << "
" << tl::to_string (QObject::tr ("Technology")) << ": " << tl::escaped_to_html (m_h->technology ()->description (), true) << tl::escaped_to_html (format_tech_name (m_h->tech_name ()), true) << "
" << tl::to_string (QObject::tr ("Database unit")) << ": " << tl::sprintf ("%.12g ", layout.dbu ()) << tl::to_string (QObject::tr ("micron")) << "
" << tl::to_string (QObject::tr ("Number of cells")) << ": " << num_cells << "
" << tl::to_string (QObject::tr ("Number of layers")) << ": " << num_layers << "
" << tl::escaped_to_html (d, true) << "" << tl::escaped_to_html (meta->second.value.to_string (), true) << "
" << std::endl + << "

" << tl::to_string (QObject::tr ("Top Cells")) << "

" << std::endl + << "" << std::endl; + for (db::Layout::top_down_const_iterator tc = layout.begin_top_down (); tc != layout.end_top_cells (); ++tc) { + os << "" << std::endl; + } + os << "
" << tl::escaped_to_html (layout.cell_name (*tc), true) << "
" << std::endl; + os << "

" << std::endl; + + std::vector layers_with_oasis_names; + + std::vector layers_sorted_by_ld; + layers_sorted_by_ld.reserve (num_layers); + for (unsigned int i = 0; i < layout.layers (); ++i) { + if (layout.is_valid_layer (i)) { + layers_sorted_by_ld.push_back (i); + const db::LayerProperties &lp = layout.get_properties (i); + if (! lp.name.empty ()) { + layers_with_oasis_names.push_back (i); + } + } + } + + std::sort (layers_sorted_by_ld.begin (), layers_sorted_by_ld.end (), CompareLDName (layout)); + std::sort (layers_with_oasis_names.begin (), layers_with_oasis_names.end (), CompareNameLD (layout)); + + if (! layers_sorted_by_ld.empty ()) { + + os << "

" << tl::to_string (QObject::tr ("Layers (sorted by layer and datatype)")) << "

" << std::endl + << "

Detailed layer statistics

" << std::endl + << "

" << std::endl + << "" << std::endl + << ""; + if (! layers_with_oasis_names.empty ()) { + os << ""; + } + if (with_shape_statistics) { + os << ""; + os << ""; + } + os << "" << std::endl; + + tl::RelativeProgress progress (tl::to_string (QObject::tr ("Collecting statistics")), layers_sorted_by_ld.size () * layout.cells (), 100000); + for (std::vector ::const_iterator i = layers_sorted_by_ld.begin (); i != layers_sorted_by_ld.end (); ++i) { + + if (! layout.is_valid_layer (*i)) { + continue; + } ShapeStatistics st_hier; ShapeStatistics st_flat; - for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) { + if (with_shape_statistics) { + for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) { - ShapeStatistics st; - st.compute (layout.cell (*c).shapes (*l)); + ShapeStatistics st; + st.compute (layout.cell (*c).shapes (*i)); - st_hier += st; - st *= cc.weight (*c); - st_flat += st; + st_hier += st; + st *= cc.weight (*c); + st_flat += st; - ++progress; + ++progress; - } - - os << "" << std::endl - << "" << std::endl - // Boxes (total, single, array) - << "" << std::endl - << "" << std::endl - << "" << std::endl - // Polygons (total, single, array) - << "" << std::endl - << "" << std::endl - << "" << std::endl - // Paths (total, single, array) - << "" << std::endl - << "" << std::endl - << "" << std::endl - // Texts (total, single, array) - << "" << std::endl - << "" << std::endl - << "" << std::endl - // Edges (total) - << "" << std::endl - // User objects (total) - << "" << std::endl - // ... - << "" << std::endl - << "" << std::endl - ; - - } - - os << "
" << tl::to_string (QObject::tr ("Layer/Datatype")) << "  " << tl::to_string (QObject::tr ("Layer name")) << "" << tl::to_string (QObject::tr ("Shape count (hier)")) << "" << tl::to_string (QObject::tr ("Shape count (flat)")) << "
" << layout.get_properties (*l).to_string () << "" << st_hier.box_total () << "

" << st_flat.box_total () << "
" << st_hier.box_single () << "

" << st_flat.box_single () << "
" << st_hier.box_array () << "

" << st_flat.box_array () << "
" << st_hier.polygon_total () << "

" << st_flat.polygon_total () << "
" << st_hier.polygon_single () << "

" << st_flat.polygon_single () << "
" << st_hier.polygon_array () << "

" << st_flat.polygon_array () << "
" << st_hier.path_total () << "

" << st_flat.path_total () << "
" << st_hier.path_single () << "

" << st_flat.path_single () << "
" << st_hier.path_array () << "

" << st_flat.path_array () << "
" << st_hier.text_total () << "

" << st_flat.text_total () << "
" << st_hier.text_single () << "

" << st_flat.text_single () << "
" << st_hier.text_array () << "

" << st_flat.text_array () << "
" << st_hier.edge_total () << "

" << st_flat.edge_total () << "
" << st_hier.user_total () << "

" << st_flat.user_total () << "
" << tl::to_string (QObject::tr ("(hier)")) << "

" << tl::to_string (QObject::tr ("(flat)")) << "
" << std::endl - << "

" << std::endl - << tl::to_string (QObject::tr ("

Note

" - "

" - "\"(hier)\" is the object count where each cell counts once. " - "\"(flat)\" is the \"as if flat\" count where the cells count as many times as they are seen from the top cells." - "

" - "

" - "\"(total)\" is the effective number of shapes. \"(single)\" are the single shapes. " - "\"(arrays)\" is the number of shape arrays where each array counts as one, but contributes many individual shapes to \"(total)\"." - "

" - )) - << "" << std::endl - << ""; - - return os.str (); - - } else { - - // This is the default top level page - // TODO: handle other input as well - - const db::Layout &layout = m_h->layout (); - - std::ostringstream os; - os.imbue (std::locale ("C")); - - size_t num_cells = layout.cells (); - - size_t num_layers = 0; - for (unsigned int i = 0; i < layout.layers (); ++i) { - if (layout.is_valid_layer (i)) { - ++num_layers; - } - } - - os << "" << std::endl - << "" << std::endl - << "

" << tl::to_string (QObject::tr ("Common Statistics For '")) << m_h->name () << "'

" << std::endl - << "

" << std::endl - << "" << std::endl - << "" - << "" - << "" << std::endl; - if (! m_h->save_options ().format ().empty ()) { - os << "" - << "" - << "" << std::endl; - } - os << "" - << "" - << "" << std::endl - << "" - << "" - << "" << std::endl - << "" - << "" - << "" << std::endl - << "" - << "" - << "" << std::endl; - for (db::Layout::meta_info_iterator meta = layout.begin_meta (); meta != layout.end_meta (); ++meta) { - os << "" << std::endl; - } - os << "
" << tl::to_string (QObject::tr ("Path")) << ": " << m_h->filename () << "
" << tl::to_string (QObject::tr ("Format")) << ": " << m_h->save_options ().format () << "
" << tl::to_string (QObject::tr ("Technology")) << ": " << m_h->technology ()->description () << format_tech_name (m_h->tech_name ()) << "
" << tl::to_string (QObject::tr ("Database unit")) << ": " << tl::sprintf ("%.12g ", layout.dbu ()) << tl::to_string (QObject::tr ("micron")) << "
" << tl::to_string (QObject::tr ("Number of cells")) << ": " << num_cells << "
" << tl::to_string (QObject::tr ("Number of layers")) << ": " << num_layers << "
" << meta->description << "" << meta->value << "
" << std::endl - << "

" << tl::to_string (QObject::tr ("Top Cells")) << "

" << std::endl - << "" << std::endl; - for (db::Layout::top_down_const_iterator tc = layout.begin_top_down (); tc != layout.end_top_cells (); ++tc) { - os << "" << std::endl; - } - os << "
" << layout.cell_name (*tc) << "
" << std::endl; - os << "

" << std::endl; - - std::vector layers_with_oasis_names; - - std::vector layers_sorted_by_ld; - layers_sorted_by_ld.reserve (num_layers); - for (unsigned int i = 0; i < layout.layers (); ++i) { - if (layout.is_valid_layer (i)) { - layers_sorted_by_ld.push_back (i); - const db::LayerProperties &lp = layout.get_properties (i); - if (! lp.name.empty ()) { - layers_with_oasis_names.push_back (i); } } - } - std::sort (layers_sorted_by_ld.begin (), layers_sorted_by_ld.end (), CompareLDName (layout)); - std::sort (layers_with_oasis_names.begin (), layers_with_oasis_names.end (), CompareNameLD (layout)); - - if (! layers_sorted_by_ld.empty ()) { - - os << "

" << tl::to_string (QObject::tr ("Layers (sorted by layer and datatype)")) << "

" << std::endl - << "

Detailed layer statistics

" << std::endl - << "

" << std::endl - << "" << std::endl - << ""; + const db::LayerProperties &lp = layout.get_properties (*i); + os << "" + << ""; if (! layers_with_oasis_names.empty ()) { - os << ""; + os << ""; + } + if (with_shape_statistics) { + os << ""; + os << ""; } os << "" << std::endl; - for (std::vector ::const_iterator i = layers_sorted_by_ld.begin (); i != layers_sorted_by_ld.end (); ++i) { - if (layout.is_valid_layer (*i)) { - const db::LayerProperties &lp = layout.get_properties (*i); + } + + os << "
" << tl::to_string (QObject::tr ("Layer/Datatype")) << "  
" << tl::sprintf ("%d/%d", lp.layer, lp.datatype) << "" << tl::to_string (QObject::tr ("Layer name")) << "" << tl::escaped_to_html (lp.name, true) << "" << st_hier.all_total () << "" << st_flat.all_total () << "
" << std::endl; + os << "

" << std::endl; + + } + + if (! layers_with_oasis_names.empty ()) { + + os << "

" << tl::to_string (QObject::tr ("Layers (sorted by layer names)")) << "

" << std::endl + << "

Detailed layer statistics

" << std::endl + << "

" << std::endl + << "" << std::endl + << "" << std::endl; + + for (std::vector ::const_iterator i = layers_with_oasis_names.begin (); i != layers_with_oasis_names.end (); ++i) { + if (layout.is_valid_layer (*i)) { + const db::LayerProperties &lp = layout.get_properties (*i); + if (! lp.name.empty ()) { os << "" - << ""; - if (! layers_with_oasis_names.empty ()) { - os << ""; - } - os << "" << std::endl; + << "" + << "" + << "" << std::endl; } } - - os << "
" << tl::to_string (QObject::tr ("Layer name")) << "  " << tl::to_string (QObject::tr ("Layer/Datatype")) << "
" << tl::sprintf ("%d/%d", lp.layer, lp.datatype) << "" << lp.name << "
" << tl::escaped_to_html (lp.name, true) << "" << tl::sprintf ("%d/%d", lp.layer, lp.datatype) << "
" << std::endl; - os << "

" << std::endl; - } - if (! layers_with_oasis_names.empty ()) { + os << "" << std::endl; + os << "

" << std::endl; - os << "

" << tl::to_string (QObject::tr ("Layers (sorted by layer names)")) << "

" << std::endl - << "

Detailed layer statistics

" << std::endl - << "

" << std::endl - << "" << std::endl - << "" << std::endl; - - for (std::vector ::const_iterator i = layers_with_oasis_names.begin (); i != layers_with_oasis_names.end (); ++i) { - if (layout.is_valid_layer (*i)) { - const db::LayerProperties &lp = layout.get_properties (*i); - if (! lp.name.empty ()) { - os << "" - << "" - << "" - << "" << std::endl; - } - } - } + } - os << "
" << tl::to_string (QObject::tr ("Layer name")) << "  " << tl::to_string (QObject::tr ("Layer/Datatype")) << "
" << lp.name << "" << tl::sprintf ("%d/%d", lp.layer, lp.datatype) << "
" << std::endl; - os << "

" << std::endl; + os << "" << std::endl + << "" << std::endl; + ; - } + return os.str (); +} - os << "" << std::endl - << "" << std::endl; - ; +std::string +StatisticsSource::get_impl (const std::string &url) +{ + tl::URI uri (url); + std::string page = tl::basename (uri.path ()); - return os.str (); + if (tl::extension (page) == "stxml") { + + StatisticsTemplateProcessor tp (uri, &m_h->layout ()); + tp.process (); + std::string r = tp.get ().constData (); + return r; + + } else if (page == s_per_layer_stat_path_ld || page == s_per_layer_stat_path_name) { + + return per_layer_stat_page (uri); + + } else { + + return index_page (uri); } } diff --git a/src/tl/tl/tlUri.cc b/src/tl/tl/tlUri.cc index dbd3fc9e6..c416e1e8d 100644 --- a/src/tl/tl/tlUri.cc +++ b/src/tl/tl/tlUri.cc @@ -111,12 +111,9 @@ URI::URI (const std::string &uri) } m_scheme = unescape (m_scheme); - bool prefer_authority = true; - if (m_scheme == "file") { - prefer_authority = false; - // other schemes? - } else if (m_scheme.empty ()) { - prefer_authority = false; + bool prefer_authority = false; + if (m_scheme == "http" || m_scheme == "https") { + prefer_authority = true; } ex0 = ex;