Visual Studio 2012 Support
[xy_vsfilter.git] / src / thirdparty / VirtualDub / h / vd2 / system / VDString.h
blob09a222d2d39c4e96fc1c6c02231d34f66768cc02
1 // VirtualDub - Video processing and capture application
2 // System library component
3 // Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
4 //
5 // Beginning with 1.6.0, the VirtualDub system library is licensed
6 // differently than the remainder of VirtualDub. This particular file is
7 // thus licensed as follows (the "zlib" license):
8 //
9 // This software is provided 'as-is', without any express or implied
10 // warranty. In no event will the authors be held liable for any
11 // damages arising from the use of this software.
13 // Permission is granted to anyone to use this software for any purpose,
14 // including commercial applications, and to alter it and redistribute it
15 // freely, subject to the following restrictions:
17 // 1. The origin of this software must not be misrepresented; you must
18 // not claim that you wrote the original software. If you use this
19 // software in a product, an acknowledgment in the product
20 // documentation would be appreciated but is not required.
21 // 2. Altered source versions must be plainly marked as such, and must
22 // not be misrepresented as being the original software.
23 // 3. This notice may not be removed or altered from any source
24 // distribution.
26 #ifndef f_VD2_SYSTEM_VDSTRING_H
27 #define f_VD2_SYSTEM_VDSTRING_H
29 #ifdef _MSC_VER
30 #pragma once
31 #endif
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <stddef.h>
37 #include <functional>
39 #include <vd2/system/vdtypes.h>
40 #include <vd2/system/text.h>
41 #include <vd2/system/vdstl.h>
43 ///////////////////////////////////////////////////////////////////////////
45 class VDStringSpanA {
46 public:
47 typedef char value_type;
48 typedef uint32 size_type;
49 typedef ptrdiff_t difference_type;
50 typedef value_type& reference;
51 typedef const value_type& const_reference;
52 typedef value_type * pointer;
53 typedef const value_type * const_pointer;
54 typedef pointer iterator;
55 typedef const_pointer const_iterator;
57 static const size_type npos = (size_type)-1;
59 VDStringSpanA()
60 : mpBegin(const_cast<value_type *>(sNull))
61 , mpEnd(const_cast<value_type *>(sNull))
65 explicit VDStringSpanA(const value_type *s)
66 : mpBegin(const_cast<value_type *>(s))
67 , mpEnd(const_cast<value_type *>(s) + strlen(s))
71 VDStringSpanA(const value_type *s, const value_type *t)
72 : mpBegin(const_cast<value_type *>(s))
73 , mpEnd(const_cast<value_type *>(t))
77 // 21.3.2 iterators
78 const_iterator begin() const { return mpBegin; }
79 const_iterator end() const { return mpEnd; }
81 // 21.3.3 capacity
82 size_type size() const { return (size_type)(mpEnd - mpBegin); }
83 size_type length() const { return (size_type)(mpEnd - mpBegin); }
84 bool empty() const { return mpBegin == mpEnd; }
86 // 21.3.4 element access
87 const_reference operator[](size_type pos) const { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
88 const_reference at(size_type pos) const { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
90 const_reference front() const { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
91 const_reference back() const { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
93 // 21.3.6 string operations
94 const_pointer data() const { return mpBegin; }
96 size_type copy(value_type *dst, size_type n, size_type pos = 0) const {
97 size_type len = (size_type)(mpEnd - mpBegin);
98 VDASSERT(pos <= len);
100 len -= pos;
101 if (n > len)
102 n = len;
104 memcpy(dst, mpBegin + pos, n*sizeof(value_type));
105 return n;
108 size_type find(value_type c, size_type pos = 0) const {
109 VDASSERT(pos <= (size_type)(mpEnd - mpBegin));
110 const void *p = memchr(mpBegin + pos, c, mpEnd - (mpBegin + pos));
112 return p ? (size_type)((const value_type *)p - mpBegin) : npos;
115 size_type find_last_of(value_type c) const {
116 const value_type *s = mpEnd;
118 while(s != mpBegin) {
119 --s;
121 if (*s == c)
122 return (size_type)(s - mpBegin);
125 return npos;
128 int compare(const VDStringSpanA& s) const {
129 size_type l1 = (size_type)(mpEnd - mpBegin);
130 size_type l2 = (size_type)(s.mpEnd - s.mpBegin);
131 size_type lm = l1 < l2 ? l1 : l2;
133 int r = memcmp(mpBegin, s.mpBegin, lm);
135 if (!r && l1 != l2)
136 r = (int)mpBegin[lm] - (int)s.mpBegin[lm];
138 return r;
141 int comparei(const char *s) const {
142 return comparei(VDStringSpanA(s));
145 int comparei(const VDStringSpanA& s) const {
146 size_type l1 = (size_type)(mpEnd - mpBegin);
147 size_type l2 = (size_type)(s.mpEnd - s.mpBegin);
148 size_type lm = l1 < l2 ? l1 : l2;
150 const char *p = mpBegin;
151 const char *q = s.mpBegin;
153 while(lm--) {
154 const unsigned char c = tolower((unsigned char)*p++);
155 const unsigned char d = tolower((unsigned char)*q++);
157 if (c != d)
158 return (int)c - (int)d;
161 return (int)l1 - (int)l2;
164 const VDStringSpanA trim(const value_type *s) const {
165 bool flags[256]={false};
167 while(value_type c = *s++)
168 flags[(unsigned char)c] = true;
170 const value_type *p = mpBegin;
171 const value_type *q = mpEnd;
173 while(p != q && flags[*p])
174 ++p;
176 while(p != q && flags[q[-1]])
177 --q;
179 return VDStringSpanA(p, q);
182 const VDStringSpanA subspan(size_type pos = 0, size_type n = npos) const {
184 size_type len = (size_type)(mpEnd - mpBegin);
185 VDASSERT(pos <= len);
187 len -= pos;
188 if (n > len)
189 n = len;
191 value_type *p = mpBegin + pos;
192 return VDStringSpanA(p, p+n);
195 protected:
196 friend bool operator==(const VDStringSpanA& x, const VDStringSpanA& y);
197 friend bool operator==(const VDStringSpanA& x, const char *y);
199 value_type *mpBegin;
200 value_type *mpEnd;
202 static const value_type sNull[1];
205 inline bool operator==(const VDStringSpanA& x, const VDStringSpanA& y) { VDStringSpanA::size_type len = (VDStringSpanA::size_type)(x.mpEnd - x.mpBegin); return len == (VDStringSpanA::size_type)(y.mpEnd - y.mpBegin) && !memcmp(x.mpBegin, y.mpBegin, len*sizeof(char)); }
206 inline bool operator==(const VDStringSpanA& x, const char *y) { size_t len = strlen(y); return len == (size_t)(x.mpEnd - x.mpBegin) && !memcmp(x.mpBegin, y, len*sizeof(char)); }
207 inline bool operator==(const char *x, const VDStringSpanA& y) { return y == x; }
209 inline bool operator!=(const VDStringSpanA& x, const VDStringSpanA& y) { return !(x == y); }
210 inline bool operator!=(const VDStringSpanA& x, const char *y) { return !(x == y); }
211 inline bool operator!=(const char *x, const VDStringSpanA& y) { return !(y == x); }
213 inline bool operator<(const VDStringSpanA& x, const VDStringSpanA& y) {
214 return x.compare(y) < 0;
217 inline bool operator>(const VDStringSpanA& x, const VDStringSpanA& y) {
218 return x.compare(y) > 0;
221 inline bool operator<=(const VDStringSpanA& x, const VDStringSpanA& y) {
222 return x.compare(y) <= 0;
225 inline bool operator>=(const VDStringSpanA& x, const VDStringSpanA& y) {
226 return x.compare(y) >= 0;
229 class VDStringRefA : public VDStringSpanA {
230 public:
231 typedef VDStringRefA this_type;
233 VDStringRefA() {
236 explicit VDStringRefA(const value_type *s)
237 : VDStringSpanA(s)
241 explicit VDStringRefA(const VDStringSpanA& s)
242 : VDStringSpanA(s)
246 VDStringRefA(const value_type *s, const value_type *t)
247 : VDStringSpanA(s, t)
251 this_type& operator=(const value_type *s) {
252 assign(s);
253 return *this;
256 this_type& operator=(const VDStringSpanA& str) {
257 assign(str);
258 return *this;
261 void assign(const value_type *s) {
262 static_cast<VDStringSpanA&>(*this) = VDStringSpanA(s);
265 void assign(const value_type *s, const value_type *t) {
266 static_cast<VDStringSpanA&>(*this) = VDStringSpanA(s, t);
269 void assign(const VDStringSpanA& s) {
270 static_cast<VDStringSpanA&>(*this) = s;
273 void clear() {
274 mpBegin = mpEnd = NULL;
277 bool split(value_type c, VDStringRefA& token) {
278 size_type pos = find(c);
280 if (pos == npos)
281 return false;
283 token = subspan(0, pos);
284 mpBegin += pos+1;
285 return true;
289 class VDStringA : public VDStringSpanA {
290 public:
291 typedef VDStringA this_type;
293 // 21.3.1 construct/copy/destroy
295 VDStringA()
296 : mpEOS(const_cast<value_type *>(sNull))
300 VDStringA(const VDStringSpanA& x)
301 : mpEOS(const_cast<value_type *>(sNull))
303 assign(x.begin(), x.end());
306 VDStringA(const this_type& x)
307 : mpEOS(const_cast<value_type *>(sNull))
309 assign(x);
312 explicit VDStringA(const value_type *s)
313 : mpEOS(const_cast<value_type *>(sNull))
315 assign(s);
318 explicit VDStringA(size_type n)
319 : mpEOS(const_cast<value_type *>(sNull))
321 resize(n);
324 VDStringA(const value_type *s, size_type n)
325 : mpEOS(const_cast<value_type *>(sNull))
327 assign(s, n);
330 VDStringA(const value_type *s, const value_type *t)
331 : mpEOS(const_cast<value_type *>(sNull))
333 assign(s, t);
336 ~VDStringA() {
337 if (mpBegin != sNull)
338 delete[] mpBegin;
341 this_type& operator=(const value_type *s) {
342 assign(s);
343 return *this;
346 this_type& operator=(const this_type& str) {
347 assign(str);
348 return *this;
351 this_type& operator=(const VDStringSpanA& str) {
352 assign(str);
353 return *this;
356 // 21.3.2 iterators
357 using VDStringSpanA::begin;
358 using VDStringSpanA::end;
360 iterator begin() { return mpBegin; }
361 iterator end() { return mpEnd; }
363 // 21.3.3 capacity (COMPLETE)
364 void resize(size_type n) {
365 size_type current = (size_type)(mpEnd - mpBegin);
367 if (n < current) {
368 mpEnd = mpBegin + n;
369 mpEnd[0] = 0;
370 } else if (n > current)
371 resize_slow(n, current);
374 void resize(size_type n, value_type v) {
375 size_type current = (size_type)(mpEnd - mpBegin);
377 if (n < current) {
378 mpEnd = mpBegin + n;
379 mpEnd[0] = 0;
380 } else if (n > current)
381 resize_slow(n, current, v);
384 size_type capacity() const { return (size_type)(mpEOS - mpBegin); }
386 void reserve(size_type n) {
387 size_type current = (size_type)(mpEOS - mpBegin);
389 if (n > current)
390 reserve_slow(n, current);
393 void clear() {
394 if (mpEnd != mpBegin) {
395 mpEnd = mpBegin;
396 mpEnd[0] = 0;
400 // 21.3.4 element access
401 using VDStringSpanA::operator[];
402 using VDStringSpanA::at;
403 using VDStringSpanA::front;
404 using VDStringSpanA::back;
406 reference operator[](size_type pos) { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
407 reference at(size_type pos) { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
408 reference front() { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
409 reference back() { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
411 // 21.3.5 modifiers
412 this_type& operator+=(const this_type& str) {
413 return append(str.mpBegin, str.mpEnd);
416 this_type& operator+=(const value_type *s) {
417 return append(s, s+strlen(s));
420 this_type& operator+=(value_type c) {
421 if (mpEnd == mpEOS)
422 push_back_extend();
424 *mpEnd++ = c;
425 *mpEnd = 0;
426 return *this;
429 this_type& append(const this_type& str) {
430 return append(str.mpBegin, str.mpEnd);
433 this_type& append(const this_type& str, size_type pos, size_type n) {
434 size_type len = (size_type)(str.mpEnd - str.mpBegin);
435 VDASSERT(pos <= len);
437 len -= pos;
438 if (n > len)
439 n = len;
441 return append(str.mpBegin + pos, str.mpBegin + pos + n);
444 this_type& append(const value_type *s, size_type n) {
445 return append(s, s+n);
448 this_type& append(const value_type *s) {
449 return append(s, s+strlen(s));
452 this_type& append(const value_type *s, const value_type *t) {
453 if (s != t) {
454 size_type current_size = (size_type)(mpEnd - mpBegin);
455 size_type current_capacity = (size_type)(mpEOS - mpBegin);
456 size_type n = (size_type)(t - s);
458 if (current_capacity - current_size < n)
459 reserve_amortized_slow(n, current_size, current_capacity);
461 memcpy(mpBegin + current_size, s, n*sizeof(value_type));
462 mpEnd += n;
463 *mpEnd = 0;
465 return *this;
468 void push_back(const value_type c) {
469 if (mpEnd == mpEOS)
470 push_back_extend();
472 *mpEnd++ = c;
473 *mpEnd = 0;
476 void pop_back() {
477 --mpEnd;
478 *mpEnd = 0;
481 this_type& assign(const VDStringSpanA& str) {
482 return assign(str.begin(), str.end());
485 this_type& assign(const this_type& str) {
486 return assign(str.mpBegin, str.mpEnd);
489 this_type& assign(const this_type& str, size_type pos, size_type n) {
490 size_type len = (size_type)(str.mpEnd - str.mpBegin);
491 VDASSERT(pos <= len);
493 len -= pos;
494 if (n > len)
495 n = len;
497 return assign(str.mpBegin + pos, str.mpBegin + pos + n);
500 this_type& assign(const value_type *s, size_type n) {
501 return assign(s, s+n);
504 this_type& assign(const value_type *s) {
505 return assign(s, s+strlen(s));
508 this_type& assign(size_type n, value_type c) {
509 size_type current_capacity = (size_type)(mpEOS - mpBegin);
511 if (current_capacity < n)
512 reserve_slow(n, current_capacity);
514 if (mpBegin != sNull) {
515 mpEnd = mpBegin;
516 while(n--)
517 *mpEnd++ = c;
520 return *this;
523 this_type& assign(const value_type *s, const value_type *t) {
524 size_type current_capacity = (size_type)(mpEOS - mpBegin);
525 size_type n = (size_type)(t - s);
527 if (current_capacity < n)
528 reserve_slow(n, current_capacity);
530 if (mpBegin != sNull) {
531 memcpy(mpBegin, s, sizeof(value_type)*n);
532 mpEnd = mpBegin + n;
533 *mpEnd = 0;
536 return *this;
539 this_type& insert(iterator it, value_type c) {
540 if (mpEnd == mpEOS) {
541 size_type pos = (size_type)(it - mpBegin);
542 push_back_extend();
543 it = mpBegin + pos;
546 memmove(it + 1, it, (mpEnd - it + 1)*sizeof(value_type));
547 *it = c;
548 ++mpEnd;
549 return *this;
552 this_type& erase(size_type pos = 0, size_type n = npos) {
553 size_type len = (size_type)(mpEnd - mpBegin);
555 VDASSERT(pos <= len);
556 len -= pos;
557 if (n > len)
558 n = len;
560 if (n) {
561 size_type pos2 = pos + n;
562 memmove(mpBegin + pos, mpBegin + pos2, (len + 1 - n)*sizeof(value_type));
563 mpEnd -= n;
566 return *this;
569 iterator erase(iterator x) {
570 VDASSERT(x != mpEnd);
572 memmove(x, x+1, (mpEnd - x)*sizeof(value_type));
573 --mpEnd;
574 return x;
577 iterator erase(iterator first, iterator last) {
578 VDASSERT(last >= first);
580 memmove(first, last, ((mpEnd - last) + 1)*sizeof(value_type));
581 mpEnd -= (last - first);
582 return first;
585 this_type& replace(size_type pos, size_type n1, const value_type *s, size_type n2) {
586 size_type len = (size_type)(mpEnd - mpBegin);
588 VDASSERT(pos <= len);
589 size_type limit = len - pos;
590 if (n1 > limit)
591 n1 = limit;
593 size_type len2 = len - n1 + n2;
594 size_type current_capacity = (size_type)(mpEOS - mpBegin);
596 if (current_capacity < len2)
597 reserve_slow(len2, current_capacity);
599 memmove(mpBegin + pos + n2, mpBegin + pos + n1, (limit - n1 + 1) * sizeof(value_type));
600 memcpy(mpBegin + pos, s, n2*sizeof(value_type));
601 mpEnd = mpBegin + len2;
602 return *this;
605 void swap(this_type& x) {
606 value_type *p;
608 p = mpBegin; mpBegin = x.mpBegin; x.mpBegin = p;
609 p = mpEnd; mpEnd = x.mpEnd; x.mpEnd = p;
610 p = mpEOS; mpEOS = x.mpEOS; x.mpEOS = p;
613 // 21.3.6 string operations
614 const_pointer c_str() const { return mpBegin; }
616 this_type& sprintf(const value_type *format, ...);
617 this_type& append_sprintf(const value_type *format, ...);
618 this_type& append_vsprintf(const value_type *format, va_list val);
620 void move_from(VDStringA& src);
622 protected:
623 void push_back_extend();
624 void resize_slow(size_type n, size_type current_size);
625 void resize_slow(size_type n, size_type current_size, value_type c);
626 void reserve_slow(size_type n, size_type current_capacity);
627 void reserve_amortized_slow(size_type n, size_type current_size, size_type current_capacity);
629 char *mpEOS;
632 ///////////////////////////////////////////////////////////////////////////
634 inline VDStringA operator+(const VDStringA& str, const VDStringA& s) {
635 VDStringA result;
636 result.reserve((VDStringA::size_type)(str.size() + s.size()));
637 result.assign(str);
638 result.append(s);
639 return result;
642 inline VDStringA operator+(const VDStringA& str, const char *s) {
643 VDStringA result;
644 result.reserve((VDStringA::size_type)(str.size() + strlen(s)));
645 result.assign(str);
646 result.append(s);
647 return result;
650 inline VDStringA operator+(const VDStringA& str, char c) {
651 VDStringA result;
652 result.reserve(str.size() + 1);
653 result.assign(str);
654 result += c;
655 return result;
658 namespace std {
659 template<>
660 struct less<VDStringA> : binary_function<VDStringA, VDStringA, bool> {
661 bool operator()(const VDStringA& x, const VDStringA& y) const {
662 return x.compare(y) < 0;
667 ///////////////////////////////////////////////////////////////////////////
669 class VDStringSpanW {
670 public:
671 typedef wchar_t value_type;
672 typedef uint32 size_type;
673 typedef ptrdiff_t difference_type;
674 typedef value_type& reference;
675 typedef const value_type& const_reference;
676 typedef value_type * pointer;
677 typedef const value_type * const_pointer;
678 typedef pointer iterator;
679 typedef const_pointer const_iterator;
681 static const size_type npos = (size_type)-1;
683 VDStringSpanW()
684 : mpBegin(const_cast<value_type *>(sNull))
685 , mpEnd(const_cast<value_type *>(sNull))
689 explicit VDStringSpanW(const value_type *s)
690 : mpBegin(const_cast<value_type *>(s))
691 , mpEnd(const_cast<value_type *>(s) + wcslen(s))
695 VDStringSpanW(const value_type *s, const value_type *t)
696 : mpBegin(const_cast<value_type *>(s))
697 , mpEnd(const_cast<value_type *>(t))
701 // 21.3.2 iterators
702 const_iterator begin() const { return mpBegin; }
703 const_iterator end() const { return mpEnd; }
705 // 21.3.3 capacity
706 size_type size() const { return (size_type)(mpEnd - mpBegin); }
707 size_type length() const { return (size_type)(mpEnd - mpBegin); }
708 bool empty() const { return mpBegin == mpEnd; }
710 // 21.3.4 element access
711 const_reference operator[](size_type pos) const { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
712 const_reference at(size_type pos) const { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
714 const_reference front() const { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
715 const_reference back() const { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
717 // 21.3.6 string operations
718 const_pointer data() const { return mpBegin; }
720 size_type copy(value_type *dst, size_type n, size_type pos = 0) const {
721 size_type len = (size_type)(mpEnd - mpBegin);
722 VDASSERT(pos <= len);
724 len -= pos;
725 if (n > len)
726 n = len;
728 memcpy(dst, mpBegin + pos, n*sizeof(value_type));
729 return n;
732 size_type find(value_type c, size_type pos = 0) const {
733 VDASSERT(pos <= (size_type)(mpEnd - mpBegin));
734 const void *p = wmemchr(mpBegin + pos, c, mpEnd - (mpBegin + pos));
736 return p ? (size_type)((const value_type *)p - mpBegin) : npos;
739 int compare(const VDStringSpanW& s) const {
740 size_type l1 = (size_type)(mpEnd - mpBegin);
741 size_type l2 = (size_type)(s.mpEnd - s.mpBegin);
742 size_type lm = l1 < l2 ? l1 : l2;
744 for(size_type i = 0; i < lm; ++i) {
745 if (mpBegin[i] != s.mpBegin[i])
746 return mpBegin[i] < s.mpBegin[i] ? -1 : +1;
749 if (l1 == l2)
750 return 0;
752 return l1 < l2 ? -1 : +1;
755 int comparei(const wchar_t *s) const {
756 return comparei(VDStringSpanW(s));
759 int comparei(const VDStringSpanW& s) const {
760 size_type l1 = (size_type)(mpEnd - mpBegin);
761 size_type l2 = (size_type)(s.mpEnd - s.mpBegin);
762 size_type lm = l1 < l2 ? l1 : l2;
764 for(size_type i = 0; i < lm; ++i) {
765 wint_t c = towlower(mpBegin[i]);
766 wint_t d = towlower(s.mpBegin[i]);
768 if (c != d)
769 return c < d ? -1 : +1;
772 if (l1 == l2)
773 return 0;
775 return l1 < l2 ? -1 : +1;
778 // extensions
779 const VDStringSpanW subspan(size_type pos, size_type n) const {
780 size_type len = (size_type)(mpEnd - mpBegin);
781 VDASSERT(pos <= len);
783 len -= pos;
784 if (n > len)
785 n = len;
787 value_type *p = mpBegin + pos;
788 return VDStringSpanW(p, p+n);
791 protected:
792 friend class VDStringW;
793 friend bool operator==(const VDStringSpanW& x, const VDStringSpanW& y);
794 friend bool operator==(const VDStringSpanW& x, const wchar_t *y);
796 value_type *mpBegin;
797 value_type *mpEnd;
799 static const value_type sNull[1];
802 inline bool operator==(const VDStringSpanW& x, const VDStringSpanW& y) { VDStringA::size_type len = (VDStringSpanW::size_type)(x.mpEnd - x.mpBegin); return len == (VDStringSpanW::size_type)(y.mpEnd - y.mpBegin) && !memcmp(x.mpBegin, y.mpBegin, len*sizeof(wchar_t)); }
803 inline bool operator==(const VDStringSpanW& x, const wchar_t *y) { size_t len = wcslen(y); return len == (size_t)(x.mpEnd - x.mpBegin) && !memcmp(x.mpBegin, y, len*sizeof(wchar_t)); }
804 inline bool operator==(const wchar_t *x, const VDStringSpanW& y) { return y == x; }
806 inline bool operator!=(const VDStringSpanW& x, const VDStringSpanW& y) { return !(x == y); }
807 inline bool operator!=(const VDStringSpanW& x, const wchar_t *y) { return !(x == y); }
808 inline bool operator!=(const wchar_t *x, const VDStringSpanW& y) { return !(y == x); }
810 inline bool operator<(const VDStringSpanW& x, const VDStringSpanW& y) {
811 return x.compare(y) < 0;
814 inline bool operator>(const VDStringSpanW& x, const VDStringSpanW& y) {
815 return x.compare(y) > 0;
818 inline bool operator<=(const VDStringSpanW& x, const VDStringSpanW& y) {
819 return x.compare(y) <= 0;
822 inline bool operator>=(const VDStringSpanW& x, const VDStringSpanW& y) {
823 return x.compare(y) >= 0;
826 class VDStringRefW : public VDStringSpanW {
827 public:
828 typedef VDStringRefW this_type;
830 VDStringRefW() {
833 explicit VDStringRefW(const value_type *s)
834 : VDStringSpanW(s)
838 explicit VDStringRefW(const VDStringSpanW& s)
839 : VDStringSpanW(s)
843 VDStringRefW(const value_type *s, const value_type *t)
844 : VDStringSpanW(s, t)
848 this_type& operator=(const value_type *s) {
849 assign(s);
850 return *this;
853 this_type& operator=(const VDStringSpanW& str) {
854 assign(str);
855 return *this;
858 void assign(const value_type *s) {
859 static_cast<VDStringSpanW&>(*this) = VDStringSpanW(s);
862 void assign(const value_type *s, const value_type *t) {
863 static_cast<VDStringSpanW&>(*this) = VDStringSpanW(s, t);
866 void assign(const VDStringSpanW& s) {
867 static_cast<VDStringSpanW&>(*this) = s;
870 void clear() {
871 mpBegin = mpEnd = NULL;
874 bool split(value_type c, VDStringRefW& token) {
875 size_type pos = find(c);
877 if (pos == npos)
878 return false;
880 token = subspan(0, pos);
881 mpBegin += pos+1;
882 return true;
886 class VDStringW : public VDStringSpanW {
887 public:
888 typedef VDStringW this_type;
890 // 21.3.1 construct/copy/destroy
892 VDStringW()
893 : mpEOS(const_cast<value_type *>(sNull))
897 VDStringW(const VDStringSpanW& x)
898 : mpEOS(const_cast<value_type *>(sNull))
900 assign(x.begin(), x.end());
903 VDStringW(const this_type& x)
904 : mpEOS(const_cast<value_type *>(sNull))
906 assign(x);
909 explicit VDStringW(const value_type *s)
910 : mpEOS(const_cast<value_type *>(sNull))
912 assign(s);
915 explicit VDStringW(size_type n)
916 : mpEOS(const_cast<value_type *>(sNull))
918 resize(n);
921 VDStringW(const value_type *s, size_type n)
922 : mpEOS(const_cast<value_type *>(sNull))
924 assign(s, n);
927 VDStringW(const value_type *s, const value_type *t)
928 : mpEOS(const_cast<value_type *>(sNull))
930 assign(s, t);
933 ~VDStringW() {
934 if (mpBegin != sNull)
935 delete[] mpBegin;
938 this_type& operator=(const wchar_t *s) {
939 assign(s);
940 return *this;
943 this_type& operator=(const this_type& str) {
944 assign(str);
945 return *this;
948 // 21.3.2 iterators
949 using VDStringSpanW::begin;
950 using VDStringSpanW::end;
951 iterator begin() { return mpBegin; }
952 iterator end() { return mpEnd; }
954 // 21.3.3 capacity (COMPLETE)
955 void resize(size_type n) {
956 size_type current = (size_type)(mpEnd - mpBegin);
958 if (n < current) {
959 mpEnd = mpBegin + n;
960 mpEnd[0] = 0;
961 } else if (n > current)
962 resize_slow(n, current);
965 void resize(size_type n, value_type v) {
966 size_type current = (size_type)(mpEnd - mpBegin);
968 if (n < current) {
969 mpEnd = mpBegin + n;
970 mpEnd[0] = 0;
971 } else if (n > current)
972 resize_slow(n, current);
973 wmemset(mpBegin, v, n);
976 size_type capacity() const { return (size_type)(mpEOS - mpBegin); }
978 void reserve(size_type n) {
979 size_type current = (size_type)(mpEOS - mpBegin);
981 if (n > current)
982 reserve_slow(n, current);
985 void clear() {
986 if (mpEnd != mpBegin) {
987 mpEnd = mpBegin;
988 mpEnd[0] = 0;
992 // 21.3.4 element access
993 using VDStringSpanW::operator[];
994 using VDStringSpanW::at;
995 using VDStringSpanW::front;
996 using VDStringSpanW::back;
997 reference operator[](size_type pos) { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
998 reference at(size_type pos) { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
999 reference front() { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
1000 reference back() { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
1002 // 21.3.5 modifiers
1003 this_type& operator+=(const this_type& str) {
1004 return append(str.mpBegin, str.mpEnd);
1007 this_type& operator+=(const value_type *s) {
1008 return append(s, s+wcslen(s));
1011 this_type& operator+=(value_type c) {
1012 if (mpEnd == mpEOS)
1013 push_back_extend();
1015 *mpEnd++ = c;
1016 *mpEnd = 0;
1017 return *this;
1020 this_type& append(const this_type& str) {
1021 return append(str.mpBegin, str.mpEnd);
1024 this_type& append(const this_type& str, size_type pos, size_type n) {
1025 size_type len = (size_type)(str.mpEnd - str.mpBegin);
1026 VDASSERT(pos <= len);
1028 len -= pos;
1029 if (n > len)
1030 n = len;
1032 return append(str.mpBegin + pos, str.mpBegin + pos + n);
1035 this_type& append(const value_type *s, size_type n) {
1036 return append(s, s+n);
1039 this_type& append(const value_type *s) {
1040 return append(s, s+wcslen(s));
1043 this_type& append(const value_type *s, const value_type *t) {
1044 if (s != t) {
1045 size_type current_size = (size_type)(mpEnd - mpBegin);
1046 size_type current_capacity = (size_type)(mpEOS - mpBegin);
1047 size_type n = (size_type)(t - s);
1049 if (current_capacity - current_size < n)
1050 reserve_amortized_slow(n, current_size, current_capacity);
1052 memcpy(mpBegin + current_size, s, n*sizeof(value_type));
1053 mpEnd += n;
1054 *mpEnd = 0;
1056 return *this;
1059 void push_back(const value_type c) {
1060 if (mpEnd == mpEOS)
1061 push_back_extend();
1063 *mpEnd++ = c;
1064 *mpEnd = 0;
1067 void pop_back() {
1068 --mpEnd;
1069 *mpEnd = 0;
1072 this_type& assign(const VDStringSpanW& str) {
1073 return assign(str.mpBegin, str.mpEnd);
1076 this_type& assign(const VDStringSpanW& str, size_type pos, size_type n) {
1077 size_type len = (size_type)(str.mpEnd - str.mpBegin);
1078 VDASSERT(pos <= len);
1080 len -= pos;
1081 if (n > len)
1082 n = len;
1084 return assign(str.mpBegin + pos, str.mpBegin + pos + n);
1087 this_type& assign(const value_type *s, size_type n) {
1088 return assign(s, s+n);
1091 this_type& assign(const value_type *s) {
1092 return assign(s, s+wcslen(s));
1095 this_type& assign(size_type n, value_type c) {
1096 size_type current_capacity = (size_type)(mpEOS - mpBegin);
1098 if (current_capacity < n)
1099 reserve_slow(n, current_capacity);
1101 if (mpBegin != sNull) {
1102 mpEnd = mpBegin;
1103 while(n--)
1104 *mpEnd++ = c;
1107 return *this;
1110 this_type& assign(const value_type *s, const value_type *t) {
1111 size_type current_capacity = (size_type)(mpEOS - mpBegin);
1112 size_type n = (size_type)(t - s);
1114 if (current_capacity < n)
1115 reserve_slow(n, current_capacity);
1117 if (mpBegin != sNull) {
1118 memcpy(mpBegin, s, sizeof(value_type)*n);
1119 mpEnd = mpBegin + n;
1120 *mpEnd = 0;
1123 return *this;
1126 this_type& insert(iterator it, value_type c) {
1127 if (mpEnd == mpEOS) {
1128 size_type pos = (size_type)(it - mpBegin);
1129 push_back_extend();
1130 it = mpBegin + pos;
1133 memmove(it + 1, it, (mpEnd - it + 1)*sizeof(value_type));
1134 *it = c;
1135 ++mpEnd;
1136 return *this;
1139 this_type& erase(size_type pos = 0, size_type n = npos) {
1140 size_type len = (size_type)(mpEnd - mpBegin);
1142 VDASSERT(pos <= len);
1143 len -= pos;
1144 if (n > len)
1145 n = len;
1147 if (n) {
1148 size_type pos2 = pos + n;
1149 memmove(mpBegin + pos, mpBegin + pos2, (len + 1 - n)*sizeof(value_type));
1150 mpEnd -= n;
1153 return *this;
1156 iterator erase(iterator x) {
1157 VDASSERT(x != mpEnd);
1159 memmove(x, x+1, (mpEnd - x)*sizeof(value_type));
1160 --mpEnd;
1161 return x;
1164 iterator erase(iterator first, iterator last) {
1165 VDASSERT(last >= first);
1167 memmove(first, last, ((mpEnd - last) + 1)*sizeof(value_type));
1168 mpEnd -= (last - first);
1169 return first;
1172 this_type& replace(size_type pos, size_type n1, const value_type *s, size_type n2) {
1173 size_type len = (size_type)(mpEnd - mpBegin);
1175 VDASSERT(pos <= len);
1176 size_type limit = len - pos;
1177 if (n1 > limit)
1178 n1 = limit;
1180 size_type len2 = len - n1 + n2;
1181 size_type current_capacity = (size_type)(mpEOS - mpBegin);
1183 if (current_capacity < len2)
1184 reserve_slow(len2, current_capacity);
1186 memmove(mpBegin + pos + n2, mpBegin + pos + n1, (limit - n1 + 1) * sizeof(value_type));
1187 memcpy(mpBegin + pos, s, n2*sizeof(value_type));
1188 mpEnd = mpBegin + len2;
1189 return *this;
1192 void swap(this_type& x) {
1193 value_type *p;
1195 p = mpBegin; mpBegin = x.mpBegin; x.mpBegin = p;
1196 p = mpEnd; mpEnd = x.mpEnd; x.mpEnd = p;
1197 p = mpEOS; mpEOS = x.mpEOS; x.mpEOS = p;
1200 // 21.3.6 string operations
1201 const_pointer c_str() const { return mpBegin; }
1203 this_type& sprintf(const value_type *format, ...);
1204 this_type& append_sprintf(const value_type *format, ...);
1205 this_type& append_vsprintf(const value_type *format, va_list val);
1207 void move_from(VDStringW& src);
1209 protected:
1210 void push_back_extend();
1211 void resize_slow(size_type n, size_type current_size);
1212 void reserve_slow(size_type n, size_type current_capacity);
1213 void reserve_amortized_slow(size_type n, size_type current_size, size_type current_capacity);
1215 value_type *mpEOS;
1218 ///////////////////////////////////////////////////////////////////////////
1220 inline VDStringW operator+(const VDStringW& str, const VDStringW& s) {
1221 VDStringW result;
1222 result.reserve((VDStringA::size_type)(str.size() + s.size()));
1223 result.assign(str);
1224 result.append(s);
1225 return result;
1228 inline VDStringW operator+(const VDStringW& str, const wchar_t *s) {
1229 VDStringW result;
1230 result.reserve((VDStringA::size_type)(str.size() + wcslen(s)));
1231 result.assign(str);
1232 result.append(s);
1233 return result;
1236 inline VDStringW operator+(const VDStringW& str, wchar_t c) {
1237 VDStringW result;
1238 result.reserve(str.size() + 1);
1239 result.assign(str);
1240 result += c;
1241 return result;
1244 ///////////////////////////////////////////////////////////////////////////
1246 typedef VDStringA VDString;
1248 template<> VDStringA *vdmove_forward(VDStringA *src1, VDStringA *src2, VDStringA *dst);
1249 template<> VDStringW *vdmove_forward(VDStringW *src1, VDStringW *src2, VDStringW *dst);
1250 template<> VDStringA *vdmove_backward(VDStringA *src1, VDStringA *src2, VDStringA *dst);
1251 template<> VDStringW *vdmove_backward(VDStringW *src1, VDStringW *src2, VDStringW *dst);
1254 #endif