1 // VirtualDub - Video processing and capture application
2 // System library component
3 // Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
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):
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
26 #ifndef f_VD2_SYSTEM_VDSTRING_H
27 #define f_VD2_SYSTEM_VDSTRING_H
39 #include <vd2/system/vdtypes.h>
40 #include <vd2/system/text.h>
41 #include <vd2/system/vdstl.h>
43 ///////////////////////////////////////////////////////////////////////////
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;
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
))
78 const_iterator
begin() const { return mpBegin
; }
79 const_iterator
end() const { return mpEnd
; }
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
);
104 memcpy(dst
, mpBegin
+ pos
, n
*sizeof(value_type
));
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
) {
122 return (size_type
)(s
- mpBegin
);
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
);
136 r
= (int)mpBegin
[lm
] - (int)s
.mpBegin
[lm
];
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
;
154 const unsigned char c
= tolower((unsigned char)*p
++);
155 const unsigned char d
= tolower((unsigned char)*q
++);
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
])
176 while(p
!= q
&& flags
[q
[-1]])
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
);
191 value_type
*p
= mpBegin
+ pos
;
192 return VDStringSpanA(p
, p
+n
);
196 friend bool operator==(const VDStringSpanA
& x
, const VDStringSpanA
& y
);
197 friend bool operator==(const VDStringSpanA
& x
, const char *y
);
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
{
231 typedef VDStringRefA this_type
;
236 explicit VDStringRefA(const value_type
*s
)
241 explicit VDStringRefA(const VDStringSpanA
& s
)
246 VDStringRefA(const value_type
*s
, const value_type
*t
)
247 : VDStringSpanA(s
, t
)
251 this_type
& operator=(const value_type
*s
) {
256 this_type
& operator=(const VDStringSpanA
& str
) {
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
;
274 mpBegin
= mpEnd
= NULL
;
277 bool split(value_type c
, VDStringRefA
& token
) {
278 size_type pos
= find(c
);
283 token
= subspan(0, pos
);
289 class VDStringA
: public VDStringSpanA
{
291 typedef VDStringA this_type
;
293 // 21.3.1 construct/copy/destroy
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
))
312 explicit VDStringA(const value_type
*s
)
313 : mpEOS(const_cast<value_type
*>(sNull
))
318 explicit VDStringA(size_type n
)
319 : mpEOS(const_cast<value_type
*>(sNull
))
324 VDStringA(const value_type
*s
, size_type n
)
325 : mpEOS(const_cast<value_type
*>(sNull
))
330 VDStringA(const value_type
*s
, const value_type
*t
)
331 : mpEOS(const_cast<value_type
*>(sNull
))
337 if (mpBegin
!= sNull
)
341 this_type
& operator=(const value_type
*s
) {
346 this_type
& operator=(const this_type
& str
) {
351 this_type
& operator=(const VDStringSpanA
& str
) {
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
);
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
);
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
);
390 reserve_slow(n
, current
);
394 if (mpEnd
!= mpBegin
) {
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]; }
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
) {
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
);
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
) {
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
));
468 void push_back(const value_type c
) {
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
);
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
) {
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
);
539 this_type
& insert(iterator it
, value_type c
) {
540 if (mpEnd
== mpEOS
) {
541 size_type pos
= (size_type
)(it
- mpBegin
);
546 memmove(it
+ 1, it
, (mpEnd
- it
+ 1)*sizeof(value_type
));
552 this_type
& erase(size_type pos
= 0, size_type n
= npos
) {
553 size_type len
= (size_type
)(mpEnd
- mpBegin
);
555 VDASSERT(pos
<= len
);
561 size_type pos2
= pos
+ n
;
562 memmove(mpBegin
+ pos
, mpBegin
+ pos2
, (len
+ 1 - n
)*sizeof(value_type
));
569 iterator
erase(iterator x
) {
570 VDASSERT(x
!= mpEnd
);
572 memmove(x
, x
+1, (mpEnd
- x
)*sizeof(value_type
));
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
);
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
;
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
;
605 void swap(this_type
& x
) {
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
);
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
);
632 ///////////////////////////////////////////////////////////////////////////
634 inline VDStringA
operator+(const VDStringA
& str
, const VDStringA
& s
) {
636 result
.reserve((VDStringA::size_type
)(str
.size() + s
.size()));
642 inline VDStringA
operator+(const VDStringA
& str
, const char *s
) {
644 result
.reserve((VDStringA::size_type
)(str
.size() + strlen(s
)));
650 inline VDStringA
operator+(const VDStringA
& str
, char c
) {
652 result
.reserve(str
.size() + 1);
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
{
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;
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
))
702 const_iterator
begin() const { return mpBegin
; }
703 const_iterator
end() const { return mpEnd
; }
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
);
728 memcpy(dst
, mpBegin
+ pos
, n
*sizeof(value_type
));
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;
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
]);
769 return c
< d
? -1 : +1;
775 return l1
< l2
? -1 : +1;
779 const VDStringSpanW
subspan(size_type pos
, size_type n
) const {
780 size_type len
= (size_type
)(mpEnd
- mpBegin
);
781 VDASSERT(pos
<= len
);
787 value_type
*p
= mpBegin
+ pos
;
788 return VDStringSpanW(p
, p
+n
);
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
);
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
{
828 typedef VDStringRefW this_type
;
833 explicit VDStringRefW(const value_type
*s
)
838 explicit VDStringRefW(const VDStringSpanW
& s
)
843 VDStringRefW(const value_type
*s
, const value_type
*t
)
844 : VDStringSpanW(s
, t
)
848 this_type
& operator=(const value_type
*s
) {
853 this_type
& operator=(const VDStringSpanW
& str
) {
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
;
871 mpBegin
= mpEnd
= NULL
;
874 bool split(value_type c
, VDStringRefW
& token
) {
875 size_type pos
= find(c
);
880 token
= subspan(0, pos
);
886 class VDStringW
: public VDStringSpanW
{
888 typedef VDStringW this_type
;
890 // 21.3.1 construct/copy/destroy
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
))
909 explicit VDStringW(const value_type
*s
)
910 : mpEOS(const_cast<value_type
*>(sNull
))
915 explicit VDStringW(size_type n
)
916 : mpEOS(const_cast<value_type
*>(sNull
))
921 VDStringW(const value_type
*s
, size_type n
)
922 : mpEOS(const_cast<value_type
*>(sNull
))
927 VDStringW(const value_type
*s
, const value_type
*t
)
928 : mpEOS(const_cast<value_type
*>(sNull
))
934 if (mpBegin
!= sNull
)
938 this_type
& operator=(const wchar_t *s
) {
943 this_type
& operator=(const this_type
& str
) {
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
);
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
);
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
);
982 reserve_slow(n
, current
);
986 if (mpEnd
!= mpBegin
) {
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]; }
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
) {
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
);
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
) {
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
));
1059 void push_back(const value_type c
) {
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
);
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
) {
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
;
1126 this_type
& insert(iterator it
, value_type c
) {
1127 if (mpEnd
== mpEOS
) {
1128 size_type pos
= (size_type
)(it
- mpBegin
);
1133 memmove(it
+ 1, it
, (mpEnd
- it
+ 1)*sizeof(value_type
));
1139 this_type
& erase(size_type pos
= 0, size_type n
= npos
) {
1140 size_type len
= (size_type
)(mpEnd
- mpBegin
);
1142 VDASSERT(pos
<= len
);
1148 size_type pos2
= pos
+ n
;
1149 memmove(mpBegin
+ pos
, mpBegin
+ pos2
, (len
+ 1 - n
)*sizeof(value_type
));
1156 iterator
erase(iterator x
) {
1157 VDASSERT(x
!= mpEnd
);
1159 memmove(x
, x
+1, (mpEnd
- x
)*sizeof(value_type
));
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
);
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
;
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
;
1192 void swap(this_type
& x
) {
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
);
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
);
1218 ///////////////////////////////////////////////////////////////////////////
1220 inline VDStringW
operator+(const VDStringW
& str
, const VDStringW
& s
) {
1222 result
.reserve((VDStringA::size_type
)(str
.size() + s
.size()));
1228 inline VDStringW
operator+(const VDStringW
& str
, const wchar_t *s
) {
1230 result
.reserve((VDStringA::size_type
)(str
.size() + wcslen(s
)));
1236 inline VDStringW
operator+(const VDStringW
& str
, wchar_t c
) {
1238 result
.reserve(str
.size() + 1);
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
);