Logo ROOT  
Reference Guide
RWrap_libcpp_string_view.h
Go to the documentation of this file.
1// -*- C++ -*-
2// Author: Philippe Canal, March 2015
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//===---------------------wrap string_view ----------------------------===//
13// Wrapper header adapting the snapshot of sring_view.h to build without
14// the libc++ infrastructure header files.
15
16#ifndef RWrap_libcpp_string_view_h
17#define RWrap_libcpp_string_view_h
18
19#ifndef RStringView_H
20#error "Do not use RWrap_libcpp_string_view.h directly. #include \"ROOT/RStringView.hxx\" instead."
21#endif // RStringView_H
22
23// In case we are connected with a libc++ which defines those, we need
24// to include it first, so we avoid being silently over-ridden.
25
26// To import a new version of the original file do:
27//
28/*
29 svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx
30
31 cat original/string_view | \
32 sed -e 's:_LIBCPP_BEGIN_NAMESPACE_LFTS:_ROOT_LIBCPP_BEGIN_NAMESPACE_LFTS:' \
33 -e 's:_LIBCPP_END_NAMESPACE_LFTS:_ROOT_LIBCPP_END_NAMESPACE_LFTS:' \
34 -e 's:#include <__debug>://#include <__debug>:' \
35 -e 's:#include <experimental/__config>://#include <experimental/__config>:' \
36 -e 's:__put_character_sequence:R__put_character_sequence:g' \
37 > core/base/inc/libcpp_string_view.h
38*/
39
40#include <string>
41#include <algorithm>
42#include <iterator>
43#include <ostream>
44#include <iomanip>
45#include <stdexcept>
46
47#ifndef R__WIN32
48
49#define _ROOT_LIBCPP_BEGIN_NAMESPACE_LFTS \
50namespace std { \
51namespace experimental { inline namespace __ROOT {
52#define _ROOT_LIBCPP_END_NAMESPACE_LFTS } } }
53#else
54
55// Microsoft compiler does not support inline namespace yet.
56#define _ROOT_LIBCPP_BEGIN_NAMESPACE_LFTS \
57namespace std { \
58namespace experimental { namespace __ROOT {
59#define _ROOT_LIBCPP_END_NAMESPACE_LFTS } using namespace __ROOT; } }
60
61#endif
62
63
64#ifndef _LIBCPP_BEGIN_NAMESPACE_STD
65#define _LOCAL_LIBCPP_BEGIN_NAMESPACE_STD
66#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
67#define _LIBCPP_END_NAMESPACE_STD }
68#endif
69
70#ifndef _LIBCPP_CONSTEXPR
71#define _LOCAL_LIBCPP_CONSTEXPR
72#define _LIBCPP_CONSTEXPR constexpr
73#endif
74
75#ifndef _VSTD
76#define _LOCAL_VSTD
77#define _VSTD ::std
78#endif
79
80#ifndef _LIBCPP_INLINE_VISIBILITY
81#define _LOCAL_LIBCPP_INLINE_VISIBILITY
82#define _LIBCPP_INLINE_VISIBILITY inline
83#endif
84
85#ifndef _LIBCPP_EXPLICIT
86#define _LOCAL_LIBCPP_EXPLICIT
87#define _LIBCPP_EXPLICIT explicit
88#endif
89
90//#ifndef _LIBCPP_CONSTEXPR_AFTER_CXX11
91//#define _LOCAL_LIBCPP_CONSTEXPR_AFTER_CXX11
92//#define _LIBCPP_CONSTEXPR_AFTER_CXX11 constexpr
93//#endif
94
95#ifdef _LIBCPP_STD_VER
96#define _LOCAL_LIBCPP_STD_VER
97#define _LIBCPP_STD_VER 11
98#endif
99
100#ifndef _LIBCPP_TYPE_VIS_ONLY
101#define _LOCAL_LIBCPP_TYPE_VIS_ONLY
102#define _LIBCPP_TYPE_VIS_ONLY
103#endif
104
105#ifndef _LIBCPP_CONSTEXPR_AFTER_CXX11
106#define _LOCAL_LIBCPP_CONSTEXPR_AFTER_CXX11
107#define _LIBCPP_CONSTEXPR_AFTER_CXX11
108#endif
109
110#ifndef _NOEXCEPT
111#define _LOCAL_NOEXCEPT
112#define _NOEXCEPT
113#endif
114
115#ifndef _LIBCPP_ASSERT
116#define _LOCAL_LIBCPP_ASSERT
117#define _LIBCPP_ASSERT(X,Y) ((void)0)
118#endif
119
120/* Also used:
121 _LIBCPP_TYPE_VIS_ONLY
122 _LIBCPP_CONSTEXPR_AFTER_CXX11
123 */
124
125namespace std {
126#ifdef _LOCAL_VSTD
127inline namespace __ROOT {
128#else
129// libC++ wins.
130inline namespace __1 {
131#endif
132
133 // template <class _Traits>
134 // struct _LIBCPP_HIDDEN __traits_eq
135 // {
136 // typedef typename _Traits::char_type char_type;
137 // _LIBCPP_INLINE_VISIBILITY
138 // bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT
139 // {return _Traits::eq(__x, __y);}
140 // };
141 template <class _CharT, class _OutputIterator>
142 _OutputIterator
143 __pad_and_output(_OutputIterator __s,
144 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
145 ios_base& __iob, _CharT __fl)
146 {
147 streamsize __sz = __oe - __ob;
148 streamsize __ns = __iob.width();
149 if (__ns > __sz)
150 __ns -= __sz;
151 else
152 __ns = 0;
153 for (;__ob < __op; ++__ob, ++__s)
154 *__s = *__ob;
155 for (; __ns; --__ns, ++__s)
156 *__s = __fl;
157 for (; __ob < __oe; ++__ob, ++__s)
158 *__s = *__ob;
159 __iob.width(0);
160 return __s;
161 }
162
163 template<class _CharT, class _Traits>
164 basic_ostream<_CharT, _Traits>&
165 R__put_character_sequence(basic_ostream<_CharT, _Traits>& __os,
166 const _CharT* __str, size_t __len)
167 {
168#if 0
169//#ifndef _LIBCPP_NO_EXCEPTIONS
170 try
171 {
172#endif // _LIBCPP_NO_EXCEPTIONS
173 typename basic_ostream<_CharT, _Traits>::sentry __s(__os);
174 if (__s)
175 {
176 typedef ostreambuf_iterator<_CharT, _Traits> _Ip;
177 if (__pad_and_output(_Ip(__os),
178 __str,
179 (__os.flags() & ios_base::adjustfield) == ios_base::left ?
180 __str + __len :
181 __str,
182 __str + __len,
183 __os,
184 __os.fill()).failed())
185 __os.setstate(ios_base::badbit | ios_base::failbit);
186 }
187#if 0
188//#ifndef _LIBCPP_NO_EXCEPTIONS
189 }
190 catch (...)
191 {
192 __os.__set_badbit_and_consider_rethrow();
193 }
194#endif // _LIBCPP_NO_EXCEPTIONS
195 return __os;
196 }
197
198#ifdef _LOCAL_VSTD
199 // search
200
201 template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2>
202 _ForwardIterator1
203 __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
204 _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred,
205 forward_iterator_tag, forward_iterator_tag)
206 {
207 if (__first2 == __last2)
208 return __first1; // Everything matches an empty sequence
209 while (true)
210 {
211 // Find first element in sequence 1 that matchs *__first2, with a mininum of loop checks
212 while (true)
213 {
214 if (__first1 == __last1) // return __last1 if no element matches *__first2
215 return __last1;
216 if (__pred(*__first1, *__first2))
217 break;
218 ++__first1;
219 }
220 // *__first1 matches *__first2, now match elements after here
221 _ForwardIterator1 __m1 = __first1;
222 _ForwardIterator2 __m2 = __first2;
223 while (true)
224 {
225 if (++__m2 == __last2) // If pattern exhausted, __first1 is the answer (works for 1 element pattern)
226 return __first1;
227 if (++__m1 == __last1) // Otherwise if source exhaused, pattern not found
228 return __last1;
229 if (!__pred(*__m1, *__m2)) // if there is a mismatch, restart with a new __first1
230 {
231 ++__first1;
232 break;
233 } // else there is a match, check next elements
234 }
235 }
236 }
237
238 template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
239 _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator1
240 __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
241 _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred,
242 random_access_iterator_tag, random_access_iterator_tag)
243 {
244 typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _D1;
245 typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _D2;
246 // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern
247 _D2 __len2 = __last2 - __first2;
248 if (__len2 == 0)
249 return __first1;
250 _D1 __len1 = __last1 - __first1;
251 if (__len1 < __len2)
252 return __last1;
253 const _RandomAccessIterator1 __s = __last1 - (__len2 - 1); // Start of pattern match can't go beyond here
254 while (true)
255 {
256#if !_LIBCPP_UNROLL_LOOPS
257 while (true)
258 {
259 if (__first1 == __s)
260 return __last1;
261 if (__pred(*__first1, *__first2))
262 break;
263 ++__first1;
264 }
265#else // !_LIBCPP_UNROLL_LOOPS
266 for (_D1 __loop_unroll = (__s - __first1) / 4; __loop_unroll > 0; --__loop_unroll)
267 {
268 if (__pred(*__first1, *__first2))
269 goto __phase2;
270 if (__pred(*++__first1, *__first2))
271 goto __phase2;
272 if (__pred(*++__first1, *__first2))
273 goto __phase2;
274 if (__pred(*++__first1, *__first2))
275 goto __phase2;
276 ++__first1;
277 }
278 switch (__s - __first1)
279 {
280 case 3:
281 if (__pred(*__first1, *__first2))
282 break;
283 ++__first1;
284 case 2:
285 if (__pred(*__first1, *__first2))
286 break;
287 ++__first1;
288 case 1:
289 if (__pred(*__first1, *__first2))
290 break;
291 case 0:
292 return __last1;
293 }
294 __phase2:
295#endif // !_LIBCPP_UNROLL_LOOPS
296 _RandomAccessIterator1 __m1 = __first1;
297 _RandomAccessIterator2 __m2 = __first2;
298#if !_LIBCPP_UNROLL_LOOPS
299 while (true)
300 {
301 if (++__m2 == __last2)
302 return __first1;
303 ++__m1; // no need to check range on __m1 because __s guarantees we have enough source
304 if (!__pred(*__m1, *__m2))
305 {
306 ++__first1;
307 break;
308 }
309 }
310#else // !_LIBCPP_UNROLL_LOOPS
311 ++__m2;
312 ++__m1;
313 for (_D2 __loop_unroll = (__last2 - __m2) / 4; __loop_unroll > 0; --__loop_unroll)
314 {
315 if (!__pred(*__m1, *__m2))
316 goto __continue;
317 if (!__pred(*++__m1, *++__m2))
318 goto __continue;
319 if (!__pred(*++__m1, *++__m2))
320 goto __continue;
321 if (!__pred(*++__m1, *++__m2))
322 goto __continue;
323 ++__m1;
324 ++__m2;
325 }
326 switch (__last2 - __m2)
327 {
328 case 3:
329 if (!__pred(*__m1, *__m2))
330 break;
331 ++__m1;
332 ++__m2;
333 case 2:
334 if (!__pred(*__m1, *__m2))
335 break;
336 ++__m1;
337 ++__m2;
338 case 1:
339 if (!__pred(*__m1, *__m2))
340 break;
341 case 0:
342 return __first1;
343 }
344 __continue:
345 ++__first1;
346#endif // !_LIBCPP_UNROLL_LOOPS
347 }
348 }
349
350#endif // _LOCAL_VSTD for __search
351
352 template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
353 _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator1
354 __find_first_of_ce(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
355 _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred)
356 {
357 for (; __first1 != __last1; ++__first1)
358 for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
359 if (__pred(*__first1, *__j))
360 return __first1;
361 return __last1;
362 }
363
364 // __str_find
365 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
367 __str_find(const _CharT *__p, _SizeT __sz,
368 _CharT __c, _SizeT __pos) _NOEXCEPT
369 {
370 if (__pos >= __sz)
371 return __npos;
372 const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
373 if (__r == 0)
374 return __npos;
375 return static_cast<_SizeT>(__r - __p);
376}
377
378 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
380 __str_find(const _CharT *__p, _SizeT __sz,
381 const _CharT* __s, _SizeT __pos, _SizeT __n)
382 {
383 if (__pos > __sz || __sz - __pos < __n)
384 return __npos;
385 if (__n == 0)
386 return __pos;
387 const _CharT* __r =
388 _VSTD::__search(__p + __pos, __p + __sz,
389 __s, __s + __n, _Traits::eq,
390 random_access_iterator_tag(), random_access_iterator_tag());
391 if (__r == __p + __sz)
392 return __npos;
393 return static_cast<_SizeT>(__r - __p);
394 }
395
396
397 // __str_rfind
398
399 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
401 __str_rfind(const _CharT *__p, _SizeT __sz,
402 _CharT __c, _SizeT __pos)
403 {
404 if (__sz < 1)
405 return __npos;
406 if (__pos < __sz)
407 ++__pos;
408 else
409 __pos = __sz;
410 for (const _CharT* __ps = __p + __pos; __ps != __p;)
411 {
412 if (_Traits::eq(*--__ps, __c))
413 return static_cast<_SizeT>(__ps - __p);
414 }
415 return __npos;
416 }
417
418 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
420 __str_rfind(const _CharT *__p, _SizeT __sz,
421 const _CharT* __s, _SizeT __pos, _SizeT __n)
422 {
423 __pos = _VSTD::min(__pos, __sz);
424 if (__n < __sz - __pos)
425 __pos += __n;
426 else
427 __pos = __sz;
428 const _CharT* __r = _VSTD::__find_end(
429 __p, __p + __pos, __s, __s + __n, _Traits::eq,
430 random_access_iterator_tag(), random_access_iterator_tag());
431 if (__n > 0 && __r == __p + __pos)
432 return __npos;
433 return static_cast<_SizeT>(__r - __p);
434 }
435
436 // __str_find_first_of
437 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
439 __str_find_first_of(const _CharT *__p, _SizeT __sz,
440 const _CharT* __s, _SizeT __pos, _SizeT __n)
441 {
442 if (__pos >= __sz || __n == 0)
443 return __npos;
444 const _CharT* __r = _VSTD::__find_first_of_ce
445 (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
446 if (__r == __p + __sz)
447 return __npos;
448 return static_cast<_SizeT>(__r - __p);
449 }
450
451
452 // __str_find_last_of
453 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
455 __str_find_last_of(const _CharT *__p, _SizeT __sz,
456 const _CharT* __s, _SizeT __pos, _SizeT __n)
457 {
458 if (__n != 0)
459 {
460 if (__pos < __sz)
461 ++__pos;
462 else
463 __pos = __sz;
464 for (const _CharT* __ps = __p + __pos; __ps != __p;)
465 {
466 const _CharT* __r = _Traits::find(__s, __n, *--__ps);
467 if (__r)
468 return static_cast<_SizeT>(__ps - __p);
469 }
470 }
471 return __npos;
472 }
473
474
475 // __str_find_first_not_of
476 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
478 __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
479 const _CharT* __s, _SizeT __pos, _SizeT __n)
480 {
481 if (__pos < __sz)
482 {
483 const _CharT* __pe = __p + __sz;
484 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
485 if (_Traits::find(__s, __n, *__ps) == 0)
486 return static_cast<_SizeT>(__ps - __p);
487 }
488 return __npos;
489 }
490
491
492 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
494 __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
495 _CharT __c, _SizeT __pos)
496 {
497 if (__pos < __sz)
498 {
499 const _CharT* __pe = __p + __sz;
500 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
501 if (!_Traits::eq(*__ps, __c))
502 return static_cast<_SizeT>(__ps - __p);
503 }
504 return __npos;
505 }
506
507
508 // __str_find_last_not_of
509 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
511 __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
512 const _CharT* __s, _SizeT __pos, _SizeT __n)
513 {
514 if (__pos < __sz)
515 ++__pos;
516 else
517 __pos = __sz;
518 for (const _CharT* __ps = __p + __pos; __ps != __p;)
519 if (_Traits::find(__s, __n, *--__ps) == 0)
520 return static_cast<_SizeT>(__ps - __p);
521 return __npos;
522 }
523
524
525 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
527 __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
528 _CharT __c, _SizeT __pos)
529 {
530 if (__pos < __sz)
531 ++__pos;
532 else
533 __pos = __sz;
534 for (const _CharT* __ps = __p + __pos; __ps != __p;)
535 if (!_Traits::eq(*--__ps, __c))
536 return static_cast<_SizeT>(__ps - __p);
537 return __npos;
538 }
539
540} // namespace __1 or __ROOT
541
542} // namespace std
543
544// Now include the main meat
545#include "libcpp_string_view.h"
546
547
548// And undo
549#ifdef _LOCAL_LIBCPP_BEGIN_NAMESPACE_LFTS
550#undef _LIBCPP_BEGIN_NAMESPACE_LFTS
551#undef _LIBCPP_END_NAMESPACE_LFTS
552#endif
553
554#ifdef _LOCAL_LIBCPP_BEGIN_NAMESPACE_STD
555#undef _LIBCPP_BEGIN_NAMESPACE_STD
556#undef _LIBCPP_END_NAMESPACE_STD
557#endif
558
559#ifdef _LOCAL_LIBCPP_CONSTEXPR
560#undef _LIBCPP_CONSTEXPR
561#endif
562
563#ifdef _LOCAL_VSTD
564#undef _VSTD
565#endif
566
567#ifdef _LOCAL_LIBCPP_INLINE_VISIBILITY
568#undef _LIBCPP_INLINE_VISIBILITY
569#endif
570
571#ifdef _LOCAL_LIBCPP_STD_VER
572#undef _LIBCPP_STD_VER
573#endif
574
575#ifdef _LOCAL_LIBCPP_TYPE_VIS_ONLY
576#undef _LIBCPP_TYPE_VIS_ONLY
577#endif
578
579#ifdef _LOCAL_LIBCPP_CONSTEXPR_AFTER_CXX11
580#undef _LIBCPP_CONSTEXPR_AFTER_CXX11
581#endif
582
583#ifdef _LOCAL_NOEXCEPT
584#undef _NOEXCEPT
585#endif
586
587#ifdef _LOCAL_LIBCPP_ASSERT
588#undef _LIBCPP_ASSERT
589#endif
590
591#endif // RWrap_libcpp_string_view_h
#define _LIBCPP_INLINE_VISIBILITY
#define _LIBCPP_CONSTEXPR_AFTER_CXX11
#define _NOEXCEPT