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
211 template<std::size_t N, typename T>
212 struct ConstCharArrayDetector<sal_Unicode const [N], T> {
213  using TypeUtf16 = T;
214  static constexpr bool const ok = true;
215  static constexpr std::size_t const length = N - 1;
216  static constexpr sal_Unicode const * toPointer(
217  sal_Unicode const (& literal)[N])
218  { return literal; }
219 };
220 template<typename T> struct ConstCharArrayDetector<
221 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 \
222  && !defined __clang__
223  OUStringLiteral1_ const,
224 #else
225  OUStringLiteral1,
226 #endif
227  T>
228 {
229  using TypeUtf16 = T;
230  static constexpr bool const ok = true;
231  static constexpr std::size_t const length = 1;
232  static constexpr sal_Unicode const * toPointer(
233  OUStringLiteral1_ const & literal)
234  { return &literal.c; }
235 };
236 #endif
237 
238 // this one is used to rule out only const char[N]
239 template< typename T >
241 {
242  typedef Dummy Type;
243 };
244 template< int N >
245 struct ExceptConstCharArrayDetector< const char[ N ] >
246 {
247 };
248 #if defined LIBO_INTERNAL_ONLY
249 template<std::size_t N>
250 struct ExceptConstCharArrayDetector<sal_Unicode const[N]> {};
251 template<> struct ExceptConstCharArrayDetector<
252 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 \
253  && !defined __clang__
254  OUStringLiteral1_ const
255 #else
256  OUStringLiteral1
257 #endif
258  >
259 {};
260 #endif
261 
262 // this one is used to rule out only const char[N]
263 // (const will be brought in by 'const T&' in the function call)
264 // msvc needs const char[N] here (not sure whether gcc or msvc
265 // are right, it doesn't matter).
266 template< typename T >
268 {
269  typedef Dummy Type;
270 };
271 template< int N >
272 struct ExceptCharArrayDetector< char[ N ] >
273 {
274 };
275 template< int N >
276 struct ExceptCharArrayDetector< const char[ N ] >
277 {
278 };
279 #if defined LIBO_INTERNAL_ONLY
280 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode[N]> {};
281 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode const[N]> {};
282 template<> struct ExceptCharArrayDetector<OUStringLiteral1_> {};
283 #endif
284 
285 template< typename T1, typename T2 = void >
287 {
288  static const bool ok = false;
289 };
290 template< typename T >
291 struct SalUnicodePtrDetector< const sal_Unicode*, T >
292 {
293  typedef T Type;
294  static const bool ok = true;
295 };
296 template< typename T >
297 struct SalUnicodePtrDetector< sal_Unicode*, T >
298 {
299  typedef T Type;
300  static const bool ok = true;
301 };
302 
303 // SFINAE helper class
304 template< typename T, bool >
305 struct Enable
306  {
307  };
308 
309 template< typename T >
310 struct Enable< T, true >
311  {
312  typedef T Type;
313  };
314 
315 
316 } /* Namespace */
317 
318 } /* Namespace */
319 
320 #endif // INCLUDED_RTL_STRINGUTILS_HXX
321 
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool isValid(char const (&literal)[N])
Definition: stringutils.hxx:174
#define SAL_WARN_UNUSED
Annotate classes where a compiler should warn if an instance is unused.
Definition: types.h:602
Definition: stringutils.hxx:305
T Type
Definition: stringutils.hxx:312
static char const * toPointer(char const (&literal)[N])
Definition: stringutils.hxx:185
Definition: stringutils.hxx:120
sal_uInt16 sal_Unicode
Definition: types.h:141
Definition: bootstrap.hxx:29
Definition: stringutils.hxx:118
Dummy Type
Definition: stringutils.hxx:269
Dummy Type
Definition: stringutils.hxx:242