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