From 8d0fcad676b6358bdb8842219f574c9a80f776d3 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Sun, 19 Apr 2009 20:05:26 +0000 Subject: [PATCH] Speedup the expandLabel by avoiding the recursive part. The labelstrings are computed recursively to get rid of any \thexxx string by the method flattenLabelString. The values are cached in Counter objects. On my mac, the total time (updatelabels+redraw) goes down by 30%. YMMV. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@29342 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Counters.cpp | 101 ++++++++++++++++++++++++++++++---------------- src/Counters.h | 35 ++++++++++------ src/Paragraph.cpp | 2 +- 3 files changed, 89 insertions(+), 49 deletions(-) diff --git a/src/Counters.cpp b/src/Counters.cpp index e3596477a7..0ff9f022cd 100644 --- a/src/Counters.cpp +++ b/src/Counters.cpp @@ -138,15 +138,23 @@ docstring const & Counter::master() const } -docstring const & Counter::labelString() const +docstring const & Counter::labelString(bool in_appendix) const { - return labelstring_; + return in_appendix ? labelstringappendix_ : labelstring_; } -docstring const & Counter::labelStringAppendix() const +docstring const & Counter::flatLabelString(bool in_appendix) const { - return labelstringappendix_; + return in_appendix ? flatlabelstringappendix_ : flatlabelstring_; +} + + +docstring const & Counter::setFlatLabelStrings(docstring const & fls, + docstring const & flsa) +{ + flatlabelstring_ = fls; + flatlabelstringappendix_ = flsa; } @@ -251,8 +259,17 @@ void Counters::reset() current_float_.erase(); CounterList::iterator it = counterList_.begin(); CounterList::iterator const end = counterList_.end(); + std::vector callers; for (; it != end; ++it) { it->second.reset(); + // Compute the explicit counter labels without any + // \thexxx strings, in order to avoid recursion. + // It only needs to be done when the textclass is + // updated, but in practice the extra work is probably + // not noticeable (JMarc) + docstring const fls = flattenLabelString(it->first, false, callers); + docstring const flsa = flattenLabelString(it->first, true, callers); + it->second.setFlatLabelStrings(fls, flsa); } } @@ -417,52 +434,68 @@ docstring Counters::labelItem(docstring const & ctr, docstring Counters::theCounter(docstring const & counter) const { - std::set callers; - return theCounter(counter, callers); + CounterList::const_iterator it = counterList_.find(counter); + if (it == counterList_.end()) + return from_ascii("??"); + return counterLabel(it->second.flatLabelString(appendix())); } -docstring Counters::theCounter(docstring const & counter, - std::set & callers) const + +docstring Counters::flattenLabelString(docstring const & counter, bool in_appendix, + vector & callers) const { docstring label; - if (callers.find(counter) == callers.end()) { + if (find(callers.begin(), callers.end(), counter) != callers.end()) { + // recursion detected + lyxerr << "Warning: Recursion in label for counter `" + << counter << "' detected" + << endl; + return from_ascii("??"); + } - CounterList::const_iterator it = counterList_.find(counter); - if (it == counterList_.end()) - return from_ascii("??"); - Counter const & c = it->second; + CounterList::const_iterator it = counterList_.find(counter); + if (it == counterList_.end()) + return from_ascii("??"); + Counter const & c = it->second; - docstring ls = appendix() ? c.labelStringAppendix() : c.labelString(); + docstring ls = c.labelString(in_appendix); - if (ls.empty()) { - if (!c.master().empty()) - ls = from_ascii("\\the") + c.master() + from_ascii("."); - ls += from_ascii("\\arabic{") + counter + "}"; - } + callers.push_back(counter); + if (ls.empty()) { + if (!c.master().empty()) + ls = flattenLabelString(c.master(), in_appendix, callers) + + from_ascii("."); + callers.pop_back(); + return ls + from_ascii("\\arabic{") + counter + "}"; + } - pair::iterator, bool> const result = callers.insert(counter); - label = counterLabel(ls, &callers); - callers.erase(result.first); - } else { - // recursion detected - lyxerr << "Warning: Recursion in label for counter `" - << counter << "' detected" - << endl; + while (true) { + //lyxerr << "ls=" << to_utf8(ls) << endl; + size_t const i = ls.find(from_ascii("\\the"), 0); + if (i == docstring::npos) + break; + size_t const j = i + 4; + size_t k = j; + while (k < ls.size() && lowercase(ls[k]) >= 'a' + && lowercase(ls[k]) <= 'z') + ++k; + docstring const newc = ls.substr(j, k - j); + docstring const repl = flattenLabelString(newc, in_appendix, callers); + ls.replace(i, k - j + 4, repl); } + callers.pop_back(); - return label; + return ls; } -docstring Counters::counterLabel(docstring const & format, - std::set * callers) const +docstring Counters::counterLabel(docstring const & format) const { docstring label = format; // FIXME: Using regexps would be better, but we compile boost without // wide regexps currently. - while (true) { //lyxerr << "label=" << to_utf8(label) << endl; size_t const i = label.find(from_ascii("\\the"), 0); @@ -473,12 +506,10 @@ docstring Counters::counterLabel(docstring const & format, while (k < label.size() && lowercase(label[k]) >= 'a' && lowercase(label[k]) <= 'z') ++k; - docstring const counter = label.substr(j, k - j); - docstring const repl = callers? theCounter(counter, *callers): - theCounter(counter); + docstring const newc = label.substr(j, k - j); + docstring const repl = theCounter(newc); label.replace(i, k - j + 4, repl); } - while (true) { //lyxerr << "label=" << to_utf8(label) << endl; diff --git a/src/Counters.h b/src/Counters.h index b9ed95c7a1..6ca12991c2 100644 --- a/src/Counters.h +++ b/src/Counters.h @@ -18,7 +18,7 @@ #include "support/docstring.h" #include -#include +#include namespace lyx { @@ -49,14 +49,20 @@ public: docstring const & master() const; /// Returns a LaTeX-like string to format the counter. /** This is similar to what one gets in LaTeX when using - * "\the". + * "\the". The \c in_appendix bool tells whether + * we want the version shown in an appendix. */ - docstring const & labelString() const; - /// Returns a LaTeX-like string to format the counter in appendix. + docstring const & labelString(bool in_appendix) const; + /// Returns a LaTeX-like string to format the counter. /** This is similar to what one gets in LaTeX when using - * "\the" in an appendix. + * "\the". The \c in_appendix bool tells whether + * we want the version shown in an appendix. This version does + * not contain any \\the expression. */ - docstring const & labelStringAppendix() const; + docstring const & flatLabelString(bool in_appendix) const; + /// set the \c flatLabelString values. + docstring const & setFlatLabelStrings(docstring const & fls, + docstring const & flsa); private: /// int value_; @@ -70,6 +76,10 @@ private: docstring labelstring_; /// The same as labelstring_, but in appendices. docstring labelstringappendix_; + /// A version of the labelstring with \\the expressions expanded + docstring flatlabelstring_; + /// A version of the appendix labelstring with \\the expressions expanded + docstring flatlabelstringappendix_; }; @@ -114,9 +124,8 @@ public: docstring theCounter(docstring const & c) const; /// Replace in \c format all the LaTeX-like macros that depend on /// counters. - docstring counterLabel(docstring const & format, - std::set * callers = 0) const; - /// Are we in apendix? + docstring counterLabel(docstring const & format) const; + /// Are we in appendix? bool appendix() const { return appendix_; }; /// Set the state variable indicating whether we are in appendix. void appendix(bool a) { appendix_ = a; }; @@ -129,10 +138,10 @@ public: /// Set the state variable indicating whether we are in a subfloat. void isSubfloat(bool s) { subfloat_ = s; }; private: - /// returns the expanded string representation of the counter - /// with recursion protection through callers. - docstring theCounter(docstring const & c, - std::set & callers) const; + /// expands recusrsively any \\the macro in the + /// labelstring of \c counter. + docstring flattenLabelString(docstring const & counter, bool in_appendix, + std::vector & callers) const; /// Returns the value of the counter according to the /// numbering scheme numbertype. /** Available numbering schemes are arabic (1, 2,...), roman diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 3f0a06d625..52714b8f11 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -1620,7 +1620,7 @@ docstring Paragraph::expandLabel(Layout const & layout, if (fmt.empty() && layout.labeltype == LABEL_COUNTER && !layout.counter.empty()) - fmt = "\\the" + layout.counter; + return tclass.counters().theCounter(layout.counter); // handle 'inherited level parts' in 'fmt', // i.e. the stuff between '@' in '@Section@.\arabic{subsection}' -- 2.39.2