LibreOffice
LibreOffice 6.4 SDK C/C++ API Reference
stringutils.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #ifndef INCLUDED_RTL_STRINGUTILS_HXX
11 #define INCLUDED_RTL_STRINGUTILS_HXX
12 
13 #include "sal/config.h"
14 
15 #include <cassert>
16 #include <cstddef>
17 
18 #include "sal/types.h"
19 
20 // The unittest uses slightly different code to help check that the proper
21 // calls are made. The class is put into a different namespace to make
22 // sure the compiler generates a different (if generating also non-inline)
23 // copy of the function and does not merge them together. The class
24 // is "brought" into the proper rtl namespace by a typedef below.
25 #ifdef RTL_STRING_UNITTEST
26 #define rtl rtlunittest
27 #endif
28 
29 namespace rtl
30 {
31 
32 #ifdef RTL_STRING_UNITTEST
33 #undef rtl
34 #endif
35 
36 #if defined LIBO_INTERNAL_ONLY
37 
39 // A simple wrapper around a single char. Can be useful in string concatenation contexts, like in
40 //
41 // OString s = ...;
42 // char c = ...;
43 // s += OStringChar(c);
44 //
45 struct SAL_WARN_UNUSED OStringChar {
46  constexpr OStringChar(char theC): c(theC) {}
47  template<typename T> OStringChar(T &&) = delete;
48  char const c;
49 };
50 
93 struct SAL_WARN_UNUSED OUStringChar_ {
94  constexpr OUStringChar_(sal_Unicode theC): c(theC) {}
95  constexpr OUStringChar_(char theC): c(theC) { assert(c <= 0x7F); }
96  template<typename T> OUStringChar_(T &&) = delete;
97  sal_Unicode const c;
98 };
99 using OUStringChar = OUStringChar_ const;
100 
102 #endif
103 
104 namespace libreoffice_internal
105 {
106 /*
107 These templates use SFINAE (Substitution failure is not an error) to help distinguish the various
108 plain C string types: char*, const char*, char[N], const char[N], char[] and const char[].
109 There are 2 cases:
110 1) Only string literal (i.e. const char[N]) is wanted, not any of the others.
111  In this case it is necessary to distinguish between const char[N] and char[N], as the latter
112  would be automatically converted to the const variant, which is not wanted (not a string literal
113  with known size of the content). In this case ConstCharArrayDetector is used to ensure the function
114  is called only with const char[N] arguments. There's no other plain C string type overload.
115 2) All plain C string types are wanted, and const char[N] needs to be handled differently.
116  In this case const char[N] would match const char* argument type (not exactly sure why, but it's
117  consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type
118  avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer
119  arguments. The const in the argument is necessary to handle the case when something is explicitly
120  cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference
121  being const, it would also match const char[N], so another overload with a reference to non-const
122  and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N].
123 Additionally, char[] and const char[] (i.e. size unknown) are rather tricky. Their usage with 'T&' would
124 mean it would be 'char(&)[]', which seems to be invalid. But gcc and clang somehow manage when it is
125 a template. while msvc complains about no conversion from char[] to char[1]. And the reference cannot
126 be avoided, because 'const char[]' as argument type would match also 'const char[N]'
127 So char[] and const char[] should always be used with their contents specified (which automatically
128 turns them into char[N] or const char[N]), or char* and const char* should be used.
129 */
130 struct Dummy {};
131 template< typename T1, typename T2 = void >
133 {
134  static const bool ok = false;
135 };
136 template< typename T >
137 struct CharPtrDetector< const char*, T >
138 {
139  typedef T Type;
140  static const bool ok = true;
141 };
142 template< typename T >
143 struct CharPtrDetector< char*, T >
144 {
145  typedef T Type;
146  static const bool ok = true;
147 };
148 #if defined LIBO_INTERNAL_ONLY
149 template<typename T> struct CharPtrDetector<sal_Unicode *, T> { using TypeUtf16 = T; };
150 template<typename T> struct CharPtrDetector<sal_Unicode const *, T> { using TypeUtf16 = T; };
151 template<typename T> struct CharPtrDetector<sal_Unicode[], T> { using TypeUtf16 = T; };
152 template<typename T> struct CharPtrDetector<sal_Unicode const[], T> { using TypeUtf16 = T; };
153 #endif
154 
155 template< typename T1, typename T2 >
157 {
158 };
159 template< typename T, int N >
160 struct NonConstCharArrayDetector< char[ N ], T >
161 {
162  typedef T Type;
163 };
164 #ifdef RTL_STRING_UNITTEST
165 // never use, until all compilers handle this
166 template< typename T >
167 struct NonConstCharArrayDetector< char[], T >
168 {
169  typedef T Type;
170 };
171 template< typename T >
172 struct NonConstCharArrayDetector< const char[], T >
173 {
174  typedef T Type;
175 };
176 #endif
177 #if defined LIBO_INTERNAL_ONLY
178 template<typename T, std::size_t N> struct NonConstCharArrayDetector<sal_Unicode[N], T> {
179  using TypeUtf16 = T;
180 };
181 #endif
182 
183 template< typename T1, typename T2 = void >
185 {
186  static const bool ok = false;
187 };
188 template< std::size_t N, typename T >
189 struct ConstCharArrayDetector< const char[ N ], T >
190 {
191  typedef T Type;
192  static const std::size_t length = N - 1;
193  static const bool ok = true;
194 #if defined LIBO_INTERNAL_ONLY
195  constexpr
196 #endif
197  static bool isValid(char const (& literal)[N]) {
198  for (std::size_t i = 0; i != N - 1; ++i) {
199  if (literal[i] == '\0') {
200  return false;
201  }
202  }
203  return literal[N - 1] == '\0';
204  }
205 #if defined LIBO_INTERNAL_ONLY
206  constexpr
207 #endif
208  static char const * toPointer(char const (& literal)[N]) { return literal; }
209 };
210 
211 #if defined(__COVERITY__)
212 //to silence over zealous warnings that the loop is logically dead
213 //for the single char case
214 template< typename T >
215 struct ConstCharArrayDetector< const char[ 1 ], T >
216 {
217  typedef T Type;
218  static const std::size_t length = 0;
219  static const bool ok = true;
220 #if defined LIBO_INTERNAL_ONLY
221  constexpr
222 #endif
223  static bool isValid(char const (& literal)[1]) {
224  return literal[0] == '\0';
225  }
226 #if defined LIBO_INTERNAL_ONLY
227  constexpr
228 #endif
229  static char const * toPointer(char const (& literal)[1]) { return literal; }
230 };
231 #endif
232 
233 #if defined LIBO_INTERNAL_ONLY && defined __cpp_char8_t
234 template<std::size_t N, typename T>
235 struct ConstCharArrayDetector<char8_t const [N], T> {
236  using Type = T;
237  static constexpr bool const ok = true;
238  static constexpr std::size_t const length = N - 1;
239  static constexpr bool isValid(char8_t const (& literal)[N]) {
240  for (std::size_t i = 0; i != N - 1; ++i) {
241  if (literal[i] == u8'\0') {
242  return false;
243  }
244  }
245  return literal[N - 1] == u8'\0';
246  }
247  static constexpr char const * toPointer(char8_t const (& literal)[N])
248  { return reinterpret_cast<char const *>(literal); }
249 };
250 #endif
251 
252 #if defined LIBO_INTERNAL_ONLY
253 template<std::size_t N, typename T>
254 struct ConstCharArrayDetector<sal_Unicode const [N], T> {
255  using TypeUtf16 = T;
256  static constexpr bool const ok = true;
257  static constexpr std::size_t const length = N - 1;
258  static constexpr sal_Unicode const * toPointer(
259  sal_Unicode const (& literal)[N])
260  { return literal; }
261 };
262 template<typename T> struct ConstCharArrayDetector<
263  OUStringChar,
264  T>
265 {
266  using TypeUtf16 = T;
267  static constexpr bool const ok = true;
268  static constexpr std::size_t const length = 1;
269  static constexpr sal_Unicode const * toPointer(
270  OUStringChar_ const & literal)
271  { return &literal.c; }
272 };
273 #endif
274 
275 // this one is used to rule out only const char[N]
276 template< typename T >
278 {
279  typedef Dummy Type;
280 };
281 template< int N >
282 struct ExceptConstCharArrayDetector< const char[ N ] >
283 {
284 };
285 #if defined LIBO_INTERNAL_ONLY
286 template<std::size_t N>
287 struct ExceptConstCharArrayDetector<sal_Unicode const[N]> {};
288 template<> struct ExceptConstCharArrayDetector<
289  OUStringChar
290  >
291 {};
292 #endif
293 
294 // this one is used to rule out only const char[N]
295 // (const will be brought in by 'const T&' in the function call)
296 // msvc needs const char[N] here (not sure whether gcc or msvc
297 // are right, it doesn't matter).
298 template< typename T >
300 {
301  typedef Dummy Type;
302 };
303 template< int N >
304 struct ExceptCharArrayDetector< char[ N ] >
305 {
306 };
307 template< int N >
308 struct ExceptCharArrayDetector< const char[ N ] >
309 {
310 };
311 #if defined LIBO_INTERNAL_ONLY
312 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode[N]> {};
313 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode const[N]> {};
314 template<> struct ExceptCharArrayDetector<OUStringChar_> {};
315 #endif
316 
317 template< typename T1, typename T2 = void >
319 {
320  static const bool ok = false;
321 };
322 template< typename T >
324 {
325  typedef T Type;
326  static const bool ok = true;
327 };
328 template< typename T >
330 {
331  typedef T Type;
332  static const bool ok = true;
333 };
334 
335 // SFINAE helper class
336 template< typename T, bool >
337 struct Enable
338  {
339  };
340 
341 template< typename T >
342 struct Enable< T, true >
343  {
344  typedef T Type;
345  };
346 
347 
348 } /* Namespace */
349 
350 } /* Namespace */
351 
352 #endif // INCLUDED_RTL_STRINGUTILS_HXX
353 
354 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: stringutils.hxx:130
#define SAL_WARN_UNUSED
Annotate classes where a compiler should warn if an instance is unused.
Definition: types.h:578
static const bool ok
Definition: stringutils.hxx:320
sal_uInt16 sal_Unicode
Definition: types.h:141
Definition: stringutils.hxx:337
static const bool ok
Definition: stringutils.hxx:186
Definition: bootstrap.hxx:29
static bool isValid(char const (&literal)[N])
Definition: stringutils.hxx:197
Definition: stringutils.hxx:132
static const bool ok
Definition: stringutils.hxx:134
T Type
Definition: stringutils.hxx:344
Dummy Type
Definition: stringutils.hxx:279
Dummy Type
Definition: stringutils.hxx:301
static char const * toPointer(char const (&literal)[N])
Definition: stringutils.hxx:208