From: Stanislav Malyshev Date: Mon, 7 Jul 2008 23:10:15 +0000 (+0000) Subject: Merge intl extension X-Git-Tag: php-5.3.0alpha1~450 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9eb22ce7f7d669f38ae46642d8cb365b450dd4ce;p=php Merge intl extension --- diff --git a/ext/intl/dateformat/dateformat.c b/ext/intl/dateformat/dateformat.c new file mode 100755 index 0000000000..b61d268d72 --- /dev/null +++ b/ext/intl/dateformat/dateformat.c @@ -0,0 +1,363 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "php_intl.h" +#include "intl_convert.h" +#include "dateformat_class.h" +#include "dateformat.h" + +/* {{{ dateformat_register_constants + * Register constants common for the both (OO and procedural) + * APIs. + */ +void dateformat_register_constants( INIT_FUNC_ARGS ) +{ + if( IntlDateFormatter_ce_ptr == NULL) { + zend_error(E_ERROR, "DateFormat class not defined"); + return; + } + + #define DATEFORMATTER_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS) + #define DATEFORMATTER_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( IntlDateFormatter_ce_ptr, ZEND_STRS( #x ) - 1, UDAT_##x TSRMLS_CC ); + #define DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( IntlDateFormatter_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC ); + + #define DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST(x) zend_declare_class_constant_long( IntlDateFormatter_ce_ptr, ZEND_STRS( #x ) - 1, UCAL_##x TSRMLS_CC ); + + // UDateFormatStyle constants + DATEFORMATTER_EXPOSE_CLASS_CONST( FULL ); + DATEFORMATTER_EXPOSE_CLASS_CONST( LONG ); + DATEFORMATTER_EXPOSE_CLASS_CONST( MEDIUM ); + DATEFORMATTER_EXPOSE_CLASS_CONST( SHORT ); + DATEFORMATTER_EXPOSE_CLASS_CONST( NONE ); + +/* + DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "GREGORIAN", DATEF_GREGORIAN ); + DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "CUSTOMARY", DATEF_CUSTOMARY ); + DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "BUDDHIST", DATEF_BUDDHIST ); + DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "JAPANESE_IMPERIAL", DATEF_JAPANESE_IMPERIAL ); +*/ + + DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST( GREGORIAN ); + DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST( TRADITIONAL ); + + #undef DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST + #undef DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST + #undef DATEFORMATTER_EXPOSE_CLASS_CONST + #undef DATEFORMATTER_EXPOSE_CONST +} +/* }}} */ + +/* {{{ proto IntlDateFormatter IntlDateFormatter::create( string $locale , long date_type, long time_type[,string $timezone_str, long $calendar , string $pattern] ) + * Create formatter. }}} */ +/* {{{ proto IntlDateFormatter datefmt_create( string $locale, long date_type, long time_type[,string $timezone_str, long $calendar , string $pattern] ) + + * Create formatter. + */ +PHP_FUNCTION( datefmt_create ) +{ + char* locale; + int locale_len = 0; + zval* object; + + long date_type = 0; + long time_type = 0; + long calendar = 1; + int all_done = 0; + //zval* timezone = NULL; + + char* timezone_str = NULL; + int timezone_str_len = 0; + char* pattern_str = NULL; + int pattern_str_len = 0; + UChar* svalue = NULL; //UTF-16 pattern_str + int slength = 0; + UChar* timezone_utf16 = NULL; //UTF-16 timezone_str + int timezone_utf16_len = 0; + UCalendar ucal_obj = NULL; + + + IntlDateFormatter_object* mfo; + + intl_error_reset( NULL TSRMLS_CC ); + + // Parse parameters. + if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sll|sls", + &locale, &locale_len, &date_type, & time_type , &timezone_str, &timezone_str_len , &calendar ,&pattern_str , &pattern_str_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_create: unable to parse input params", 0 TSRMLS_CC ); + RETURN_NULL(); + } + + + // Create a IntlDateFormatter object and save the ICU formatter into it. + if( ( object = getThis() ) == NULL ) + object = return_value; + + if( Z_TYPE_P( object ) != IS_OBJECT ) + object_init_ex( object, IntlDateFormatter_ce_ptr ); + + DATE_FORMAT_METHOD_FETCH_OBJECT; + + if(locale_len == 0) { + locale = INTL_G(default_locale); + } + + // Convert pattern (if specified) to UTF-16. + if( pattern_str && pattern_str_len>0 ){ + intl_convert_utf8_to_utf16(&svalue, &slength, pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting pattern to UTF-16" ); + } + + // Convert pattern (if specified) to UTF-16. + if( timezone_str && timezone_str_len >0 ){ + intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, timezone_str, timezone_str_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting timezone_str to UTF-16" ); + } + + // Create an ICU date formatter. + while( U_FAILURE( INTL_DATA_ERROR_CODE(mfo)) || (all_done==0) ){ + // Convert pattern (if specified) to UTF-16. + if( pattern_str && pattern_str_len>0 ){ + DATE_FORMAT_OBJECT(mfo) = udat_open(UDAT_IGNORE,UDAT_IGNORE, locale, timezone_utf16, timezone_utf16_len ,svalue ,slength , &INTL_DATA_ERROR_CODE((mfo))); + }else{ + DATE_FORMAT_OBJECT(mfo) = udat_open(time_type,date_type, locale, timezone_utf16, timezone_utf16_len ,svalue ,slength , &INTL_DATA_ERROR_CODE((mfo))); + } + + //Set the calendar if passed + if( calendar) { + ucal_obj = ucal_open( timezone_utf16 , timezone_utf16_len , locale , calendar , &INTL_DATA_ERROR_CODE(mfo) ); + udat_setCalendar( DATE_FORMAT_OBJECT(mfo), ucal_obj ); + } + all_done = 1; + + }//end of while + + + if( U_FAILURE( INTL_DATA_ERROR_CODE((mfo)) ) ) + { + intl_error_set( NULL, INTL_DATA_ERROR_CODE((mfo)) , + "__construct: date formatter creation failed", 0 TSRMLS_CC ); + zval_dtor(object); + ZVAL_NULL(object); + if( svalue){ + efree(svalue); + } + if( timezone_utf16){ + efree(timezone_utf16); + } + RETURN_NULL(); + } + + if( svalue){ + efree(svalue); + } + if( timezone_utf16){ + efree(timezone_utf16); + } + //Set the class variables + mfo->date_type = date_type; + mfo->time_type = time_type; + mfo->calendar = calendar; + if( timezone_str && timezone_str_len > 0){ + if( mfo->timezone_id ){ + efree(mfo->timezone_id); + } + mfo->timezone_id = estrndup( timezone_str, timezone_str_len); + } +} +/* }}} */ + +/* {{{ proto void IntlDateFormatter::__construct( string $locale, string $pattern ) + * IntlDateFormatter object constructor. + */ +PHP_METHOD( IntlDateFormatter, __construct ) +{ + char* locale = NULL; + int locale_len = 0; + long date_type = 0; + long time_type = 0; + long calendar = 1; + + char* timezone_str = NULL; + int timezone_str_len = 0; + char* pattern_str = NULL; + int pattern_str_len = 0; + UChar* svalue = NULL; + int slength = 0; + UChar* timezone_utf16 = NULL; //UTF-16 timezone_str + int timezone_utf16_len = 0; + + UCalendar ucal_obj = NULL; + int all_done = 0; + + zval* object; + IntlDateFormatter_object* mfo; + + intl_error_reset( NULL TSRMLS_CC ); + + object = getThis(); + + // Parse parameters. + if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sll|slsb", + &locale, &locale_len, &date_type, & time_type , &timezone_str, &timezone_str_len , &calendar ,&pattern_str , &pattern_str_len ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "__construct: unable to parse input params", 0 TSRMLS_CC ); + zval_dtor(object); + ZVAL_NULL(object); + RETURN_NULL(); + } + +/* + //Check if timezone is in proper type + if( (Z_TYPE_P(timezone) != IS_STRING) && (Z_TYPE_P(timezone) != IS_OBJECT) ){ + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "__construct: unable to parse input params", 0 TSRMLS_CC ); + zval_dtor(object); + ZVAL_NULL(object); + RETURN_NULL(); + } +*/ + + mfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + intl_error_reset( &mfo->datef_data.error TSRMLS_CC ); + + if(locale_len == 0) { + locale = INTL_G(default_locale); + } + + // Convert pattern (if specified) to UTF-16. + if( pattern_str && pattern_str_len>0 ){ + intl_convert_utf8_to_utf16(&svalue, &slength, pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting pattern to UTF-16" ); + } + + // Convert pattern (if specified) to UTF-16. + if( timezone_str && timezone_str_len >0 ){ + intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, timezone_str, timezone_str_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting timezone_str to UTF-16" ); + } + + + // Create an ICU date formatter. + while( U_FAILURE( INTL_DATA_ERROR_CODE(mfo)) || (all_done==0) ){ + if( pattern_str && pattern_str_len>0 ){ + DATE_FORMAT_OBJECT(mfo) = udat_open(UDAT_IGNORE,UDAT_IGNORE, locale, timezone_utf16, timezone_utf16_len ,svalue ,slength , &INTL_DATA_ERROR_CODE((mfo))); + }else{ + DATE_FORMAT_OBJECT(mfo) = udat_open(time_type,date_type, locale, timezone_utf16, timezone_utf16_len ,svalue ,slength , &INTL_DATA_ERROR_CODE((mfo))); + } + + + //Set the calendar if passed + if( calendar) { + ucal_obj = ucal_open( timezone_utf16 , timezone_utf16_len , locale , calendar , &INTL_DATA_ERROR_CODE(mfo) ); + udat_setCalendar( DATE_FORMAT_OBJECT(mfo), ucal_obj ); + } + all_done = 1; + + }//end of while + + + if( U_FAILURE( INTL_DATA_ERROR_CODE((mfo)) ) ) + { + intl_error_set( NULL, INTL_DATA_ERROR_CODE(mfo), + "__construct: date formatter creation failed", 0 TSRMLS_CC ); + if( svalue){ + efree(svalue); + } + zval_dtor(object); + ZVAL_NULL(object); + RETURN_NULL(); + } + + if( svalue){ + efree(svalue); + } + + //Set the class variables + mfo->date_type = date_type; + mfo->time_type = time_type; + mfo->calendar = calendar; + if( timezone_str && timezone_str_len > 0){ + mfo->timezone_id = estrndup( timezone_str, timezone_str_len); + } +} +/* }}} */ + +/* {{{ proto int IntlDateFormatter::getErrorCode() + * Get formatter's last error code. }}} */ +/* {{{ proto int datefmt_get_error_code( IntlDateFormatter $nf ) + * Get formatter's last error code. + */ +PHP_FUNCTION( datefmt_get_error_code ) +{ + zval* object = NULL; + IntlDateFormatter_object* mfo = NULL; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_error_code: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + mfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + // Return formatter's last error code. + RETURN_LONG( INTL_DATA_ERROR_CODE(mfo) ); +} +/* }}} */ + +/* {{{ proto string IntlDateFormatter::getErrorMessage( ) + * Get text description for formatter's last error code. }}} */ +/* {{{ proto string datefmt_get_error_message( IntlDateFormatter $coll ) + * Get text description for formatter's last error code. + */ +PHP_FUNCTION( datefmt_get_error_message ) +{ + char* message = NULL; + zval* object = NULL; + IntlDateFormatter_object* mfo = NULL; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_error_message: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + mfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + // Return last error message. + message = intl_error_get_message( &mfo->datef_data.error TSRMLS_CC ); + RETURN_STRING( message, 0); +} +/* }}} */ diff --git a/ext/intl/dateformat/dateformat.h b/ext/intl/dateformat/dateformat.h new file mode 100755 index 0000000000..f11918b79f --- /dev/null +++ b/ext/intl/dateformat/dateformat.h @@ -0,0 +1,45 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMATTER_H +#define DATE_FORMATTER_H + +#include + +PHP_FUNCTION( datefmt_create ); +PHP_FUNCTION( datefmt_get_error_code ); +PHP_FUNCTION( datefmt_get_error_message ); +PHP_METHOD( IntlDateFormatter, __construct ); +void dateformat_register_constants( INIT_FUNC_ARGS ); + +/* +These are not necessary at this point of time +#define DATEF_GREGORIAN 1 +#define DATEF_CUSTOMARY 2 +#define DATEF_BUDDHIST 3 +#define DATEF_JAPANESE_IMPERIAL 4 +*/ + +#define CALENDAR_SEC "tm_sec" +#define CALENDAR_MIN "tm_min" +#define CALENDAR_HOUR "tm_hour" +#define CALENDAR_MDAY "tm_mday" +#define CALENDAR_MON "tm_mon" +#define CALENDAR_YEAR "tm_year" +#define CALENDAR_WDAY "tm_wday" +#define CALENDAR_YDAY "tm_yday" +#define CALENDAR_ISDST "tm_isdst" + +#endif // DATE_FORMATTER_H diff --git a/ext/intl/dateformat/dateformat_attr.c b/ext/intl/dateformat/dateformat_attr.c new file mode 100755 index 0000000000..09997b6ee3 --- /dev/null +++ b/ext/intl/dateformat/dateformat_attr.c @@ -0,0 +1,416 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_intl.h" +#include "intl_convert.h" +#include "dateformat_class.h" +#include "dateformat_attr.h" + +#include +#include +#include + +static void internal_set_calendar(IntlDateFormatter_object *mfo, char* timezone_id , int timezone_id_len , int calendar ,zval* return_value TSRMLS_DC){ + + int timezone_utf16_len = 0; + UChar* timezone_utf16 = NULL; //timezone_id in UTF-16 + + char* locale = NULL; + int locale_type =ULOC_ACTUAL_LOCALE; + + UCalendar* ucal_obj = NULL; + + //check for the validity of value of calendar passed + intl_error_reset( NULL TSRMLS_CC ); + if( calendar > 1){ + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_set_calendar: calendar value specified is out of valid range", 0 TSRMLS_CC); + RETURN_FALSE; + } + + // Convert timezone to UTF-16. + intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, timezone_id, timezone_id_len , &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting timezone to UTF-16" ); + + + //Get the lcoale for the dateformatter + locale = (char *)udat_getLocaleByType(DATE_FORMAT_OBJECT(mfo), locale_type ,&INTL_DATA_ERROR_CODE(mfo)); + + //Set the calendar if passed + ucal_obj = ucal_open( timezone_utf16 , timezone_utf16_len , locale , calendar , &INTL_DATA_ERROR_CODE(mfo) ); + udat_setCalendar( DATE_FORMAT_OBJECT(mfo), ucal_obj ); + INTL_METHOD_CHECK_STATUS(mfo, "Error setting the calendar."); + + if( timezone_utf16){ + efree(timezone_utf16); + } + +} + +/* {{{ proto unicode IntlDateFormatter::getDateType( ) + * Get formatter datetype. }}} */ +/* {{{ proto string datefmt_get_datetype( IntlDateFormatter $mf ) + * Get formatter datetype. + */ +PHP_FUNCTION( datefmt_get_datetype ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL , U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_datetype: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + INTL_METHOD_CHECK_STATUS(mfo, "Error getting formatter datetype." ); + + RETURN_LONG(mfo->date_type ); +} +/* }}} */ + +/* {{{ proto unicode IntlDateFormatter::getTimeType( ) + * Get formatter timetype. }}} */ +/* {{{ proto string datefmt_get_timetype( IntlDateFormatter $mf ) + * Get formatter timetype. + */ +PHP_FUNCTION( datefmt_get_timetype ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL , U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_timetype: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + INTL_METHOD_CHECK_STATUS(mfo, "Error getting formatter timetype." ); + + RETURN_LONG(mfo->time_type ); +} +/* }}} */ + + +/* {{{ proto unicode IntlDateFormatter::getCalendar( ) + * Get formatter calendar. }}} */ +/* {{{ proto string datefmt_get_calendar( IntlDateFormatter $mf ) + * Get formatter calendar. + */ +PHP_FUNCTION( datefmt_get_calendar ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL , U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_calendar: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + INTL_METHOD_CHECK_STATUS(mfo, "Error getting formatter calendar." ); + + RETURN_LONG(mfo->calendar ); +} +/* }}} */ + +/* {{{ proto unicode IntlDateFormatter::getTimeZoneId( ) + * Get formatter timezone_id. }}} */ +/* {{{ proto string datefmt_get_timezone_id( IntlDateFormatter $mf ) + * Get formatter timezone_id. + */ +PHP_FUNCTION( datefmt_get_timezone_id ) +{ + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL , U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_timezone_id: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + INTL_METHOD_CHECK_STATUS(mfo, "Error getting formatter timezone_id." ); + + if( mfo->timezone_id ){ + RETURN_STRING((char*)mfo->timezone_id ,TRUE ); + }else{ + RETURN_NULL(); + } +} + +/* {{{ proto boolean IntlDateFormatter::setTimeZoneId( $timezone_id) + * Set formatter timezone_id. }}} */ +/* {{{ proto boolean datefmt_set_timezone_id( IntlDateFormatter $mf ,$timezone_id) + * Set formatter timezone_id. + */ +PHP_FUNCTION( datefmt_set_timezone_id ) +{ + char* timezone_id = NULL; + int timezone_id_len = 0; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, IntlDateFormatter_ce_ptr ,&timezone_id , &timezone_id_len) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_set_timezone_id: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + //set the timezone for the calendar + internal_set_calendar( mfo , timezone_id , timezone_id_len , mfo->calendar ,return_value TSRMLS_CC ); + + //Set the IntlDateFormatter variable + if( mfo->timezone_id ){ + efree(mfo->timezone_id); + } + mfo->timezone_id = estrndup(timezone_id , timezone_id_len); + + RETURN_TRUE; +} + +/* {{{ proto string IntlDateFormatter::getPattern( ) + * Get formatter pattern. }}} */ +/* {{{ proto string datefmt_get_pattern( IntlDateFormatter $mf ) + * Get formatter pattern. + */ +PHP_FUNCTION( datefmt_get_pattern ) +{ + UChar value_buf[64]; + int length = USIZE( value_buf ); + UChar* value = value_buf; + zend_bool is_pattern_localized =FALSE; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_pattern: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + length = udat_toPattern(DATE_FORMAT_OBJECT(mfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(mfo)); + if(INTL_DATA_ERROR_CODE(mfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; // to avoid U_STRING_NOT_TERMINATED_WARNING + INTL_DATA_ERROR_CODE(mfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = udat_toPattern(DATE_FORMAT_OBJECT(mfo), is_pattern_localized , value, length, &INTL_DATA_ERROR_CODE(mfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS(mfo, "Error getting formatter pattern" ); + + INTL_METHOD_RETVAL_UTF8( mfo, value, length, ( value != value_buf ) ); +} +/* }}} */ + +/* {{{ proto bool IntlDateFormatter::setPattern( string $pattern ) + * Set formatter pattern. }}} */ +/* {{{ proto bool datefmt_set_pattern( IntlDateFormatter $mf, string $pattern ) + * Set formatter pattern. + */ +PHP_FUNCTION( datefmt_set_pattern ) +{ + char* value = NULL; + int value_len = 0; + int slength = 0; + UChar* svalue = NULL; + zend_bool is_pattern_localized =FALSE; + + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", + &object, IntlDateFormatter_ce_ptr, &value, &value_len ) == FAILURE ) + { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_set_pattern: unable to parse input params", 0 TSRMLS_CC); + RETURN_FALSE; + } + + DATE_FORMAT_METHOD_FETCH_OBJECT; + + // Convert given pattern to UTF-16. + intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting pattern to UTF-16" ); + + udat_applyPattern(DATE_FORMAT_OBJECT(mfo), (UBool)is_pattern_localized , svalue, slength); + + efree(svalue); + INTL_METHOD_CHECK_STATUS(mfo, "Error setting symbol value"); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string IntlDateFormatter::getLocale() + * Get formatter locale. }}} */ +/* {{{ proto string datefmt_get_locale(IntlDateFormatter $mf) + * Get formatter locale. + */ +PHP_FUNCTION( datefmt_get_locale ) +{ + char *loc; + long loc_type =ULOC_ACTUAL_LOCALE; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", + &object, IntlDateFormatter_ce_ptr ,&loc_type) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_get_locale: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + loc = (char *)udat_getLocaleByType(DATE_FORMAT_OBJECT(mfo), loc_type ,&INTL_DATA_ERROR_CODE(mfo)); + RETURN_STRING(loc, 1); +} +/* }}} */ + +/* {{{ proto string IntlDateFormatter::isLenient() + * Get formatter isLenient. }}} */ +/* {{{ proto string datefmt_isLenient(IntlDateFormatter $mf) + * Get formatter locale. + */ +PHP_FUNCTION( datefmt_is_lenient ) +{ + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, IntlDateFormatter_ce_ptr ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_is_lenient: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + RETVAL_BOOL(udat_isLenient(DATE_FORMAT_OBJECT(mfo))); +} +/* }}} */ + +/* {{{ proto string IntlDateFormatter::setLenient() + * Set formatter lenient. }}} */ +/* {{{ proto string datefmt_setLenient(IntlDateFormatter $mf) + * Set formatter lenient. + */ +PHP_FUNCTION( datefmt_set_lenient ) +{ + + zend_bool isLenient = FALSE; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", + &object, IntlDateFormatter_ce_ptr ,&isLenient ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_set_lenient: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + udat_setLenient(DATE_FORMAT_OBJECT(mfo) , (UBool)isLenient ); +} +/* }}} */ + +/* {{{ proto bool IntlDateFormatter::setPattern( int $calendar ) + * Set formatter calendar. }}} */ +/* {{{ proto bool datefmt_set_calendar( IntlDateFormatter $mf, int $calendar ) + * Set formatter calendar. + */ +PHP_FUNCTION( datefmt_set_calendar ) +{ + long calendar = 0; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, IntlDateFormatter_ce_ptr, &calendar ) == FAILURE ) + { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_set_calendar: unable to parse input params", 0 TSRMLS_CC); + RETURN_FALSE; + } + + //check for the validity of value of calendar passed + intl_error_reset( NULL TSRMLS_CC ); + if( calendar > 1){ + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_set_calendar: calendar value specified is out of valid range", 0 TSRMLS_CC); + RETURN_FALSE; + } + + DATE_FORMAT_METHOD_FETCH_OBJECT; + + internal_set_calendar( mfo , mfo->timezone_id , strlen(mfo->timezone_id) , calendar ,return_value TSRMLS_CC ); + + //Set the calendar value in the IntlDateFormatter object + mfo->calendar = calendar ; + + RETURN_TRUE; +} +/* }}} */ + + diff --git a/ext/intl/dateformat/dateformat_attr.h b/ext/intl/dateformat/dateformat_attr.h new file mode 100755 index 0000000000..bf28824d63 --- /dev/null +++ b/ext/intl/dateformat/dateformat_attr.h @@ -0,0 +1,34 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_ATTR_H +#define DATE_FORMAT_ATTR_H + +#include + +//PHP_FUNCTION( datefmt_get_timezone ); +PHP_FUNCTION( datefmt_get_datetype ); +PHP_FUNCTION( datefmt_get_timetype ); +PHP_FUNCTION( datefmt_get_calendar ); +PHP_FUNCTION( datefmt_set_calendar ); +PHP_FUNCTION( datefmt_get_locale ); +PHP_FUNCTION( datefmt_get_timezone_id ); +PHP_FUNCTION( datefmt_set_timezone_id ); +PHP_FUNCTION( datefmt_get_pattern ); +PHP_FUNCTION( datefmt_set_pattern ); +PHP_FUNCTION( datefmt_is_lenient ); +PHP_FUNCTION( datefmt_set_lenient ); + +#endif // DATE_FORMAT_ATTR_H diff --git a/ext/intl/dateformat/dateformat_class.c b/ext/intl/dateformat/dateformat_class.c new file mode 100755 index 0000000000..e582467231 --- /dev/null +++ b/ext/intl/dateformat/dateformat_class.c @@ -0,0 +1,132 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#include + +#include "dateformat_class.h" +#include "php_intl.h" +#include "dateformat_data.h" +#include "dateformat_format.h" +#include "dateformat_parse.h" +#include "dateformat.h" +#include "dateformat_attr.h" + +zend_class_entry *IntlDateFormatter_ce_ptr = NULL; + +///////////////////////////////////////////////////////////////////////////// +// Auxiliary functions needed by objects of 'IntlDateFormatter' class +///////////////////////////////////////////////////////////////////////////// + +/* {{{ IntlDateFormatter_objects_dtor */ +static void IntlDateFormatter_object_dtor(void *object, zend_object_handle handle TSRMLS_DC ) +{ + zend_objects_destroy_object( object, handle TSRMLS_CC ); +} +/* }}} */ + +/* {{{ IntlDateFormatter_objects_free */ +void IntlDateFormatter_object_free( zend_object *object TSRMLS_DC ) +{ + IntlDateFormatter_object* mfo = (IntlDateFormatter_object*)object; + + zend_object_std_dtor( &mfo->zo TSRMLS_CC ); + + dateformat_data_free( &mfo->datef_data TSRMLS_CC ); + + if( mfo->timezone_id ){ + efree(mfo->timezone_id); + } + + efree( mfo ); +} +/* }}} */ + +/* {{{ IntlDateFormatter_object_create */ +zend_object_value IntlDateFormatter_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + IntlDateFormatter_object* intern; + + intern = ecalloc( 1, sizeof(IntlDateFormatter_object) ); + dateformat_data_init( &intern->datef_data TSRMLS_CC ); + zend_object_std_init( &intern->zo, ce TSRMLS_CC ); + intern->date_type = 0; + intern->time_type = 0; + intern->calendar = 1; //Gregorian calendar + intern->timezone_id = NULL; + + retval.handle = zend_objects_store_put( + intern, + IntlDateFormatter_object_dtor, + (zend_objects_free_object_storage_t)IntlDateFormatter_object_free, + NULL TSRMLS_CC ); + + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} +/* }}} */ + +///////////////////////////////////////////////////////////////////////////// +// 'IntlDateFormatter' class registration structures & functions +///////////////////////////////////////////////////////////////////////////// + +/* {{{ IntlDateFormatter_class_functions + * Every 'IntlDateFormatter' class method has an entry in this table + */ + +static function_entry IntlDateFormatter_class_functions[] = { + PHP_ME( IntlDateFormatter, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR ) + ZEND_FENTRY( create, ZEND_FN( datefmt_create ), NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC ) + PHP_NAMED_FE( getDateType, ZEND_FN( datefmt_get_datetype ), NULL ) + PHP_NAMED_FE( getTimeType, ZEND_FN( datefmt_get_timetype ), NULL ) + PHP_NAMED_FE( getCalendar, ZEND_FN( datefmt_get_calendar ), NULL ) + PHP_NAMED_FE( setCalendar, ZEND_FN( datefmt_set_calendar ), NULL ) + PHP_NAMED_FE( getTimeZoneId, ZEND_FN( datefmt_get_timezone_id ), NULL ) + PHP_NAMED_FE( setTimeZoneId, ZEND_FN( datefmt_set_timezone_id ), NULL ) + PHP_NAMED_FE( setPattern, ZEND_FN( datefmt_set_pattern ), NULL ) + PHP_NAMED_FE( getPattern, ZEND_FN( datefmt_get_pattern ), NULL ) + PHP_NAMED_FE( getLocale, ZEND_FN( datefmt_get_locale ), NULL ) + PHP_NAMED_FE( setLenient, ZEND_FN( datefmt_set_lenient ), NULL ) + PHP_NAMED_FE( isLenient, ZEND_FN( datefmt_is_lenient ), NULL ) + PHP_NAMED_FE( format, ZEND_FN( datefmt_format ), NULL ) + PHP_NAMED_FE( parse, ZEND_FN( datefmt_parse), NULL ) + PHP_NAMED_FE( localtime, ZEND_FN( datefmt_localtime ), NULL ) + PHP_NAMED_FE( getErrorCode, ZEND_FN( datefmt_get_error_code ), NULL ) + PHP_NAMED_FE( getErrorMessage, ZEND_FN( datefmt_get_error_message ), NULL ) + { NULL, NULL, NULL } +}; +/* }}} */ + +/* {{{ dateformat_register_class + * Initialize 'IntlDateFormatter' class + */ +void dateformat_register_IntlDateFormatter_class( TSRMLS_D ) +{ + zend_class_entry ce; + + // Create and register 'IntlDateFormatter' class. + INIT_CLASS_ENTRY( ce, "IntlDateFormatter", IntlDateFormatter_class_functions ); + ce.create_object = IntlDateFormatter_object_create; + IntlDateFormatter_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC ); + + // Declare 'IntlDateFormatter' class properties. + if( !IntlDateFormatter_ce_ptr ) + { + zend_error(E_ERROR, "Failed to register IntlDateFormatter class"); + return; + } +} +/* }}} */ diff --git a/ext/intl/dateformat/dateformat_class.h b/ext/intl/dateformat/dateformat_class.h new file mode 100755 index 0000000000..039ff1a59a --- /dev/null +++ b/ext/intl/dateformat/dateformat_class.h @@ -0,0 +1,44 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_CLASS_H +#define DATE_FORMAT_CLASS_H + +#include + +#include "intl_common.h" +#include "intl_error.h" +#include "intl_data.h" +#include "dateformat_data.h" + +typedef struct { + zend_object zo; + dateformat_data datef_data; + int date_type ; + int time_type ; + int calendar ; + char* timezone_id; +} IntlDateFormatter_object; + +void dateformat_register_IntlDateFormatter_class( TSRMLS_D ); +extern zend_class_entry *IntlDateFormatter_ce_ptr; + +/* Auxiliary macros */ + +#define DATE_FORMAT_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(IntlDateFormatter, mfo) +#define DATE_FORMAT_METHOD_FETCH_OBJECT INTL_METHOD_FETCH_OBJECT(IntlDateFormatter, mfo) +#define DATE_FORMAT_OBJECT(mfo) (mfo)->datef_data.udatf + +#endif // #ifndef DATE_FORMAT_CLASS_H diff --git a/ext/intl/dateformat/dateformat_data.c b/ext/intl/dateformat/dateformat_data.c new file mode 100755 index 0000000000..33451e1c51 --- /dev/null +++ b/ext/intl/dateformat/dateformat_data.c @@ -0,0 +1,62 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dateformat_data.h" + +/* {{{ void dateformat_data_init( dateformat_data* datef_data ) + * Initialize internals of dateformat_data. + */ +void dateformat_data_init( dateformat_data* datef_data TSRMLS_DC ) +{ + if( !datef_data ) + return; + + datef_data->udatf = NULL; + intl_error_reset( &datef_data->error TSRMLS_CC ); +} +/* }}} */ + +/* {{{ void dateformat_data_free( dateformat_data* datef_data ) + * Clean up memory allocated for dateformat_data + */ +void dateformat_data_free( dateformat_data* datef_data TSRMLS_DC ) +{ + if( !datef_data ) + return; + + if( datef_data->udatf ) + udat_close( datef_data->udatf ); + + datef_data->udatf = NULL; + intl_error_reset( &datef_data->error TSRMLS_CC ); +} +/* }}} */ + +/* {{{ dateformat_data* dateformat_data_create() + * Allocate memory for dateformat_data and initialize it with default values. + */ +dateformat_data* dateformat_data_create( TSRMLS_D ) +{ + dateformat_data* datef_data = ecalloc( 1, sizeof(dateformat_data) ); + + dateformat_data_init( datef_data TSRMLS_CC ); + + return datef_data; +} +/* }}} */ diff --git a/ext/intl/dateformat/dateformat_data.h b/ext/intl/dateformat/dateformat_data.h new file mode 100755 index 0000000000..cde9e363c9 --- /dev/null +++ b/ext/intl/dateformat/dateformat_data.h @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_DATA_H +#define DATE_FORMAT_DATA_H + +#include + +#include + +#include "intl_error.h" + +typedef struct { + // error hangling + intl_error error; + + // formatter handling + UDateFormat * udatf; +} dateformat_data; + +dateformat_data* dateformat_data_create( TSRMLS_D ); +void dateformat_data_init( dateformat_data* datef_data TSRMLS_DC ); +void dateformat_data_free( dateformat_data* datef_data TSRMLS_DC ); + +#endif // DATE_FORMAT_DATA_H diff --git a/ext/intl/dateformat/dateformat_format.c b/ext/intl/dateformat/dateformat_format.c new file mode 100755 index 0000000000..c23ab3203d --- /dev/null +++ b/ext/intl/dateformat/dateformat_format.c @@ -0,0 +1,184 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "php_intl.h" +#include "intl_convert.h" +#include "dateformat.h" +#include "dateformat_class.h" +#include "dateformat_format.h" +#include "dateformat_data.h" + +/* {{{ + * Internal function which calls the udat_format +*/ +static void internal_format(IntlDateFormatter_object *mfo, UDate timestamp , zval *return_value TSRMLS_DC){ + UChar* formatted = NULL; + int32_t resultlengthneeded =0 ; + + resultlengthneeded=udat_format( DATE_FORMAT_OBJECT(mfo), timestamp, NULL, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(mfo)); + if(INTL_DATA_ERROR_CODE(mfo)==U_BUFFER_OVERFLOW_ERROR) + { + INTL_DATA_ERROR_CODE(mfo)=U_ZERO_ERROR; + formatted=(UChar*)emalloc(sizeof(UChar) * resultlengthneeded); + udat_format( DATE_FORMAT_OBJECT(mfo), timestamp, formatted, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(mfo)); + } + + if (formatted && U_FAILURE( INTL_DATA_ERROR_CODE(mfo) ) ) { + efree(formatted); + } + + INTL_METHOD_CHECK_STATUS( mfo, "Date formatting failed" ); + INTL_METHOD_RETVAL_UTF8( mfo, formatted, resultlengthneeded, 1 ); + +} +/* }}} */ + + +/* {{{ + * Internal function which fetches an element from the passed array for the key_name passed +*/ +static double internal_get_arr_ele(IntlDateFormatter_object *mfo , HashTable* hash_arr ,char* key_name TSRMLS_DC){ + zval** ele_value = NULL; + UDate result = -1; + + if( zend_hash_find( hash_arr , key_name , strlen(key_name) + 1 ,(void **)&ele_value ) == SUCCESS ){ + if( Z_TYPE_PP(ele_value)!= IS_LONG ){ + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_format: parameter array does not contain a long element.", 0 TSRMLS_CC ); + }else{ + result = Z_LVAL_PP(ele_value); + } + } + //printf("\n Inside internal_get_arr_ele key_name= %s , result = %g \n" , key_name, result); + return result; +} +/* }}} */ + +/* {{{ + * Internal function which creates a UCalendar from the passed array +*/ +static void internal_create_ucal(IntlDateFormatter_object *mfo, HashTable* hash_arr , UCalendar* pcal TSRMLS_DC){ + long year =0; + long month =0; + long hour =0; + long minute =0; + long second =0; + long wday =0; + long yday =0; + long mday =0; + UBool isInDST = FALSE; + + //Fetch values from the incoming array + year = internal_get_arr_ele( mfo , hash_arr , CALENDAR_YEAR TSRMLS_CC) + 1900; //tm_year is years since 1900 + //Month in ICU and PHP starts from January =0 + month = internal_get_arr_ele( mfo , hash_arr , CALENDAR_MON TSRMLS_CC); + hour = internal_get_arr_ele( mfo , hash_arr , CALENDAR_HOUR TSRMLS_CC); + minute = internal_get_arr_ele( mfo , hash_arr , CALENDAR_MIN TSRMLS_CC); + second = internal_get_arr_ele( mfo , hash_arr , CALENDAR_SEC TSRMLS_CC); + wday = internal_get_arr_ele( mfo , hash_arr , CALENDAR_WDAY TSRMLS_CC); + yday = internal_get_arr_ele( mfo , hash_arr , CALENDAR_YDAY TSRMLS_CC); + isInDST = internal_get_arr_ele( mfo , hash_arr , CALENDAR_ISDST TSRMLS_CC); + //For the ucal_setDateTime() function , this is the 'date' value + mday = internal_get_arr_ele( mfo , hash_arr , CALENDAR_MDAY TSRMLS_CC); + + //set the incoming values for the calendar + ucal_setDateTime( pcal, year, month , mday , hour , minute , second , &INTL_DATA_ERROR_CODE(mfo)); + if( INTL_DATA_ERROR_CODE(mfo) != U_ZERO_ERROR){ + return; + } + //ICU UCAL_DAY_OF_WEEK starts from SUNDAY=1 thru SATURDAY=7 + //whereas PHP localtime has tm_wday SUNDAY=0 thru SATURDAY=6 + ucal_set( pcal, UCAL_DAY_OF_WEEK , (wday+1)); + ucal_set( pcal, UCAL_DAY_OF_YEAR , yday); + + //TO DO :How to set the isInDST field?Is it required to set +} + + +/* {{{ proto string IntlDateFormatter::format( [mixed]int $args or array $args ) + * Format the time value as a string. }}}*/ +/* {{{ proto string datefmt_format( [mixed]int $args or array $args ) + * Format the time value as a string. }}}*/ +PHP_FUNCTION(datefmt_format) +{ + UDate timestamp =0; + UDate p_timestamp =0; + UCalendar* temp_cal ; + HashTable* hash_arr = NULL; + zval* zarg = NULL; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &object, IntlDateFormatter_ce_ptr ,&zarg ) == FAILURE ) + { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_format: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + + switch(Z_TYPE_P(zarg) ){ + case IS_LONG: + p_timestamp = Z_LVAL_P(zarg) ; + timestamp = p_timestamp * 1000; + break; + case IS_DOUBLE: + //timestamp*1000 since ICU expects it in milliseconds + p_timestamp = Z_DVAL_P(zarg) ; + timestamp = p_timestamp * 1000; + break; + case IS_ARRAY: + hash_arr = Z_ARRVAL_P(zarg); + if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) + RETURN_FALSE; + //Create a UCalendar object from the array and then format it + temp_cal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &INTL_DATA_ERROR_CODE(mfo)); + ucal_clear(temp_cal); + INTL_METHOD_CHECK_STATUS( mfo, "datefmt_format: Date formatting failed while creating calendar from the array" ) + internal_create_ucal( mfo , hash_arr , temp_cal TSRMLS_CC); + INTL_METHOD_CHECK_STATUS( mfo, "datefmt_format: Date formatting failed while creating calendar from the array" ) + //Fetch the timestamp from the created UCalendar + timestamp = ucal_getMillis(temp_cal , &INTL_DATA_ERROR_CODE(mfo) ); + INTL_METHOD_CHECK_STATUS( mfo, "datefmt_format: Date formatting failed" ) + break; +/* + case IS_OBJECT: + break; +*/ + default: + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_format: takes either an array or an integer TimeStamp value ", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + internal_format( mfo, timestamp ,return_value TSRMLS_CC); + +} + +/* }}} */ + diff --git a/ext/intl/dateformat/dateformat_format.h b/ext/intl/dateformat/dateformat_format.h new file mode 100755 index 0000000000..49f34c6892 --- /dev/null +++ b/ext/intl/dateformat/dateformat_format.h @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Stanislav Malyshev | + +----------------------------------------------------------------------+ + */ + +#ifndef DATE_FORMAT_FORMAT_H +#define DATE_FORMAT_FORMAT_H + +#include + +PHP_FUNCTION( datefmt_format ); + +#endif // DATE_FORMAT_FORMAT_H diff --git a/ext/intl/dateformat/dateformat_parse.c b/ext/intl/dateformat/dateformat_parse.c new file mode 100755 index 0000000000..0e9e936502 --- /dev/null +++ b/ext/intl/dateformat/dateformat_parse.c @@ -0,0 +1,181 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "php_intl.h" +#include "intl_convert.h" +#include "dateformat.h" +#include "dateformat_class.h" +#include "dateformat_parse.h" +#include "dateformat_data.h" + +/* {{{ + * Internal function which calls the udat_parse + * param int store_error acts like a boolean + * if set to 1 - store any error encountered in the parameter parse_error + * if set to 0 - no need to store any error encountered in the parameter parse_error +*/ +static void internal_parse_to_timestamp(IntlDateFormatter_object *mfo, char* text_to_parse , int32_t text_len, int parse_pos , zval *return_value TSRMLS_DC){ + long result = 0; + UDate timestamp =0; + UChar* text_utf16 = NULL; + int32_t text_utf16_len = 0; + + // Convert timezone to UTF-16. + intl_convert_utf8_to_utf16(&text_utf16 , &text_utf16_len , text_to_parse , text_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting timezone to UTF-16" ); + + timestamp = udat_parse( DATE_FORMAT_OBJECT(mfo), text_utf16 , text_utf16_len , &parse_pos , &INTL_DATA_ERROR_CODE(mfo)); + if( text_utf16 ){ + efree(text_utf16); + } + + INTL_METHOD_CHECK_STATUS( mfo, "Date parsing failed" ); + + //Since return is in sec. + result = (long )( timestamp / 1000 ); + if( result != (timestamp/1000) ) { + intl_error_set( NULL, U_BUFFER_OVERFLOW_ERROR, + "datefmt_parse: parsing of input parametrs resulted in value larger than data type long can handle.\nThe valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT.", 0 TSRMLS_CC ); + } + RETURN_LONG( result ); +} +/* }}} */ + +static void add_to_localtime_arr( IntlDateFormatter_object *mfo, zval* return_value ,UCalendar parsed_calendar , long calendar_field , char* key_name TSRMLS_DC){ + long calendar_field_val = ucal_get( parsed_calendar , calendar_field , &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS( mfo, "Date parsing - localtime failed : could not get a field from calendar" ); + + if( strcmp(key_name , CALENDAR_YEAR )==0 ){ + //since tm_year is years from 1900 + add_assoc_long( return_value, key_name ,( calendar_field_val-1900) ); + }else if( strcmp(key_name , CALENDAR_WDAY )==0 ){ + //since tm_wday starts from 0 whereas ICU WDAY start from 1 + add_assoc_long( return_value, key_name ,( calendar_field_val-1) ); + }else{ + add_assoc_long( return_value, key_name , calendar_field_val ); + } +} + +/* {{{ + * Internal function which calls the udat_parseCalendar +*/ +static void internal_parse_to_localtime(IntlDateFormatter_object *mfo, char* text_to_parse , int32_t text_len, int parse_pos , zval *return_value TSRMLS_DC){ + UCalendar* parsed_calendar = NULL ; + UChar* text_utf16 = NULL; + int32_t text_utf16_len = 0; + long isInDST = 0; + + // Convert timezone to UTF-16. + intl_convert_utf8_to_utf16(&text_utf16 , &text_utf16_len , text_to_parse , text_len, &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS(mfo, "Error converting timezone to UTF-16" ); + + parsed_calendar = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &INTL_DATA_ERROR_CODE(mfo)); + udat_parseCalendar( DATE_FORMAT_OBJECT(mfo), parsed_calendar , text_utf16 , text_utf16_len , &parse_pos , &INTL_DATA_ERROR_CODE(mfo)); + if( text_utf16 ){ + efree(text_utf16); + } + + INTL_METHOD_CHECK_STATUS( mfo, "Date parsing failed" ); + + + array_init( return_value ); + //Add entries from various fields of the obtained parsed_calendar + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_SECOND , CALENDAR_SEC TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_MINUTE , CALENDAR_MIN TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_HOUR_OF_DAY , CALENDAR_HOUR TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_YEAR , CALENDAR_YEAR TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_DAY_OF_MONTH , CALENDAR_MDAY TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_DAY_OF_WEEK , CALENDAR_WDAY TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_DAY_OF_YEAR , CALENDAR_YDAY TSRMLS_CC); + add_to_localtime_arr( mfo , return_value , parsed_calendar , UCAL_MONTH , CALENDAR_MON TSRMLS_CC); + + //Is in DST? + isInDST = ucal_inDaylightTime(parsed_calendar , &INTL_DATA_ERROR_CODE(mfo)); + INTL_METHOD_CHECK_STATUS( mfo, "Date parsing - localtime failed : while checking if currently in DST." ); + add_assoc_long( return_value, CALENDAR_ISDST ,(isInDST==1?1:0)); +} +/* }}} */ + + +/* {{{ proto integer IntlDateFormatter::parse( string $text_to_parse , int $parse_pos ) + * Parse the string $value starting at parse_pos to a Unix timestamp -int }}}*/ +/* {{{ proto integer datefmt_parse( IntlDateFormatter $fmt, string $text_to_parse , int $parse_pos ) + * Parse the string $value starting at parse_pos to a Unix timestamp -int }}}*/ +PHP_FUNCTION(datefmt_parse) +{ + + char* text_to_parse = NULL; + int32_t text_len =0; + long parse_pos =0; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", + &object, IntlDateFormatter_ce_ptr, &text_to_parse , &text_len , &parse_pos ) == FAILURE ){ + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_parse: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + internal_parse_to_timestamp( mfo, text_to_parse , text_len , + parse_pos , + return_value TSRMLS_CC); + +} +/* }}} */ + +/* {{{ proto integer IntlDateFormatter::localtime( string $text_to_parse, int $parse_pos ) + * Parse the string $value to a localtime array }}}*/ +/* {{{ proto integer datefmt_localtime( IntlDateFormatter $fmt, string $text_to_parse, int $parse_pos ) + * Parse the string $value to a localtime array }}}*/ +PHP_FUNCTION(datefmt_localtime) +{ + + char* text_to_parse = NULL; + int32_t text_len =0; + long parse_pos =0; + + DATE_FORMAT_METHOD_INIT_VARS; + + // Parse parameters. + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osl", + &object, IntlDateFormatter_ce_ptr, &text_to_parse , &text_len , &parse_pos ) == FAILURE ){ + + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_parse_to_localtime: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + // Fetch the object. + DATE_FORMAT_METHOD_FETCH_OBJECT; + + internal_parse_to_localtime( mfo, text_to_parse , text_len , + parse_pos, + return_value TSRMLS_CC); + +} +/* }}} */ + diff --git a/ext/intl/dateformat/dateformat_parse.h b/ext/intl/dateformat/dateformat_parse.h new file mode 100755 index 0000000000..c74a3d5f15 --- /dev/null +++ b/ext/intl/dateformat/dateformat_parse.h @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Kirti Velankar | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_PARSE_H +#define DATE_FORMAT_PARSE_H + +#include + +PHP_FUNCTION( datefmt_parse ); +PHP_FUNCTION( datefmt_localtime ); + +#endif // DATE_FORMAT_PARSE_H