root/ext/intl/formatter/formatter_format.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHP_FUNCTION
  2. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | This source file is subject to version 3.01 of the PHP license,      |
   6    | that is bundled with this package in the file LICENSE, and is        |
   7    | available through the world-wide-web at the following url:           |
   8    | http://www.php.net/license/3_01.txt                                  |
   9    | If you did not receive a copy of the PHP license and are unable to   |
  10    | obtain it through the world-wide-web, please send a note to          |
  11    | license@php.net so we can mail you a copy immediately.               |
  12    +----------------------------------------------------------------------+
  13    | Authors: Stanislav Malyshev <stas@zend.com>                          |
  14    +----------------------------------------------------------------------+
  15  */
  16 
  17 #ifdef HAVE_CONFIG_H
  18 #include "config.h"
  19 #endif
  20 
  21 #include <unicode/ustring.h>
  22 
  23 #include "php_intl.h"
  24 #include "formatter_class.h"
  25 #include "formatter_format.h"
  26 #include "intl_convert.h"
  27 
  28 /* {{{ proto mixed NumberFormatter::format( mixed $num[, int $type] )
  29  * Format a number. }}} */
  30 /* {{{ proto mixed numfmt_format( NumberFormatter $nf, mixed $num[, int type] )
  31  * Format a number.
  32  */
  33 PHP_FUNCTION( numfmt_format )
  34 {
  35         zval *number;
  36         zend_long type = FORMAT_TYPE_DEFAULT;
  37         UChar format_buf[32];
  38         UChar* formatted = format_buf;
  39         int32_t formatted_len = USIZE(format_buf);
  40         FORMATTER_METHOD_INIT_VARS;
  41 
  42         /* Parse parameters. */
  43         if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oz|l",
  44                 &object, NumberFormatter_ce_ptr,  &number, &type ) == FAILURE )
  45         {
  46                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
  47                         "numfmt_format: unable to parse input params", 0 );
  48 
  49                 RETURN_FALSE;
  50         }
  51 
  52         /* Fetch the object. */
  53         FORMATTER_METHOD_FETCH_OBJECT;
  54 
  55         if(type == FORMAT_TYPE_DEFAULT) {
  56                 if(Z_TYPE_P(number) == IS_STRING) {
  57                         convert_scalar_to_number_ex(number);
  58                 }
  59 
  60                 if(Z_TYPE_P(number) == IS_LONG) {
  61                         /* take INT32 on 32-bit, int64 on 64-bit */
  62                         type = (sizeof(zend_long) == 8)?FORMAT_TYPE_INT64:FORMAT_TYPE_INT32;
  63                 } else if(Z_TYPE_P(number) == IS_DOUBLE) {
  64                         type = FORMAT_TYPE_DOUBLE;
  65                 } else {
  66                         type = FORMAT_TYPE_INT32;
  67                 }
  68         }
  69 
  70         if(Z_TYPE_P(number) != IS_DOUBLE && Z_TYPE_P(number) != IS_LONG) {
  71                 convert_scalar_to_number(number );
  72         }
  73 
  74         switch(type) {
  75                 case FORMAT_TYPE_INT32:
  76                         convert_to_long_ex(number);
  77                         formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number),
  78                                 formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
  79                         if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
  80                                 intl_error_reset(INTL_DATA_ERROR_P(nfo));
  81                                 formatted = eumalloc(formatted_len);
  82                                 formatted_len = unum_format(FORMATTER_OBJECT(nfo), (int32_t)Z_LVAL_P(number),
  83                                         formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
  84                                 if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
  85                                         efree(formatted);
  86                                 }
  87                         }
  88                         INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
  89                         break;
  90 
  91                 case FORMAT_TYPE_INT64:
  92                 {
  93                         int64_t value = (Z_TYPE_P(number) == IS_DOUBLE)?(int64_t)Z_DVAL_P(number):Z_LVAL_P(number);
  94                         formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
  95                         if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
  96                                 intl_error_reset(INTL_DATA_ERROR_P(nfo));
  97                                 formatted = eumalloc(formatted_len);
  98                                 formatted_len = unum_formatInt64(FORMATTER_OBJECT(nfo), value, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
  99                                 if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
 100                                         efree(formatted);
 101                                 }
 102                         }
 103                         INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
 104                 }
 105                         break;
 106 
 107                 case FORMAT_TYPE_DOUBLE:
 108                         convert_to_double_ex(number);
 109                         formatted_len = unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
 110                         if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
 111                                 intl_error_reset(INTL_DATA_ERROR_P(nfo));
 112                                 formatted = eumalloc(formatted_len);
 113                                 unum_formatDouble(FORMATTER_OBJECT(nfo), Z_DVAL_P(number), formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
 114                                 if (U_FAILURE( INTL_DATA_ERROR_CODE(nfo) ) ) {
 115                                         efree(formatted);
 116                                 }
 117                         }
 118                         INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" );
 119                         break;
 120 
 121                 default:
 122                         php_error_docref(NULL, E_WARNING, "Unsupported format type %pd", type);
 123                         RETURN_FALSE;
 124                         break;
 125         }
 126 
 127         INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) );
 128 }
 129 /* }}} */
 130 
 131 /* {{{ proto mixed NumberFormatter::formatCurrency( double $num, string $currency )
 132  * Format a number as currency. }}} */
 133 /* {{{ proto mixed numfmt_format_currency( NumberFormatter $nf, double $num, string $currency )
 134  * Format a number as currency.
 135  */
 136 PHP_FUNCTION( numfmt_format_currency )
 137 {
 138         double     number;
 139         UChar      format_buf[32];
 140         UChar*     formatted     = format_buf;
 141         int32_t    formatted_len = USIZE(format_buf);
 142         char*      currency      = NULL;
 143         size_t     currency_len  = 0;
 144         UChar*     scurrency     = NULL;
 145         int32_t    scurrency_len = 0;
 146         FORMATTER_METHOD_INIT_VARS;
 147 
 148         /* Parse parameters. */
 149         if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Ods",
 150                 &object, NumberFormatter_ce_ptr,  &number, &currency, &currency_len ) == FAILURE )
 151         {
 152                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
 153                         "numfmt_format_currency: unable to parse input params", 0 );
 154 
 155                 RETURN_FALSE;
 156         }
 157 
 158         /* Fetch the object. */
 159         FORMATTER_METHOD_FETCH_OBJECT;
 160 
 161         /* Convert currency to UTF-16. */
 162         intl_convert_utf8_to_utf16(&scurrency, &scurrency_len, currency, currency_len, &INTL_DATA_ERROR_CODE(nfo));
 163         INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-16 failed" );
 164 
 165         /* Format the number using a fixed-length buffer. */
 166         formatted_len = unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
 167 
 168         /* If the buffer turned out to be too small
 169          * then allocate another buffer dynamically
 170          * and use it to format the number.
 171          */
 172         if (INTL_DATA_ERROR_CODE(nfo) == U_BUFFER_OVERFLOW_ERROR) {
 173                 intl_error_reset(INTL_DATA_ERROR_P(nfo));
 174                 formatted = eumalloc(formatted_len);
 175                 unum_formatDoubleCurrency(FORMATTER_OBJECT(nfo), number, scurrency, formatted, formatted_len, NULL, &INTL_DATA_ERROR_CODE(nfo));
 176         }
 177 
 178         if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) ) {
 179                 intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((nfo)) );
 180                 intl_errors_set_custom_msg( INTL_DATA_ERROR_P(nfo), "Number formatting failed", 0 );
 181                 RETVAL_FALSE;
 182                 if (formatted != format_buf) {
 183                         efree(formatted);
 184                 }
 185         } else {
 186                 INTL_METHOD_RETVAL_UTF8( nfo, formatted, formatted_len, ( formatted != format_buf ) );
 187         }
 188 
 189         if(scurrency) {
 190                 efree(scurrency);
 191         }
 192 }
 193 
 194 /* }}} */
 195 
 196 /*
 197  * Local variables:
 198  * tab-width: 4
 199  * c-basic-offset: 4
 200  * End:
 201  * vim600: noet sw=4 ts=4 fdm=marker
 202  * vim<600: noet sw=4 ts=4
 203  */

/* [<][>][^][v][top][bottom][index][help] */