home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / text.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  15.3 KB  |  653 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. #include "stdafx.h"
  27. #include <vector>
  28. #include <algorithm>
  29.  
  30. #include <stdarg.h>
  31. #include <stdio.h>
  32.  
  33. #include <windows.h>
  34.  
  35. #include <vd2/system/vdtypes.h>
  36. #include <vd2/system/vdstl.h>
  37. #include <vd2/system/text.h>
  38. #include <vd2/system/tls.h>
  39. #include <vd2/system/VDString.h>
  40.  
  41. int VDTextWToA(char *dst, int max_dst, const wchar_t *src, int max_src) {
  42.     VDASSERTPTR(dst);
  43.     VDASSERTPTR(src);
  44.     VDASSERT(max_dst>0);
  45.  
  46.     *dst = 0;
  47.  
  48.     int len = WideCharToMultiByte(CP_ACP, 0, src, max_src, dst, max_dst, NULL, NULL);
  49.  
  50.     // remove null terminator if source was null-terminated (source
  51.     // length was provided)
  52.     return max_src<0 && len>0 ? len-1 : len;
  53. }
  54.  
  55. int VDTextAToW(wchar_t *dst, int max_dst, const char *src, int max_src) {
  56.     VDASSERTPTR(dst);
  57.     VDASSERTPTR(src);
  58.     VDASSERT(max_dst>0);
  59.  
  60.     *dst = 0;
  61.  
  62.     int len = MultiByteToWideChar(CP_ACP, 0, src, max_src, dst, max_dst);
  63.  
  64.     // remove null terminator if source was null-terminated (source
  65.     // length was provided)
  66.     return max_src<0 && len>0 ? len-1 : len;
  67. }
  68.  
  69. VDStringA VDTextWToA(const VDStringW& sw) {
  70.     return VDTextWToA(sw.data(), sw.length());
  71. }
  72.  
  73. VDStringA VDTextWToA(const wchar_t *src, int srclen) {
  74.     VDStringA s;
  75.  
  76.     if (src) {
  77.         int l = VDTextWToALength(src, srclen);
  78.  
  79.         if (l) {
  80.             s.resize(l);
  81.             VDTextWToA((char *)s.data(), l+1, src, srclen);
  82.         }
  83.     }
  84.  
  85.     return s;
  86. }
  87.  
  88. VDStringW VDTextAToW(const VDStringA& s) {
  89.     return VDTextAToW(s.data(), s.length());
  90. }
  91.  
  92. VDStringW VDTextAToW(const char *src, int srclen) {
  93.     VDStringW sw;
  94.  
  95.     if (src) {
  96.         int l = VDTextAToWLength(src, srclen);
  97.  
  98.         if (l) {
  99.             sw.resize(l);
  100.             VDTextAToW(&sw[0], sw.length()+1, src, srclen);
  101.         }
  102.     }
  103.  
  104.     return sw;
  105. }
  106.  
  107. int VDTextWToALength(const wchar_t *s, int length) {
  108.     SetLastError(0);
  109.     int rv = WideCharToMultiByte(CP_ACP, 0, s, length, NULL, 0, NULL, 0);
  110.  
  111.     if (length < 0 && rv>0)
  112.         --rv;
  113.  
  114.     return rv;
  115. }
  116.  
  117. int VDTextAToWLength(const char *s, int length) {
  118.     SetLastError(0);
  119.     int rv = MultiByteToWideChar(CP_ACP, 0, s, length, NULL, 0);
  120.  
  121.     if (length < 0 && rv > 0)
  122.         --rv;
  123.  
  124.     return rv;
  125. }
  126.  
  127. namespace {
  128.     // UTF8:
  129.     //      000000000xxxxxxx -> 0xxxxxxx
  130.     //      00000yyyyyxxxxxx -> 110yyyyy 10xxxxxx
  131.     //      zzzzyyyyyyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx
  132.     // uuuuuzzzzyyyyyyxxxxxx -> 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
  133.     //               (UTF16) -> 110110wwwwzzzzyy (uuuuu = wwww+1)
  134.     //                          110111yyyyxxxxxx
  135.     int VDGetCharLengthInUTF8(wchar_t c) {
  136.         if (c < 0x0080)            // 7 bits
  137.             return 1;
  138.         else if (c < 0x0800)    // 11 bits
  139.             return 2;
  140.         else if (c < 0x10000)    // 16 bits
  141.             return 3;
  142.         else if (c < 0x200000)    // 21 bits
  143.             return 4;
  144.         else {
  145.             VDASSERT(false);
  146.             return 1;            // Uh oh.  Well, we're screwed.
  147.         }
  148.     }
  149.  
  150.     bool VDIsUnicodeSurrogateFirst(wchar_t c) {
  151.         return (c >= 0xD800 && c < 0xDC00); 
  152.     }
  153.  
  154.     bool VDIsUnicodeSurrogateSecond(wchar_t c) {
  155.         return (c >= 0xDC00 && c < 0xE000);
  156.     }
  157. };
  158.  
  159. VDStringA VDTextWToU8(const VDStringW& s) {
  160.     return VDTextWToU8(s.data(), s.length());
  161. }
  162.  
  163. VDStringA VDTextWToU8(const wchar_t *s, int length) {
  164.     vdfastvector<char> temp;
  165.  
  166.     if (length<0) {
  167.         const wchar_t *t = s;
  168.         do {
  169.             ++length;
  170.         } while(*t++);
  171.     }
  172.  
  173.     while(length--) {
  174.         uint32 c = *s++;
  175.  
  176.         if (VDIsUnicodeSurrogateFirst(c)) {
  177.             if (!length || !VDIsUnicodeSurrogateSecond(*s)) {
  178.                 VDASSERT(false);
  179.                 c = '?';
  180.             } else {
  181.                 c = 0x10000 + ((c & 0x3ff)<<10) + (*s++ & 0x3ff);
  182.                 --length;
  183.             }
  184.         }
  185.  
  186.         if (c < 0x0080) {
  187.             temp.push_back((char)c);
  188.         } else {
  189.             if (c < 0x0800)
  190.                 temp.push_back((char)(0xc0 + (c>>6)));
  191.             else {
  192.                 if (c < 0x10000)
  193.                     temp.push_back((char)(0xe0 + (c>>12)));
  194.                 else {
  195.                     temp.push_back((char)(0xf0 + ((c>>18) & 0x07)));
  196.                     temp.push_back((char)(0x80 + ((c>>12) & 0x3f)));
  197.                 }
  198.                 temp.push_back((char)(0x80 + ((c>>6) & 0x3f)));
  199.             }
  200.             temp.push_back((char)(0x80 + (c & 0x3f)));
  201.         }
  202.     }
  203.  
  204.     VDStringA a(temp.data(), temp.size());
  205.  
  206.     return a;
  207. }
  208.  
  209. VDStringW VDTextU8ToW(const VDStringA& s) {
  210.     return VDTextU8ToW(s.data(), s.length());
  211. }
  212.  
  213. VDStringW VDTextU8ToW(const char *s, int length) {
  214.     vdfastvector<wchar_t> temp;
  215.  
  216.     if (length<0) {
  217.         const char *t = s;
  218.         VDASSERT(length == -1);
  219.         do {
  220.             ++length;
  221.         } while(*t++);
  222.     }
  223.  
  224.     while(length--) {
  225.         unsigned char c = (char)*s++;
  226.         uint32    wc = c;            // we reconstruct UTF-32 first and then split to UTF-16 if necessary
  227.  
  228.         if (c >= 0x80) {
  229.             int required_extra = 0;
  230.  
  231.             if (c < 0xc0 || c >= 0xf7) {
  232.                 VDASSERT(false);
  233.                 break;
  234.             }
  235.  
  236.             while(c >= 0xc0) {
  237.                 c <<= 1;
  238.                 ++required_extra;
  239.             }
  240.  
  241.             wc = (c&0x3f) >> required_extra;
  242.  
  243.             do {
  244.                 char d;
  245.  
  246.                 if (!length-- || (((d=*s++)&0xc0)!=0x80))
  247.                     goto bad_sequence_exit;
  248.  
  249.                 wc = (wc<<6) + (d&0x3f);
  250.             } while(--required_extra);
  251.         }
  252.  
  253.         // Two cases here.  If we are using UTF-16, surrogates need to be split in half.  If we are using
  254.         // UTF-32, surrogates need to be combined.
  255.  
  256.         if (sizeof(wchar_t) > 2) {
  257.             if (VDIsUnicodeSurrogateSecond(wc)) {
  258.                 if (temp.empty() || !VDIsUnicodeSurrogateFirst(temp.back())) {
  259.                     VDASSERT(false);
  260.                     break;
  261.                 }
  262.  
  263.                 temp.back() = 0x10000 + ((temp.back()&0x3ff) << 10) + (wc & 0x3ff);
  264.                 continue;
  265.             }
  266.         } else {
  267.             if (wc >= 0x10000) {
  268.                 wc -= 0x10000;
  269.                 temp.push_back(0xD800 + ((wc & 0x3ff) >> 10));
  270.                 wc = 0xDC00 + (wc&0x3ff);
  271.             }
  272.         }
  273.         temp.push_back(wc);
  274.     }
  275. bad_sequence_exit:
  276.  
  277.     VDStringW w(temp.data(), temp.size());
  278.  
  279.     return w;
  280. }
  281.  
  282. ///////////////////////////////////////////////////////////////////////////
  283. //
  284. //    VirtualDub's very own printf() functions.
  285. //
  286. //    VD[v|a]swprintf() differs from wsprintf() in the following ways:
  287. //
  288. //    * The output is a string.
  289. //    * All parameters must be passed by pointer instead of by value.
  290. //    * The 'll' modifier permits long long / __int64 integers.
  291. //    * [n] allows picking parameters out of order.
  292. //    * %lc/%ls forces Unicode; %hc/%hs forces ANSI.
  293.  
  294. VDStringW VDaswprintf(const wchar_t *format, int args, const void *const *argv) {
  295.     const void *const *argv0 = argv;
  296.     vdfastfixedvector<wchar_t, 256> out;
  297.     wchar_t c;
  298.  
  299.     VDStringW tempConv;
  300.  
  301.     while(c = *format) {
  302.         if (c != L'%') {
  303.             const wchar_t *s = format;
  304.  
  305.             while(*s && *s != L'%')
  306.                 ++s;
  307.  
  308.             int len = s - format;
  309.             int clen = out.size();
  310.  
  311.             out.resize(clen + len);
  312.  
  313.             std::copy(format, s, &out[clen]);
  314.  
  315.             format = s;
  316.         } else {
  317.             ++format;
  318.  
  319.             // check for %%
  320.  
  321.             if (*format == L'%') {
  322.                 ++format;
  323.                 out.push_back(L'%');
  324.                 continue;
  325.             }
  326.  
  327.             // Check for a renumbering identifier.
  328.  
  329.             if (*format == L'[') {
  330.                 ++format;
  331.  
  332.                 int newid = wcstol(format, const_cast<wchar_t **>(&format), 0);
  333.  
  334.                 VDASSERT(newid >= 0 && newid < args);
  335.  
  336.                 argv = argv0 + newid;
  337.  
  338.                 VDVERIFY(*format++ == L']');
  339.             }
  340.  
  341.             // process flags
  342.  
  343.             struct {
  344.                 bool bLeftAlign:1,        // pad right with spaces (priority over zero pad)
  345.                     bZeroPad:1,            // pad left with zeroes
  346.                     bPositiveSign:1,    // prefix with + or -; priority over bPositiveBlank
  347.                     bPositiveBlank:1,    // prefix with space for nonnegative
  348.                     bPrefix:1;            // prefix with 0, 0x, 0X, or force decimal point
  349.             } flags={false};
  350.             int width = 0;
  351.             int precision = -1;
  352.  
  353.             for(;;) {
  354.                 c = *format;
  355.  
  356.                 if (c == L'0')
  357.                     flags.bZeroPad = true;
  358.                 else if (c == L' ')
  359.                     flags.bPositiveBlank = true;
  360.                 else if (c == L'#')
  361.                     flags.bPrefix = true;
  362.                 else if (c == L'-')
  363.                     flags.bLeftAlign = true;
  364.                 else if (c == L'+')
  365.                     flags.bPositiveSign = true;
  366.                 else
  367.                     break;
  368.  
  369.                 ++format;
  370.             }
  371.  
  372.             // process width
  373.  
  374.             c = *format;
  375.             if (c == L'*') {
  376.                 ++format;
  377.                 width = *(int *)*argv++;
  378.             } else if (iswdigit(c))
  379.                 width = (int)wcstol(format, const_cast<wchar_t **>(&format), 0);
  380.  
  381.             // process precision
  382.  
  383.             if (*format == L'.') {
  384.                 c = *++format;
  385.  
  386.                 if (c == L'*') {
  387.                     ++format;
  388.                     precision = *(int *)*argv++;
  389.                 } else if (iswdigit(c))
  390.                     precision = (int)wcstol(format, const_cast<wchar_t **>(&format), 0);
  391.             }
  392.  
  393.             // process flags
  394.  
  395.             enum { kDefault, kLong, kLongLong, kShort } size = kDefault;
  396.  
  397.             c = *format;
  398.  
  399.             if (c == L'l') {
  400.                 ++format;
  401.                 size = kLong;
  402.  
  403.                 if (*format == L'l') {
  404.                     ++format;
  405.                     size = kLongLong;
  406.                 }
  407.  
  408.             } else if (c == L'h') {
  409.                 ++format;
  410.                 size = kShort;
  411.             }
  412.  
  413.             // process format character
  414.  
  415.             wchar_t xf[32], buf[32], *pxf = xf, *pbuf0 = buf, *pbuf = buf;
  416.             int zero_pad = 0;
  417.  
  418.             switch(*format++) {
  419.             case L'd':
  420.             case L'i':
  421.             case L'o':
  422.             case L'u':
  423.             case L'x':
  424.             case L'X':
  425.                 *pxf++ = '%';
  426.                 if (flags.bPrefix)
  427.                     *pxf++ = '#';
  428.                 if (flags.bPositiveBlank)
  429.                     *pxf++ = ' ';
  430.                 if (flags.bPositiveSign)
  431.                     *pxf++ = '+';
  432.  
  433.                 switch(size) {
  434.                 case kShort:
  435.                     *pxf++ = 'h';
  436.                     *pxf++ = format[-1];
  437.                     *pxf = 0;
  438.                     pbuf += swprintf(pbuf, sizeof buf / sizeof buf[0], xf, *(const short *)*argv++);
  439.                     break;
  440.                 case kDefault:
  441.                     *pxf++ = format[-1];
  442.                     *pxf = 0;
  443.                     pbuf += swprintf(pbuf, sizeof buf / sizeof buf[0], xf, *(const int *)*argv++);
  444.                     break;
  445.                 case kLong:
  446.                     *pxf++ = 'l';
  447.                     *pxf++ = format[-1];
  448.                     *pxf = 0;
  449.                     pbuf += swprintf(pbuf, sizeof buf / sizeof buf[0], xf, *(const long *)*argv++);
  450.                     break;
  451.                 case kLongLong:
  452. #if defined(_MSC_VER)
  453.                     *pxf++ = 'I';
  454.                     *pxf++ = '6';
  455.                     *pxf++ = '4';
  456. #elif defined(__GNUC__)
  457.                     *pxf++ = 'l';
  458.                     *pxf++ = 'l';
  459. #else
  460. #error Please insert the appropriate 64-bit printf format for your platform.
  461. #endif
  462.                     *pxf++ = format[-1];
  463.                     *pxf = 0;
  464.                     pbuf += swprintf(pbuf, sizeof buf / sizeof buf[0], xf, *(const int64 *)*argv++);
  465.                     break;
  466.                 default:
  467.                     VDNEVERHERE;
  468.                 }
  469.  
  470.                 if (pbuf - pbuf0 < precision)
  471.                     zero_pad = precision - (pbuf - pbuf0);
  472.  
  473.                 break;
  474.  
  475.             case L'c':
  476.                 if (size == kShort) {
  477.                     char buf[2] = {*(const char *)*argv++, 0};
  478.                     pbuf += VDTextAToW(pbuf, 4, buf);
  479.                 } else
  480.                     *pbuf++ = *(const wchar_t *)*argv++;
  481.                 break;
  482.  
  483.             case L's':
  484.                 if (size == kShort) {
  485.                     const char *s = *(const char *const *)*argv++;
  486.                     int maxsrc = strlen(s);
  487.  
  488.                     if (precision >= 0 && precision < maxsrc)
  489.                         maxsrc = precision;
  490.  
  491.                     tempConv = VDTextAToW(s, maxsrc);
  492.                     pbuf0 = const_cast<wchar_t *>(tempConv.c_str());
  493.  
  494.                     pbuf = pbuf0 + tempConv.size();
  495.                 } else {
  496.                     pbuf = pbuf0 = *(wchar_t *const *)*argv++;
  497.  
  498.                     while(*pbuf && precision) {
  499.                         ++pbuf;
  500.                         --precision;
  501.                     }
  502.                 }
  503.                 break;
  504.  
  505.             case L'e':
  506.             case L'E':
  507.             case L'f':
  508.             case L'F':
  509.             case L'g':
  510.             case L'G':
  511.                 // We place an artificial limit of 256 characters on the precision value.
  512.                 {
  513.                     if (precision > 256)
  514.                         precision = 256;
  515.  
  516.                     tempConv.resize(256);
  517.                     pbuf0 = pbuf = const_cast<wchar_t *>(tempConv.data());
  518.  
  519.                     *pxf++ = '%';
  520.                     if (flags.bPrefix)
  521.                         *pxf++ = '#';
  522.                     if (flags.bPositiveBlank)
  523.                         *pxf++ = ' ';
  524.                     if (flags.bPositiveSign)
  525.                         *pxf++ = '+';
  526.                     if (precision>=0) {
  527.                         *pxf++ = '.';
  528.                         *pxf++ = '*';
  529.                     }
  530.                     *pxf++ = format[-1];
  531.                     *pxf = 0;
  532.  
  533.                     if (precision >= 0)
  534.                         pbuf += swprintf(pbuf, 256, xf, precision, *(const double *)*argv++);
  535.                     else
  536.                         pbuf += swprintf(pbuf, 256, xf, *(const double *)*argv++);
  537.                 }
  538.                 break;
  539.  
  540.             case L'n':    // no flags honored; precision ignored
  541.                 *(int *)(*argv++) = out.size();
  542.                 continue;
  543.             case L'p':    // no flags honored; precision ignored
  544.                 pbuf += swprintf(pbuf, sizeof buf / sizeof buf[0], L"%p", *(void *const *)*argv++);
  545.                 break;
  546.  
  547.             case L'z':
  548.                 switch(*format++) {
  549.                 case L's':
  550.                     {
  551.                         int64 value;
  552.  
  553.                         switch(size) {
  554.                         case kShort:    value = *(const short *)*argv++;    break;
  555.                         case kDefault:    value = *(const int *)*argv++;        break;
  556.                         case kLong:        value = *(const long *)*argv++;        break;
  557.                         case kLongLong:    value = *(const int64 *)*argv++;    break;
  558.                             break;
  559.                         default:
  560.                             VDNEVERHERE;
  561.                         }
  562.  
  563.                         if (value < 0)
  564.                             *pbuf++ = L'-';
  565.                         else if (flags.bPositiveSign)
  566.                             *pbuf++ = L'+';
  567.                         else if (flags.bPositiveBlank)
  568.                             *pbuf++ = L' ';
  569.  
  570.                         if (value < (VD64(10) << 10))
  571.                             pbuf += swprintf(pbuf, (buf + sizeof(buf) / sizeof(buf[0])) - pbuf, L"%d bytes", (int)value);
  572.                         else if (value < (VD64(10) << 20))
  573.                             pbuf += swprintf(pbuf, (buf + sizeof(buf) / sizeof(buf[0])) - pbuf, L"%d KB", (int)((sint32)value >> 10));
  574.                         else if (value < (VD64(10) << 30))
  575.                             pbuf += swprintf(pbuf, (buf + sizeof(buf) / sizeof(buf[0])) - pbuf, L"%d MB", (int)((sint32)value >> 20));
  576.                         else if (value < (VD64(10) << 40))
  577.                             pbuf += swprintf(pbuf, (buf + sizeof(buf) / sizeof(buf[0])) - pbuf, L"%d GB", (int)(value >> 30));
  578.                         else
  579.                             pbuf += swprintf(pbuf, (buf + sizeof(buf) / sizeof(buf[0])) - pbuf, L"%d TB", (int)(value >> 40));
  580.                     }
  581.  
  582.                     break;
  583.                 }
  584.                 break;
  585.  
  586.             }
  587.  
  588.             int string_width = (pbuf - pbuf0) + zero_pad;
  589.             int string_delta = width - string_width;
  590.  
  591.             if (!flags.bLeftAlign && string_delta > 0) {
  592.                 int siz = out.size();
  593.                 out.resize(siz + string_delta, flags.bZeroPad ? L'0' : L' ');
  594.             }
  595.  
  596.             if (zero_pad) {
  597.                 int siz = out.size();
  598.                 out.resize(siz + zero_pad);
  599.                 std::fill(&out[siz], &out[siz+zero_pad], L'0');
  600.             }
  601.  
  602.             if (pbuf != pbuf0) {
  603.                 int siz = out.size();
  604.                 out.resize(siz + (pbuf - pbuf0));
  605.  
  606.                 std::copy(pbuf0, pbuf, &out[siz]);
  607.             }
  608.  
  609.             if (flags.bLeftAlign && string_delta > 0) {
  610.                 int siz = out.size();
  611.                 out.resize(siz + string_delta);
  612.                 std::fill(&out[siz], &out[siz+string_delta], L' ');
  613.             }
  614.         }
  615.     }
  616.  
  617.     out.push_back(0);
  618.  
  619.     return VDStringW(out.data());
  620. }
  621.  
  622. VDStringW VDvswprintf(const wchar_t *format, int args, va_list val) {
  623.     if (args < 16) {
  624.         const void *argv[16];
  625.  
  626.         for(int i=0; i<args; ++i)
  627.             argv[i] = va_arg(val, const void *);
  628.  
  629.         va_end(val);
  630.  
  631.         return VDaswprintf(format, args, argv);
  632.     } else {
  633.         vdblock<const void *> argv(args);
  634.  
  635.         for(int i=0; i<args; ++i)
  636.             argv[i] = va_arg(val, const void *);
  637.  
  638.         va_end(val);
  639.  
  640.         return VDaswprintf(format, args, argv.data());
  641.     }
  642. }
  643.  
  644. VDStringW VDswprintf(const wchar_t *format, int args, ...) {
  645.     va_list val;
  646.  
  647.     va_start(val, args);
  648.     VDStringW r = VDvswprintf(format, args, val);
  649.     va_end(val);
  650.  
  651.     return r;
  652. }
  653.