LibreOffice
LibreOffice 5.3 SDK C/C++ API Reference
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 #include <cstring>
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 
74 struct SAL_WARN_UNUSED OUStringLiteral1_ {
75  SAL_CONSTEXPR OUStringLiteral1_(sal_Unicode theC): c(theC) {}
76  sal_Unicode const c;
77 };
78 #if defined _MSC_VER && _MSC_VER <= 1900 && !defined __clang__
79  // Visual Studio 2015
80 using OUStringLiteral1 = OUStringLiteral1_;
81 #pragma warning(disable: 4239)
82 #else
83 using OUStringLiteral1 = OUStringLiteral1_ const;
84 #endif
85 
87 #endif
88 
89 namespace libreoffice_internal
90 {
91 /*
92 These templates use SFINAE (Substitution failure is not an error) to help distinguish the various
93 plain C string types: char*, const char*, char[N], const char[N], char[] and const char[].
94 There are 2 cases:
95 1) Only string literal (i.e. const char[N]) is wanted, not any of the others.
96  In this case it is necessary to distinguish between const char[N] and char[N], as the latter
97  would be automatically converted to the const variant, which is not wanted (not a string literal
98  with known size of the content). In this case ConstCharArrayDetector is used to ensure the function
99  is called only with const char[N] arguments. There's no other plain C string type overload.
100 2) All plain C string types are wanted, and const char[N] needs to be handled differently.
101  In this case const char[N] would match const char* argument type (not exactly sure why, but it's
102  consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type
103  avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer
104  arguments. The const in the argument is necessary to handle the case when something is explicitly
105  cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference
106  being const, it would also match const char[N], so another overload with a reference to non-const
107  and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N].
108 Additionally, char[] and const char[] (i.e. size unknown) are rather tricky. Their usage with 'T&' would
109 mean it would be 'char(&)[]', which seems to be invalid. But gcc and clang somehow manage when it is
110 a template. while msvc complains about no conversion from char[] to char[1]. And the reference cannot
111 be avoided, because 'const char[]' as argument type would match also 'const char[N]'
112 So char[] and const char[] should always be used with their contents specified (which automatically
113 turns them into char[N] or const char[N]), or char* and const char* should be used.
114 */
115 struct Dummy {};
116 template< typename T1, typename T2 = void >
118 {
119  static const bool ok = false;
120 };
121 template< typename T >
122 struct CharPtrDetector< const char*, T >
123 {
124  typedef T Type;
125  static const bool ok = true;
126 };
127 template< typename T >
128 struct CharPtrDetector< char*, T >
129 {
130  typedef T Type;
131  static const bool ok = true;
132 };
133 
134 template< typename T1, typename T2 >
136 {
137 };
138 template< typename T, int N >
139 struct NonConstCharArrayDetector< char[ N ], T >
140 {
141  typedef T Type;
142 };
143 #ifdef RTL_STRING_UNITTEST
144 // never use, until all compilers handle this
145 template< typename T >
146 struct NonConstCharArrayDetector< char[], T >
147 {
148  typedef T Type;
149 };
150 template< typename T >
151 struct NonConstCharArrayDetector< const char[], T >
152 {
153  typedef T Type;
154 };
155 #endif
156 
157 template< typename T1, typename T2 = void >
159 {
160  static const bool ok = false;
161 };
162 template< std::size_t N, typename T >
163 struct ConstCharArrayDetector< const char[ N ], T >
164 {
165  typedef T Type;
166  static const std::size_t length = N - 1;
167  static const bool ok = true;
168  static bool isValid(char const (& literal)[N])
169  { return std::strlen(literal) == length; }
170  static char const * toPointer(char const (& literal)[N]) { return literal; }
171 };
172 #if defined LIBO_INTERNAL_ONLY
173 template<std::size_t N, typename T>
174 struct ConstCharArrayDetector<sal_Unicode const [N], T> {
175  using TypeUtf16 = T;
176  static SAL_CONSTEXPR bool const ok = true;
177  static SAL_CONSTEXPR std::size_t const length = N - 1;
178  static SAL_CONSTEXPR sal_Unicode const * toPointer(
179  sal_Unicode const (& literal)[N])
180  { return literal; }
181 };
182 template<typename T> struct ConstCharArrayDetector<
183 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 \
184  && !defined __clang__
185  OUStringLiteral1_ const,
186 #else
187  OUStringLiteral1,
188 #endif
189  T>
190 {
191  using TypeUtf16 = T;
192  static SAL_CONSTEXPR bool const ok = true;
193  static SAL_CONSTEXPR std::size_t const length = 1;
194  static SAL_CONSTEXPR sal_Unicode const * toPointer(
195  OUStringLiteral1_ const & literal)
196  { return &literal.c; }
197 };
198 #endif
199 
200 // this one is used to rule out only const char[N]
201 template< typename T >
203 {
204  typedef Dummy Type;
205 };
206 template< int N >
207 struct ExceptConstCharArrayDetector< const char[ N ] >
208 {
209 };
210 #if defined LIBO_INTERNAL_ONLY
211 template<std::size_t N>
212 struct ExceptConstCharArrayDetector<sal_Unicode const[N]> {};
213 template<> struct ExceptConstCharArrayDetector<
214 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 \
215  && !defined __clang__
216  OUStringLiteral1_ const
217 #else
218  OUStringLiteral1
219 #endif
220  >
221 {};
222 #endif
223 
224 // this one is used to rule out only const char[N]
225 // (const will be brought in by 'const T&' in the function call)
226 // msvc needs const char[N] here (not sure whether gcc or msvc
227 // are right, it doesn't matter).
228 template< typename T >
230 {
231  typedef Dummy Type;
232 };
233 template< int N >
234 struct ExceptCharArrayDetector< char[ N ] >
235 {
236 };
237 template< int N >
238 struct ExceptCharArrayDetector< const char[ N ] >
239 {
240 };
241 #if defined LIBO_INTERNAL_ONLY
242 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode[N]> {};
243 template<std::size_t N> struct ExceptCharArrayDetector<sal_Unicode const[N]> {};
244 template<> struct ExceptCharArrayDetector<OUStringLiteral1_> {};
245 #endif
246 
247 template< typename T1, typename T2 = void >
249 {
250  static const bool ok = false;
251 };
252 template< typename T >
254 {
255  typedef T Type;
256  static const bool ok = true;
257 };
258 template< typename T >
260 {
261  typedef T Type;
262  static const bool ok = true;
263 };
264 
265 // SFINAE helper class
266 template< typename T, bool >
267 struct Enable
268  {
269  };
270 
271 template< typename T >
272 struct Enable< T, true >
273  {
274  typedef T Type;
275  };
276 
277 
278 } /* Namespace */
279 
280 } /* Namespace */
281 
282 #endif // INCLUDED_RTL_STRINGUTILS_HXX
283 
284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool isValid(char const (&literal)[N])
Definition: stringutils.hxx:168
#define SAL_WARN_UNUSED
Annotate classes where a compiler should warn if an instance is unused.
Definition: types.h:624
static const bool ok
Definition: stringutils.hxx:119
Definition: stringutils.hxx:267
T Type
Definition: stringutils.hxx:274
static char const * toPointer(char const (&literal)[N])
Definition: stringutils.hxx:170
Definition: stringutils.hxx:117
sal_uInt16 sal_Unicode
Definition: types.h:155
#define SAL_CONSTEXPR
C++11 &quot;constexpr&quot; feature.
Definition: types.h:445
Definition: stringutils.hxx:115
Dummy Type
Definition: stringutils.hxx:231
Dummy Type
Definition: stringutils.hxx:204
static const bool ok
Definition: stringutils.hxx:250
static const bool ok
Definition: stringutils.hxx:160