示例#1
0
inline static void appenddouble(char **buffer, int *pos,
                                int *size, double number,
                                int width, char padding,
                                int alignment, int precision,
                                int adjust, char fmt,
                                int always_sign) {
  char num_buf[NUM_BUF_SIZE];
  char *s = NULL;
  int s_len = 0, is_negative = 0;

  if ((adjust & ADJ_PRECISION) == 0) {
    precision = FLOAT_PRECISION;
  } else if (precision > MAX_FLOAT_PRECISION) {
    precision = MAX_FLOAT_PRECISION;
  }

  if (isnan(number)) {
    is_negative = (number<0);
    appendstring(buffer, pos, size, "NaN", 3, 0, padding,
                 alignment, 3, is_negative, 0, always_sign);
    return;
  }

  if (isinf(number)) {
    is_negative = (number<0);
    appendstring(buffer, pos, size, "INF", 3, 0, padding,
                 alignment, 3, is_negative, 0, always_sign);
    return;
  }

  switch (fmt) {
  case 'e':
  case 'E':
  case 'f':
  case 'F':
    s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision, '.',
                    &is_negative, &num_buf[1], &s_len);
    if (is_negative) {
      num_buf[0] = '-';
      s = num_buf;
      s_len++;
    } else if (always_sign) {
      num_buf[0] = '+';
      s = num_buf;
      s_len++;
    }
    break;

  case 'g':
  case 'G':
    if (precision == 0)
      precision = 1;
    /*
     * * We use &num_buf[ 1 ], so that we have room for the sign
     */
    s = php_gcvt(number, precision, '.', (fmt == 'G')?'E':'e', &num_buf[1]);
    is_negative = 0;
    if (*s == '-') {
      is_negative = 1;
      s = &num_buf[1];
    } else if (always_sign) {
      num_buf[0] = '+';
      s = num_buf;
    }

    s_len = strlen(s);
    break;
  }

  appendstring(buffer, pos, size, s, width, 0, padding,
               alignment, s_len, is_negative, 0, always_sign);
}
示例#2
0
inline static void appenddouble(StringBuffer *buffer,
                                double number,
                                int width, char padding,
                                int alignment, int precision,
                                int adjust, char fmt,
                                int always_sign) {
  char num_buf[NUM_BUF_SIZE];
  char *s = nullptr;
  int s_len = 0, is_negative = 0;

  if ((adjust & ADJ_PRECISION) == 0) {
    precision = FLOAT_PRECISION;
  } else if (precision > MAX_FLOAT_PRECISION) {
    precision = MAX_FLOAT_PRECISION;
  }

  if (std::isnan(number)) {
    is_negative = (number<0);
    appendstring(buffer, "NaN", 3, 0, padding,
                 alignment, 3, is_negative, 0, always_sign);
    return;
  }

  if (std::isinf(number)) {
    is_negative = (number<0);
    appendstring(buffer, "INF", 3, 0, padding,
                 alignment, 3, is_negative, 0, always_sign);
    return;
  }

#if defined(HAVE_LOCALE_H)
  struct lconv *lconv;
  lconv = localeconv();
# define APPENDDOUBLE_LCONV_DECIMAL_POINT (*lconv->decimal_point)
#else
# define APPENDDOUBLE_LCONV_DECIMAL_POINT '.'
#endif

  switch (fmt) {
  case 'e':
  case 'E':
  case 'f':
  case 'F':
    s = php_conv_fp((fmt == 'f')?'F':fmt,
                    number, 0, precision,
                    (fmt == 'f')?APPENDDOUBLE_LCONV_DECIMAL_POINT:'.',
                    &is_negative, &num_buf[1], &s_len);
    if (is_negative) {
      num_buf[0] = '-';
      s = num_buf;
      s_len++;
    } else if (always_sign) {
      num_buf[0] = '+';
      s = num_buf;
      s_len++;
    }
    break;

  case 'g':
  case 'G':
    if (precision == 0)
      precision = 1;
    /*
     * * We use &num_buf[ 1 ], so that we have room for the sign
     */
    s = php_gcvt(number, precision,
                 APPENDDOUBLE_LCONV_DECIMAL_POINT,
                 (fmt == 'G')?'E':'e',
                 &num_buf[1]);
    is_negative = 0;
    if (*s == '-') {
      is_negative = 1;
      s = &num_buf[1];
    } else if (always_sign) {
      num_buf[0] = '+';
      s = num_buf;
    }

    s_len = strlen(s);
    break;
  }

  appendstring(buffer, s, width, 0, padding,
               alignment, s_len, is_negative, 0, always_sign);
}
示例#3
0
/* php_spintf_appenddouble() {{{ */
inline static void
php_sprintf_appenddouble(char **buffer, int *pos,
						 int *size, double number,
						 int width, char padding,
						 int alignment, int precision,
						 int adjust, char fmt,
						 int always_sign
						 TSRMLS_DC)
{
	char num_buf[NUM_BUF_SIZE];
	char *s = NULL;
	int s_len = 0, is_negative = 0;
#ifdef HAVE_LOCALE_H
	struct lconv *lconv;
#endif

	PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
				  *buffer, pos, size, number, width, padding, alignment, fmt));
	if ((adjust & ADJ_PRECISION) == 0) {
		precision = FLOAT_PRECISION;
	} else if (precision > MAX_FLOAT_PRECISION) {
		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Requested precision of %d digits was truncated to PHP maximum of %d digits", precision, MAX_FLOAT_PRECISION);
		precision = MAX_FLOAT_PRECISION;
	}
	
	if (zend_isnan(number)) {
		is_negative = (number<0);
		php_sprintf_appendstring(buffer, pos, size, "NaN", 3, 0, padding,
								 alignment, 3, is_negative, 0, always_sign);
		return;
	}

	if (zend_isinf(number)) {
		is_negative = (number<0);
		php_sprintf_appendstring(buffer, pos, size, "INF", 3, 0, padding,
								 alignment, 3, is_negative, 0, always_sign);
		return;
	}

	switch (fmt) {			
		case 'e':
		case 'E':
		case 'f':
		case 'F':
#ifdef HAVE_LOCALE_H
			lconv = localeconv();
#endif
			s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
						(fmt == 'f')?LCONV_DECIMAL_POINT:'.',
						&is_negative, &num_buf[1], &s_len);
			if (is_negative) {
				num_buf[0] = '-';
				s = num_buf;
				s_len++;
			} else if (always_sign) {
				num_buf[0] = '+';
				s = num_buf;
				s_len++;
			}
			break;

		case 'g':
		case 'G':
			if (precision == 0)
				precision = 1;
			/*
			 * * We use &num_buf[ 1 ], so that we have room for the sign
			 */
#ifdef HAVE_LOCALE_H
			lconv = localeconv();
#endif
			s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
			is_negative = 0;
			if (*s == '-') {
				is_negative = 1;
				s = &num_buf[1];
			} else if (always_sign) {
				num_buf[0] = '+';
				s = num_buf;
			}

			s_len = strlen(s);
			break;
	}

	php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding,
							 alignment, s_len, is_negative, 0, always_sign);
}
示例#4
0
/* {{{ ps_fetch_float */
static void
ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
{
	float fval;
	double dval;
	DBG_ENTER("ps_fetch_float");
	float4get(fval, *row);
	(*row)+= 4;
	DBG_INF_FMT("value=%f", fval);

	/*
	 * The following is needed to correctly support 4-byte floats.
	 * Otherwise, a value of 9.99 in a FLOAT column comes out of mysqli
	 * as 9.9998998641968.
	 *
	 * For GCC, we use the built-in decimal support to "up-convert" a
	 * 4-byte float to a 8-byte double.
	 * When that is not available, we fall back to converting the float
	 * to a string and then converting the string to a double. This mimics
	 * what MySQL does.
	 */
#ifdef HAVE_DECIMAL_FP_SUPPORT
	{
		typedef float dec32 __attribute__((mode(SD)));
		dec32 d32val = fval;

		/* The following cast is guaranteed to do the right thing */
		dval = (double) d32val;
	}
#elif defined(PHP_WIN32)
	{
		/* float datatype on Winows is already 4 byte but has a precision of 7 digits */
		char num_buf[2048];
		(void)_gcvt_s(num_buf, 2048, fval, field->decimals >= 31 ? 7 : field->decimals);
		dval = zend_strtod(num_buf, NULL);
	}
#else
	{
		char num_buf[2048]; /* Over allocated */
		char *s;

#ifndef FLT_DIG
# define FLT_DIG 6
#endif
		/* Convert to string. Ignoring localization, etc.
		 * Following MySQL's rules. If precision is undefined (NOT_FIXED_DEC i.e. 31)
		 * or larger than 31, the value is limited to 6 (FLT_DIG).
		 */
		s = php_gcvt(fval,
			     field->decimals >= 31 ? FLT_DIG : field->decimals,
			     '.',
			     'e',
			     num_buf);

		/* And now convert back to double */
		dval = zend_strtod(s, NULL);
	}
#endif

	ZVAL_DOUBLE(zv, dval);
	DBG_VOID_RETURN;
}