my_vsnprintf.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:5k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <my_global.h>
  14. #include <m_string.h>
  15. #include <stdarg.h>
  16. #include <m_ctype.h>
  17. /*
  18.   Limited snprintf() implementations
  19.   IMPLEMENTION:
  20.     Supports following formats:
  21.     %#[l]d
  22.     %#[l]u
  23.     %#[l]x
  24.     %#.#s Note first # is ignored
  25.     
  26.   RETURN
  27.     length of result string
  28. */
  29. int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
  30. {
  31.   char *start=to, *end=to+n-1;
  32.   uint length, width, pre_zero, have_long;
  33.   for (; *fmt ; fmt++)
  34.   {
  35.     if (fmt[0] != '%')
  36.     {
  37.       if (to == end) /* End of buffer */
  38. break;
  39.       *to++= *fmt; /* Copy ordinary char */
  40.       continue;
  41.     }
  42.     fmt++; /* skip '%' */
  43.     /* Read max fill size (only used with %d and %u) */
  44.     if (*fmt == '-')
  45.       fmt++;
  46.     length= width= pre_zero= have_long= 0;
  47.     for (;my_isdigit(&my_charset_latin1,*fmt); fmt++)
  48.     {
  49.       length=length*10+ (uint) (*fmt-'0');
  50.       if (!length)
  51.         pre_zero= 1; /* first digit was 0 */
  52.     }
  53.     if (*fmt == '.')
  54.       for (fmt++;my_isdigit(&my_charset_latin1,*fmt); fmt++)
  55.         width=width*10+ (uint) (*fmt-'0');
  56.     else
  57.       width= ~0;
  58.     if (*fmt == 'l')
  59.     {
  60.       fmt++;
  61.       have_long= 1;
  62.     }
  63.     if (*fmt == 's') /* String parameter */
  64.     {
  65.       reg2 char *par = va_arg(ap, char *);
  66.       uint plen,left_len = (uint)(end-to)+1;
  67.       if (!par) par = (char*)"(null)";
  68.       plen = (uint) strlen(par);
  69.       set_if_smaller(plen,width);
  70.       if (left_len <= plen)
  71. plen = left_len - 1;
  72.       to=strnmov(to,par,plen);
  73.       continue;
  74.     }
  75.     else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x') /* Integer parameter */
  76.     {
  77.       register long larg;
  78.       uint res_length, to_length;
  79.       char *store_start= to, *store_end;
  80.       char buff[32];
  81.       if ((to_length= (uint) (end-to)) < 16 || length)
  82. store_start= buff;
  83.       if (have_long)
  84.         larg = va_arg(ap, long);
  85.       else
  86.         if (*fmt == 'd')
  87.           larg = va_arg(ap, int);
  88.         else
  89.           larg= (long) (uint) va_arg(ap, int);
  90.       if (*fmt == 'd')
  91. store_end= int10_to_str(larg, store_start, -10);
  92.       else
  93.         if (*fmt== 'u')
  94.           store_end= int10_to_str(larg, store_start, 10);
  95.         else
  96.           store_end= int2str(larg, store_start, 16, 0);
  97.       if ((res_length= (uint) (store_end - store_start)) > to_length)
  98. break; /* num doesn't fit in output */
  99.       /* If %#d syntax was used, we have to pre-zero/pre-space the string */
  100.       if (store_start == buff)
  101.       {
  102. length= min(length, to_length);
  103. if (res_length < length)
  104. {
  105.   uint diff= (length- res_length);
  106.   bfill(to, diff, pre_zero ? '0' : ' ');
  107.   to+= diff;
  108. }
  109. bmove(to, store_start, res_length);
  110.       }
  111.       to+= res_length;
  112.       continue;
  113.     }
  114.     /* We come here on '%%', unknown code or too long parameter */
  115.     if (to == end)
  116.       break;
  117.     *to++='%'; /* % used as % or unknown code */
  118.   }
  119.   DBUG_ASSERT(to <= end);
  120.   *to=''; /* End of errmessage */
  121.   return (uint) (to - start);
  122. }
  123. int my_snprintf(char* to, size_t n, const char* fmt, ...)
  124. {
  125.   int result;
  126.   va_list args;
  127.   va_start(args,fmt);
  128.   result= my_vsnprintf(to, n, fmt, args);
  129.   va_end(args);
  130.   return result;
  131. }
  132. #ifdef MAIN
  133. #define OVERRUN_SENTRY  250
  134. static void my_printf(const char * fmt, ...)
  135. {
  136.   char buf[33];
  137.   int n;
  138.   va_list ar;
  139.   va_start(ar, fmt);
  140.   buf[sizeof(buf)-1]=OVERRUN_SENTRY;
  141.   n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
  142.   printf(buf);
  143.   printf("n=%d, strlen=%dn", n, strlen(buf));
  144.   if ((uchar) buf[sizeof(buf)-1] != OVERRUN_SENTRY)
  145.   {
  146.     fprintf(stderr, "Buffer overrunn");
  147.     abort();
  148.   }
  149.   va_end(ar);
  150. }
  151. int main()
  152. {
  153.   my_printf("Hellon");
  154.   my_printf("Hello int, %dn", 1);
  155.   my_printf("Hello string '%s'n", "I am a string");
  156.   my_printf("Hello hack hack hack hack hack hack hack %dn", 1);
  157.   my_printf("Hello %d hack  %dn", 1, 4);
  158.   my_printf("Hello %d hack hack hack hack hack %dn", 1, 4);
  159.   my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhn", "hack");
  160.   my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssssn", 1);
  161.   my_printf("Hello  %un", 1);
  162.   my_printf("Hex:   %lx  '%6lx'n", 32, 65);
  163.   my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:
  164.  `%-.64s' (%-.64s)", 1, 0,0,0,0);
  165.   return 0;
  166. }
  167. #endif