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