home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / h / vd2 / system / VDString.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  28.2 KB  |  1,135 lines

  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.
  12. //
  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:
  16. //
  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.
  25.  
  26. #ifndef f_VD2_SYSTEM_VDSTRING_H
  27. #define f_VD2_SYSTEM_VDSTRING_H
  28.  
  29. #ifdef _MSC_VER
  30.     #pragma once
  31. #endif
  32.  
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <stdarg.h>
  36. #include <stddef.h>
  37. #include <functional>
  38.  
  39. #include <vd2/system/vdtypes.h>
  40. #include <vd2/system/text.h>
  41.  
  42. ///////////////////////////////////////////////////////////////////////////
  43.  
  44. class VDStringSpanA {
  45. public:
  46.     typedef char                    value_type;
  47.     typedef uint32                    size_type;
  48.     typedef ptrdiff_t                difference_type;
  49.     typedef value_type&                reference;
  50.     typedef const value_type&        const_reference;
  51.     typedef value_type *            pointer;
  52.     typedef const value_type *        const_pointer;
  53.     typedef pointer                    iterator;
  54.     typedef const_pointer            const_iterator;
  55.  
  56.     static const size_type npos = (size_type)-1;
  57.  
  58.     VDStringSpanA() 
  59.         : mpBegin(const_cast<value_type *>(sNull))
  60.         , mpEnd(const_cast<value_type *>(sNull))
  61.     {
  62.     }
  63.  
  64.     explicit VDStringSpanA(const value_type *s)
  65.         : mpBegin(const_cast<value_type *>(s))
  66.         , mpEnd(const_cast<value_type *>(s) + strlen(s))
  67.     {
  68.     }
  69.  
  70.     VDStringSpanA(const value_type *s, const value_type *t)
  71.         : mpBegin(const_cast<value_type *>(s))
  72.         , mpEnd(const_cast<value_type *>(t))
  73.     {
  74.     }
  75.  
  76.     // 21.3.2 iterators
  77.     const_iterator        begin() const        { return mpBegin; }
  78.     const_iterator        end() const            { return mpEnd; }
  79.  
  80.     // 21.3.3 capacity
  81.     size_type            size() const        { return mpEnd - mpBegin; }
  82.     size_type            length() const        { return mpEnd - mpBegin; }
  83.     bool                empty() const        { return mpBegin == mpEnd; }
  84.  
  85.     // 21.3.4 element access
  86.     const_reference        operator[](size_type pos) const    { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  87.     const_reference        at(size_type pos) const            { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  88.  
  89.     const_reference        front() const        { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  90.     const_reference        back() const        { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  91.  
  92.     // 21.3.6 string operations
  93.     const_pointer        data() const        { return mpBegin; }
  94.  
  95.     size_type copy(value_type *dst, size_type n, size_type pos = 0) const {
  96.         size_type len = (size_type)(mpEnd - mpBegin);
  97.         VDASSERT(pos <= len);
  98.  
  99.         len -= pos;
  100.         if (n > len)
  101.             n = len;
  102.  
  103.         memcpy(dst, mpBegin + pos, n*sizeof(value_type));
  104.         return n;
  105.     }
  106.  
  107.     size_type find(value_type c, size_type pos = 0) const {
  108.         VDASSERT(pos <= (size_type)(mpEnd - mpBegin));
  109.         const void *p = memchr(mpBegin + pos, c, mpEnd - (mpBegin + pos));
  110.  
  111.         return p ? (const value_type *)p - mpBegin : npos;
  112.     }
  113.  
  114.     int compare(const VDStringSpanA& s) const {
  115.         size_type l1 = mpEnd - mpBegin;
  116.         size_type l2 = s.mpEnd - s.mpBegin;
  117.         size_type lm = l1 < l2 ? l1 : l2;
  118.  
  119.         int r = memcmp(mpBegin, s.mpBegin, lm);
  120.  
  121.         if (!r)
  122.             r = (int)mpBegin[lm] - (int)s.mpBegin[lm];
  123.  
  124.         return r;
  125.     }
  126.  
  127.     const VDStringSpanA trim(const value_type *s) const {
  128.         bool flags[256]={false};
  129.  
  130.         while(value_type c = *s++)
  131.             flags[(unsigned char)c] = true;
  132.  
  133.         const value_type *p = mpBegin;
  134.         const value_type *q = mpEnd;
  135.  
  136.         while(p != q && flags[*p])
  137.             ++p;
  138.  
  139.         while(p != q && flags[q[-1]])
  140.             --q;
  141.  
  142.         return VDStringSpanA(p, q);
  143.     }
  144.  
  145.     const VDStringSpanA subspan(size_type pos = 0, size_type n = npos) const {
  146.         
  147.         size_type len = (size_type)(mpEnd - mpBegin);
  148.         VDASSERT(pos <= len);
  149.  
  150.         len -= pos;
  151.         if (n > len)
  152.             n = len;
  153.  
  154.         value_type *p = mpBegin + pos;
  155.         return VDStringSpanA(p, p+n);
  156.     }
  157.  
  158. protected:
  159.     friend bool operator==(const VDStringSpanA& x, const VDStringSpanA& y);
  160.     friend bool operator==(const VDStringSpanA& x, const char *y);
  161.  
  162.     value_type *mpBegin;
  163.     value_type *mpEnd;
  164.  
  165.     static const value_type sNull[1];
  166. };
  167.  
  168. 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)); }
  169. 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)); }
  170. inline bool operator==(const char *x, const VDStringSpanA& y) { return y == x; }
  171.  
  172. inline bool operator!=(const VDStringSpanA& x, const VDStringSpanA& y) { return !(x == y); }
  173. inline bool operator!=(const VDStringSpanA& x, const char *y) { return !(x == y); }
  174. inline bool operator!=(const char *x, const VDStringSpanA& y) { return !(y == x); }
  175.  
  176. inline bool operator<(const VDStringSpanA& x, const VDStringSpanA& y) {
  177.     return x.compare(y) < 0;
  178. }
  179.  
  180. inline bool operator>(const VDStringSpanA& x, const VDStringSpanA& y) {
  181.     return x.compare(y) > 0;
  182. }
  183.  
  184. inline bool operator<=(const VDStringSpanA& x, const VDStringSpanA& y) {
  185.     return x.compare(y) <= 0;
  186. }
  187.  
  188. inline bool operator>=(const VDStringSpanA& x, const VDStringSpanA& y) {
  189.     return x.compare(y) >= 0;
  190. }
  191.  
  192. class VDStringRefA : public VDStringSpanA {
  193. public:
  194.     typedef VDStringRefA this_type;
  195.  
  196.     VDStringRefA()  {
  197.     }
  198.  
  199.     explicit VDStringRefA(const value_type *s)
  200.         : VDStringSpanA(s)
  201.     {
  202.     }
  203.  
  204.     explicit VDStringRefA(const VDStringSpanA& s)
  205.         : VDStringSpanA(s)
  206.     {
  207.     }
  208.  
  209.     VDStringRefA(const value_type *s, const value_type *t)
  210.         : VDStringSpanA(s, t)
  211.     {
  212.     }
  213.  
  214.     this_type& operator=(const value_type *s) {
  215.         assign(s);
  216.         return *this;
  217.     }
  218.  
  219.     this_type& operator=(const VDStringSpanA& str) {
  220.         assign(str);
  221.         return *this;
  222.     }
  223.  
  224.     void assign(const value_type *s) {
  225.         static_cast<VDStringSpanA&>(*this) = VDStringSpanA(s);
  226.     }
  227.  
  228.     void assign(const value_type *s, const value_type *t) {
  229.         static_cast<VDStringSpanA&>(*this) = VDStringSpanA(s, t);
  230.     }
  231.  
  232.     void assign(const VDStringSpanA& s) {
  233.         static_cast<VDStringSpanA&>(*this) = s;
  234.     }
  235.  
  236.     bool split(value_type c, VDStringRefA& token) {
  237.         size_type pos = find(c);
  238.  
  239.         if (pos == npos)
  240.             return false;
  241.  
  242.         token = subspan(0, pos);
  243.         mpBegin += pos+1;
  244.         return true;
  245.     }
  246. };
  247.  
  248. class VDStringA : public VDStringSpanA {
  249. public:
  250.     typedef VDStringA                this_type;
  251.  
  252.     // 21.3.1 construct/copy/destroy
  253.  
  254.     VDStringA()
  255.         : mpEOS(const_cast<value_type *>(sNull))
  256.     {
  257.     }
  258.  
  259.     VDStringA(const VDStringSpanA& x)
  260.         : mpEOS(const_cast<value_type *>(sNull))
  261.     {
  262.         assign(x.begin(), x.end());
  263.     }
  264.  
  265.     VDStringA(const this_type& x)
  266.         : mpEOS(const_cast<value_type *>(sNull))
  267.     {
  268.         assign(x);
  269.     }
  270.  
  271.     explicit VDStringA(const value_type *s)
  272.         : mpEOS(const_cast<value_type *>(sNull))
  273.     {
  274.         assign(s);
  275.     }
  276.  
  277.     explicit VDStringA(size_type n)
  278.         : mpEOS(const_cast<value_type *>(sNull))
  279.     {
  280.         resize(n);
  281.     }
  282.  
  283.     VDStringA(const value_type *s, size_type n)
  284.         : mpEOS(const_cast<value_type *>(sNull))
  285.     {
  286.         assign(s, n);
  287.     }
  288.  
  289.     VDStringA(const value_type *s, const value_type *t)
  290.         : mpEOS(const_cast<value_type *>(sNull))
  291.     {
  292.         assign(s, t);
  293.     }
  294.  
  295.     ~VDStringA() {
  296.         if (mpBegin != sNull)
  297.             delete[] mpBegin;
  298.     }
  299.  
  300.     this_type& operator=(const value_type *s) {
  301.         assign(s);
  302.         return *this;
  303.     }
  304.  
  305.     this_type& operator=(const this_type& str) {
  306.         assign(str);
  307.         return *this;
  308.     }
  309.  
  310.     this_type& operator=(const VDStringSpanA& str) {
  311.         assign(str);
  312.         return *this;
  313.     }
  314.  
  315.     // 21.3.2 iterators
  316.     using VDStringSpanA::begin;
  317.     using VDStringSpanA::end;
  318.  
  319.     iterator            begin()                { return mpBegin; }
  320.     iterator            end()                { return mpEnd; }
  321.  
  322.     // 21.3.3 capacity (COMPLETE)
  323.     void resize(size_type n) {
  324.         size_type current = (size_type)(mpEnd - mpBegin);
  325.  
  326.         if (n < current) {
  327.             mpEnd = mpBegin + n;
  328.             mpEnd[0] = 0;
  329.         } else if (n > current)
  330.             resize_slow(n, current);
  331.     }
  332.  
  333.     void resize(size_type n, value_type v) {
  334.         size_type current = (size_type)(mpEnd - mpBegin);
  335.  
  336.         if (n < current) {
  337.             mpEnd = mpBegin + n;
  338.             mpEnd[0] = 0;
  339.         } else if (n > current)
  340.             resize_slow(n, current, v);
  341.     }
  342.  
  343.     size_type            capacity() const    { return mpEOS - mpBegin; }
  344.  
  345.     void reserve(size_t n) {
  346.         size_type current = (size_type)(mpEOS - mpBegin);
  347.  
  348.         if (n > current)
  349.             reserve_slow(n, current);
  350.     }
  351.  
  352.     void clear() {
  353.         if (mpEnd != mpBegin) {
  354.             mpEnd = mpBegin;
  355.             mpEnd[0] = 0;
  356.         }
  357.     }
  358.  
  359.     // 21.3.4 element access
  360.     using VDStringSpanA::operator[];
  361.     using VDStringSpanA::at;
  362.     using VDStringSpanA::front;
  363.     using VDStringSpanA::back;
  364.  
  365.     reference            operator[](size_type pos)        { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  366.     reference            at(size_type pos)                { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  367.     reference            front()                { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  368.     reference            back()                { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  369.  
  370.     // 21.3.5 modifiers
  371.     this_type& operator+=(const this_type& str) {
  372.         return append(str.mpBegin, str.mpEnd);
  373.     }
  374.  
  375.     this_type& operator+=(const value_type *s) {
  376.         return append(s, s+strlen(s));
  377.     }
  378.  
  379.     this_type& operator+=(value_type c) {
  380.         if (mpEnd == mpEOS)
  381.             push_back_extend();
  382.  
  383.         *mpEnd++ = c;
  384.         *mpEnd = 0;
  385.         return *this;
  386.     }
  387.  
  388.     this_type& append(const this_type& str) {
  389.         return append(str.mpBegin, str.mpEnd);
  390.     }
  391.  
  392.     this_type& append(const this_type& str, size_type pos, size_type n) {
  393.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  394.         VDASSERT(pos <= len);
  395.  
  396.         len -= pos;
  397.         if (n > len)
  398.             n = len;
  399.  
  400.         return append(str.mpBegin + pos, str.mpBegin + pos + n);
  401.     }
  402.  
  403.     this_type& append(const value_type *s, size_type n) {
  404.         return append(s, s+n);
  405.     }
  406.  
  407.     this_type& append(const value_type *s) {
  408.         return append(s, s+strlen(s));
  409.     }
  410.  
  411.     this_type& append(const value_type *s, const value_type *t) {
  412.         if (s != t) {
  413.             size_type current_size = (size_type)(mpEnd - mpBegin);
  414.             size_type current_capacity = (size_type)(mpEOS - mpBegin);
  415.             size_type n = (size_type)(t - s);
  416.  
  417.             if (current_capacity - current_size < n)
  418.                 reserve_amortized_slow(n, current_size, current_capacity);
  419.  
  420.             memcpy(mpBegin + current_size, s, n*sizeof(value_type));
  421.             mpEnd += n;
  422.             *mpEnd = 0;
  423.         }
  424.         return *this;
  425.     }
  426.  
  427.     void push_back(const value_type c) {
  428.         if (mpEnd == mpEOS)
  429.             push_back_extend();
  430.  
  431.         *mpEnd++ = c;
  432.         *mpEnd = 0;
  433.     }
  434.  
  435.     this_type& assign(const VDStringSpanA& str) {
  436.         return assign(str.begin(), str.end());
  437.     }
  438.  
  439.     this_type& assign(const this_type& str) {
  440.         return assign(str.mpBegin, str.mpEnd);
  441.     }
  442.  
  443.     this_type& assign(const this_type& str, size_type pos, size_type n) {
  444.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  445.         VDASSERT(pos <= len);
  446.  
  447.         len -= pos;
  448.         if (n > len)
  449.             n = len;
  450.  
  451.         return assign(str.mpBegin + pos, str.mpBegin + pos + n);
  452.     }
  453.  
  454.     this_type& assign(const value_type *s, size_type n) {
  455.         return assign(s, s+n);
  456.     }
  457.  
  458.     this_type& assign(const value_type *s) {
  459.         return assign(s, s+strlen(s));
  460.     }
  461.  
  462.     this_type& assign(size_type n, value_type c) {
  463.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  464.  
  465.         if (current_capacity < n)
  466.             reserve_slow(n, current_capacity);
  467.  
  468.         if (mpBegin != sNull) {
  469.             mpEnd = mpBegin;
  470.             while(n--)
  471.                 *mpEnd++ = c;
  472.         }
  473.  
  474.         return *this;
  475.     }
  476.  
  477.     this_type& assign(const value_type *s, const value_type *t) {
  478.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  479.         size_type n = (size_type)(t - s);
  480.  
  481.         if (current_capacity < n)
  482.             reserve_slow(n, current_capacity);
  483.  
  484.         if (mpBegin != sNull) {
  485.             memcpy(mpBegin, s, sizeof(value_type)*n);
  486.             mpEnd = mpBegin + n;
  487.             *mpEnd = 0;
  488.         }
  489.  
  490.         return *this;
  491.     }
  492.  
  493.     this_type& insert(iterator it, value_type c) {
  494.         if (mpEnd == mpEOS) {
  495.             size_type pos = (size_type)(it - mpBegin);
  496.             push_back_extend();
  497.             it = mpBegin + pos;
  498.         }
  499.  
  500.         memmove(it + 1, it, (mpEnd - it + 1)*sizeof(value_type));
  501.         *it = c;
  502.         ++mpEnd;
  503.         return *this;
  504.     }
  505.  
  506.     this_type& erase(size_type pos = 0, size_type n = npos) {
  507.         size_type len = (size_type)(mpEnd - mpBegin);
  508.  
  509.         VDASSERT(pos <= len);
  510.         len -= pos;
  511.         if (n > len)
  512.             n = len;
  513.  
  514.         if (n) {
  515.             size_type pos2 = pos + n;
  516.             memmove(mpBegin + pos, mpBegin + pos2, (len + 1 - n)*sizeof(value_type));
  517.             mpEnd -= n;
  518.         }
  519.  
  520.         return *this;
  521.     }
  522.  
  523.     iterator erase(iterator x) {
  524.         VDASSERT(x != mpEnd);
  525.  
  526.         memmove(x, x+1, (mpEnd - x)*sizeof(value_type));
  527.         --mpEnd;
  528.         return x;
  529.     }
  530.  
  531.     iterator erase(iterator first, iterator last) {
  532.         VDASSERT(last >= first);
  533.  
  534.         memmove(first, last, ((mpEnd - last) + 1)*sizeof(value_type));
  535.         mpEnd -= (last - first);
  536.         return first;
  537.     }
  538.  
  539.     this_type& replace(size_type pos, size_type n1, const value_type *s, size_type n2) {
  540.         size_type len = (size_type)(mpEnd - mpBegin);
  541.  
  542.         VDASSERT(pos <= len);
  543.         size_type limit = len - pos;
  544.         if (n1 > limit)
  545.             n1 = limit;
  546.  
  547.         size_type len2 = len - n1 + n2;
  548.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  549.  
  550.         if (current_capacity < len2)
  551.             reserve_slow(len2, current_capacity);
  552.  
  553.         memmove(mpBegin + pos + n2, mpBegin + pos + n1, (limit - n1 + 1) * sizeof(value_type));
  554.         memcpy(mpBegin + pos, s, n2*sizeof(value_type));
  555.         mpEnd = mpBegin + len2;
  556.         return *this;
  557.     }
  558.  
  559.     void swap(this_type& x) {
  560.         value_type *p;
  561.  
  562.         p = mpBegin;    mpBegin = x.mpBegin;    x.mpBegin = p;
  563.         p = mpEnd;        mpEnd = x.mpEnd;        x.mpEnd = p;
  564.         p = mpEOS;        mpEOS = x.mpEOS;        x.mpEOS = p;
  565.     }
  566.  
  567.     // 21.3.6 string operations
  568.     const_pointer        c_str() const        { return mpBegin; }
  569.  
  570.     this_type& sprintf(const value_type *format, ...);
  571.     this_type& append_sprintf(const value_type *format, ...);
  572.     this_type& append_vsprintf(const value_type *format, va_list val);
  573.  
  574. protected:
  575.     void push_back_extend();
  576.     void resize_slow(size_type n, size_type current_size);
  577.     void resize_slow(size_type n, size_type current_size, value_type c);
  578.     void reserve_slow(size_type n, size_type current_capacity);
  579.     void reserve_amortized_slow(size_type n, size_type current_size, size_type current_capacity);
  580.  
  581.     char *mpEOS;
  582. };
  583.  
  584. ///////////////////////////////////////////////////////////////////////////
  585.  
  586. inline VDStringA operator+(const VDStringA& str, const VDStringA& s) {
  587.     VDStringA result;
  588.     result.reserve(str.size() + s.size());
  589.     result.assign(str);
  590.     result.append(s);
  591.     return result;
  592. }
  593.  
  594. inline VDStringA operator+(const VDStringA& str, const char *s) {
  595.     VDStringA result;
  596.     result.reserve(str.size() + strlen(s));
  597.     result.assign(str);
  598.     result.append(s);
  599.     return result;
  600. }
  601.  
  602. inline VDStringA operator+(const VDStringA& str, char c) {
  603.     VDStringA result;
  604.     result.reserve(str.size() + 1);
  605.     result.assign(str);
  606.     result += c;
  607.     return result;
  608. }
  609.  
  610. namespace std {
  611.     template<>
  612.     struct less<VDStringA> : binary_function<VDStringA, VDStringA, bool> {
  613.         bool operator()(const VDStringA& x, const VDStringA& y) const {
  614.             return x.compare(y) < 0;
  615.         }
  616.     };
  617. }
  618.  
  619. ///////////////////////////////////////////////////////////////////////////
  620.  
  621. class VDStringSpanW {
  622. public:
  623.     typedef wchar_t                    value_type;
  624.     typedef uint32                    size_type;
  625.     typedef ptrdiff_t                difference_type;
  626.     typedef value_type&                reference;
  627.     typedef const value_type&        const_reference;
  628.     typedef value_type *            pointer;
  629.     typedef const value_type *        const_pointer;
  630.     typedef pointer                    iterator;
  631.     typedef const_pointer            const_iterator;
  632.  
  633.     static const size_type npos = (size_type)-1;
  634.  
  635.     VDStringSpanW() 
  636.         : mpBegin(const_cast<value_type *>(sNull))
  637.         , mpEnd(const_cast<value_type *>(sNull))
  638.     {
  639.     }
  640.  
  641.     explicit VDStringSpanW(const value_type *s)
  642.         : mpBegin(const_cast<value_type *>(s))
  643.         , mpEnd(const_cast<value_type *>(s) + wcslen(s))
  644.     {
  645.     }
  646.  
  647.     VDStringSpanW(const value_type *s, const value_type *t)
  648.         : mpBegin(const_cast<value_type *>(s))
  649.         , mpEnd(const_cast<value_type *>(t))
  650.     {
  651.     }
  652.  
  653.     // 21.3.2 iterators
  654.     const_iterator        begin() const        { return mpBegin; }
  655.     const_iterator        end() const            { return mpEnd; }
  656.  
  657.     // 21.3.3 capacity
  658.     size_type            size() const        { return mpEnd - mpBegin; }
  659.     size_type            length() const        { return mpEnd - mpBegin; }
  660.     bool                empty() const        { return mpBegin == mpEnd; }
  661.  
  662.     // 21.3.4 element access
  663.     const_reference        operator[](size_type pos) const    { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  664.     const_reference        at(size_type pos) const            { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  665.  
  666.     const_reference        front() const        { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  667.     const_reference        back() const        { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  668.  
  669.     // 21.3.6 string operations
  670.     const_pointer        data() const        { return mpBegin; }
  671.  
  672.     size_type copy(value_type *dst, size_type n, size_type pos = 0) const {
  673.         size_type len = (size_type)(mpEnd - mpBegin);
  674.         VDASSERT(pos <= len);
  675.  
  676.         len -= pos;
  677.         if (n > len)
  678.             n = len;
  679.  
  680.         memcpy(dst, mpBegin + pos, n*sizeof(value_type));
  681.         return n;
  682.     }
  683.  
  684.     size_type find(value_type c, size_type pos = 0) const {
  685.         VDASSERT(pos <= (size_type)(mpEnd - mpBegin));
  686.         const void *p = wmemchr(mpBegin + pos, c, mpEnd - (mpBegin + pos));
  687.  
  688.         return p ? (const value_type *)p - mpBegin : npos;
  689.     }
  690.  
  691.     // extensions
  692.     const VDStringSpanW subspan(size_type pos, size_type n) const {
  693.         size_type len = (size_type)(mpEnd - mpBegin);
  694.         VDASSERT(pos <= len);
  695.  
  696.         len -= pos;
  697.         if (n > len)
  698.             n = len;
  699.  
  700.         value_type *p = mpBegin + pos;
  701.         return VDStringSpanW(p, p+n);
  702.     }
  703.  
  704. protected:
  705.     friend bool operator==(const VDStringSpanW& x, const VDStringSpanW& y);
  706.     friend bool operator==(const VDStringSpanW& x, const wchar_t *y);
  707.  
  708.     value_type *mpBegin;
  709.     value_type *mpEnd;
  710.  
  711.     static const value_type sNull[1];
  712. };
  713.  
  714. 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)); }
  715. 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)); }
  716. inline bool operator==(const wchar_t *x, const VDStringSpanW& y) { return y == x; }
  717.  
  718. inline bool operator!=(const VDStringSpanW& x, const VDStringSpanW& y) { return !(x == y); }
  719. inline bool operator!=(const VDStringSpanW& x, const wchar_t *y) { return !(x == y); }
  720. inline bool operator!=(const wchar_t *x, const VDStringSpanW& y) { return !(y == x); }
  721.  
  722. class VDStringRefW : public VDStringSpanW {
  723. public:
  724.     typedef VDStringRefW this_type;
  725.  
  726.     VDStringRefW()  {
  727.     }
  728.  
  729.     explicit VDStringRefW(const value_type *s)
  730.         : VDStringSpanW(s)
  731.     {
  732.     }
  733.  
  734.     explicit VDStringRefW(const VDStringSpanW& s)
  735.         : VDStringSpanW(s)
  736.     {
  737.     }
  738.  
  739.     VDStringRefW(const value_type *s, const value_type *t)
  740.         : VDStringSpanW(s, t)
  741.     {
  742.     }
  743.  
  744.     this_type& operator=(const value_type *s) {
  745.         assign(s);
  746.         return *this;
  747.     }
  748.  
  749.     this_type& operator=(const VDStringSpanW& str) {
  750.         assign(str);
  751.         return *this;
  752.     }
  753.  
  754.     void assign(const value_type *s) {
  755.         static_cast<VDStringSpanW&>(*this) = VDStringSpanW(s);
  756.     }
  757.  
  758.     void assign(const value_type *s, const value_type *t) {
  759.         static_cast<VDStringSpanW&>(*this) = VDStringSpanW(s, t);
  760.     }
  761.  
  762.     void assign(const VDStringSpanW& s) {
  763.         static_cast<VDStringSpanW&>(*this) = s;
  764.     }
  765.  
  766.     bool split(value_type c, VDStringRefW& token) {
  767.         size_type pos = find(c);
  768.  
  769.         if (pos == npos)
  770.             return false;
  771.  
  772.         token = subspan(0, pos);
  773.         mpBegin += pos+1;
  774.         return true;
  775.     }
  776. };
  777.  
  778. class VDStringW : public VDStringSpanW {
  779. public:
  780.     typedef VDStringW                this_type;
  781.  
  782.     // 21.3.1 construct/copy/destroy
  783.  
  784.     VDStringW()
  785.         : mpEOS(const_cast<value_type *>(sNull))
  786.     {
  787.     }
  788.  
  789.     VDStringW(const VDStringSpanW& x)
  790.         : mpEOS(const_cast<value_type *>(sNull))
  791.     {
  792.         assign(x.begin(), x.end());
  793.     }
  794.  
  795.     VDStringW(const this_type& x)
  796.         : mpEOS(const_cast<value_type *>(sNull))
  797.     {
  798.         assign(x);
  799.     }
  800.  
  801.     explicit VDStringW(const value_type *s)
  802.         : mpEOS(const_cast<value_type *>(sNull))
  803.     {
  804.         assign(s);
  805.     }
  806.  
  807.     explicit VDStringW(size_type n)
  808.         : mpEOS(const_cast<value_type *>(sNull))
  809.     {
  810.         resize(n);
  811.     }
  812.  
  813.     VDStringW(const value_type *s, size_type n)
  814.         : mpEOS(const_cast<value_type *>(sNull))
  815.     {
  816.         assign(s, n);
  817.     }
  818.  
  819.     VDStringW(const value_type *s, const value_type *t)
  820.         : mpEOS(const_cast<value_type *>(sNull))
  821.     {
  822.         assign(s, t);
  823.     }
  824.  
  825.     ~VDStringW() {
  826.         if (mpBegin != sNull)
  827.             delete[] mpBegin;
  828.     }
  829.  
  830.     this_type& operator=(const wchar_t *s) {
  831.         assign(s);
  832.         return *this;
  833.     }
  834.  
  835.     this_type& operator=(const this_type& str) {
  836.         assign(str);
  837.         return *this;
  838.     }
  839.  
  840.     // 21.3.2 iterators
  841.     using VDStringSpanW::begin;
  842.     using VDStringSpanW::end;
  843.     iterator            begin()                { return mpBegin; }
  844.     iterator            end()                { return mpEnd; }
  845.  
  846.     // 21.3.3 capacity (COMPLETE)
  847.     void resize(size_type n) {
  848.         size_type current = (size_type)(mpEnd - mpBegin);
  849.  
  850.         if (n < current) {
  851.             mpEnd = mpBegin + n;
  852.             mpEnd[0] = 0;
  853.         } else if (n > current)
  854.             resize_slow(n, current);
  855.     }
  856.  
  857.     void resize(size_type n, value_type v) {
  858.         size_type current = (size_type)(mpEnd - mpBegin);
  859.  
  860.         if (n < current) {
  861.             mpEnd = mpBegin + n;
  862.             mpEnd[0] = 0;
  863.         } else if (n > current)
  864.             resize_slow(n, current);
  865.         wmemset(mpBegin, v, n);
  866.     }
  867.  
  868.     size_type            capacity() const    { return mpEOS - mpBegin; }
  869.  
  870.     void reserve(size_t n) {
  871.         size_type current = (size_type)(mpEOS - mpBegin);
  872.  
  873.         if (n > current)
  874.             reserve_slow(n, current);
  875.     }
  876.  
  877.     void clear() {
  878.         if (mpEnd != mpBegin) {
  879.             mpEnd = mpBegin;
  880.             mpEnd[0] = 0;
  881.         }
  882.     }
  883.  
  884.     // 21.3.4 element access
  885.     using VDStringSpanW::operator[];
  886.     using VDStringSpanW::at;
  887.     using VDStringSpanW::front;
  888.     using VDStringSpanW::back;
  889.     reference            operator[](size_type pos)        { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  890.     reference            at(size_type pos)                { VDASSERT(pos < (size_type)(mpEnd - mpBegin)); return mpBegin[pos]; }
  891.     reference            front()                { VDASSERT(mpBegin != mpEnd); return *mpBegin; }
  892.     reference            back()                { VDASSERT(mpBegin != mpEnd); return mpEnd[-1]; }
  893.  
  894.     // 21.3.5 modifiers
  895.     this_type& operator+=(const this_type& str) {
  896.         return append(str.mpBegin, str.mpEnd);
  897.     }
  898.  
  899.     this_type& operator+=(const value_type *s) {
  900.         return append(s, s+wcslen(s));
  901.     }
  902.  
  903.     this_type& operator+=(value_type c) {
  904.         if (mpEnd == mpEOS)
  905.             push_back_extend();
  906.  
  907.         *mpEnd++ = c;
  908.         *mpEnd = 0;
  909.         return *this;
  910.     }
  911.  
  912.     this_type& append(const this_type& str) {
  913.         return append(str.mpBegin, str.mpEnd);
  914.     }
  915.  
  916.     this_type& append(const this_type& str, size_type pos, size_type n) {
  917.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  918.         VDASSERT(pos <= len);
  919.  
  920.         len -= pos;
  921.         if (n > len)
  922.             n = len;
  923.  
  924.         return append(str.mpBegin + pos, str.mpBegin + pos + n);
  925.     }
  926.  
  927.     this_type& append(const value_type *s, size_type n) {
  928.         return append(s, s+n);
  929.     }
  930.  
  931.     this_type& append(const value_type *s) {
  932.         return append(s, s+wcslen(s));
  933.     }
  934.  
  935.     this_type& append(const value_type *s, const value_type *t) {
  936.         if (s != t) {
  937.             size_type current_size = (size_type)(mpEnd - mpBegin);
  938.             size_type current_capacity = (size_type)(mpEOS - mpBegin);
  939.             size_type n = (size_type)(t - s);
  940.  
  941.             if (current_capacity - current_size < n)
  942.                 reserve_amortized_slow(n, current_size, current_capacity);
  943.  
  944.             memcpy(mpBegin + current_size, s, n*sizeof(value_type));
  945.             mpEnd += n;
  946.             *mpEnd = 0;
  947.         }
  948.         return *this;
  949.     }
  950.  
  951.     void push_back(const value_type c) {
  952.         if (mpEnd == mpEOS)
  953.             push_back_extend();
  954.  
  955.         *mpEnd++ = c;
  956.         *mpEnd = 0;
  957.     }
  958.  
  959.     this_type& assign(const this_type& str) {
  960.         return assign(str.mpBegin, str.mpEnd);
  961.     }
  962.  
  963.     this_type& assign(const this_type& str, size_type pos, size_type n) {
  964.         size_type len = (size_type)(str.mpEnd - str.mpBegin);
  965.         VDASSERT(pos <= len);
  966.  
  967.         len -= pos;
  968.         if (n > len)
  969.             n = len;
  970.  
  971.         return assign(str.mpBegin + pos, str.mpBegin + pos + n);
  972.     }
  973.  
  974.     this_type& assign(const value_type *s, size_type n) {
  975.         return assign(s, s+n);
  976.     }
  977.  
  978.     this_type& assign(const value_type *s) {
  979.         return assign(s, s+wcslen(s));
  980.     }
  981.  
  982.     this_type& assign(size_type n, value_type c) {
  983.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  984.  
  985.         if (current_capacity < n)
  986.             reserve_slow(n, current_capacity);
  987.  
  988.         if (mpBegin != sNull) {
  989.             mpEnd = mpBegin;
  990.             while(n--)
  991.                 *mpEnd++ = c;
  992.         }
  993.  
  994.         return *this;
  995.     }
  996.  
  997.     this_type& assign(const value_type *s, const value_type *t) {
  998.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  999.         size_type n = (size_type)(t - s);
  1000.  
  1001.         if (current_capacity < n)
  1002.             reserve_slow(n, current_capacity);
  1003.  
  1004.         if (mpBegin != sNull) {
  1005.             memcpy(mpBegin, s, sizeof(value_type)*n);
  1006.             mpEnd = mpBegin + n;
  1007.             *mpEnd = 0;
  1008.         }
  1009.  
  1010.         return *this;
  1011.     }
  1012.  
  1013.     this_type& insert(iterator it, value_type c) {
  1014.         if (mpEnd == mpEOS) {
  1015.             size_type pos = (size_type)(it - mpBegin);
  1016.             push_back_extend();
  1017.             it = mpBegin + pos;
  1018.         }
  1019.  
  1020.         memmove(it + 1, it, (mpEnd - it + 1)*sizeof(value_type));
  1021.         *it = c;
  1022.         ++mpEnd;
  1023.         return *this;
  1024.     }
  1025.  
  1026.     this_type& erase(size_type pos = 0, size_type n = npos) {
  1027.         size_type len = (size_type)(mpEnd - mpBegin);
  1028.  
  1029.         VDASSERT(pos <= len);
  1030.         len -= pos;
  1031.         if (n > len)
  1032.             n = len;
  1033.  
  1034.         if (n) {
  1035.             size_type pos2 = pos + n;
  1036.             memmove(mpBegin + pos, mpBegin + pos2, (len + 1 - n)*sizeof(value_type));
  1037.             mpEnd -= n;
  1038.         }
  1039.  
  1040.         return *this;
  1041.     }
  1042.  
  1043.     iterator erase(iterator x) {
  1044.         VDASSERT(x != mpEnd);
  1045.  
  1046.         memmove(x, x+1, (mpEnd - x)*sizeof(value_type));
  1047.         --mpEnd;
  1048.         return x;
  1049.     }
  1050.  
  1051.     iterator erase(iterator first, iterator last) {
  1052.         VDASSERT(last >= first);
  1053.  
  1054.         memmove(first, last, ((mpEnd - last) + 1)*sizeof(value_type));
  1055.         mpEnd -= (last - first);
  1056.         return first;
  1057.     }
  1058.  
  1059.     this_type& replace(size_type pos, size_type n1, const value_type *s, size_type n2) {
  1060.         size_type len = (size_type)(mpEnd - mpBegin);
  1061.  
  1062.         VDASSERT(pos <= len);
  1063.         size_type limit = len - pos;
  1064.         if (n1 > limit)
  1065.             n1 = limit;
  1066.  
  1067.         size_type len2 = len - n1 + n2;
  1068.         size_type current_capacity = (size_type)(mpEOS - mpBegin);
  1069.  
  1070.         if (current_capacity < len2)
  1071.             reserve_slow(len2, current_capacity);
  1072.  
  1073.         memmove(mpBegin + pos + n2, mpBegin + pos + n1, (limit - n1 + 1) * sizeof(value_type));
  1074.         memcpy(mpBegin + pos, s, n2*sizeof(value_type));
  1075.         mpEnd = mpBegin + len2;
  1076.         return *this;
  1077.     }
  1078.  
  1079.     void swap(this_type& x) {
  1080.         value_type *p;
  1081.  
  1082.         p = mpBegin;    mpBegin = x.mpBegin;    x.mpBegin = p;
  1083.         p = mpEnd;        mpEnd = x.mpEnd;        x.mpEnd = p;
  1084.         p = mpEOS;        mpEOS = x.mpEOS;        x.mpEOS = p;
  1085.     }
  1086.  
  1087.     // 21.3.6 string operations
  1088.     const_pointer        c_str() const        { return mpBegin; }
  1089.  
  1090.     this_type& sprintf(const value_type *format, ...);
  1091.     this_type& append_sprintf(const value_type *format, ...);
  1092.     this_type& append_vsprintf(const value_type *format, va_list val);
  1093.  
  1094. protected:
  1095.     void push_back_extend();
  1096.     void resize_slow(size_type n, size_type current_size);
  1097.     void reserve_slow(size_type n, size_type current_capacity);
  1098.     void reserve_amortized_slow(size_type n, size_type current_size, size_type current_capacity);
  1099.  
  1100.     value_type *mpEOS;
  1101. };
  1102.  
  1103. ///////////////////////////////////////////////////////////////////////////
  1104.  
  1105. inline VDStringW operator+(const VDStringW& str, const VDStringW& s) {
  1106.     VDStringW result;
  1107.     result.reserve(str.size() + s.size());
  1108.     result.assign(str);
  1109.     result.append(s);
  1110.     return result;
  1111. }
  1112.  
  1113. inline VDStringW operator+(const VDStringW& str, const wchar_t *s) {
  1114.     VDStringW result;
  1115.     result.reserve(str.size() + wcslen(s));
  1116.     result.assign(str);
  1117.     result.append(s);
  1118.     return result;
  1119. }
  1120.  
  1121. inline VDStringW operator+(const VDStringW& str, wchar_t c) {
  1122.     VDStringW result;
  1123.     result.reserve(str.size() + 1);
  1124.     result.assign(str);
  1125.     result += c;
  1126.     return result;
  1127. }
  1128.  
  1129. ///////////////////////////////////////////////////////////////////////////
  1130.  
  1131. typedef VDStringA                VDString;
  1132.  
  1133.  
  1134. #endif
  1135.