LibreOffice
LibreOffice 6.2 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 <cstddef>
16 
17 #include "sal/types.h"
18 
19 #if defined LIBO_INTERNAL_ONLY
20 #include "config_global.h"
21 #endif
22 
23 // The unittest uses slightly different code to help check that the proper
24 // calls are made. The class is put into a different namespace to make
25 // sure the compiler generates a different (if generating also non-inline)
26 // copy of the function and does not merge them together. The class
27 // is "brought" into the proper rtl namespace by a typedef below.
28 #ifdef RTL_STRING_UNITTEST
29 #define rtl rtlunittest
30 #endif
31 
32 namespace rtl
33 {
34 
35 #ifdef RTL_STRING_UNITTEST
36 #undef rtl
37 #endif
38 
39 #if defined LIBO_INTERNAL_ONLY
40 
77 struct SAL_WARN_UNUSED OUStringLiteral1_ {
78  constexpr OUStringLiteral1_(sal_Unicode theC): c(theC) {}
79  sal_Unicode const c;
80 };
81 #if defined _MSC_VER && _MSC_VER <= 1900 && !defined __clang__
82  // Visual Studio 2015
83 using OUStringLiteral1 = OUStringLiteral1_;
84 #pragma warning(disable: 4239) // nonstandard extension used: 'argument': conversion from 'rtl::OUStringLiteral1_' to 'rtl::OUStringLiteral1_ &'
85 #else
86 using OUStringLiteral1 = OUStringLiteral1_ const;
87 #endif
88 
90 #endif
91 
92 namespace libreoffice_internal
93 {
94 /*
95 These templates use SFINAE (Substitution failure is not an error) to help distinguish the various
96 plain C string types: char*, const char*, char[N], const char[N], char[] and const char[].
97 There are 2 cases:
98 1) Only string literal (i.e. const char[N]) is wanted, not any of the others.
99  In this case it is necessary to distinguish between const char[N] and char[N], as the latter
100  would be automatically converted to the const variant, which is not wanted (not a string literal
101  with known size of the content). In this case ConstCharArrayDetector is used to ensure the function
102  is called only with const char[N] arguments. There's no other plain C string type overload.
103 2) All plain C string types are wanted, and const char[N] needs to be handled differently.
104  In this case const char[N] would match const char* argument type (not exactly sure why, but it's
105  consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type
106  avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer
107  arguments. The const in the argument is necessary to handle the case when something is explicitly
108  cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference
109  being const, it would also match const char[N], so another overload with a reference to non-const
110  and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N].
111 Additionally, char[] and const char[] (i.e. size unknown) are rather tricky. Their usage with 'T&' would
112 mean it would be 'char(&)[]', which seems to be invalid. But gcc and clang somehow manage when it is
113 a template. while msvc complains about no conversion from char[] to char[1]. And the reference cannot
114 be avoided, because 'const char[]' as argument type would match also 'const char[N]'
115 So char[] and const char[] should always be used with their contents specified (which automatically
116 turns them into char[N] or const char[N]), or char* and const char* should be used.
117 */
118 struct Dummy {};
119 template< typename T1, typename T2 = void >
121 {
122  static const bool ok = false;
123 };
124 template< typename T >
125 struct CharPtrDetector< const char*, T >
126 {
127  typedef T Type;
128  static const bool ok = true;
129 };
130 template< typename T >
131 struct CharPtrDetector< char*, T >
132 {
133  typedef T Type;
134  static const bool ok = true;
135 };
136 
137 template< typename T1, typename T2 >
139 {
140 };
141 template< typename T, int N >
142 struct NonConstCharArrayDetector< char[ N ], T >
143 {
144  typedef T Type;
145 };
146 #ifdef RTL_STRING_UNITTEST
147 // never use, until all compilers handle this
148 template< typename T >
149 struct NonConstCharArrayDetector< char[], T >
150 {
151  typedef T Type;
152 };
153 template< typename T >
154 struct NonConstCharArrayDetector< const char[], T >
155 {
156  typedef T Type;
157 };
158 #endif
159 
160 template< typename T1, typename T2 = void >
162 {
163  static const bool ok = false;
164 };
165 template< std::size_t N, typename T >
166 struct ConstCharArrayDetector< const char[ N ], T >
167 {
168  typedef T Type;
169  static const std::size_t length = N - 1;
170  static const bool ok = true;
171 #if defined LIBO_INTERNAL_ONLY && HAVE_CXX14_CONSTEXPR
172  constexpr
173 #endif
174  static bool isValid(char const (& literal)[N]) {
175  for (std::size_t i = 0; i != N - 1; ++i) {
176  if (literal[i] == '\0') {
177  return false;
178  }
179  }
180  return literal[N - 1] == '\0';
181  }
182 #if defined LIBO_INTERNAL_ONLY
183  constexpr
184 #endif
185  static char const * toPointer(char const (& literal)[N]) { return literal; }
186 };
187 
188 #if defined(__COVERITY__)
189 //to silence over zealous warnings that the loop is logically dead
190 //for the single char case
191 template< typename T >
192 struct ConstCharArrayDetector< const char[ 1 ], T >
193 {
194  typedef T Type;
195  static const std::size_t length = 0;
196  static const bool ok = true;
197 #if defined LIBO_INTERNAL_ONLY && HAVE_CXX14_CONSTEXPR
198  constexpr
199 #endif
200  static bool isValid(char const (& literal)[1]) {
201  return literal[0] == '\0';
202  }
203 #if defined LIBO_INTERNAL_ONLY
204  constexpr
205 #endif
206  static char const * toPointer(char const (& literal)[1]) { return literal; }
207 };
208 #endif
209 
210 #if defined LIBO_INTERNAL_ONLY && defined __cpp_char8_t
211 template<std::size_t N, typename T>
212 struct ConstCharArrayDetector<char8_t const [N], T> {
213  using Type = T;
214  static constexpr bool const ok = true;
215  static constexpr std::size_t const length = N - 1;
216 #if HAVE_CXX14_CONSTEXPR
217  constexpr
218 #endif
219  static bool isValid(char8_t const (& literal)[N]) {
220  for (std::size_t i = 0; i != N - 1; ++i) {
221  if (literal[i] == u8'\0') {
222  return false;
223  }
224  }
225  return literal[N - 1] == u8'\0';
226  }
227  static constexpr char const * toPointer(char8_t const (& literal)[N])
228  { return reinterpret_cast<char const *>(literal); }
229 };
230 #endif
231 
232 #if defined LIBO_INTERNAL_ONLY
233 template<std::size_t N, typename T>
234 struct ConstCharArrayDetector<sal_Unicode const [N], T> {
235  using TypeUtf16 = T;
236  static constexpr bool const ok = true;
237  static constexpr std::size_t const length = N - 1;
238  static constexpr sal_Unicode const * toPointer(
239  sal_Unicode const (& literal)[N])
240  { return literal; }
241 };
242 template<typename T> struct ConstCharArrayDetector<
243 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 \
244  && !defined __clang__
245  OUStringLiteral1_ const,
246 #else
247  OUStringLiteral1,
248 #endif
249  T>
250 {
251  using TypeUtf16 = T;
252  static constexpr bool const ok = true;
253  static constexpr std::size_t const length = 1;
254  static constexpr sal_Unicode const * toPointer(
255  OUStringLiteral1_ const & literal)
256  { return &literal.c; }
257 };
258 #endif
259 
260 // this one is used to rule out only const char[N]
261 template< typename T >
263 {
264  typedef Dummy Type;
265 };
266 template< int N >
267 struct ExceptConstCharArrayDetector< const char[ N ] >
268 {
269 };
270 #if defined LIBO_INTERNAL_ONLY
271 template<std::size_t N>
272 struct ExceptConstCharArrayDetector<sal_Unicode const[N]> {};
273 template<> struct ExceptConstCharArrayDetector<
274 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 \
275  && !defined __clang__
276  OUStringLiteral1_ const
277 #else
278  OUStringLiteral1
279 #endif
280  >
281 {};
282 #endif
283 
284 // this one is used to rule out only const char[N]
285 // (const will be brought in by 'const T&' in the function call)
286 // msvc needs const char[N] here (not sure whether gcc or msvc
287 // are right, it doesn't matter).
288 template< typename T >
290 {
291  typedef Dummy Type;
292 };
293 template< int N >
294 struct ExceptCharArrayDetector< char[ N ] >
295 {
296 };
297 template< int N >
298 struct ExceptCharArrayDetector< const char[ N ] >
299 {
300 };
301 #if defined LIBO_INTERNAL_ONLY
302 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode[N]> {};
303 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode const[N]> {};
304 template<> struct ExceptCharArrayDetector<OUStringLiteral1_> {};
305 #endif
306 
307 template< typename T1, typename T2 = void >
309 {
310  static const bool ok = false;
311 };
312 template< typename T >
314 {
315  typedef T Type;
316  static const bool ok = true;
317 };
318 template< typename T >
320 {
321  typedef T Type;
322  static const bool ok = true;
323 };
324 
325 // SFINAE helper class
326 template< typename T, bool >
327 struct Enable
328  {
329  };
330 
331 template< typename T >
332 struct Enable< T, true >
333  {
334  typedef T Type;
335  };
336 
337 
338 } /* Namespace */
339 
340 } /* Namespace */
341 
342 #endif // INCLUDED_RTL_STRINGUTILS_HXX
343 
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Dummy Type
Definition: stringutils.hxx:264
static const bool ok
Definition: stringutils.hxx:122
static const bool ok
Definition: stringutils.hxx:310
Definition: bootstrap.hxx:29
T Type
Definition: stringutils.hxx:334
#define SAL_WARN_UNUSED
Annotate classes where a compiler should warn if an instance is unused.
Definition: types.h:590
static const bool ok
Definition: stringutils.hxx:163
sal_uInt16 sal_Unicode
Definition: types.h:141
static bool isValid(char const (&literal)[N])
Definition: stringutils.hxx:174
Definition: stringutils.hxx:327
Definition: stringutils.hxx:120
Dummy Type
Definition: stringutils.hxx:291
static char const * toPointer(char const (&literal)[N])
Definition: stringutils.hxx:185
Definition: stringutils.hxx:118