Dear all, Here's a few patches proposing to improve the definitions in support/strfwd.h, results of my experiments.
1. Define docstring using the Unicode strings from C++11 (with char_type=char32_t). This allows us to write docstrings directly with the syntax U"". By extension this is necessary to have Unicode translation strings as discussed before. This is not the final version of the patch however because there is one big disappointment: the C++11 standard does not require several facets (including ctype<char32_t>) that are necessary to use stringstreams of char32_t. So these need to be defined by hand. I reused ones that are currently in support/docstring.cpp written about 10yrs ago but I wonder whether one cannot just copy ones for wchar_t from libstdc++ or libc++ (while being no expert on this matter). Help/opinions on this problem are welcome. 3. This patch addresses the issue of std::basic_string being thread-unsafe on gcc < 5.1 by noticing that the thread-safe implementation from gcc 5.1 is available for gcc >= 4.6 in <ext/vstring.h>. I think that this works well. 4. This patch is just to show what it would involve to completely get rid of trivstring.h in favour of <ext/vstring.h>. Given the result I do not recommend its inclusion because it adds a lot of noise with the explicit conversions. The patches can be applied independently. (For 3. this requires a small adaptation but docstring can be made thread-safe independently of whether Unicode strings are used.) Guillaume
>From 7ca4a7383c4a77d85996d77dbb3b9f4110a83cc5 Mon Sep 17 00:00:00 2001 From: Guillaume Munch <g...@lyx.org> Date: Sat, 20 Aug 2016 16:27:52 +0100 Subject: [PATCH 1/4] typedef char32_t char_type; typedef std::u32string docstring; MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit char_type is now defined as char32_t and docstring is now defined as std::u32string on all platforms. * Enable the use of Unicode literals, i.e. one can write: docstring s = U"Here is a Unicode literalâº"; char_type ellipsis = U'\u2026'; s == U"\u203D"; etc. * Remove empty_string() and empty_docstring() as they are now useless. * Remove the now useless USE_WCHAR_T and all related code * Note that gcc < 5.1 is not compliant with C++11 regarding thread-safety. It is still necesary to use trivstring and trivdocstring for thread-safety. * Note that the C++11 standard does not require all facets for char32_t which are required for using char32_t streams (!). This patch reuses the ascii_*_facets from support/docstring.cpp. --- configure.ac | 20 ------ src/Buffer.h | 2 +- src/Encoding.cpp | 4 +- src/Format.h | 2 +- src/LaTeX.cpp | 2 +- src/LaTeX.h | 8 +-- src/LayoutFile.h | 2 +- src/frontends/alert.h | 9 ++- src/frontends/qt4/qt_helpers.h | 2 +- src/insets/InsetText.h | 3 +- src/mathed/InsetMathHull.cpp | 8 +-- src/mathed/InsetMathUnknown.h | 4 +- src/support/FileName.h | 8 +-- src/support/ForkedCalls.h | 4 +- src/support/Makefile.am | 1 - src/support/Systemcall.h | 6 +- src/support/docstream.cpp | 90 ------------------------- src/support/docstream.h | 15 ----- src/support/docstring.cpp | 22 ++++--- src/support/docstring.h | 5 ++ src/support/lstrings.cpp | 17 +---- src/support/numpunct_lyx_char_type.h | 58 ---------------- src/support/os.h | 2 +- src/support/strfwd.h | 124 +++++++++++------------------------ src/tex2lyx/Preamble.cpp | 6 +- 25 files changed, 94 insertions(+), 330 deletions(-) delete mode 100644 src/support/numpunct_lyx_char_type.h diff --git a/configure.ac b/configure.ac index 75df6c7..4b609ad 100644 --- a/configure.ac +++ b/configure.ac @@ -133,22 +133,6 @@ LYX_CHECK_CALLSTACK_PRINTING # C++14 only LYX_CHECK_DEF(make_unique, memory, [using std::make_unique;]) -# Needed for our char_type -AC_CHECK_SIZEOF(wchar_t) - -# Taken from gettext, needed for libiconv -AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], - [AC_TRY_COMPILE([#include <stddef.h> - wchar_t foo = (wchar_t)'\0';], , - [gt_cv_c_wchar_t=yes], [gt_cv_c_wchar_t=no])]) -if test $gt_cv_c_wchar_t = yes; then - AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) - HAVE_WCHAR_T=1 -else - HAVE_WCHAR_T=0 -fi -AC_SUBST([HAVE_WCHAR_T]) - # Needed for Mingw-w64 AC_TYPE_LONG_LONG_INT if test "$ac_cv_type_long_long_int" = yes; then @@ -330,10 +314,6 @@ char * strerror(int n); # endif #endif -#if defined(HAVE_WCHAR_T) && SIZEOF_WCHAR_T == 4 -# define USE_WCHAR_T -#endif - #ifdef HAVE_LONG_LONG_INT #if SIZEOF_LONG_LONG > SIZEOF_LONG #define LYX_USE_LONG_LONG diff --git a/src/Buffer.h b/src/Buffer.h index 477a8ac..52152cb 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -749,7 +749,7 @@ public: /// where it was saved, return the correct path relative to the new /// location. std::string includedFilePath(std::string const & name, - std::string const & ext = empty_string()) const; + std::string const & ext = "") const; /// compute statistics between \p from and \p to /// \p from initial position diff --git a/src/Encoding.cpp b/src/Encoding.cpp index 73edc84..7c09f75 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -277,7 +277,7 @@ bool Encodings::latexMathChar(char_type c, bool mathmode, Encoding const * encoding, docstring & command, bool & needsTermination) { - command = empty_docstring(); + command = U""; if (encoding) if (encoding->encodable(c)) command = docstring(1, c); @@ -347,7 +347,7 @@ docstring Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype, bool & needsTermination, docstring & rem, set<string> * req) { needsTermination = false; - rem = empty_docstring(); + rem = U""; bool const mathmode = cmdtype & MATH_CMD; bool const textmode = cmdtype & TEXT_CMD; docstring symbols; diff --git a/src/Format.h b/src/Format.h index 74d2c4e..6ebcf84 100644 --- a/src/Format.h +++ b/src/Format.h @@ -61,7 +61,7 @@ public: /// std::string const extension() const { - return extension_list_.empty() ? empty_string() : extension_list_[0]; + return extension_list_.empty() ? std::string() : extension_list_[0]; } /// std::string const extensions() const; diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index cfa6e1d..5a570906 100644 --- a/src/LaTeX.cpp +++ b/src/LaTeX.cpp @@ -687,7 +687,7 @@ int LaTeX::scanLogFile(TeXErrors & terr) --pnest; } } - child_name = child.empty() ? empty_string() : child.top().first; + child_name = child.empty() ? "" : child.top().first; if (contains(token, "file:line:error style messages enabled")) fle_style = true; diff --git a/src/LaTeX.h b/src/LaTeX.h index 2575683..6205588 100644 --- a/src/LaTeX.h +++ b/src/LaTeX.h @@ -62,8 +62,8 @@ public: Errors::const_iterator end() const { return errors.end(); } /// void insertError(int line, docstring const & error_desc, - docstring const & error_text, - std::string const & child_name = empty_string()); + docstring const & error_text, + std::string const & child_name = ""); /// void clearErrors() { errors.clear(); } private: @@ -161,8 +161,8 @@ public: */ LaTeX(std::string const & cmd, OutputParams const &, support::FileName const & file, - std::string const & path = empty_string(), - std::string const & lpath = empty_string(), + std::string const & path = "", + std::string const & lpath = "", bool const clean_start = false); /// runs LaTeX several times diff --git a/src/LayoutFile.h b/src/LayoutFile.h index e911aa5..a22f7ac 100644 --- a/src/LayoutFile.h +++ b/src/LayoutFile.h @@ -120,7 +120,7 @@ public: /// empty string if no file was loaded. LayoutFileIndex addLocalLayout(std::string const & textclass, std::string const & path, - std::string const & oldpath = empty_string()); + std::string const & oldpath = ""); /// a list of the available classes std::vector<LayoutFileIndex> classList() const; diff --git a/src/frontends/alert.h b/src/frontends/alert.h index 2be612a..2fddc4e 100644 --- a/src/frontends/alert.h +++ b/src/frontends/alert.h @@ -31,10 +31,9 @@ namespace Alert { * slap you with fish, and not in an enjoyable way either. */ int prompt(docstring const & title, docstring const & question, - int default_button, int cancel_button, - docstring const & b1, docstring const & b2, - docstring const & b3 = empty_docstring(), - docstring const & b4 = empty_docstring()); + int default_button, int cancel_button, + docstring const & b1, docstring const & b2, + docstring const & b3 = U"", docstring const & b4 = U""); /** * Display a warning to the user. Title should be a short (general) summary. @@ -65,7 +64,7 @@ void information(docstring const & title, docstring const & message); * (even empty string). dflt stands for default message in the dialog. */ bool askForText(docstring & response, docstring const & msg, - docstring const & dflt = empty_docstring()); + docstring const & dflt = U""); } // namespace Alert } // namespace frontend diff --git a/src/frontends/qt4/qt_helpers.h b/src/frontends/qt4/qt_helpers.h index 5574212..61a03af 100644 --- a/src/frontends/qt4/qt_helpers.h +++ b/src/frontends/qt4/qt_helpers.h @@ -155,7 +155,7 @@ QString browseRelToSub(QString const & filename, * \param arg: cls, sty, bst, or bib, as required by TeXFiles.py. * Can be a list of these, too. */ -void rescanTexStyles(std::string const & arg = empty_string()); +void rescanTexStyles(std::string const & arg = ""); /** Fill \c contents from one of the three texfiles. * Each entry in the file list is returned as a name_with_path diff --git a/src/insets/InsetText.h b/src/insets/InsetText.h index 2834019..f866449 100644 --- a/src/insets/InsetText.h +++ b/src/insets/InsetText.h @@ -207,8 +207,7 @@ public: /// of that sort. (Note: unnecessary internal copies have been removed /// since the previous note. The efficiency would have to be assessed /// again by profiling.) - docstring toolTipText(docstring prefix = empty_docstring(), - size_t len = 400) const; + docstring toolTipText(docstring prefix = U"", size_t len = 400) const; /// std::string contextMenu(BufferView const &, int, int) const; diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index 5dffc3d..3c93af1 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -169,7 +169,7 @@ static InsetLabel * dummy_pointer = 0; InsetMathHull::InsetMathHull(Buffer * buf) : InsetMathGrid(buf, 1, 1), type_(hullNone), numbered_(1, NUMBER), - numbers_(1, empty_docstring()), label_(1, dummy_pointer), + numbers_(1, U""), label_(1, dummy_pointer), preview_(new RenderPreview(this)) { //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl; @@ -184,7 +184,7 @@ InsetMathHull::InsetMathHull(Buffer * buf) InsetMathHull::InsetMathHull(Buffer * buf, HullType type) : InsetMathGrid(buf, getCols(type), 1), type_(type), numbered_(1, NUMBER), - numbers_(1, empty_docstring()), label_(1, dummy_pointer), + numbers_(1, U""), label_(1, dummy_pointer), preview_(new RenderPreview(this)) { buffer_ = buf; @@ -289,7 +289,7 @@ void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) cnts.step(eqstr, utype); numbers_[i] = cnts.theCounter(eqstr, lang); } else - numbers_[i] = empty_docstring(); + numbers_[i] = U""; } } } @@ -1151,7 +1151,7 @@ void InsetMathHull::addRow(row_type row) bool numbered = numberedType(); // Move the number and raw pointer, do not call label() (bug 7511) InsetLabel * label = dummy_pointer; - docstring number = empty_docstring(); + docstring number; if (type_ == hullMultline) { if (row + 1 == nrows()) { numbered_[row] = NONUMBER; diff --git a/src/mathed/InsetMathUnknown.h b/src/mathed/InsetMathUnknown.h index 2effe3c..4a4eee2 100644 --- a/src/mathed/InsetMathUnknown.h +++ b/src/mathed/InsetMathUnknown.h @@ -22,8 +22,8 @@ class InsetMathUnknown : public InsetMath { public: /// explicit InsetMathUnknown(docstring const & name, - docstring const & selection = empty_docstring(), - bool final = true, bool black = false); + docstring const & selection = U"", + bool final = true, bool black = false); /// void metrics(MetricsInfo & mi, Dimension & dim) const; /// diff --git a/src/support/FileName.h b/src/support/FileName.h index cfa0c65..4564683 100644 --- a/src/support/FileName.h +++ b/src/support/FileName.h @@ -262,10 +262,10 @@ public: /// bool saveAbsPath() const { return save_abs_path_; } /// \param buffer_path if empty, uses `pwd` - std::string relFileName(std::string const & buffer_path = empty_string()) const; + std::string relFileName(std::string const & buffer_path = "") const; /// \param buf_path if empty, uses `pwd` - std::string outputFileName(std::string const & buf_path = empty_string()) const; - + std::string outputFileName(std::string const & buf_path = "") const; + /** @returns a mangled representation of the absolute file name * suitable for use in the temp dir when, for example, converting * an image file to another format. @@ -287,7 +287,7 @@ public: * with @c dir. */ std::string - mangledFileName(std::string const & dir = empty_string()) const; + mangledFileName(std::string const & dir = "") const; /// \return the absolute file name without its .gz, .z, .Z extension std::string unzippedFileName() const; diff --git a/src/support/ForkedCalls.h b/src/support/ForkedCalls.h index 1ed2f75..8aed814 100644 --- a/src/support/ForkedCalls.h +++ b/src/support/ForkedCalls.h @@ -152,8 +152,8 @@ private: class ForkedCall : public ForkedProcess { public: /// - ForkedCall(std::string const & path = empty_string(), - std::string const & lpath = empty_string()); + ForkedCall(std::string const & path = "", + std::string const & lpath = ""); /// virtual std::shared_ptr<ForkedProcess> clone() const { return std::make_shared<ForkedCall>(*this); diff --git a/src/support/Makefile.am b/src/support/Makefile.am index 08f1c71..1b0cecc 100644 --- a/src/support/Makefile.am +++ b/src/support/Makefile.am @@ -78,7 +78,6 @@ liblyxsupport_a_SOURCES = \ mutex.cpp \ Messages.cpp \ Messages.h \ - numpunct_lyx_char_type.h \ os.cpp \ os.h \ PathChanger.cpp \ diff --git a/src/support/Systemcall.h b/src/support/Systemcall.h index 876aa35..80d1fdc 100644 --- a/src/support/Systemcall.h +++ b/src/support/Systemcall.h @@ -49,9 +49,9 @@ public: * blocked while processing the external command. */ int startscript(Starttype how, std::string const & what, - std::string const & path = empty_string(), - std::string const & lpath = empty_string(), - bool process_events = false); + std::string const & path = "", + std::string const & lpath = "", + bool process_events = false); }; } // namespace support diff --git a/src/support/docstream.cpp b/src/support/docstream.cpp index de5a6df..60bed0e 100644 --- a/src/support/docstream.cpp +++ b/src/support/docstream.cpp @@ -26,27 +26,6 @@ using namespace std; using lyx::ucs4_codeset; -#if defined(_MSC_VER) && (_MSC_VER >= 1600) -std::locale::id numpunct<lyx::char_type>::id; - -namespace std { -// Implementation of numpunct<lyx::char_type> defined in numpunct_lyx_char_type.h -typedef basic_string<lyx::char_type> string_type; - -string_type numpunct<lyx::char_type>::truename() const -{ - return lyx::from_ascii(numpunct<char>::truename()); -} - -string_type numpunct<lyx::char_type>::falsename() const -{ - return lyx::from_ascii(numpunct<char>::falsename()); -} - -} // namespace std - -#endif // _MSC_VER >= 1600 - namespace { @@ -439,74 +418,5 @@ idocstream & operator<<(idocstream & is, SetEnc e) } -#if ! defined(USE_WCHAR_T) -odocstream & operator<<(odocstream & os, char c) -{ - os.put(c); - return os; } -#endif -} - - -#if ! defined(USE_WCHAR_T) && defined(__GNUC__) -// We get undefined references to these virtual methods. This looks like -// a bug in gcc. The implementation here does not do anything useful, since -// it is overriden in iconv_codecvt_facet. -namespace std { - -template<> codecvt<lyx::char_type, char, mbstate_t>::result -codecvt<lyx::char_type, char, mbstate_t>::do_out( - mbstate_t &, const lyx::char_type *, const lyx::char_type *, - const lyx::char_type *&, char *, char *, char *&) const -{ - return error; -} - - -template<> codecvt<lyx::char_type, char, mbstate_t>::result -codecvt<lyx::char_type, char, mbstate_t>::do_unshift( - mbstate_t &, char *, char *, char *&) const -{ - return error; -} - - -template<> codecvt<lyx::char_type, char, mbstate_t>::result -codecvt<lyx::char_type, char, mbstate_t>::do_in( - mbstate_t &, const char *, const char *, const char *&, - lyx::char_type *, lyx::char_type *, lyx::char_type *&) const -{ - return error; -} - - -template<> -int codecvt<lyx::char_type, char, mbstate_t>::do_encoding() const throw() -{ - return 0; -} - - -template<> -bool codecvt<lyx::char_type, char, mbstate_t>::do_always_noconv() const throw() -{ - return true; -} - -template<> -int codecvt<lyx::char_type, char, mbstate_t>::do_length( - mbstate_t &, const char *, const char *, size_t) const -{ - return 1; -} - -template<> -int codecvt<lyx::char_type, char, mbstate_t>::do_max_length() const throw() -{ - return 4; -} - -} // namespace std -#endif diff --git a/src/support/docstream.h b/src/support/docstream.h index 460a9b7..59135bc 100644 --- a/src/support/docstream.h +++ b/src/support/docstream.h @@ -25,21 +25,6 @@ public: virtual const char * what() const throw(); }; -/// Base class for UCS4 input streams -typedef std::basic_istream<char_type> idocstream; - -/** Base class for UCS4 output streams. - If you want to output a single UCS4 character, use \code - os.put(c); - \endcode, not \code - os << c; - \endcode . The latter will not output the character, but the code point - as number if USE_WCHAR_T is not defined. This is because we can't overload - operator<< (our character type is not always a real type but sometimes a - typedef). Narrow characters of type char can be output as usual. - */ -typedef std::basic_ostream<char_type> odocstream; - struct SetEnc; /// File stream for reading UTF8-encoded files with automatic conversion to diff --git a/src/support/docstring.cpp b/src/support/docstring.cpp index 95c86b3..9cb5fe5 100644 --- a/src/support/docstring.cpp +++ b/src/support/docstring.cpp @@ -21,10 +21,9 @@ //Needed in Ubuntu #include <typeinfo> -#if ! defined(USE_WCHAR_T) && defined(__GNUC__) + #include <locale> #include <iostream> -#endif using namespace std; @@ -243,11 +242,15 @@ lyx::docstring & operator+=(lyx::docstring & l, char r) } // namespace lyx -#if ! defined(USE_WCHAR_T) && defined(__GNUC__) -// gcc does not have proper locale facets for lyx::char_type if -// sizeof(wchar_t) == 2, so we have to implement them on our own. +// C++11 does not guarantee proper locale facets for char32_t, so we have to +// implement them on our own. The standard misses implementations of: +// * std::ctype<char32_t> +// * std::numpunct<char32_t> +// * std::num_put<char32_t> +// * std::num_get<char32_t> +#if defined(__GNUC__) // We get undefined references to these virtual methods. This looks like // a bug in gcc. The implementation here does not do anything useful, since @@ -275,6 +278,8 @@ template<> const lyx::char_type * ctype<lyx::char_type>::do_narrow(const lyx::char_type *, const lyx::char_type *, char, char *) const { return 0; } } +#endif // defined(__GNUC__) + namespace lyx { @@ -773,7 +778,7 @@ private: } for (; iit != eit && isDigitOrSep(*iit, sep); ++iit) s += static_cast<char>(*iit); - if (iit != eit && *iit == dot) { + if (iit != eit && *iit == static_cast<lyx::char_type>(dot)) { s += dot; ++iit; for (; iit != eit && isDigitOrSep(*iit, 0); ++iit) @@ -796,7 +801,8 @@ private: bool isDigitOrSep(lyx::char_type const c, char const sep) const { - return (c >= '0' && c <= '9') || (c != 0 && c == sep); + return (c >= '0' && c <= '9') || + (c != 0 && sep > 0 && c == static_cast<lyx::char_type>(sep)); } }; @@ -822,4 +828,4 @@ static locale_initializer initializer; } } -#endif + diff --git a/src/support/docstring.h b/src/support/docstring.h index 2c2901b..3cd5eef 100644 --- a/src/support/docstring.h +++ b/src/support/docstring.h @@ -20,6 +20,7 @@ namespace lyx { /// Creates a docstring from a C string of ASCII characters +/// This is deprecated. Use unicode literals instead, i.e. s = U"a". docstring const from_ascii(char const *); /// Creates a docstring from a std::string of ASCII characters @@ -62,15 +63,19 @@ docstring const from_iconv_encoding(std::string const & s, docstring const normalize_c(docstring const & s); /// Compare a docstring with a C string of ASCII characters +/// This is deprecated. Use unicode literals instead, i.e. s == U"a". bool operator==(docstring const &, char const *); /// Compare a C string of ASCII characters with a docstring +/// This is deprecated. Use unicode literals instead, i.e. U"a" == s. inline bool operator==(char const * l, docstring const & r) { return r == l; } /// Compare a docstring with a C string of ASCII characters +/// This is deprecated. Use unicode literals instead, i.e. s != U"a". inline bool operator!=(docstring const & l, char const * r) { return !(l == r); } /// Compare a C string of ASCII characters with a docstring +/// This is deprecated. Use unicode literals instead, i.e. U"a" != s. inline bool operator!=(char const * l, docstring const & r) { return !(r == l); } /// Concatenate a docstring and a C string of ASCII characters diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp index 6d5f866..80048e5 100644 --- a/src/support/lstrings.cpp +++ b/src/support/lstrings.cpp @@ -34,22 +34,6 @@ using namespace std; namespace lyx { -// Using this allows us to have docstring default arguments in headers -// without #include "support/docstring" there. -docstring const & empty_docstring() -{ - static const docstring s; - return s; -} - -// Using this allows us to have string default arguments in headers -// without #include <string> -string const & empty_string() -{ - static const string s; - return s; -} - namespace { /** * Convert a QChar into a UCS4 character. @@ -79,6 +63,7 @@ inline QChar const ucs4_to_qchar(char_type const ucs4) /// Maximum valid UCS4 code point char_type const ucs4_max = 0x10ffff; + } // anon namespace diff --git a/src/support/numpunct_lyx_char_type.h b/src/support/numpunct_lyx_char_type.h deleted file mode 100644 index 7ec661c..0000000 --- a/src/support/numpunct_lyx_char_type.h +++ /dev/null @@ -1,58 +0,0 @@ -// -*- C++ -*- -/** - * \file numpunct_lyx_char_type.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Peter Kümmel - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef LYX_NUMPUNCT_LYX_CHAR_TYPE_H -#define LYX_NUMPUNCT_LYX_CHAR_TYPE_H - - -#include <locale> - - -namespace std -{ - - template<> - class numpunct<lyx::char_type> : public numpunct<char> - { - public: - - typedef lyx::char_type char_type; - typedef basic_string<lyx::char_type> string_type; - - static locale::id id; - - explicit numpunct(size_t __refs = 0) : numpunct<char>(__refs) - {} - - char_type decimal_point() const - { return numpunct<char>::decimal_point(); } - - char_type thousands_sep() const - { return numpunct<char>::thousands_sep(); } - - string grouping() const - { return numpunct<char>::grouping(); } - - // Implementation can be found in docstream.cpp - string_type truename() const; - string_type falsename() const; - - - protected: - virtual ~numpunct(); - - }; - - // Fixed in VC11: - // http://connect.microsoft.com/VisualStudio/feedback/details/572376/msvc10-c-std-numpunct-has-a-hardcoded-dllimport-in-definition - -} -#endif diff --git a/src/support/os.h b/src/support/os.h index 73eb86d..503aa37 100644 --- a/src/support/os.h +++ b/src/support/os.h @@ -153,7 +153,7 @@ bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode); * \returns whether or not the file is viewed (or edited) successfully. */ bool autoOpenFile(std::string const & filename, auto_open_mode const mode, - std::string const & path = empty_string()); + std::string const & path = ""); /** Resolves a path such that it does not contain '.', '..', or symbolic links. * \p path and the return value are encoded in utf8. diff --git a/src/support/strfwd.h b/src/support/strfwd.h index 58b44f5..1bccf6c 100644 --- a/src/support/strfwd.h +++ b/src/support/strfwd.h @@ -1,114 +1,68 @@ // -*- C++ -*- - -// Heavily inspired by /usr/include/c++/4.1/bits -// -// Copyright (C) 2001, 2002 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 2, or (at your option) -// any later version. +/** + * \file strfwd.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * Full author contact details are available in file CREDITS. + */ #ifndef STRFWD_H #define STRFWD_H -#ifdef USE_WCHAR_T -// Prefer this if possible because GNU libstdc++ has usable -// std::ctype<wchar_t> locale facets but not -// std::ctype<boost::uint32_t>. gcc older than 3.4 is also missing -// usable std::char_traits<boost::uint32_t>. -namespace lyx { typedef wchar_t char_type; } - -#else - -#if defined(_MSC_VER) && (_MSC_VER >= 1600) -#include <cstdint> -namespace lyx { typedef uint32_t char_type; } -#include "support/numpunct_lyx_char_type.h" // implementation for our char_type needed -#else -#include <boost/cstdint.hpp> -namespace lyx { typedef boost::uint32_t char_type; } -#endif - -#endif - -// Forward definitions do not work with libc++ -// For gcc5 with the new std::string ABI forward declarations would work in -// principle, but I am not sure whether we want non-standard -// "namespace __cxx11" in our sources. -#if defined(USE_LLVM_LIBCPP) || defined(USE_GLIBCXX_CXX11_ABI) +#include <iosfwd> #include <string> -#else - -namespace std { - -template<typename Alloc> class allocator; - -template<typename Char> struct char_traits; -template<> struct char_traits<char>; -#ifdef USE_WCHAR_T -template<> struct char_traits<wchar_t>; -#endif - -template<typename Char, typename Traits, typename Alloc> class basic_string; -typedef basic_string<char, char_traits<char>, allocator<char> > string; - -template<class Char, class Traits> class basic_istream; -template<class Char, class Traits> class basic_ostream; -template<class Char, class Traits, class Allocator> class basic_ostringstream; - -typedef basic_istream<char, char_traits<char> > istream; -typedef basic_ostream<char, char_traits<char> > ostream; -typedef basic_ostringstream<char, char_traits<char>, allocator<char> > ostringstream; - -} // namepace std - -#endif - - - namespace lyx { -/** - * String type for storing the main text in UCS4 encoding. - * Use std::string only in cases 7-bit ASCII is to be manipulated - * within the variable. - */ -typedef std::basic_string<char_type, std::char_traits<char_type>, - std::allocator<char_type> > docstring; + +typedef char32_t char_type; + +// String type for storing the main text in UCS4 encoding. +// Use std::string only for 7-bit ASCII strings! +typedef std::u32string docstring; /// Base class for UCS4 input streams -typedef std::basic_istream<char_type, std::char_traits<char_type> > idocstream; +typedef std::basic_istream<char_type> idocstream; /// Base class for UCS4 output streams -typedef std::basic_ostream<char_type, std::char_traits<char_type> > odocstream; +typedef std::basic_ostream<char_type> odocstream; /// UCS4 output stringstream -typedef std::basic_ostringstream<char_type, std::char_traits<char_type>, std::allocator<char_type> > odocstringstream; +typedef std::basic_ostringstream<char_type> odocstringstream; -#if ! defined(USE_WCHAR_T) -extern odocstream & operator<<(odocstream &, char); -#endif - -// defined in lstrings.cpp -docstring const & empty_docstring(); -std::string const & empty_string(); -// defined in docstring.cpp -bool operator==(docstring const &, char const *); #ifdef STD_STRING_USES_COW + +// For gcc < 5.1 +// +// The implementation of std::string and docstring is not thread-safe because it +// uses copy-on-write. See: +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html +// +// Once we require gcc >= 5.1, std::string and docstring will be thread-safe(*), +// and triv(doc)string can be removed. +// +// (*): A read-only access does not need synchronization between multiple +// threads, i.e. is thread-safe without locking. Therefore you can safely use a +// const triv(doc)string object in multiple threads at the same time. +// +// trivial_string is declared in src/support/trivstring.h template<typename Char> class trivial_string; typedef trivial_string<char> trivstring; typedef trivial_string<char_type> trivdocstring; + #else + +// We assume that std::string and docstring comply with C++11 regarding +// thread-safety. typedef std::string trivstring; typedef docstring trivdocstring; -#endif + +#endif // !defined(STD_STRING_USES_COW) + } // namespace lyx -#endif +#endif // STRFWD_H diff --git a/src/tex2lyx/Preamble.cpp b/src/tex2lyx/Preamble.cpp index a52927f..be69975 100644 --- a/src/tex2lyx/Preamble.cpp +++ b/src/tex2lyx/Preamble.cpp @@ -378,7 +378,7 @@ void Preamble::suppressDate(bool suppress) void Preamble::registerAuthor(std::string const & name) { - Author author(from_utf8(name), empty_docstring()); + Author author(from_utf8(name), U""); author.setUsed(true); authors_.record(author); h_tracking_changes = "true"; @@ -388,7 +388,7 @@ void Preamble::registerAuthor(std::string const & name) Author const & Preamble::getAuthor(std::string const & name) const { - Author author(from_utf8(name), empty_docstring()); + Author author(from_utf8(name), U""); for (AuthorList::Authors::const_iterator it = authors_.begin(); it != authors_.end(); ++it) if (*it == author) @@ -1115,7 +1115,7 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc, string const & outfiled << "\\save_transient_properties " << h_save_transient_properties << "\n" << "\\origin " << origin << "\n" << "\\textclass " << h_textclass << "\n"; - string const raw = subdoc ? empty_string() : h_preamble.str(); + string const raw = subdoc ? "" : h_preamble.str(); if (!raw.empty()) { os << "\\begin_preamble\n"; for (string::size_type i = 0; i < raw.size(); ++i) { -- 2.7.4
>From 27ce061208b51bbdc5d438c1058111906311295c Mon Sep 17 00:00:00 2001 From: Guillaume Munch <g...@lyx.org> Date: Mon, 22 Aug 2016 00:02:40 +0100 Subject: [PATCH 2/4] Replace boost::cstdint with std::cstdint --- 3rdparty/boost/extract.sh | 1 - src/Encoding.cpp | 15 ++++++--------- src/frontends/qt4/GuiClipboard.h | 5 +++-- src/support/Messages.cpp | 4 +--- src/support/unicode.cpp | 5 ++--- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/3rdparty/boost/extract.sh b/3rdparty/boost/extract.sh index 04eeb5c..783806d 100755 --- a/3rdparty/boost/extract.sh +++ b/3rdparty/boost/extract.sh @@ -23,7 +23,6 @@ bcp --boost=$1 \ boost/any.hpp \ boost/assert.hpp \ boost/crc.hpp \ - boost/cstdint.hpp \ boost/lexical_cast.hpp \ boost/regex.hpp \ boost/signals2.hpp \ diff --git a/src/Encoding.cpp b/src/Encoding.cpp index 7c09f75..5820fdc 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -23,10 +23,9 @@ #include "support/textutils.h" #include "support/unicode.h" -#include <boost/cstdint.hpp> - -#include <sstream> #include <algorithm> +#include <cstdint> +#include <sstream> using namespace std; using namespace lyx::support; @@ -661,8 +660,6 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile) symbolslex.setFile(symbolsfile); bool getNextToken = true; while (symbolslex.isOK()) { - char_type symbol; - if (getNextToken) { if (!symbolslex.next(true)) break; @@ -670,12 +667,12 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile) getNextToken = true; istringstream is(symbolslex.getString()); - // reading symbol directly does not work if - // char_type == wchar_t. - boost::uint32_t tmp; + // parse an integer written in hexadecimal + uint32_t tmp; if(!(is >> hex >> tmp)) break; - symbol = tmp; + // convert into a unicode character + char_type symbol(tmp); if (!symbolslex.next(true)) break; diff --git a/src/frontends/qt4/GuiClipboard.h b/src/frontends/qt4/GuiClipboard.h index 4514eb2..2cdaad6 100644 --- a/src/frontends/qt4/GuiClipboard.h +++ b/src/frontends/qt4/GuiClipboard.h @@ -20,7 +20,8 @@ #include <QObject> #include <QStringList> -#include <boost/cstdint.hpp> +#include <cstdint> + namespace lyx { namespace frontend { @@ -94,7 +95,7 @@ private: /// that can be stored in the clipboard CacheMimeData cache_; /// checksum for internal clipboard data (used on Mac) - boost::uint32_t checksum; + uint32_t checksum; }; QString const lyxMimeType(); diff --git a/src/support/Messages.cpp b/src/support/Messages.cpp index da1c3cc..2e9892b 100644 --- a/src/support/Messages.cpp +++ b/src/support/Messages.cpp @@ -83,9 +83,8 @@ #include "support/lassert.h" -#include <boost/cstdint.hpp> - #include <cerrno> +#include <cstdint> #include <fstream> #include <utility> @@ -94,7 +93,6 @@ #endif using namespace std; -using boost::uint32_t; namespace lyx { diff --git a/src/support/unicode.cpp b/src/support/unicode.cpp index 2620ddb..9b64d57 100644 --- a/src/support/unicode.cpp +++ b/src/support/unicode.cpp @@ -19,9 +19,8 @@ #include <iconv.h> -#include <boost/cstdint.hpp> - #include <cerrno> +#include <cstdint> #include <map> #include <ostream> //Needed in MSVC @@ -143,7 +142,7 @@ int IconvProcessor::convert(char const * buf, size_t buflen, for (size_t i = 0; i < buflen; ++i) { // char may be signed, avoid output of // something like 0xffffffc2 - boost::uint32_t const b = + uint32_t const b = *reinterpret_cast<unsigned char const *>(buf + i); lyxerr << " 0x" << (unsigned int)b; } -- 2.7.4
>From d06872a5c7d1e1da0f59a9663264b2b732f2fafe Mon Sep 17 00:00:00 2001 From: Guillaume Munch <g...@lyx.org> Date: Mon, 22 Aug 2016 00:02:54 +0100 Subject: [PATCH 3/4] Make docstring thread-safe for read-only access. gcc < 5.1 provides a C++11-compliant implementation of std::basic_string under the name __gnu_cxx::__versa_string. This removes trivdocstring and replace docstring the thread-safe __gnu_cxx::__versa_string<char32_t> when the library is not compliant. std::string remains thread-unsafe until gcc > 5.1 with CXX11 ABI is made a requirement. At this point, trivstring can be removed and the definition of strings will be entirely uniform and standard. --- src/Converter.h | 1 + src/Encoding.h | 4 +- src/Language.h | 2 +- src/TexRow.cpp | 2 +- src/insets/InsetERT.cpp | 3 +- src/support/docstream.h | 33 ++++++++++++++++- src/support/strfwd.h | 67 +++++++++++++++++++++++----------- src/support/tests/check_trivstring.cpp | 18 ++++----- src/support/trivstring.cpp | 13 +------ src/support/trivstring.h | 4 +- 10 files changed, 95 insertions(+), 52 deletions(-) diff --git a/src/Converter.h b/src/Converter.h index 082b2d3..46753eb 100644 --- a/src/Converter.h +++ b/src/Converter.h @@ -14,6 +14,7 @@ #include "Graph.h" #include "OutputParams.h" + #include "support/trivstring.h" #include <vector> diff --git a/src/Encoding.h b/src/Encoding.h index 5e289ca..757fd64 100644 --- a/src/Encoding.h +++ b/src/Encoding.h @@ -99,9 +99,9 @@ public: /// private: /// LaTeX command (text mode) for this character - trivdocstring textcommand_; + docstring textcommand_; /// LaTeX command (math mode) for this character - trivdocstring mathcommand_; + docstring mathcommand_; /// Needed LaTeX preamble (or feature) for text mode trivstring textpreamble_; /// Needed LaTeX preamble (or feature) for math mode diff --git a/src/Language.h b/src/Language.h index ed1bd87..43caaa5 100644 --- a/src/Language.h +++ b/src/Language.h @@ -88,7 +88,7 @@ public: /// bool readLanguage(Lexer & lex); /// - typedef std::map<trivstring, trivdocstring> TranslationMap; + typedef std::map<trivstring, docstring> TranslationMap; /// void readLayoutTranslations(TranslationMap const & trans, bool replace); // for the use in std::map diff --git a/src/TexRow.cpp b/src/TexRow.cpp index 4e23cf7..4634572 100644 --- a/src/TexRow.cpp +++ b/src/TexRow.cpp @@ -21,9 +21,9 @@ #include "support/debug.h" #include "support/docstring_list.h" +#include "support/docstream.h" #include <algorithm> -#include <sstream> namespace lyx { diff --git a/src/insets/InsetERT.cpp b/src/insets/InsetERT.cpp index ce9d383..c3c5859 100644 --- a/src/insets/InsetERT.cpp +++ b/src/insets/InsetERT.cpp @@ -31,8 +31,7 @@ #include "support/gettext.h" #include "support/lstrings.h" - -#include <sstream> +#include "support/docstream.h" using namespace std; using namespace lyx::support; diff --git a/src/support/docstream.h b/src/support/docstream.h index 59135bc..9318f2a 100644 --- a/src/support/docstream.h +++ b/src/support/docstream.h @@ -63,9 +63,38 @@ public: }; +#ifdef STD_STRING_USES_COW + +// otherwise declared in support/strfwd.h + +// std::basic_istringstream<char_type> extended with conversions to/from +// gcc's vstrings +class idocstringstream : public std::basic_istringstream<char_type> { + typedef std::basic_istringstream<char_type> base; +public: + explicit idocstringstream(base::openmode mode = base::in) : base(mode) {} + explicit idocstringstream(docstring const & str, + base::openmode mode = base::in) + : base(str.c_str(), mode) {} + docstring str() const { return base::str().c_str(); } + void str(docstring const & s) { return base::str(s.c_str()); } +}; + +// std::basic_ostringstream<char_type> extended with conversions to/from +// gcc's vstrings +class odocstringstream : public std::basic_ostringstream<char_type> { + typedef std::basic_ostringstream<char_type> base; +public: + explicit odocstringstream(base::openmode mode = base::out) : base(mode) {} + explicit odocstringstream(docstring const & str, + base::openmode mode = base::out) + : base(str.c_str(), mode) {} + docstring str() const { return base::str().c_str(); } + void str(docstring const & s) { return base::str(s.c_str()); } +}; + +#endif -/// UCS4 input stringstream -typedef std::basic_istringstream<char_type> idocstringstream; /// UCS4 output manipulator typedef odocstream & (*odocstream_manip)(odocstream &); diff --git a/src/support/strfwd.h b/src/support/strfwd.h index 1bccf6c..f0670c4 100644 --- a/src/support/strfwd.h +++ b/src/support/strfwd.h @@ -13,52 +13,77 @@ #include <iosfwd> #include <string> +#ifdef STD_STRING_USES_COW +// thread-safe string implementation for gcc <= 5.1: +#include <ext/vstring.h> +#endif + namespace lyx { typedef char32_t char_type; -// String type for storing the main text in UCS4 encoding. -// Use std::string only for 7-bit ASCII strings! -typedef std::u32string docstring; - /// Base class for UCS4 input streams typedef std::basic_istream<char_type> idocstream; /// Base class for UCS4 output streams typedef std::basic_ostream<char_type> odocstream; + +#ifndef STD_STRING_USES_COW + +// docstring below is thread-safe(*) thanks to specific definitions below for +// gcc < 5.1. +// +// (*): A read-only access does not need synchronization between multiple +// threads, i.e. is thread-safe without locking. Therefore you can safely use a +// const {triv,doc}string object in multiple threads at the same time. + +// String type for storing the main text in UCS4 encoding. +// Use std::string only for 7-bit ASCII strings +typedef std::u32string docstring; + /// UCS4 output stringstream typedef std::basic_ostringstream<char_type> odocstringstream; +/// UCS4 input stringstream +typedef std::basic_istringstream<char_type> idocstringstream; -#ifdef STD_STRING_USES_COW +// trivstring is a partial and thread-safe implementation of std::string thanks +// to specific definitions below for gcc < 5.1. +typedef std::string trivstring; + +#else // For gcc < 5.1 // -// The implementation of std::string and docstring is not thread-safe because it -// uses copy-on-write. See: +// The implementation of std::string and std::u32string is not thread-safe +// because it uses copy-on-write. See: // https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html // -// Once we require gcc >= 5.1, std::string and docstring will be thread-safe(*), -// and triv(doc)string can be removed. -// -// (*): A read-only access does not need synchronization between multiple -// threads, i.e. is thread-safe without locking. Therefore you can safely use a -// const triv(doc)string object in multiple threads at the same time. +// Fortunately, a preview of the C++11-compliant short-string-optimised +// implementation of std::string from gcc 5 is provided under the name +// "versatile strings". See: https://stackoverflow.com/a/10463927 // +// Once we require gcc >= 5.1, std::string and std::u32string will be +// C++11-compliant and this and trivstring below can be removed. + +typedef __gnu_cxx::__versa_string<char32_t> docstring; + +// Defined in support/docstream.h. It requires additional conversions of +// docstring to/from std::basic_string<char32_t>. +class odocstringstream; +class idocstringstream; + // trivial_string is declared in src/support/trivstring.h +// +// Note: using __gnu_cxx::__vstring to provide a thread-safe implementation of +// std::string is harder because std::string is hard-coded in the LyX sources, +// and on the other hand using it only as a replacement of trivstring requires +// conversions to and from std::string. template<typename Char> class trivial_string; typedef trivial_string<char> trivstring; -typedef trivial_string<char_type> trivdocstring; - -#else - -// We assume that std::string and docstring comply with C++11 regarding -// thread-safety. -typedef std::string trivstring; -typedef docstring trivdocstring; #endif // !defined(STD_STRING_USES_COW) diff --git a/src/support/tests/check_trivstring.cpp b/src/support/tests/check_trivstring.cpp index 1b60465..e81f07d 100644 --- a/src/support/tests/check_trivstring.cpp +++ b/src/support/tests/check_trivstring.cpp @@ -89,13 +89,13 @@ void test_trivdocstring() size_t const n = sizeof(input) / sizeof(input[0]); for (size_t i = 0; i < n; ++i) { // construction from std::string - trivdocstring const a(input[i]); + docstring const a(input[i]); // construction from trivstring - trivdocstring const b(a); + docstring const b(a); // assignment from trivstring - trivdocstring const c = a; + docstring const c = a; // assignment from std::string - trivdocstring d = input[i]; + docstring d = input[i]; // assignment from trivstring docstring const e = a; // assignment from trivstring via C string @@ -112,17 +112,17 @@ void test_trivdocstring() cout << to_ascii(e) << endl; cout << to_ascii(f) << endl; // swap - trivdocstring g(from_ascii("swap")); + docstring g(from_ascii("swap")); cout << to_ascii(g) << endl; d.swap(g); cout << to_ascii(d) << endl; cout << to_ascii(g) << endl; } // comparison - trivdocstring const a; - trivdocstring const b(from_ascii("a")); - trivdocstring const c(from_ascii("b")); - trivdocstring const d(from_ascii("42")); + docstring const a; + docstring const b(from_ascii("a")); + docstring const c(from_ascii("b")); + docstring const d(from_ascii("42")); cout << (a == a) << ' ' << (a < a) << endl; // equal strings cout << (a == b) << ' ' << (a < b) << endl; // different strings, same length cout << (b == a) << ' ' << (b < a) << endl; // different strings, same length diff --git a/src/support/trivstring.cpp b/src/support/trivstring.cpp index 127a8d3..f1d0bb5 100644 --- a/src/support/trivstring.cpp +++ b/src/support/trivstring.cpp @@ -57,7 +57,7 @@ trivial_string<Char>::trivial_string(Char const * that, size_t n) : size_(n) template trivial_string<char>::trivial_string(string const &); -template trivial_string<char_type>::trivial_string(docstring const &); + template<typename Char> trivial_string<Char>::trivial_string(_stdstring const & that) : size_(that.length()) @@ -103,8 +103,6 @@ trivial_string<Char> & trivial_string<Char>::operator=(trivial_string const & th template trivial_string<char> & trivial_string<char>::operator=(string const &); -template trivial_string<char_type> & -trivial_string<char_type>::operator=(docstring const &); template<typename Char> trivial_string<Char> & trivial_string<Char>::operator=(_stdstring const & that) @@ -174,7 +172,6 @@ trivial_string<Char> trivial_string<Char>::substr(size_t pos, size_t n) const template trivial_string<char>::operator string() const; -template trivial_string<char_type>::operator docstring() const; template<typename Char> trivial_string<Char>::operator _stdstring() const { @@ -188,7 +185,6 @@ trivial_string<Char>::operator _stdstring() const template char const * trivial_string<char>::c_str() const; -template char_type const * trivial_string<char_type>::c_str() const; template<typename Char> Char const * trivial_string<Char>::c_str() const { if (use_sso()) @@ -202,7 +198,6 @@ template<typename Char> Char const * trivial_string<Char>::c_str() const template char trivial_string<char>::operator[](size_t) const; -template char_type trivial_string<char_type>::operator[](size_t) const; template <typename Char> Char trivial_string<Char>::operator[](size_t i) const { return c_str()[i]; @@ -211,8 +206,6 @@ template <typename Char> Char trivial_string<Char>::operator[](size_t i) const template bool operator<(trivial_string<char> const &, trivial_string<char> const &); -template bool operator<(trivial_string<char_type> const &, - trivial_string<char_type> const &); template <typename Char> bool operator<(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs) { @@ -222,8 +215,6 @@ bool operator<(trivial_string<Char> const & lhs, trivial_string<Char> const & rh template bool operator==(trivial_string<char> const &, trivial_string<char> const &); -template bool operator==(trivial_string<char_type> const &, - trivial_string<char_type> const &); template <typename Char> bool operator==(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs) { @@ -232,7 +223,6 @@ bool operator==(trivial_string<Char> const & lhs, trivial_string<Char> const & r template bool operator==(trivial_string<char> const &, char const *); -template bool operator==(trivial_string<char_type> const &, char_type const *); template <typename Char> bool operator==(trivial_string<Char> const & lhs, Char const * rhs) { @@ -241,7 +231,6 @@ bool operator==(trivial_string<Char> const & lhs, Char const * rhs) template bool operator==(char const *, trivial_string<char> const &); -template bool operator==(char_type const *, trivial_string<char_type> const &); template <typename Char> bool operator==(Char const * lhs, trivial_string<Char> const & rhs) { diff --git a/src/support/trivstring.h b/src/support/trivstring.h index 6b935ee..e147523 100644 --- a/src/support/trivstring.h +++ b/src/support/trivstring.h @@ -112,5 +112,5 @@ operator<<(std::basic_ostream<Char, std::char_traits<Char> > &, trivial_string<C } // namespace lyx #else #include <string> -#endif -#endif +#endif // STD_STRING_USES_COW +#endif // LYX_TRIVSTRING_H -- 2.7.4
>From e5f6f851038a729c68150fcc64a32b9816c3320e Mon Sep 17 00:00:00 2001 From: Guillaume Munch <g...@lyx.org> Date: Sun, 21 Aug 2016 23:48:10 +0100 Subject: [PATCH 4/4] Replace trivial_string with proper thread-safe strings --- src/Converter.cpp | 34 ++--- src/Converter.h | 22 ++- src/Encoding.cpp | 19 +-- src/Encoding.h | 15 +- src/Format.cpp | 7 +- src/Format.h | 25 ++-- src/Language.cpp | 22 +-- src/Language.h | 31 ++-- src/Lexer.h | 2 +- src/support/Makefile.am | 2 - src/support/strfwd.h | 14 +- src/support/tests/check_trivstring.cpp | 1 - src/support/trivstring.cpp | 251 --------------------------------- src/support/trivstring.h | 116 --------------- 14 files changed, 91 insertions(+), 470 deletions(-) delete mode 100644 src/support/trivstring.cpp delete mode 100644 src/support/trivstring.h diff --git a/src/Converter.cpp b/src/Converter.cpp index 465e256..f956a53 100644 --- a/src/Converter.cpp +++ b/src/Converter.cpp @@ -98,7 +98,7 @@ private: Converter::Converter(string const & f, string const & t, string const & c, string const & l) - : from_(f), to_(t), command_(c), flags_(l), + : from_(f.c_str()), to_(t.c_str()), command_(c.c_str()), flags_(l.c_str()), From_(0), To_(0), latex_(false), xml_(false), need_aux_(false), nice_(false) {} @@ -106,7 +106,7 @@ Converter::Converter(string const & f, string const & t, void Converter::readFlags() { - string flag_list(flags_); + string flag_list(flags_.c_str()); while (!flag_list.empty()) { string flag_name, flag_value; flag_list = split(flag_list, flag_value, ','); @@ -114,23 +114,23 @@ void Converter::readFlags() if (flag_name == "latex") { latex_ = true; latex_flavor_ = flag_value.empty() ? - "latex" : flag_value; + "latex" : flag_value.c_str(); } else if (flag_name == "xml") xml_ = true; else if (flag_name == "needaux") need_aux_ = true; else if (flag_name == "resultdir") result_dir_ = (flag_value.empty()) - ? token_base : flag_value; + ? token_base.c_str() : flag_value.c_str(); else if (flag_name == "resultfile") - result_file_ = flag_value; + result_file_ = flag_value.c_str(); else if (flag_name == "parselog") - parselog_ = flag_value; + parselog_ = flag_value.c_str(); else if (flag_name == "nice") nice_ = true; } if (!result_dir_.empty() && result_file_.empty()) - result_file_ = "index." + formats.extension(to_); + result_file_ = trivstring("index.") + formats.extension(to_.c_str()).c_str(); //if (!contains(command, token_from)) // latex = true; } @@ -183,19 +183,19 @@ void Converters::add(string const & from, string const & to, if (converter.latex()) { if (latex_command_.empty() || converter.latex_flavor() == "latex") - latex_command_ = subst(command, token_from, ""); + latex_command_ = subst(command, token_from, "").c_str(); if (dvilualatex_command_.empty() || converter.latex_flavor() == "dvilualatex") - dvilualatex_command_ = subst(command, token_from, ""); + dvilualatex_command_ = subst(command, token_from, "").c_str(); if (lualatex_command_.empty() || converter.latex_flavor() == "lualatex") - lualatex_command_ = subst(command, token_from, ""); + lualatex_command_ = subst(command, token_from, "").c_str(); if (pdflatex_command_.empty() || converter.latex_flavor() == "pdflatex") - pdflatex_command_ = subst(command, token_from, ""); + pdflatex_command_ = subst(command, token_from, "").c_str(); if (xelatex_command_.empty() || converter.latex_flavor() == "xelatex") - xelatex_command_ = subst(command, token_from, ""); + xelatex_command_ = subst(command, token_from, "").c_str(); } if (it == converterlist_.end()) { @@ -416,19 +416,19 @@ bool Converters::convert(Buffer const * buffer, string command; switch (runparams.flavor) { case OutputParams::DVILUATEX: - command = dvilualatex_command_; + command = dvilualatex_command_.c_str(); break; case OutputParams::LUATEX: - command = lualatex_command_; + command = lualatex_command_.c_str(); break; case OutputParams::PDFLATEX: - command = pdflatex_command_; + command = pdflatex_command_.c_str(); break; case OutputParams::XETEX: - command = xelatex_command_; + command = xelatex_command_.c_str(); break; default: - command = latex_command_; + command = latex_command_.c_str(); break; } if (!command.empty()) { diff --git a/src/Converter.h b/src/Converter.h index 46753eb..05ef965 100644 --- a/src/Converter.h +++ b/src/Converter.h @@ -15,8 +15,6 @@ #include "Graph.h" #include "OutputParams.h" -#include "support/trivstring.h" - #include <vector> #include <set> #include <string> @@ -41,17 +39,17 @@ public: /// void readFlags(); /// - std::string const from() const { return from_; } + std::string const from() const { return from_.c_str(); } /// - std::string const to() const { return to_; } + std::string const to() const { return to_.c_str(); } /// - std::string const command() const { return command_; } + std::string const command() const { return command_.c_str(); } /// - void setCommand(std::string const & command) { command_ = command; } + void setCommand(std::string const & command) { command_ = command.c_str(); } /// - std::string const flags() const { return flags_; } + std::string const flags() const { return flags_.c_str(); } /// - void setFlags(std::string const & flags) { flags_ = flags; } + void setFlags(std::string const & flags) { flags_ = flags.c_str(); } /// Format const * From() const { return From_; } /// @@ -63,7 +61,7 @@ public: /// bool latex() const { return latex_; } /// - std::string const latex_flavor() const { return latex_flavor_; } + std::string const latex_flavor() const { return latex_flavor_.c_str(); } /// bool xml() const { return xml_; } /// @@ -71,11 +69,11 @@ public: /// bool nice() const { return nice_; } /// - std::string const result_dir() const { return result_dir_; } + std::string const result_dir() const { return result_dir_.c_str(); } /// - std::string const result_file() const { return result_file_; } + std::string const result_file() const { return result_file_.c_str(); } /// - std::string const parselog() const { return parselog_; } + std::string const parselog() const { return parselog_.c_str(); } private: /// trivstring from_; diff --git a/src/Encoding.cpp b/src/Encoding.cpp index 5820fdc..1d92a3a 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -77,16 +77,17 @@ CharInfo::CharInfo( std::string const & textpreamble, std::string const & mathpreamble, std::string const & tipashortcut, unsigned int flags) : textcommand_(textcommand), mathcommand_(mathcommand), - textpreamble_(textpreamble), mathpreamble_(mathpreamble), - tipashortcut_(tipashortcut), flags_(flags) + textpreamble_(textpreamble.c_str()), mathpreamble_(mathpreamble.c_str()), + tipashortcut_(tipashortcut.c_str()), flags_(flags) { } Encoding::Encoding(string const & n, string const & l, string const & g, string const & i, bool f, bool u, Encoding::Package p) - : name_(n), latexName_(l), guiName_(g), iconvName_(i), fixedwidth_(f), - unsafe_(u), forced_(&forcedselected[n]), package_(p) + : name_(n.c_str()), latexName_(l.c_str()), guiName_(g.c_str()), + iconvName_(i.c_str()), fixedwidth_(f), unsafe_(u), + forced_(&forcedselected[n]), package_(p) { if (n == "ascii") { // ASCII can encode 128 code points and nothing else @@ -134,7 +135,8 @@ void Encoding::init() const // if we check all 256 code points of this encoding. for (unsigned short j = 0; j < 256; ++j) { char const c = char(j); - vector<char_type> const ucs4 = eightbit_to_ucs4(&c, 1, iconvName_); + vector<char_type> const ucs4 = eightbit_to_ucs4(&c, 1, + iconvName_.c_str()); if (ucs4.size() != 1) continue; char_type const uc = ucs4[0]; @@ -152,7 +154,8 @@ void Encoding::init() const // therefore we need to check all UCS4 code points. // This is expensive! for (char_type c = 0; c < max_ucs4; ++c) { - vector<char> const eightbit = ucs4_to_eightbit(&c, 1, iconvName_); + vector<char> const eightbit = ucs4_to_eightbit(&c, 1, + iconvName_.c_str()); if (!eightbit.empty()) { CharInfoMap::const_iterator const it = unicodesymbols.find(c); if (it == unicodesymbols.end()) @@ -603,7 +606,7 @@ bool Encodings::isMathAlpha(char_type c) Encoding const * Encodings::fromLyXName(string const & name, bool allowUnsafe) const { - EncodingList::const_iterator const it = encodinglist.find(name); + EncodingList::const_iterator const it = encodinglist.find(name.c_str()); if (it == encodinglist.end()) return 0; if (!allowUnsafe && it->second.unsafe()) @@ -849,7 +852,7 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile) lex.printError("Unknown package"); LYXERR(Debug::INFO, "Reading encoding " << name); - encodinglist[name] = Encoding(name, latexname, + encodinglist[name.c_str()] = Encoding(name, latexname, guiname, iconvname, fixedwidth, unsafe, package); diff --git a/src/Encoding.h b/src/Encoding.h index 757fd64..d6301fa 100644 --- a/src/Encoding.h +++ b/src/Encoding.h @@ -14,7 +14,6 @@ #define ENCODING_H #include "support/docstring.h" -#include "support/trivstring.h" #include "support/types.h" #include <map> @@ -72,9 +71,9 @@ public: /// LaTeX command (math mode) for this character docstring mathcommand() const { return mathcommand_; } /// Needed LaTeX preamble (or feature) for text mode - std::string textpreamble() const { return textpreamble_; } + std::string textpreamble() const { return textpreamble_.c_str(); } /// Needed LaTeX preamble (or feature) for math mode - std::string mathpreamble() const { return mathpreamble_; } + std::string mathpreamble() const { return mathpreamble_.c_str(); } /// Is this a combining character? bool combining() const { return flags_ & CharInfoCombining ? true : false; } /// Is \c textpreamble a feature known by LaTeXFeatures, or a raw LaTeX @@ -91,7 +90,7 @@ public: /// Disable LaTeX command => char_type conversion for this deprecated symbol? bool deprecated() const { return flags_ & CharInfoDeprecated ? true : false; } /// TIPA shortcut - std::string const tipashortcut() const { return tipashortcut_; } + std::string const tipashortcut() const { return tipashortcut_.c_str(); } /// \c textcommand needs no termination (such as {} or space). bool textnotermination() const { return flags_ & CharInfoTextNoTermination ? true : false; } /// \c mathcommand needs no termination (such as {} or space). @@ -139,13 +138,13 @@ public: /// void init() const; /// - std::string const name() const { return name_; } + std::string const name() const { return name_.c_str(); } /// - std::string const latexName() const { return latexName_; } + std::string const latexName() const { return latexName_.c_str(); } /// - std::string const guiName() const { return guiName_; } + std::string const guiName() const { return guiName_.c_str(); } /// - std::string const iconvName() const { return iconvName_; } + std::string const iconvName() const { return iconvName_.c_str(); } /// bool hasFixedWidth() const { return fixedwidth_; } /// diff --git a/src/Format.cpp b/src/Format.cpp index c94481b..92e1626 100644 --- a/src/Format.cpp +++ b/src/Format.cpp @@ -118,8 +118,9 @@ bool operator<(Format const & a, Format const & b) Format::Format(string const & n, string const & e, string const & p, string const & s, string const & v, string const & ed, string const & m, int flags) - : name_(n), prettyname_(p), shortcut_(s), viewer_(v), - editor_(ed), mime_(m), flags_(flags) + : name_(n.c_str()), prettyname_(p.c_str()), shortcut_(s.c_str()), + viewer_(v.c_str()), editor_(ed.c_str()), mime_(m.c_str()), + flags_(flags) { extension_list_ = getVectorFromString(e, ","); LYXERR(Debug::GRAPHICS, "New Format: n=" << n << ", flags=" << flags); @@ -155,7 +156,7 @@ bool Format::isChildFormat() const string const Format::parentFormat() const { - return name_.substr(0, name_.length() - 1); + return name_.substr(0, name_.length() - 1).c_str(); } diff --git a/src/Format.h b/src/Format.h index 6ebcf84..1c599c5 100644 --- a/src/Format.h +++ b/src/Format.h @@ -13,7 +13,6 @@ #define FORMAT_H #include "support/docstring.h" -#include "support/trivstring.h" #include "OutputParams.h" @@ -55,9 +54,9 @@ public: /// Name fo the parent format std::string const parentFormat() const; /// - std::string const name() const { return name_; } + std::string const name() const { return name_.c_str(); } /// - void setName(std::string const & v) { name_ = v; } + void setName(std::string const & v) { name_ = v.c_str(); } /// std::string const extension() const { @@ -68,25 +67,25 @@ public: /// void setExtensions(std::string const & v); /// - std::string const prettyname() const { return prettyname_; } + std::string const prettyname() const { return prettyname_.c_str(); } /// - void setPrettyname(std::string const & v) { prettyname_ = v; } + void setPrettyname(std::string const & v) { prettyname_ = v.c_str(); } /// - std::string const shortcut() const { return shortcut_; } + std::string const shortcut() const { return shortcut_.c_str(); } /// - void setShortcut(std::string const & v) { shortcut_ = v; } + void setShortcut(std::string const & v) { shortcut_ = v.c_str(); } /// - std::string const viewer() const { return viewer_; } + std::string const viewer() const { return viewer_.c_str(); } /// - void setViewer(std::string const & v) { viewer_ = v; } + void setViewer(std::string const & v) { viewer_ = v.c_str(); } /// - std::string const editor() const { return editor_; } + std::string const editor() const { return editor_.c_str(); } /// - void setEditor(std::string const & v) { editor_ = v; } + void setEditor(std::string const & v) { editor_ = v.c_str(); } /// - std::string const mime() const { return mime_; } + std::string const mime() const { return mime_.c_str(); } /// - void setMime(std::string const & m) { mime_ = m; } + void setMime(std::string const & m) { mime_ = m.c_str(); } /// bool documentFormat() const { return flags_ & document; } /// diff --git a/src/Language.cpp b/src/Language.cpp index dc38bfc..ad462d3 100644 --- a/src/Language.cpp +++ b/src/Language.cpp @@ -55,7 +55,7 @@ docstring const Language::translateLayout(string const & m) const return from_utf8(m); } - TranslationMap::const_iterator it = layoutTranslations_.find(m); + TranslationMap::const_iterator it = layoutTranslations_.find(m.c_str()); if (it != layoutTranslations_.end()) return it->second; @@ -169,11 +169,11 @@ bool Language::readLanguage(Lexer & lex) break; case LA_POSTBABELPREAMBLE: babel_postsettings_ = - lex.getLongString("EndPostBabelPreamble"); + lex.getLongString("EndPostBabelPreamble").c_str(); break; case LA_PREBABELPREAMBLE: babel_presettings_ = - lex.getLongString("EndPreBabelPreamble"); + lex.getLongString("EndPreBabelPreamble").c_str(); break; case LA_REQUIRES: lex >> requires_; @@ -200,17 +200,17 @@ bool Language::read(Lexer & lex) return false; } - lang_ = lex.getString(); - LYXERR(Debug::INFO, "Reading language " << lang_); + lang_ = lex.getString().c_str(); + LYXERR(Debug::INFO, "Reading language " << lang_.c_str()); if (!readLanguage(lex)) { - LYXERR0("Error parsing language `" << lang_ << '\''); + LYXERR0("Error parsing language `" << lang_.c_str() << '\''); return false; } - encoding_ = encodings.fromLyXName(encodingStr_); + encoding_ = encodings.fromLyXName(encodingStr_.c_str()); if (!encoding_ && !encodingStr_.empty()) { encoding_ = encodings.fromLyXName("iso8859-1"); - LYXERR0("Unknown encoding " << encodingStr_); + LYXERR0("Unknown encoding " << encodingStr_.c_str()); } return true; } @@ -260,7 +260,7 @@ void Languages::read(FileName const & filename) static const Language ignore_lang = l; ignore_language = &ignore_lang; } else - languagelist[l.lang()] = l; + languagelist[l.lang().c_str()] = l; } default_language = getLanguage("english"); @@ -289,7 +289,7 @@ bool readTranslations(Lexer & lex, Language::TranslationMap & trans) if (!lex.next(true)) return false; docstring const val = lex.getDocString(); - trans[key] = val; + trans[key.c_str()] = val; } return true; } @@ -387,7 +387,7 @@ Language const * Languages::getLanguage(string const & language) const return reset_language; if (language == "ignore") return ignore_language; - const_iterator it = languagelist.find(language); + const_iterator it = languagelist.find(language.c_str()); return it == languagelist.end() ? reset_language : &it->second; } diff --git a/src/Language.h b/src/Language.h index 43caaa5..f800b20 100644 --- a/src/Language.h +++ b/src/Language.h @@ -16,7 +16,6 @@ #define LANGUAGE_H #include "support/docstring.h" -#include "support/trivstring.h" #include <map> @@ -35,21 +34,21 @@ public: Language() : rightToLeft_(false), encoding_(0), internal_enc_(false), as_babel_options_(false), has_gui_support_(false) {} /// LyX language name - std::string const lang() const { return lang_; } + std::string const lang() const { return lang_.c_str(); } /// Babel language name - std::string const babel() const { return babel_; } + std::string const babel() const { return babel_.c_str(); } /// polyglossia language name - std::string const polyglossia() const { return polyglossia_name_; } + std::string const polyglossia() const { return polyglossia_name_.c_str(); } /// polyglossia language options - std::string const polyglossiaOpts() const { return polyglossia_opts_; } + std::string const polyglossiaOpts() const { return polyglossia_opts_.c_str(); } /// Is this language only supported by polyglossia? bool isPolyglossiaExclusive() const; /// quotation marks style - std::string const quoteStyle() const { return quote_style_; } + std::string const quoteStyle() const { return quote_style_.c_str(); } /// requirement (package, function) - std::string const requires() const { return requires_; } + std::string const requires() const { return requires_.c_str(); } /// translatable GUI name - std::string const display() const { return display_; } + std::string const display() const { return display_.c_str(); } /// is this a RTL language? bool rightToLeft() const { return rightToLeft_; } /** @@ -62,23 +61,23 @@ public: /// default encoding Encoding const * encoding() const { return encoding_; } /// - std::string const encodingStr() const { return encodingStr_; } + std::string const encodingStr() const { return encodingStr_.c_str(); } /// language code - std::string const code() const { return code_; } + std::string const code() const { return code_.c_str(); } /// set code (needed for rc.spellchecker_alt_lang) - void setCode(std::string const & c) { code_ = c; } + void setCode(std::string const & c) { code_ = c.c_str(); } /// language variety (needed by aspell checker) - std::string const variety() const { return variety_; } + std::string const variety() const { return variety_.c_str(); } /// set variety (needed for rc.spellchecker_alt_lang) - void setVariety(std::string const & v) { variety_ = v; } + void setVariety(std::string const & v) { variety_ = v.c_str(); } /// preamble settings after babel was called - std::string const babel_postsettings() const { return babel_postsettings_; } + std::string const babel_postsettings() const { return babel_postsettings_.c_str(); } /// preamble settings before babel is called - std::string const babel_presettings() const { return babel_presettings_; } + std::string const babel_presettings() const { return babel_presettings_.c_str(); } /// This language internally sets a font encoding bool internalFontEncoding() const { return internal_enc_; } /// fontenc encoding(s) - std::string const fontenc() const { return fontenc_; } + std::string const fontenc() const { return fontenc_.c_str(); } /// This language needs to be passed to babel itself (not the class) bool asBabelOptions() const { return as_babel_options_; } /// This language corresponds to a translation of the GUI diff --git a/src/Lexer.h b/src/Lexer.h index 5e87ebc..3b08214 100644 --- a/src/Lexer.h +++ b/src/Lexer.h @@ -222,7 +222,7 @@ template <class T> Lexer & operator>>(Lexer & lex, T & t) { if (lex.next()) - t = T(lex.getString()); + t = T(lex.getString().c_str()); return lex; } diff --git a/src/support/Makefile.am b/src/support/Makefile.am index 1b0cecc..d486db6 100644 --- a/src/support/Makefile.am +++ b/src/support/Makefile.am @@ -102,8 +102,6 @@ liblyxsupport_a_SOURCES = \ Translator.h \ Timeout.cpp \ Timeout.h \ - trivstring.cpp \ - trivstring.h \ types.h \ unique_ptr.h \ userinfo.cpp \ diff --git a/src/support/strfwd.h b/src/support/strfwd.h index f0670c4..cacf3b7 100644 --- a/src/support/strfwd.h +++ b/src/support/strfwd.h @@ -50,8 +50,8 @@ typedef std::basic_ostringstream<char_type> odocstringstream; /// UCS4 input stringstream typedef std::basic_istringstream<char_type> idocstringstream; -// trivstring is a partial and thread-safe implementation of std::string thanks -// to specific definitions below for gcc < 5.1. +// trivstring is a thread-safe implementation of std::string thanks to specific +// definitions below for gcc < 5.1. typedef std::string trivstring; #else @@ -70,21 +70,13 @@ typedef std::string trivstring; // C++11-compliant and this and trivstring below can be removed. typedef __gnu_cxx::__versa_string<char32_t> docstring; +typedef __gnu_cxx::__versa_string<char> trivstring; // Defined in support/docstream.h. It requires additional conversions of // docstring to/from std::basic_string<char32_t>. class odocstringstream; class idocstringstream; -// trivial_string is declared in src/support/trivstring.h -// -// Note: using __gnu_cxx::__vstring to provide a thread-safe implementation of -// std::string is harder because std::string is hard-coded in the LyX sources, -// and on the other hand using it only as a replacement of trivstring requires -// conversions to and from std::string. -template<typename Char> class trivial_string; -typedef trivial_string<char> trivstring; - #endif // !defined(STD_STRING_USES_COW) diff --git a/src/support/tests/check_trivstring.cpp b/src/support/tests/check_trivstring.cpp index e81f07d..3bbeeb7a 100644 --- a/src/support/tests/check_trivstring.cpp +++ b/src/support/tests/check_trivstring.cpp @@ -1,6 +1,5 @@ #include <config.h> -#include "../trivstring.h" #include "../docstring.h" #include <iostream> diff --git a/src/support/trivstring.cpp b/src/support/trivstring.cpp deleted file mode 100644 index f1d0bb5..0000000 --- a/src/support/trivstring.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/** - * \file trivstring.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Georg Baum - * - * Full author contact details are available in file CREDITS. - */ - -#include <config.h> - -#include "support/trivstring.h" -#include "support/docstring.h" - -#ifdef STD_STRING_USES_COW -#include <algorithm> -#include <ostream> -#include <stdexcept> - -using namespace std; - -namespace lyx { - -template trivial_string<char>::trivial_string(trivial_string const &); -template trivial_string<char_type>::trivial_string(trivial_string const &); -template<typename Char> -trivial_string<Char>::trivial_string(trivial_string const & that) : size_(that.size_) -{ - if (use_sso()) - copy(that.data_sso(), that.data_sso() + size_ + 1, data_sso()); - else if (size_ > 0) { - data_ = new Char[size_ + 1]; - copy(that.data_, that.data_ + size_ + 1, data_); - } else { - // Happens only for really big Char types - data_ = 0; - } -} - - -template<typename Char> -trivial_string<Char>::trivial_string(Char const * that, size_t n) : size_(n) -{ - if (use_sso()) { - copy(that, that + size_, data_sso()); - data_sso()[size_] = '\0'; - } else if (size_ > 0) { - data_ = new Char[size_ + 1]; - copy(that, that + size_, data_); - data_[size_] = '\0'; - } else { - // Happens only for really big Char types - data_ = 0; - } -} - - -template trivial_string<char>::trivial_string(string const &); - -template<typename Char> -trivial_string<Char>::trivial_string(_stdstring const & that) - : size_(that.length()) -{ - if (use_sso()) { - copy(that.begin(), that.end(), data_sso()); - data_sso()[size_] = '\0'; - } else if (size_ > 0) { - data_ = new Char[size_ + 1]; - copy(that.begin(), that.end(), data_); - data_[size_] = '\0'; - } else { - // Happens only for really big Char types - data_ = 0; - } -} - - -template trivial_string<char> & -trivial_string<char>::operator=(trivial_string const &); -template trivial_string<char_type> & -trivial_string<char_type>::operator=(trivial_string const &); -template<typename Char> -trivial_string<Char> & trivial_string<Char>::operator=(trivial_string const & that) -{ - if (&that == this) - return *this; - if (!use_sso()) - delete[] data_; - size_ = that.size_; - if (use_sso()) - copy(that.data_sso(), that.data_sso() + size_ + 1, data_sso()); - else if (size_ > 0) { - data_ = new Char[size_ + 1]; - copy(that.data_, that.data_ + size_ + 1, data_); - } else { - // Happens only for really big Char types - data_ = 0; - } - return *this; -} - - -template trivial_string<char> & -trivial_string<char>::operator=(string const &); -template<typename Char> -trivial_string<Char> & -trivial_string<Char>::operator=(_stdstring const & that) -{ - if (!use_sso()) - delete[] data_; - size_ = that.size(); - if (use_sso()) { - copy(that.begin(), that.end(), data_sso()); - data_sso()[size_] = '\0'; - } else if (size_ > 0) { - data_ = new Char[size_ + 1]; - copy(that.begin(), that.end(), data_); - } else { - // Happens only for really big Char types - data_ = 0; - } - return *this; -} - - -template void -trivial_string<char>::swap(trivial_string<char> &); -template void -trivial_string<char_type>::swap(trivial_string<char_type> &); -template<typename Char> -void trivial_string<Char>::swap(trivial_string & that) -{ - size_t const sizetmp = that.size_; - that.size_ = size_; - size_ = sizetmp; - Char * const datatmp = that.data_; - that.data_ = data_; - data_ = datatmp; -} - - -template<typename Char> -int trivial_string<Char>::compare(trivial_string const & other) const -{ - size_t const lsize = this->length(); - size_t const rsize = other.length(); - size_t const len = min(lsize, rsize); - int r = char_traits<Char>::compare(c_str(), other.c_str(), len); - if (r == 0) { - if (lsize > rsize) - r = 1; - else if (lsize < rsize) - r = -1; - } - return r; -} - - -template trivial_string<char> trivial_string<char>::substr(size_t, size_t) const; -template trivial_string<char_type> trivial_string<char_type>::substr(size_t, size_t) const; -template<typename Char> -trivial_string<Char> trivial_string<Char>::substr(size_t pos, size_t n) const -{ - if (pos > length()) - throw out_of_range("trivial_string::substr"); - if (n == _stdstring::npos) - n = length() - pos; - size_t const l = min(pos + n, length()); - return trivial_string(c_str() + pos, l - pos); -} - - -template trivial_string<char>::operator string() const; -template<typename Char> -trivial_string<Char>::operator _stdstring() const -{ - if (use_sso()) - return _stdstring(data_sso(), size_); - if (size_ > 0) - return _stdstring(data_, size_); - // Happens only for really big Char types - return _stdstring(); -} - - -template char const * trivial_string<char>::c_str() const; -template<typename Char> Char const * trivial_string<Char>::c_str() const -{ - if (use_sso()) - return data_sso(); - if (size_ > 0) - return data_; - // Happens only for really big Char types - static const Char empty_char = '\0'; - return &empty_char; -} - - -template char trivial_string<char>::operator[](size_t) const; -template <typename Char> Char trivial_string<Char>::operator[](size_t i) const -{ - return c_str()[i]; -} - - -template bool operator<(trivial_string<char> const &, - trivial_string<char> const &); -template <typename Char> -bool operator<(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs) -{ - return lhs.compare(rhs) < 0; -} - - -template bool operator==(trivial_string<char> const &, - trivial_string<char> const &); -template <typename Char> -bool operator==(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs) -{ - return lhs.compare(rhs) == 0; -} - - -template bool operator==(trivial_string<char> const &, char const *); -template <typename Char> -bool operator==(trivial_string<Char> const & lhs, Char const * rhs) -{ - return lhs.compare(trivial_string<Char>(rhs)) == 0; -} - - -template bool operator==(char const *, trivial_string<char> const &); -template <typename Char> -bool operator==(Char const * lhs, trivial_string<Char> const & rhs) -{ - return rhs.compare(trivial_string<Char>(lhs)) == 0; -} - - -template ostream & operator<<(ostream &, trivial_string<char> const &); -template odocstream & operator<<(odocstream &, trivial_string<char_type> const &); -template <typename Char> -basic_ostream<Char, char_traits<Char> > & -operator<<(basic_ostream<Char, char_traits<Char> > & os, trivial_string<Char> const & s) -{ - return os << basic_string<Char, char_traits<Char>, allocator<Char> >(s); -} - -} // namespace lyx -#endif diff --git a/src/support/trivstring.h b/src/support/trivstring.h deleted file mode 100644 index e147523..0000000 --- a/src/support/trivstring.h +++ /dev/null @@ -1,116 +0,0 @@ -// -*- C++ -*- -/** - * \file trivstring.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Georg Baum - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef LYX_TRIVSTRING_H -#define LYX_TRIVSTRING_H - -#include "support/strfwd.h" - -#ifdef STD_STRING_USES_COW -#include <cstdlib> - -namespace lyx { - -/** - * Trivial string class with almost no features. - * The public interface is a subset of the std::basic_string interface. - * The only important feature is that any read-only access does not need - * synchronization between multiple threads, i.e. it is thread-safe without - * locking. - * Therefore you can safely use a const trivial_string object in multiple - * threads at the same time. This is not the case for std::basic_string in some - * STL implementations (e. g. GNU libcstd++, see bug 9336 and - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21334. - * This class should not be used for anything else than providing thread-safety. - * It should be removed as soon as LyX requires C++11, and all supported STL - * implementations provide a C++11 conformant std::basic_string. - * - * If you change anything in this class please ensure that the unit test - * tests/check_trivstring.cpp still tests 100% of the public interface. - */ -template <typename Char> class trivial_string -{ -public: - /// Corresponding std::basic_string - typedef std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > _stdstring; - /// Construct an empty string - trivial_string() : size_(0), data_(0) {} - /// Construct a string from a copy of \p that - trivial_string(trivial_string const & that); - /// Construct a string from a copy of \p that - trivial_string(Char const * that, size_t n); - /// Construct a string from a copy of \p that - trivial_string(_stdstring const & that); - /// - ~trivial_string() { if (!use_sso()) delete[] data_; } - /// Assign a copy of \p that - trivial_string & operator=(trivial_string const & that); - /// Assign a copy of \p that - trivial_string & operator=(_stdstring const & that); - /// Exchange contents with contents of \p that - void swap(trivial_string & that); - /// The length of the string, excluding the final 0 character - size_t length() const { return size_; } - /// Is this string empty? - bool empty() const { return size_ == 0; } - /// Is this string ordered before, at the same position or after \p other? - int compare(trivial_string const & other) const; - /// Return substring of length \p n starting at \p pos - trivial_string substr(size_t pos = 0, size_t n = _stdstring::npos) const; - /// Create a copy as std::basic_string - operator _stdstring() const; - /// Return a C-compatible string, terminated by a 0 character. - /// This is never a copy and only valid for the life time of the trivial_string instance. - Char const * c_str() const; - /// Return character at position \p i (validity of \i is not checked) - Char operator[](size_t i) const; -private: - /** - * Whether short string optimization is used. - * Short string optimization is a technique where no additional memory - * needs to be allocated to store the string contents. - * Instead, the memory which would be used to store the pointer to the - * character buffer is reinterpreted to be a Char * buffer. - * On most 64 bit systems and with Char == char this allows to store - * strings of up to 7 characters without allocating additional memory. - */ - bool use_sso() const { return (size_ + 1) * sizeof(Char) <= sizeof(Char *); } - /// The character storage if sso is used - Char * data_sso() { return reinterpret_cast<Char * >(&data_); } - /// The character storage if sso is used - Char const * data_sso() const { return reinterpret_cast<Char const *>(&data_); } - /// The length of the string, excluding the final 0 character - size_t size_; - /// The character storage - Char * data_; -}; - - -/// Comparison operator (needed for std::set etc) -template <typename Char> bool operator<(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs); - - -/// Equality operator -template <typename Char> bool operator==(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs); -template <typename Char> bool operator==(trivial_string<Char> const & lhs, Char const * rhs); -template <typename Char> bool operator==(Char const * lhs, trivial_string<Char> const & rhs); - - -/// Stream output operator -template <typename Char> -std::basic_ostream<Char, std::char_traits<Char> > & -operator<<(std::basic_ostream<Char, std::char_traits<Char> > &, trivial_string<Char> const &); - -} // namespace lyx -#else -#include <string> -#endif // STD_STRING_USES_COW -#endif // LYX_TRIVSTRING_H -- 2.7.4