⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vasnprintf.c

📁 this is a glib for c language
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vsprintf with automatic memory allocation.   Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.   This program is free software; you can redistribute it and/or modify it   under the terms of the GNU Library General Public License as published   by the Free Software Foundation; either version 2, or (at your option)   any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Library General Public License for more details.   You should have received a copy of the GNU Library General Public   License along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,   USA.  */#ifndef _WIN32/* Tell glibc's <stdio.h> to provide a prototype for snprintf().   This must come before <config.h> because <config.h> may include   <features.h>, and once <features.h> has been included, it's too late.  */#ifndef _GNU_SOURCE# define _GNU_SOURCE    1#endif#endif#ifdef HAVE_CONFIG_H# include <config.h>#endif#include "glib/galloca.h"#include "g-gnulib.h"/* Specification.  */#include "vasnprintf.h"#include <stdio.h>	/* snprintf(), sprintf() */#include <stdlib.h>	/* abort(), malloc(), realloc(), free() */#include <string.h>	/* memcpy(), strlen() */#include <errno.h>	/* errno */#include <limits.h>	/* CHAR_BIT */#include <float.h>	/* DBL_MAX_EXP, LDBL_MAX_EXP */#include "printf-parse.h"#ifdef HAVE_WCHAR_T# ifdef HAVE_WCSLEN#  define local_wcslen wcslen# else   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid      a dependency towards this library, here is a local substitute.      Define this substitute only once, even if this file is included      twice in the same compilation unit.  */#  ifndef local_wcslen_defined#   define local_wcslen_defined 1static size_tlocal_wcslen (const wchar_t *s){  const wchar_t *ptr;  for (ptr = s; *ptr != (wchar_t) 0; ptr++)    ;  return ptr - s;}#  endif# endif#endif/* For those losing systems which don't have 'alloca' we have to add   some additional code emulating it.  */ #ifdef HAVE_ALLOCA # define freea(p) /* nothing */#else# define alloca(n) malloc (n) # define freea(p) free (p) #endif#ifndef HAVE_LONG_LONG_FORMATstatic intprint_long_long (char *buf, 		 int len, 		 int width,		 int precision,		 unsigned long flags,		 char conversion,		 unsigned long long number){  int negative = FALSE;  char buffer[128];  char *bufferend;  char *pointer;  int base;  static const char *upper = "0123456789ABCDEFX";  static const char *lower = "0123456789abcdefx";  const char *digits;  int i;  char *p;  int count;#define EMIT(c)           \  if (p - buf == len - 1) \    {                     \      *p++ = '\0';        \      return len;         \    }                     \  else                    \    *p++ = c;    p = buf;    switch (conversion)     {    case 'o':      base = 8;      digits = lower;      negative = FALSE;      break;    case 'x':      base = 16;      digits = lower;      negative = FALSE;      break;    case 'X':      base = 16;      digits = upper;      negative = FALSE;      break;    default:      base = 10;      digits = lower;      negative = (long long)number < 0;      if (negative) 	number = -((long long)number);      break;    }  /* Build number */  pointer = bufferend = &buffer[sizeof(buffer) - 1];  *pointer-- = '\0';  for (i = 1; i < (int)sizeof(buffer); i++)    {      *pointer-- = digits[number % base];      number /= base;      if (number == 0)	break;    }  /* Adjust width */  width -= (bufferend - pointer) - 1;  /* Adjust precision */  if (precision != -1)    {      precision -= (bufferend - pointer) - 1;      if (precision < 0)	precision = 0;      flags |= FLAG_ZERO;    }  /* Adjust width further */  if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE))    width--;  if (flags & FLAG_ALT)    {      switch (base)	{	case 16:	  width -= 2;	  break;	case 8:	  width--;	  break;        default:	  break;	}    }  /* Output prefixes spaces if needed */  if (! ((flags & FLAG_LEFT) ||	 ((flags & FLAG_ZERO) && (precision == -1))))    {      count = (precision == -1) ? 0 : precision;      while (width-- > count)	*p++ = ' ';    }  /* width has been adjusted for signs and alternatives */  if (negative)     {      EMIT ('-');    }  else if (flags & FLAG_SHOWSIGN)     {      EMIT('+');    }  else if (flags & FLAG_SPACE)     {      EMIT(' ');    }    if (flags & FLAG_ALT)    {      switch (base)	{	case 8:	  EMIT('0');	  break;	case 16:	  EMIT('0');	  EMIT(digits[16]);	  break;	default:	  break;	} /* switch base */    }    /* Output prefixed zero padding if needed */  if (flags & FLAG_ZERO)    {      if (precision == -1)	precision = width;      while (precision-- > 0)	{	  EMIT('0');	  width--;	}    }    /* Output the number itself */  while (*(++pointer))    {      EMIT(*pointer);    }    /* Output trailing spaces if needed */  if (flags & FLAG_LEFT)    {      while (width-- > 0)	EMIT(' ');    }    EMIT('\0');    return p - buf - 1;}#endifchar *vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args){  char_directives d;  arguments a;  if (printf_parse (format, &d, &a) < 0)    {      errno = EINVAL;      return NULL;    }#define CLEANUP() \  free (d.dir);								\  if (a.arg)								\    free (a.arg);  if (printf_fetchargs (args, &a) < 0)    {      CLEANUP ();      errno = EINVAL;      return NULL;    }  {    char *buf =      (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);    const char *cp;    unsigned int i;    char_directive *dp;    /* Output string accumulator.  */    char *result;    size_t allocated;    size_t length;    if (resultbuf != NULL)      {	result = resultbuf;	allocated = *lengthp;      }    else      {	result = NULL;	allocated = 0;      }    length = 0;    /* Invariants:       result is either == resultbuf or == NULL or malloc-allocated.       If length > 0, then result != NULL.  */#define ENSURE_ALLOCATION(needed) \    if ((needed) > allocated)						\      {									\	char *memory;							\									\	allocated = (allocated > 0 ? 2 * allocated : 12);		\	if ((needed) > allocated)					\	  allocated = (needed);						\	if (result == resultbuf || result == NULL)			\	  memory = (char *) malloc (allocated);				\	else								\	  memory = (char *) realloc (result, allocated);		\									\	if (memory == NULL)						\	  {								\	    if (!(result == resultbuf || result == NULL))		\	      free (result);						\	    freea (buf);						\	    CLEANUP ();							\	    errno = ENOMEM;						\	    return NULL;						\	  }								\	if (result == resultbuf && length > 0)				\	  memcpy (memory, result, length);				\	result = memory;						\      }    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)      {	if (cp != dp->dir_start)	  {	    size_t n = dp->dir_start - cp;	    ENSURE_ALLOCATION (length + n);	    memcpy (result + length, cp, n);	    length += n;	  }	if (i == d.count)	  break;	/* Execute a single directive.  */	if (dp->conversion == '%')	  {	    if (!(dp->arg_index < 0))	      abort ();	    ENSURE_ALLOCATION (length + 1);	    result[length] = '%';	    length += 1;	  }	else	  {	    if (!(dp->arg_index >= 0))	      abort ();	    if (dp->conversion == 'n')	      {		switch (a.arg[dp->arg_index].type)		  {		  case TYPE_COUNT_SCHAR_POINTER:		    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;		    break;		  case TYPE_COUNT_SHORT_POINTER:		    *a.arg[dp->arg_index].a.a_count_short_pointer = length;		    break;		  case TYPE_COUNT_INT_POINTER:		    *a.arg[dp->arg_index].a.a_count_int_pointer = length;		    break;		  case TYPE_COUNT_LONGINT_POINTER:		    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;		    break;#ifdef HAVE_LONG_LONG		  case TYPE_COUNT_LONGLONGINT_POINTER:		    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;		    break;#endif		  default:		    abort ();		  }	      }	    else	      {		arg_type type = a.arg[dp->arg_index].type;		char *p;		unsigned int prefix_count;		int prefixes[2];#if !HAVE_SNPRINTF		unsigned int tmp_length;		char tmpbuf[700];		char *tmp;		/* Allocate a temporary buffer of sufficient size for calling		   sprintf.  */		{		  unsigned int width;		  unsigned int precision;		  width = 0;		  if (dp->width_start != dp->width_end)		    {		      if (dp->width_arg_index >= 0)			{			  int arg;			  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))			    abort ();			  arg = a.arg[dp->width_arg_index].a.a_int;			  width = (arg < 0 ? -arg : arg);			}		      else			{			  const char *digitp = dp->width_start;			  do			    width = width * 10 + (*digitp++ - '0');			  while (digitp != dp->width_end);			}		    }		  precision = 6;		  if (dp->precision_start != dp->precision_end)		    {		      if (dp->precision_arg_index >= 0)			{			  int arg;			  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))			    abort ();			  arg = a.arg[dp->precision_arg_index].a.a_int;			  precision = (arg < 0 ? 0 : arg);			}		      else			{			  const char *digitp = dp->precision_start + 1;			  precision = 0;			  while (digitp != dp->precision_end)			    precision = precision * 10 + (*digitp++ - '0');			}		    }		  switch (dp->conversion)		    {		    case 'd': case 'i': case 'u':# ifdef HAVE_LONG_LONG		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)			tmp_length =			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT					  * 0.30103 /* binary -> decimal */					  * 2 /* estimate for FLAG_GROUP */					 )			  + 1 /* turn floor into ceil */			  + 1; /* account for leading sign */		      else# endif		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)			tmp_length =			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT					  * 0.30103 /* binary -> decimal */					  * 2 /* estimate for FLAG_GROUP */					 )			  + 1 /* turn floor into ceil */			  + 1; /* account for leading sign */		      else			tmp_length =			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT					  * 0.30103 /* binary -> decimal */					  * 2 /* estimate for FLAG_GROUP */					 )			  + 1 /* turn floor into ceil */			  + 1; /* account for leading sign */		      break;		    case 'o':# ifdef HAVE_LONG_LONG		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)			tmp_length =			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT					  * 0.333334 /* binary -> octal */					 )			  + 1 /* turn floor into ceil */			  + 1; /* account for leading sign */		      else# endif		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)			tmp_length =			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT					  * 0.333334 /* binary -> octal */					 )			  + 1 /* turn floor into ceil */			  + 1; /* account for leading sign */		      else			tmp_length =			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT					  * 0.333334 /* binary -> octal */					 )			  + 1 /* turn floor into ceil */			  + 1; /* account for leading sign */		      break;		    case 'x': case 'X':# ifdef HAVE_LONG_LONG		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)			tmp_length =			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT					  * 0.25 /* binary -> hexadecimal */					 )			  + 1 /* turn floor into ceil */			  + 2; /* account for leading sign or alternate form */		      else# endif# ifdef HAVE_INT64_AND_I64		      if (type == TYPE_INT64 || type == TYPE_UINT64)			tmp_length =			  (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT					  * 0.25 /* binary -> hexadecimal */					  )			  + 1 /* turn floor into ceil */			  + 2; /* account for leading sign or alternate form */		      else# endif		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)			tmp_length =			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT					  * 0.25 /* binary -> hexadecimal */					 )			  + 1 /* turn floor into ceil */			  + 2; /* account for leading sign or alternate form */		      else			tmp_length =			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT					  * 0.25 /* binary -> hexadecimal */					 )			  + 1 /* turn floor into ceil */			  + 2; /* account for leading sign or alternate form */		      break;		    case 'f': case 'F':# ifdef HAVE_LONG_DOUBLE		      if (type == TYPE_LONGDOUBLE)			tmp_length =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -