mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 01:59:02 +00:00
Make trivstring class ready for use
The interface is now 100% unit tested, and the typedefs depend on the new STD_STRING_USES_COW configuration variable. The only missing bit is to detect clang and disable STD_STRING_USES_COW for clang.
This commit is contained in:
parent
46f7b578b2
commit
83bee109db
@ -259,10 +259,13 @@ if(UNIX OR MINGW)
|
||||
endif()
|
||||
set(LYX_GCC11_MODE "${CXX11_FLAG}")
|
||||
endif()
|
||||
set(STD_STRING_USES_COW 1)
|
||||
else()
|
||||
if(MSVC10)
|
||||
set(LYX_USE_TR1 1)
|
||||
#set(LYX_USE_TR1_REGEX 1) #TODO should we use it in ECMAScript mode?
|
||||
else()
|
||||
set(STD_STRING_USES_COW 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -297,6 +297,7 @@ if test x$GXX = xyes; then
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_DEFINE(STD_STRING_USES_COW, 1, [std::string uses copy-on-write])
|
||||
fi
|
||||
test "$lyx_pch_comp" = yes && lyx_flags="$lyx_flags pch"
|
||||
AM_CONDITIONAL(LYX_BUILD_PCH, test "$lyx_pch_comp" = yes)
|
||||
|
@ -101,6 +101,8 @@ liblyxsupport_a_SOURCES = \
|
||||
Translator.h \
|
||||
Timeout.cpp \
|
||||
Timeout.h \
|
||||
trivstring.cpp \
|
||||
trivstring.h \
|
||||
types.h \
|
||||
userinfo.cpp \
|
||||
userinfo.h \
|
||||
@ -143,18 +145,21 @@ EXTRA_DIST += \
|
||||
tests/test_lstrings \
|
||||
tests/regfiles/convert \
|
||||
tests/regfiles/filetools \
|
||||
tests/regfiles/lstrings
|
||||
tests/regfiles/lstrings \
|
||||
tests/regfiles/trivstring
|
||||
|
||||
|
||||
TESTS = \
|
||||
tests/test_convert \
|
||||
tests/test_filetools \
|
||||
tests/test_lstrings
|
||||
tests/test_lstrings \
|
||||
tests/test_trivstring
|
||||
|
||||
check_PROGRAMS = \
|
||||
check_convert \
|
||||
check_filetools \
|
||||
check_lstrings
|
||||
check_lstrings \
|
||||
check_trivstring
|
||||
|
||||
if INSTALL_MACOSX
|
||||
ADD_FRAMEWORKS = -framework QtGui -framework QtCore -framework AppKit -framework ApplicationServices
|
||||
@ -181,6 +186,13 @@ check_lstrings_SOURCES = \
|
||||
tests/dummy_functions.cpp \
|
||||
tests/boost.cpp
|
||||
|
||||
check_trivstring_LDADD = liblyxsupport.a $(LIBICONV) $(BOOST_LIBS) $(QT_CORE_LIBS) $(LIBSHLWAPI) @LIBS@
|
||||
check_trivstring_LDFLAGS = $(QT_CORE_LDFLAGS) $(ADD_FRAMEWORKS)
|
||||
check_trivstring_SOURCES = \
|
||||
tests/check_trivstring.cpp \
|
||||
tests/dummy_functions.cpp \
|
||||
tests/boost.cpp
|
||||
|
||||
makeregfiles: ${check_PROGRAMS}
|
||||
for all in ${check_PROGRAMS} ; do \
|
||||
./$$all > ${srcdir}/tests/regfiles/$$all ; \
|
||||
|
@ -95,6 +95,15 @@ std::string const & empty_string();
|
||||
// defined in docstring.cpp
|
||||
bool operator==(docstring const &, char const *);
|
||||
|
||||
#ifdef STD_STRING_USES_COW
|
||||
template<typename Char> class trivial_string;
|
||||
typedef trivial_string<char> trivstring;
|
||||
typedef trivial_string<char_type> trivdocstring;
|
||||
#else
|
||||
typedef std::string trivstring;
|
||||
typedef docstring trivdocstring;
|
||||
#endif
|
||||
|
||||
} // namespace lyx
|
||||
|
||||
#endif
|
||||
|
@ -28,7 +28,7 @@ include_directories(
|
||||
${ZLIB_INCLUDE_DIR})
|
||||
|
||||
|
||||
set(check_PROGRAMS check_convert check_filetools check_lstrings)
|
||||
set(check_PROGRAMS check_convert check_filetools check_lstrings check_trivstring)
|
||||
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/regfiles")
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include "../trivstring.h"
|
||||
#include "../docstring.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -27,22 +28,111 @@ void test_trivstring()
|
||||
// assignment from trivstring
|
||||
trivstring const c = a;
|
||||
// assignment from std::string
|
||||
trivstring const d = input[i];
|
||||
trivstring d = input[i];
|
||||
// assignment from trivstring
|
||||
string const e = a.str();
|
||||
string const e = a;
|
||||
// assignment from trivstring via C string
|
||||
string const f = a.c_str();
|
||||
if (a.empty())
|
||||
cout << "empty ";
|
||||
else
|
||||
cout << "not empty ";
|
||||
cout << a.length() << endl;
|
||||
cout << a.str() << endl;
|
||||
cout << b.str() << endl;
|
||||
cout << c.str() << endl;
|
||||
cout << d.str() << endl;
|
||||
cout << a << endl;
|
||||
cout << b << endl;
|
||||
cout << c << endl;
|
||||
cout << d << endl;
|
||||
cout << e << endl;
|
||||
cout << f << endl;
|
||||
// swap
|
||||
trivstring g("swap");
|
||||
cout << g << endl;
|
||||
d.swap(g);
|
||||
cout << d << endl;
|
||||
cout << g << endl;
|
||||
}
|
||||
// comparison
|
||||
trivstring const a;
|
||||
trivstring const b("a");
|
||||
trivstring const c("b");
|
||||
trivstring const d("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
|
||||
cout << (a == c) << ' ' << (a < c) << endl; // different strings, different length
|
||||
cout << (c == a) << ' ' << (c < a) << endl; // different strings, different length
|
||||
char const * e = "";
|
||||
char const * f = "b";
|
||||
char const * g = "42";
|
||||
cout << (a == e) << ' ' << (e == a) << endl; // empty strings
|
||||
cout << (c == a) << ' ' << (a == c) << endl; // equal strings
|
||||
cout << (a == f) << ' ' << (f == a) << endl; // different strings, same length
|
||||
cout << (a == g) << ' ' << (g == a) << endl; // different strings, different length
|
||||
}
|
||||
|
||||
void test_trivdocstring()
|
||||
{
|
||||
docstring const input[] = {
|
||||
from_ascii(""),
|
||||
from_ascii("a"),
|
||||
from_ascii("42"),
|
||||
from_ascii("max"), // max. string with sso on 64 bit
|
||||
from_ascii("something which does not fit into sso")
|
||||
};
|
||||
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]);
|
||||
// construction from trivstring
|
||||
trivdocstring const b(a);
|
||||
// assignment from trivstring
|
||||
trivdocstring const c = a;
|
||||
// assignment from std::string
|
||||
trivdocstring d = input[i];
|
||||
// assignment from trivstring
|
||||
docstring const e = a;
|
||||
// assignment from trivstring via C string
|
||||
docstring const f = a.c_str();
|
||||
if (a.empty())
|
||||
cout << "empty ";
|
||||
else
|
||||
cout << "not empty ";
|
||||
cout << a.length() << endl;
|
||||
cout << to_ascii(a) << endl;
|
||||
cout << to_ascii(b) << endl;
|
||||
cout << to_ascii(c) << endl;
|
||||
cout << to_ascii(d) << endl;
|
||||
cout << to_ascii(e) << endl;
|
||||
cout << to_ascii(f) << endl;
|
||||
// swap
|
||||
trivdocstring 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"));
|
||||
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
|
||||
cout << (a == c) << ' ' << (a < c) << endl; // different strings, different length
|
||||
cout << (c == a) << ' ' << (c < a) << endl; // different strings, different length
|
||||
// per character initialization works also if char_type != wchar
|
||||
char_type const e[1] = {'\0'};
|
||||
char_type const f[2] = {'b', '\0'};
|
||||
char_type const g[3] = {'4', '2', '\0'};
|
||||
cout << (a == e) << ' ' << (e == a) << endl; // empty strings
|
||||
cout << (c == a) << ' ' << (a == c) << endl; // equal strings
|
||||
cout << (a == f) << ' ' << (f == a) << endl; // different strings, same length
|
||||
cout << (a == g) << ' ' << (g == a) << endl; // different strings, different length
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_trivstring();
|
||||
test_trivdocstring();
|
||||
}
|
||||
|
@ -1,35 +1,118 @@
|
||||
0
|
||||
empty 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1
|
||||
swap
|
||||
swap
|
||||
|
||||
not empty 1
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
2
|
||||
swap
|
||||
swap
|
||||
a
|
||||
not empty 2
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
||||
7
|
||||
swap
|
||||
swap
|
||||
42
|
||||
not empty 7
|
||||
max sso
|
||||
max sso
|
||||
max sso
|
||||
max sso
|
||||
max sso
|
||||
max sso
|
||||
37
|
||||
swap
|
||||
swap
|
||||
max sso
|
||||
not empty 37
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
swap
|
||||
swap
|
||||
something which does not fit into sso
|
||||
1 0
|
||||
0 1
|
||||
0 0
|
||||
0 1
|
||||
0 0
|
||||
1 1
|
||||
0 0
|
||||
0 0
|
||||
0 0
|
||||
empty 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
swap
|
||||
swap
|
||||
|
||||
not empty 1
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
swap
|
||||
swap
|
||||
a
|
||||
not empty 2
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
||||
swap
|
||||
swap
|
||||
42
|
||||
not empty 3
|
||||
max
|
||||
max
|
||||
max
|
||||
max
|
||||
max
|
||||
max
|
||||
swap
|
||||
swap
|
||||
max
|
||||
not empty 37
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
something which does not fit into sso
|
||||
swap
|
||||
swap
|
||||
something which does not fit into sso
|
||||
1 0
|
||||
0 1
|
||||
0 0
|
||||
0 1
|
||||
0 0
|
||||
1 1
|
||||
0 0
|
||||
0 0
|
||||
0 0
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "support/trivstring.h"
|
||||
#include "support/docstring.h"
|
||||
|
||||
#ifdef STD_STRING_USES_COW
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
@ -136,11 +137,10 @@ int trivial_string<Char>::compare(trivial_string const & other) const
|
||||
}
|
||||
|
||||
|
||||
template string trivial_string<char>::str() const;
|
||||
template docstring trivial_string<char_type>::str() const;
|
||||
template trivial_string<char>::operator string() const;
|
||||
template trivial_string<char_type>::operator docstring() const;
|
||||
template<typename Char>
|
||||
basic_string<Char, char_traits<Char>, allocator<Char> >
|
||||
trivial_string<Char>::str() const
|
||||
trivial_string<Char>::operator basic_string<Char, char_traits<Char>, allocator<Char> >() const
|
||||
{
|
||||
if (use_sso())
|
||||
return basic_string<Char, char_traits<Char>, allocator<Char> >(
|
||||
@ -177,4 +177,44 @@ 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 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)
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
return lhs.compare(trivial_string<Char>(rhs)) == 0;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "support/strfwd.h"
|
||||
|
||||
#ifdef STD_STRING_USES_COW
|
||||
#include <cstdlib>
|
||||
|
||||
namespace lyx {
|
||||
@ -31,6 +32,9 @@ namespace lyx {
|
||||
* 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
|
||||
{
|
||||
@ -56,7 +60,7 @@ public:
|
||||
/// Is this string ordered before, at the same position or after \p other?
|
||||
int compare(trivial_string const & other) const;
|
||||
/// Create a copy as std::basic_string
|
||||
std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > str() const;
|
||||
operator std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> >() 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;
|
||||
@ -80,8 +84,25 @@ private:
|
||||
/// 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 &);
|
||||
#else
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
} // namespace lyx
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user