Advertisement
Guest User

Untitled

a guest
Sep 2nd, 2019
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.26 KB | None | 0 0
  1. #include <wchar.h>
  2. #include <string.h>
  3. #include <stdarg.h>
  4.  
  5.  
  6.  
  7. struct putchdata {
  8.     wchar_t *buffer;
  9.     size_t maxlen, count;
  10. };
  11.  
  12. static void reverse(char *str, size_t len) {
  13.     if (len > 1) {
  14.         char *start = str;
  15.         char *end = str + len - 1;
  16.         char tmp;
  17.  
  18.         while (start < end) {
  19.             tmp = *end;
  20.             *end-- = *start;
  21.             *start++ = tmp;
  22.         }
  23.     }
  24. }
  25.  
  26. static size_t itoa(unsigned num, char *dst, unsigned base, int issigned, int addplus, int uppercase) {
  27.     int a = uppercase ? 'A' : 'a';
  28.     int negative = 0;
  29.     char *d = dst;
  30.     size_t len;
  31.  
  32.     if (num == 0) {
  33.         *d = '0';
  34.         return 1;
  35.     }
  36.  
  37.     if (issigned && (int)num < 0 && base == 10) {
  38.         negative = 1;
  39.         num = -num;
  40.     }
  41.  
  42.     while (num > 0) {
  43.         unsigned rem = num % base;
  44.         num /= base;
  45.         *d++ = (rem > 9) ? (rem - 10 + a) : (rem + '0');
  46.     }
  47.  
  48.     if (negative)
  49.         *d++ = '-';
  50.     else if (addplus)
  51.         *d++ = '+';
  52.  
  53.     len = d - dst;
  54.     reverse(dst, len);
  55.  
  56.     return len;
  57. }
  58.  
  59. static size_t lltoa(unsigned long long num, char *dst, unsigned base, int issigned, int addplus, int uppercase) {
  60.     int a = uppercase ? 'A' : 'a';
  61.     int negative = 0;
  62.     char *d = dst;
  63.     size_t len;
  64.  
  65.     if (num == 0) {
  66.         *d = '0';
  67.         return 1;
  68.     }
  69.  
  70.     if (issigned && (signed long long)num < 0 && base == 10) {
  71.         negative = 1;
  72.         num = -num;
  73.     }
  74.  
  75.     while (num > 0) {
  76.         unsigned rem = num % base;
  77.         num /= base;
  78.         *d++ = (rem > 9) ? (rem - 10 + a) : (rem + '0');
  79.     }
  80.  
  81.     if (negative)
  82.         *d++ = '-';
  83.     else if (addplus)
  84.         *d++ = '+';
  85.  
  86.     len = d - dst;
  87.     reverse(dst, len);
  88.  
  89.     return len;
  90. }
  91.  
  92. static void putchproc(wchar_t ch, struct putchdata *pcd) {
  93.     size_t index = pcd->count;
  94.  
  95.     if (ch != '\0')
  96.         pcd->count++;
  97.  
  98.     if (pcd->count > pcd->maxlen)
  99.         return;
  100.  
  101.     if (pcd->count == pcd->maxlen) {
  102.         pcd->buffer[index] =  '\0';
  103.         return;
  104.     }
  105.  
  106.     pcd->buffer[index] = ch;
  107. }
  108.  
  109. #define PUTCH(ch) putchproc((ch), &pcd)
  110.  
  111. int vswprintf(wchar_t *buffer, size_t maxlen, const wchar_t *fmt, va_list ap) {
  112.     struct putchdata pcd;
  113.     wchar_t ch;
  114.     const wchar_t *src;
  115.     char tmp[128];
  116.     const char *hsrc;
  117.  
  118.     pcd.buffer = buffer;
  119.     pcd.maxlen = maxlen;
  120.     pcd.count = 0;
  121.  
  122.     while ((ch = *fmt++) != '\0') {
  123.         if (ch == '%') {
  124.             int left = 0;
  125.             int addplus = 0;
  126.             int alternate = 0;
  127.             int padzeros = 0;
  128.             size_t width = 0;
  129.             size_t limit = 0;
  130.             int longlong = 0;
  131.             int half = 0;
  132.             size_t len, i;
  133.             int uppercase;
  134.             void *ptr;
  135.             const wchar_t *start = fmt;
  136.  
  137.             if ((ch = *fmt++) == '\0')
  138.                 goto out;
  139.  
  140.             for (;;) {
  141.                 if (ch == '-')
  142.                     left = 1;
  143.                 else if (ch == '+')
  144.                     addplus = 1;
  145.                 else if (ch == '#')
  146.                     alternate = 1;
  147.                 else if (ch == '0')
  148.                     padzeros = 1;
  149.                 else
  150.                     break;
  151.  
  152.                 if ((ch = *fmt++) == '\0')
  153.                     goto out;
  154.             }
  155.  
  156.             while (ch >= '0' && ch <= '9') {
  157.                 width = 10 * width + (ch - '0');
  158.  
  159.                 if ((ch = *fmt++) == '\0')
  160.                     goto out;
  161.             }
  162.  
  163.             if (ch == '.') {
  164.                 if ((ch = *fmt++) == '\0')
  165.                     goto out;
  166.  
  167.                 if (ch == '*') {
  168.                     limit = va_arg(ap, size_t);
  169.  
  170.                     if ((ch = *fmt++) == '\0')
  171.                         goto out;
  172.                 } else {
  173.                     while (ch >= '0' && ch <= '9') {
  174.                         limit = 10 * limit + (ch - '0');
  175.  
  176.                         if ((ch = *fmt++) == '\0')
  177.                             goto out;
  178.                     }
  179.                 }
  180.             }
  181.  
  182.             if (ch == 'L') {
  183.                 longlong = 1;
  184.  
  185.                 if ((ch = *fmt++) == '\0')
  186.                     goto out;
  187.             } else if (ch == 'l') {
  188.                 if ((ch = *fmt++) == '\0')
  189.                     goto out;
  190.  
  191.                 if (ch == 'l') {
  192.                     longlong = 1;
  193.  
  194.                     if ((ch = *fmt++) == '\0')
  195.                         goto out;
  196.                 }
  197.             } else if (ch == 'h') {
  198.                 half = 1;
  199.  
  200.                 if ((ch = *fmt++) == '\0')
  201.                     goto out;
  202.             }
  203.  
  204.             switch (ch) {
  205.                 default:
  206.                     fmt = start;
  207.                     /* Fall through */
  208.                 case '%':
  209.                     PUTCH('%');
  210.                     break;
  211.                 case 'C':
  212.                 case 'c':
  213.                     PUTCH(va_arg(ap, wchar_t));
  214.                     break;
  215.                 case 'D':
  216.                 case 'd':
  217.                     uppercase = (ch == 'D');
  218.                     if (longlong)
  219.                         len = lltoa(va_arg(ap, long long), tmp, 10, 1, addplus, uppercase);
  220.                     else
  221.                         len = itoa(va_arg(ap, int), tmp, 10, 1, addplus, uppercase);
  222.  
  223.                     hsrc = tmp;
  224.  
  225.                     if (width > len)
  226.                         width -= len;
  227.                     else
  228.                         width = 0;
  229.  
  230.                     if (left == 0) {
  231.                         for (i = 0; i < width; i++) PUTCH(padzeros ? '0' : ' ');
  232.                     }
  233.  
  234.                     for (i = 0; i < len; i++) PUTCH(hsrc[i]);
  235.  
  236.                     if (left != 0) {
  237.                         for (i = 0; i < width; i++) PUTCH(' ');
  238.                     }
  239.                     break;
  240.                    
  241.                 case 'U':
  242.                 case 'u':
  243.                     uppercase = (ch == 'U');
  244.                     if (longlong)
  245.                         len = lltoa(va_arg(ap, unsigned long long), tmp, 10, 0, addplus, uppercase);
  246.                     else
  247.                         len = itoa(va_arg(ap, unsigned int), tmp, 10, 0, addplus, uppercase);
  248.  
  249.                     hsrc = tmp;
  250.  
  251.                     if (width > len)
  252.                         width -= len;
  253.                     else
  254.                         width = 0;
  255.  
  256.                     if (left == 0) {
  257.                         for (i = 0; i < width; i++) PUTCH(padzeros ? '0' : ' ');
  258.                     }
  259.  
  260.                     for (i = 0; i < len; i++) PUTCH(hsrc[i]);
  261.  
  262.                     if (left != 0) {
  263.                         for (i = 0; i < width; i++) PUTCH(' ');
  264.                     }
  265.                     break;
  266.                 case 'X':
  267.                 case 'x':
  268.                     uppercase = (ch == 'X');
  269.                     if (longlong)
  270.                         len = lltoa(va_arg(ap, unsigned long long), tmp, 16, 0, addplus, uppercase);
  271.                     else
  272.                         len = itoa(va_arg(ap, unsigned int), tmp, 16, 0, addplus, uppercase);
  273.  
  274.                     hsrc = tmp;
  275.  
  276.                     if (width > len)
  277.                         width -= len;
  278.                     else
  279.                         width = 0;
  280.  
  281.                     if (left == 0) {
  282.                         for (i = 0; i < width; i++) PUTCH(padzeros ? '0' : ' ');
  283.                     }
  284.  
  285.                     for (i = 0; i < len; i++) PUTCH(hsrc[i]);
  286.  
  287.                     if (left != 0) {
  288.                         for (i = 0; i < width; i++) PUTCH(' ');
  289.                     }
  290.                     break;
  291.                 case 'P':
  292.                 case 'p':
  293.                     uppercase = (ch == 'P');
  294.                     ptr = va_arg(ap, void *);
  295.                     len = itoa((unsigned)ptr, tmp, 16, 0, 0, uppercase);
  296.  
  297.                     hsrc = tmp;
  298.                     width = 8;
  299.  
  300.                     if (width > len)
  301.                         width -= len;
  302.                     else
  303.                         width = 0;
  304.  
  305.                     if (alternate && ptr != NULL) {
  306.                         PUTCH('0');
  307.                         PUTCH('x');
  308.                     }
  309.  
  310.                     for (i = 0; i < width; i++) PUTCH('0');
  311.  
  312.                     for (i = 0; i < len; i++) PUTCH(hsrc[i]);
  313.                     break;
  314.                    
  315.                 case 'F':
  316.                 case 'f':
  317.                     uppercase = (ch == 'D');
  318.                     len = ftoa  /*???*/
  319.                
  320.                    
  321.  
  322.  
  323.                 case 'S':
  324.                 case 's':
  325.                     if (half) {
  326.                         hsrc = va_arg(ap, const char *);
  327.                         if (hsrc == NULL)
  328.                             hsrc = "(null)";
  329.  
  330.                         len = strlen(hsrc);
  331.  
  332.                         if (limit > 0 && len > limit)
  333.                             len = limit;
  334.  
  335.                         if (width > len)
  336.                             width -= len;
  337.                         else
  338.                             width = 0;
  339.  
  340.                         if (left == 0) {
  341.                             for (i = 0; i < width; i++) PUTCH(' ');
  342.                         }
  343.  
  344.                         for (i = 0; i < len; i++) PUTCH(hsrc[i]);
  345.  
  346.                         if (left != 0) {
  347.                             for (i = 0; i < width; i++) PUTCH(' ');
  348.                         }
  349.                     } else {
  350.                         src = va_arg(ap, const wchar_t *);
  351.                         if (src == NULL)
  352.                             src = L"(null)";
  353.  
  354.                         len = wcslen(src);
  355.  
  356.                         if (limit > 0 && len > limit)
  357.                             len = limit;
  358.  
  359.                         if (width > len)
  360.                             width -= len;
  361.                         else
  362.                             width = 0;
  363.  
  364.                         if (left == 0) {
  365.                             for (i = 0; i < width; i++) PUTCH(' ');
  366.                         }
  367.  
  368.                         for (i = 0; i < len; i++) PUTCH(src[i]);
  369.  
  370.                         if (left != 0) {
  371.                             for (i = 0; i < width; i++) PUTCH(' ');
  372.                         }
  373.                     }
  374.                     break;
  375.             }
  376.         } else {
  377.             PUTCH(ch);
  378.         }
  379.     }
  380.  
  381. out:
  382.  
  383.     PUTCH('\0');
  384.  
  385.     return pcd.count;
  386. }
  387.  
  388. int swprintf(wchar_t *buffer, size_t maxlen, const wchar_t *fmt, ...) {
  389.     va_list ap;
  390.     int wc;
  391.  
  392.     va_start(ap, fmt);
  393.     wc = vswprintf(buffer, maxlen, fmt, ap);
  394.     va_end(ap);
  395.  
  396.     return wc;
  397. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement