]> git.lyx.org Git - features.git/blob - src/support/trivstring.h
Make Format class almost thread-safe
[features.git] / src / support / trivstring.h
1 // -*- C++ -*-
2 /**
3  * \file trivstring.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Georg Baum
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #ifndef LYX_TRIVSTRING_H
13 #define LYX_TRIVSTRING_H
14
15 #include "support/strfwd.h"
16
17 #ifdef STD_STRING_USES_COW
18 #include <cstdlib>
19
20 namespace lyx {
21
22 /**
23  * Trivial string class with almost no features.
24  * The public interface is a subset of the std::basic_string interface.
25  * The only important feature is that any read-only access does not need
26  * synchronization between multiple threads, i.e. it is thread-safe without
27  * locking.
28  * Therefore you can safely use a const trivial_string object in multiple
29  * threads at the same time. This is not the case for std::basic_string in some
30  * STL implementations (e. g. GNU libcstd++, see bug 9336 and
31  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21334.
32  * This class should not be used for anything else than providing thread-safety.
33  * It should be removed as soon as LyX requires C++11, and all supported STL
34  * implementations provide a C++11 conformant std::basic_string.
35  *
36  * If you change anything in this class please ensure that the unit test
37  * tests/check_trivstring.cpp still tests 100% of the public interface.
38  */
39 template <typename Char> class trivial_string
40 {
41 public:
42         /// Construct an empty string
43         trivial_string() : size_(0), data_(0) {}
44         /// Construct a string from a copy of \p that
45         trivial_string(trivial_string const & that);
46         /// Construct a string from a copy of \p that
47         trivial_string(Char const * that, size_t n);
48         /// Construct a string from a copy of \p that
49         trivial_string(std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > const & that);
50         ///
51         ~trivial_string() { if (!use_sso()) delete[] data_; }
52         /// Assign a copy of \p that
53         trivial_string & operator=(trivial_string const & that);
54         /// Assign a copy of \p that
55         trivial_string & operator=(std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> > const & that);
56         /// Exchange contents with contents of \p that
57         void swap(trivial_string & that);
58         /// The length of the string, excluding the final 0 character
59         size_t length() const { return size_; }
60         /// Is this string empty?
61         bool empty() const { return size_ == 0; }
62         /// Is this string ordered before, at the same position or after \p other?
63         int compare(trivial_string const & other) const;
64         /// Return substring of length \p n starting at \p pos
65         trivial_string substr(size_t pos = 0, size_t n = std::basic_string<Char,
66                                 std::char_traits<Char>, std::allocator<Char> >::npos) const;
67         /// Create a copy as std::basic_string
68         operator std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> >() const;
69         /// Return a C-compatible string, terminated by a 0 character.
70         /// This is never a copy and only valid for the life time of the trivial_string instance.
71         Char const * c_str() const;
72         /// Return character at position \p i (validity of \i is not checked)
73         Char operator[](size_t i) const;
74 private:
75         /**
76          * Whether short string optimization is used.
77          * Short string optimization is a technique where no additional memory
78          * needs to be allocated to store the string contents.
79          * Instead, the memory which would be used to store the pointer to the
80          * character buffer is reinterpreted to be a Char * buffer.
81          * On most 64 bit systems and with Char == char this allows to store
82          * strings of up to 7 characters without allocating additional memory.
83          */
84         bool use_sso() const { return (size_ + 1) * sizeof(Char) <= sizeof(Char *); }
85         /// The character storage if sso is used
86         Char       * data_sso()       { return reinterpret_cast<Char *      >(&data_); }
87         /// The character storage if sso is used
88         Char const * data_sso() const { return reinterpret_cast<Char const *>(&data_); }
89         /// The length of the string, excluding the final 0 character
90         size_t size_;
91         /// The character storage
92         Char * data_;
93 };
94
95
96 /// Comparison operator (needed for std::set etc)
97 template <typename Char> bool operator<(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs);
98
99
100 /// Equality operator
101 template <typename Char> bool operator==(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs);
102 template <typename Char> bool operator==(trivial_string<Char> const & lhs, Char const * rhs);
103 template <typename Char> bool operator==(Char const * lhs, trivial_string<Char> const & rhs);
104
105
106 /// Stream output operator
107 template <typename Char>
108 std::basic_ostream<Char, std::char_traits<Char> > &
109 operator<<(std::basic_ostream<Char, std::char_traits<Char> > &, trivial_string<Char> const &);
110
111 } // namespace lyx
112 #else
113 #include <string>
114 #endif
115 #endif