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