]> git.lyx.org Git - features.git/blob - src/support/trivstring.cpp
Make Format class almost thread-safe
[features.git] / src / support / trivstring.cpp
1 /**
2  * \file trivstring.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Georg Baum
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "support/trivstring.h"
14 #include "support/docstring.h"
15
16 #ifdef STD_STRING_USES_COW
17 #include <algorithm>
18 #include <ostream>
19 #include <stdexcept>
20
21 using namespace std;
22
23 namespace lyx {
24
25 template trivial_string<char>::trivial_string(trivial_string const &);
26 template trivial_string<char_type>::trivial_string(trivial_string const &);
27 template<typename Char>
28 trivial_string<Char>::trivial_string(trivial_string const & that) : size_(that.size_)
29 {
30         if (use_sso())
31                 copy(that.data_sso(), that.data_sso() + size_ + 1, data_sso());
32         else if (size_ > 0) {
33                 data_ = new Char[size_ + 1];
34                 copy(that.data_, that.data_ + size_ + 1, data_);
35         } else {
36                 // Happens only for really big Char types
37                 data_ = 0;
38         }
39 }
40
41
42 template<typename Char>
43 trivial_string<Char>::trivial_string(Char const * that, size_t n) : size_(n)
44 {
45         if (use_sso()) {
46                 copy(that, that + size_, data_sso());
47                 data_sso()[size_] = '\0';
48         } else if (size_ > 0) {
49                 data_ = new Char[size_ + 1];
50                 copy(that, that + size_, data_);
51                 data_[size_] = '\0';
52         } else {
53                 // Happens only for really big Char types
54                 data_ = 0;
55         }
56 }
57
58
59 template trivial_string<char>::trivial_string(string const &);
60 template trivial_string<char_type>::trivial_string(docstring const &);
61 template<typename Char>
62 trivial_string<Char>::trivial_string(
63                 basic_string<Char, char_traits<Char>, allocator<Char> > const & that)
64         : size_(that.length())
65 {
66         if (use_sso()) {
67                 copy(that.begin(), that.end(), data_sso());
68                 data_sso()[size_] = '\0';
69         } else if (size_ > 0) {
70                 data_ = new Char[size_ + 1];
71                 copy(that.begin(), that.end(), data_);
72                 data_[size_] = '\0';
73         } else {
74                 // Happens only for really big Char types
75                 data_ = 0;
76         }
77 }
78
79
80 template trivial_string<char> &
81 trivial_string<char>::operator=(trivial_string const &);
82 template trivial_string<char_type> &
83 trivial_string<char_type>::operator=(trivial_string const &);
84 template<typename Char>
85 trivial_string<Char> & trivial_string<Char>::operator=(trivial_string const & that)
86 {
87         if (&that == this)
88                 return *this;
89         if (!use_sso())
90                 delete[] data_;
91         size_ = that.size_;
92         if (use_sso())
93                 copy(that.data_sso(), that.data_sso() + size_ + 1, data_sso());
94         else if (size_ > 0) {
95                 data_ = new Char[size_ + 1];
96                 copy(that.data_, that.data_ + size_ + 1, data_);
97         } else {
98                 // Happens only for really big Char types
99                 data_ = 0;
100         }
101         return *this;
102 }
103
104
105 template trivial_string<char> &
106 trivial_string<char>::operator=(string const &);
107 template trivial_string<char_type> &
108 trivial_string<char_type>::operator=(docstring const &);
109 template<typename Char>
110 trivial_string<Char> &
111 trivial_string<Char>::operator=(basic_string<Char, char_traits<Char>, allocator<Char> > const & that)
112 {
113         if (!use_sso())
114                 delete[] data_;
115         size_ = that.size();
116         if (use_sso()) {
117                 copy(that.begin(), that.end(), data_sso());
118                 data_sso()[size_] = '\0';
119         } else if (size_ > 0) {
120                 data_ = new Char[size_ + 1];
121                 copy(that.begin(), that.end(), data_);
122         } else {
123                 // Happens only for really big Char types
124                 data_ = 0;
125         }
126         return *this;
127 }
128
129
130 template void
131 trivial_string<char>::swap(trivial_string<char> &);
132 template void
133 trivial_string<char_type>::swap(trivial_string<char_type> &);
134 template<typename Char>
135 void trivial_string<Char>::swap(trivial_string & that)
136 {
137         size_t const sizetmp = that.size_;
138         that.size_ = size_;
139         size_ = sizetmp;
140         Char * const datatmp = that.data_;
141         that.data_ = data_;
142         data_ = datatmp;
143 }
144
145
146 template<typename Char>
147 int trivial_string<Char>::compare(trivial_string const & other) const
148 {
149         size_t const lsize = this->length();
150         size_t const rsize = other.length();
151         size_t const len = min(lsize, rsize);
152         int r = char_traits<Char>::compare(c_str(), other.c_str(), len);
153         if (r == 0) {
154                 if (lsize > rsize)
155                         r = 1;
156                 else if (lsize < rsize)
157                         r = -1;
158         }
159         return r;
160 }
161
162
163 template trivial_string<char> trivial_string<char>::substr(size_t, size_t) const;
164 template trivial_string<char_type> trivial_string<char_type>::substr(size_t, size_t) const;
165 template<typename Char>
166 trivial_string<Char> trivial_string<Char>::substr(size_t pos, size_t n) const
167 {
168         if (pos > length())
169                 throw out_of_range("trivial_string::substr");
170         if (n == basic_string<Char, char_traits<Char>, allocator<Char> >::npos)
171                 n = length() - pos; 
172         size_t const l = min(pos + n, length());
173         return trivial_string(c_str() + pos, l - pos);
174 }
175
176
177 template trivial_string<char>::operator string() const;
178 template trivial_string<char_type>::operator docstring() const;
179 template<typename Char>
180 trivial_string<Char>::operator basic_string<Char, char_traits<Char>, allocator<Char> >() const
181 {
182         if (use_sso())
183                 return basic_string<Char, char_traits<Char>, allocator<Char> >(
184                                 data_sso(), size_);
185         if (size_ > 0)
186                 return basic_string<Char, char_traits<Char>, allocator<Char> >(
187                                 data_, size_);
188         // Happens only for really big Char types
189         return basic_string<Char, char_traits<Char>, allocator<Char> >();
190 }
191
192
193 template<typename Char> Char const * trivial_string<Char>::c_str() const
194 {
195         if (use_sso())
196                 return data_sso();
197         if (size_ > 0)
198                 return data_;
199         // Happens only for really big Char types
200         static const Char empty_char = '\0';
201         return &empty_char;
202 }
203
204
205 template char trivial_string<char>::operator[](size_t) const;
206 template char_type trivial_string<char_type>::operator[](size_t) const;
207 template <typename Char> Char trivial_string<Char>::operator[](size_t i) const
208 {
209         return c_str()[i];
210 }
211
212
213 template bool operator<(trivial_string<char> const &,
214                         trivial_string<char> const &);
215 template bool operator<(trivial_string<char_type> const &,
216                         trivial_string<char_type> const &);
217 template <typename Char>
218 bool operator<(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs)
219 {
220         return lhs.compare(rhs) < 0;
221 }
222
223
224 template bool operator==(trivial_string<char> const &,
225                          trivial_string<char> const &);
226 template bool operator==(trivial_string<char_type> const &,
227                          trivial_string<char_type> const &);
228 template <typename Char>
229 bool operator==(trivial_string<Char> const & lhs, trivial_string<Char> const & rhs)
230 {
231         return lhs.compare(rhs) == 0; 
232 }
233
234
235 template bool operator==(trivial_string<char> const &, char const *);
236 template bool operator==(trivial_string<char_type> const &, char_type const *);
237 template <typename Char>
238 bool operator==(trivial_string<Char> const & lhs, Char const * rhs)
239 {
240         return lhs.compare(trivial_string<Char>(rhs)) == 0; 
241 }
242
243
244 template bool operator==(char const *, trivial_string<char> const &);
245 template bool operator==(char_type const *, trivial_string<char_type> const &);
246 template <typename Char>
247 bool operator==(Char const * lhs, trivial_string<Char> const & rhs)
248 {
249         return rhs.compare(trivial_string<Char>(lhs)) == 0; 
250 }
251
252
253 template ostream & operator<<(ostream &, trivial_string<char> const &);
254 template odocstream & operator<<(odocstream &, trivial_string<char_type> const &);
255 template <typename Char>
256 basic_ostream<Char, char_traits<Char> > &
257 operator<<(basic_ostream<Char, char_traits<Char> > & os, trivial_string<Char> const & s)
258 {
259         return os << basic_string<Char, char_traits<Char>, allocator<Char> >(s);
260 }
261
262 } // namespace lyx
263 #endif