00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 00002 /* 00003 * Version: MPL 1.1 / GPLv3+ / LGPLv3+ 00004 * 00005 * The contents of this file are subject to the Mozilla Public License Version 00006 * 1.1 (the "License"); you may not use this file except in compliance with 00007 * the License or as specified alternatively below. You may obtain a copy of 00008 * the License at http://www.mozilla.org/MPL/ 00009 * 00010 * Software distributed under the License is distributed on an "AS IS" basis, 00011 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 00012 * for the specific language governing rights and limitations under the 00013 * License. 00014 * 00015 * Major Contributor(s): 00016 * [ Copyright (C) 2012 Lubos Lunak <l.lunak@suse.cz> (initial developer) ] 00017 * 00018 * All Rights Reserved. 00019 * 00020 * For minor contributions see the git repository. 00021 * 00022 * Alternatively, the contents of this file may be used under the terms of 00023 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or 00024 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), 00025 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable 00026 * instead of those above. 00027 */ 00028 00029 #ifndef _RTL_STRINGUTILS_HXX_ 00030 #define _RTL_STRINGUTILS_HXX_ 00031 00032 #include "sal/config.h" 00033 00034 // Manually defining RTL_DISABLE_FAST_STRING allows to force turning fast string concatenation off 00035 // (e.g. for debugging). 00036 #ifndef RTL_DISABLE_FAST_STRING 00037 #ifndef HAVE_SFINAE_ANONYMOUS_BROKEN 00038 // This feature is not part of public API and is meant to be used only internally by LibreOffice. 00039 #ifdef LIBO_INTERNAL_ONLY 00040 // Enable fast string concatenation. 00041 #define RTL_FAST_STRING 00042 #endif 00043 #endif 00044 #endif 00045 00046 // The unittest uses slightly different code to help check that the proper 00047 // calls are made. The class is put into a different namespace to make 00048 // sure the compiler generates a different (if generating also non-inline) 00049 // copy of the function and does not merge them together. The class 00050 // is "brought" into the proper rtl namespace by a typedef below. 00051 #ifdef RTL_STRING_UNITTEST 00052 #define rtl rtlunittest 00053 #endif 00054 00055 namespace rtl 00056 { 00057 00058 #ifdef RTL_STRING_UNITTEST 00059 #undef rtl 00060 #endif 00061 00062 namespace internal 00063 { 00064 /* 00065 These templates use SFINAE (Substitution failure is not an error) to help distinguish the various 00066 plain C string types: char*, const char*, char[N], const char[N], char[] and const char[]. 00067 There are 2 cases: 00068 1) Only string literal (i.e. const char[N]) is wanted, not any of the others. 00069 In this case it is necessary to distinguish between const char[N] and char[N], as the latter 00070 would be automatically converted to the const variant, which is not wanted (not a string literal 00071 with known size of the content). In this case ConstCharArrayDetector is used to ensure the function 00072 is called only with const char[N] arguments. There's no other plain C string type overload. 00073 2) All plain C string types are wanted, and const char[N] needs to be handled differently. 00074 In this case const char[N] would match const char* argument type (not exactly sure why, but it's 00075 consistent in all of gcc, clang and msvc). Using a template with a reference to const of the type 00076 avoids this problem, and CharPtrDetector ensures that the function is called only with char pointer 00077 arguments. The const in the argument is necessary to handle the case when something is explicitly 00078 cast to const char*. Additionally (non-const) char[N] needs to be handled, but with the reference 00079 being const, it would also match const char[N], so another overload with a reference to non-const 00080 and NonConstCharArrayDetector are used to ensure the function is called only with (non-const) char[N]. 00081 Additionally, char[] and const char[] (i.e. size unknown) are rather tricky. Their usage with 'T&' would 00082 mean it would be 'char(&)[]', which seems to be invalid. But gcc and clang somehow manage when it is 00083 a template. while msvc complains about no conversion from char[] to char[1]. And the reference cannot 00084 be avoided, because 'const char[]' as argument type would match also 'const char[N]' 00085 So char[] and const char[] should always be used with their contents specified (which automatically 00086 turns them into char[N] or const char[N]), or char* and const char* should be used. 00087 */ 00088 struct Dummy {}; 00089 template< typename T1, typename T2 > 00090 struct CharPtrDetector 00091 { 00092 }; 00093 template< typename T > 00094 struct CharPtrDetector< const char*, T > 00095 { 00096 typedef T Type; 00097 }; 00098 template< typename T > 00099 struct CharPtrDetector< char*, T > 00100 { 00101 typedef T Type; 00102 }; 00103 00104 template< typename T1, typename T2 > 00105 struct NonConstCharArrayDetector 00106 { 00107 }; 00108 template< typename T, int N > 00109 struct NonConstCharArrayDetector< char[ N ], T > 00110 { 00111 typedef T Type; 00112 }; 00113 #ifdef RTL_STRING_UNITTEST 00114 // never use, until all compilers handle this 00115 template< typename T > 00116 struct NonConstCharArrayDetector< char[], T > 00117 { 00118 typedef T Type; 00119 }; 00120 template< typename T > 00121 struct NonConstCharArrayDetector< const char[], T > 00122 { 00123 typedef T Type; 00124 }; 00125 #endif 00126 00127 template< typename T1, typename T2 = void > 00128 struct ConstCharArrayDetector 00129 { 00130 static const bool ok = false; 00131 }; 00132 template< int N, typename T > 00133 struct ConstCharArrayDetector< const char[ N ], T > 00134 { 00135 typedef T Type; 00136 static const int size = N; 00137 static const bool ok = true; 00138 }; 00139 00140 // this one is used to rule out only const char[N] 00141 template< typename T > 00142 struct ExceptConstCharArrayDetector 00143 { 00144 typedef Dummy Type; 00145 }; 00146 template< int N > 00147 struct ExceptConstCharArrayDetector< const char[ N ] > 00148 { 00149 }; 00150 // this one is used to rule out only const char[N] 00151 // (const will be brought in by 'const T&' in the function call) 00152 // msvc needs const char[N] here (not sure whether gcc or msvc 00153 // are right, it doesn't matter). 00154 template< typename T > 00155 struct ExceptCharArrayDetector 00156 { 00157 typedef Dummy Type; 00158 }; 00159 template< int N > 00160 struct ExceptCharArrayDetector< char[ N ] > 00161 { 00162 }; 00163 template< int N > 00164 struct ExceptCharArrayDetector< const char[ N ] > 00165 { 00166 }; 00167 00168 // SFINAE helper class 00169 template< typename T, bool > 00170 struct Enable 00171 { 00172 }; 00173 00174 template< typename T > 00175 struct Enable< T, true > 00176 { 00177 typedef T Type; 00178 }; 00179 00180 00181 } /* Namespace */ 00182 00183 } /* Namespace */ 00184 00185 #endif /* _RTL_STRINGUTILS_HXX_ */ 00186 00187 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */