diff options
Diffstat (limited to 'ext/intl/dateformat')
-rw-r--r-- | ext/intl/dateformat/dateformat.c | 272 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat.h | 45 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_attr.c | 412 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_attr.h | 34 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_class.c | 208 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_class.h | 52 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_data.c | 62 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_data.h | 37 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_format.c | 194 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_format.h | 24 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_parse.c | 199 | ||||
-rw-r--r-- | ext/intl/dateformat/dateformat_parse.h | 24 |
12 files changed, 1563 insertions, 0 deletions
diff --git a/ext/intl/dateformat/dateformat.c b/ext/intl/dateformat/dateformat.c new file mode 100644 index 0000000..8aded18 --- /dev/null +++ b/ext/intl/dateformat/dateformat.c @@ -0,0 +1,272 @@ +/* + +----------------------------------------------------------------------+ + | 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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/ustring.h> +#include <unicode/udat.h> +#include <unicode/ucal.h> + +#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 +} +/* }}} */ + +/* {{{ */ +static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) +{ + char* locale; + int locale_len = 0; + zval* object; + long date_type = 0; + long time_type = 0; + long calendar = UCAL_GREGORIAN; + 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* dfo; + + intl_error_reset( NULL TSRMLS_CC ); + object = return_value; + /* 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 parameters", 0 TSRMLS_CC ); + zval_dtor(return_value); + RETURN_NULL(); + } + + INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value); + + if (calendar != UCAL_TRADITIONAL && calendar != UCAL_GREGORIAN) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: " + "invalid value for calendar type; it must be one of " + "IntlDateFormatter::TRADITIONAL (locale's default calendar) " + "or IntlDateFormatter::GREGORIAN", 0 TSRMLS_CC); + goto error; + } + + DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; + + if (DATE_FORMAT_OBJECT(dfo) != NULL) { + intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_create: cannot call constructor twice", 0 TSRMLS_CC); + return; + } + + /* 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(dfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + /* object construction -> only set global error */ + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " + "error converting pattern to UTF-16", 0 TSRMLS_CC); + goto error; + } + } + + /* resources allocated from now on */ + + /* 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(dfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " + "error converting timezone_str to UTF-16", 0 TSRMLS_CC); + goto error; + } + } + + if(locale_len == 0) { + locale = INTL_G(default_locale); + } + + if( pattern_str && pattern_str_len>0 ){ + DATE_FORMAT_OBJECT(dfo) = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo)); + } else { + DATE_FORMAT_OBJECT(dfo) = udat_open(time_type, date_type, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo)); + } + + if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + if (calendar != UCAL_TRADITIONAL) { + ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale, + calendar, &INTL_DATA_ERROR_CODE(dfo)); + if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + udat_setCalendar(DATE_FORMAT_OBJECT(dfo), ucal_obj); + ucal_close(ucal_obj); + } else { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create" + ": error opening calendar", 0 TSRMLS_CC); + goto error; + } + } + } else { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date " + "formatter creation failed", 0 TSRMLS_CC); + goto error; + } + + /* Set the class variables */ + dfo->date_type = date_type; + dfo->time_type = time_type; + dfo->calendar = calendar; + if( timezone_str && timezone_str_len > 0){ + dfo->timezone_id = estrndup( timezone_str, timezone_str_len); + } + +error: + if (svalue) { + efree(svalue); + } + if (timezone_utf16) { + efree(timezone_utf16); + } + if (U_FAILURE(intl_error_get_code(NULL TSRMLS_CC))) { + /* free_object handles partially constructed instances fine */ + zval_dtor(return_value); + RETVAL_NULL(); + } +} +/* }}} */ + +/* {{{ 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 ) +{ + object_init_ex( return_value, IntlDateFormatter_ce_ptr ); + datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ proto void IntlDateFormatter::__construct(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern]) + * IntlDateFormatter object constructor. + */ +PHP_METHOD( IntlDateFormatter, __construct ) +{ + /* return_value param is being changed, therefore we will always return + * NULL here */ + return_value = getThis(); + datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ 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 ) +{ + 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_error_code: unable to parse input params", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + dfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + /* Return formatter's last error code. */ + RETURN_LONG( INTL_DATA_ERROR_CODE(dfo) ); +} +/* }}} */ + +/* {{{ 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; + 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_error_message: unable to parse input params", 0 TSRMLS_CC ); + + RETURN_FALSE; + } + + dfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC ); + + /* Return last error message. */ + message = intl_error_get_message( INTL_DATA_ERROR_P(dfo) TSRMLS_CC ); + RETURN_STRING( message, 0); +} +/* }}} */ diff --git a/ext/intl/dateformat/dateformat.h b/ext/intl/dateformat/dateformat.h new file mode 100644 index 0000000..f11918b --- /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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMATTER_H +#define DATE_FORMATTER_H + +#include <php.h> + +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 100644 index 0000000..b8c5f25 --- /dev/null +++ b/ext/intl/dateformat/dateformat_attr.c @@ -0,0 +1,412 @@ +/* + +----------------------------------------------------------------------+ + | 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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../php_intl.h" +#include "dateformat_class.h" +#include "../intl_convert.h" +#include "dateformat_class.h" +#include "dateformat_attr.h" + +#include <unicode/ustring.h> +#include <unicode/udat.h> +#include <unicode/ucal.h> + +static void internal_set_calendar(IntlDateFormatter_object *dfo, 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; + + 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(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); + + /* Get the locale for the dateformatter */ + locale = (char *)udat_getLocaleByType(DATE_FORMAT_OBJECT(dfo), ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(dfo)); + + /* Set the calendar if passed */ + ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale, calendar, &INTL_DATA_ERROR_CODE(dfo) ); + udat_setCalendar( DATE_FORMAT_OBJECT(dfo), ucal_obj ); + INTL_METHOD_CHECK_STATUS(dfo, "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(dfo, "Error getting formatter datetype." ); + + RETURN_LONG(dfo->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(dfo, "Error getting formatter timetype." ); + + RETURN_LONG(dfo->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(dfo, "Error getting formatter calendar." ); + + RETURN_LONG(dfo->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(dfo, "Error getting formatter timezone_id." ); + + if( dfo->timezone_id ){ + RETURN_STRING((char*)dfo->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( dfo, timezone_id, timezone_id_len, dfo->calendar, return_value TSRMLS_CC ); + + /* Set the IntlDateFormatter variable */ + if( dfo->timezone_id ){ + efree(dfo->timezone_id); + } + dfo->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(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo)); + if(INTL_DATA_ERROR_CODE(dfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) { + ++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */ + INTL_DATA_ERROR_CODE(dfo) = U_ZERO_ERROR; + value = eumalloc(length); + length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo) ); + if(U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + efree(value); + value = value_buf; + } + } + INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter pattern" ); + + INTL_METHOD_RETVAL_UTF8( dfo, 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(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting pattern to UTF-16" ); + + udat_applyPattern(DATE_FORMAT_OBJECT(dfo), (UBool)is_pattern_localized, svalue, slength); + + if (svalue) { + efree(svalue); + } + INTL_METHOD_CHECK_STATUS(dfo, "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(dfo), loc_type,&INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error getting locale"); + 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(dfo))); +} +/* }}} */ + +/* {{{ 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(dfo), (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( dfo, dfo->timezone_id, strlen(dfo->timezone_id), calendar, return_value TSRMLS_CC ); + + /* Set the calendar value in the IntlDateFormatter object */ + dfo->calendar = calendar; + + RETURN_TRUE; +} +/* }}} */ + + diff --git a/ext/intl/dateformat/dateformat_attr.h b/ext/intl/dateformat/dateformat_attr.h new file mode 100644 index 0000000..bf28824 --- /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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_ATTR_H +#define DATE_FORMAT_ATTR_H + +#include <php.h> + +//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 100644 index 0000000..49f316f --- /dev/null +++ b/ext/intl/dateformat/dateformat_class.c @@ -0,0 +1,208 @@ +/* + +----------------------------------------------------------------------+ + | 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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#include <unicode/unum.h> + +#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" + +#include <zend_exceptions.h> + +zend_class_entry *IntlDateFormatter_ce_ptr = NULL; +static zend_object_handlers IntlDateFormatter_handlers; + +/* + * 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* dfo = (IntlDateFormatter_object*)object; + + zend_object_std_dtor( &dfo->zo TSRMLS_CC ); + + dateformat_data_free( &dfo->datef_data TSRMLS_CC ); + + if( dfo->timezone_id ){ + efree(dfo->timezone_id); + } + + efree( dfo ); +} +/* }}} */ + +/* {{{ 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 ); + object_properties_init(&intern->zo, ce); + 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 = &IntlDateFormatter_handlers; + + return retval; +} +/* }}} */ + +/* {{{ IntlDateFormatter_object_clone */ +zend_object_value IntlDateFormatter_object_clone(zval *object TSRMLS_DC) +{ + zend_object_value new_obj_val; + zend_object_handle handle = Z_OBJ_HANDLE_P(object); + IntlDateFormatter_object *dfo, *new_dfo; + + DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; + + new_obj_val = IntlDateFormatter_ce_ptr->create_object(Z_OBJCE_P(object) TSRMLS_CC); + new_dfo = (IntlDateFormatter_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC); + /* clone standard parts */ + zend_objects_clone_members(&new_dfo->zo, new_obj_val, &dfo->zo, handle TSRMLS_CC); + /* clone formatter object */ + if (dfo->datef_data.udatf != NULL) { + DATE_FORMAT_OBJECT(new_dfo) = udat_clone(DATE_FORMAT_OBJECT(dfo), &INTL_DATA_ERROR_CODE(dfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + /* set up error in case error handler is interested */ + intl_errors_set(INTL_DATA_ERROR_P(dfo), INTL_DATA_ERROR_CODE(dfo), + "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC ); + zend_throw_exception(NULL, "Failed to clone IntlDateFormatter object", 0 TSRMLS_CC); + } + } else { + zend_throw_exception(NULL, "Cannot clone unconstructed IntlDateFormatter", 0 TSRMLS_CC); + } + return new_obj_val; +} +/* }}} */ + +/* + * 'IntlDateFormatter' class registration structures & functions + */ + +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(datefmt_parse_args, 0, 0, 1) + ZEND_ARG_INFO(0, string) + ZEND_ARG_INFO(1, position) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_format, 0, 0, 0) + ZEND_ARG_INFO(0, args) + ZEND_ARG_INFO(0, array) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_intldateformatter_getdatetype, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_settimezoneid, 0, 0, 1) + ZEND_ARG_INFO(0, zone) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_setpattern, 0, 0, 1) + ZEND_ARG_INFO(0, pattern) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_setlenient, 0, 0, 1) + ZEND_ARG_INFO(0, lenient) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_setcalendar, 0, 0, 1) + ZEND_ARG_INFO(0, which) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter___construct, 0, 0, 3) + ZEND_ARG_INFO(0, locale) + ZEND_ARG_INFO(0, datetype) + ZEND_ARG_INFO(0, timetype) + ZEND_ARG_INFO(0, timezone) + ZEND_ARG_INFO(0, calendar) + ZEND_ARG_INFO(0, pattern) +ZEND_END_ARG_INFO() +/* }}} */ + +/* {{{ IntlDateFormatter_class_functions + * Every 'IntlDateFormatter' class method has an entry in this table + */ +static zend_function_entry IntlDateFormatter_class_functions[] = { + PHP_ME( IntlDateFormatter, __construct, arginfo_intldateformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR ) + ZEND_FENTRY( create, ZEND_FN( datefmt_create ), arginfo_intldateformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC ) + PHP_NAMED_FE( getDateType, ZEND_FN( datefmt_get_datetype ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( getTimeType, ZEND_FN( datefmt_get_timetype ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( getCalendar, ZEND_FN( datefmt_get_calendar ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( setCalendar, ZEND_FN( datefmt_set_calendar ), arginfo_intldateformatter_setcalendar ) + PHP_NAMED_FE( getTimeZoneId, ZEND_FN( datefmt_get_timezone_id ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( setTimeZoneId, ZEND_FN( datefmt_set_timezone_id ), arginfo_intldateformatter_settimezoneid ) + PHP_NAMED_FE( setPattern, ZEND_FN( datefmt_set_pattern ), arginfo_intldateformatter_setpattern ) + PHP_NAMED_FE( getPattern, ZEND_FN( datefmt_get_pattern ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( getLocale, ZEND_FN( datefmt_get_locale ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( setLenient, ZEND_FN( datefmt_set_lenient ), arginfo_intldateformatter_setlenient ) + PHP_NAMED_FE( isLenient, ZEND_FN( datefmt_is_lenient ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( format, ZEND_FN( datefmt_format ), arginfo_intldateformatter_format ) + PHP_NAMED_FE( parse, ZEND_FN( datefmt_parse), datefmt_parse_args ) + PHP_NAMED_FE( localtime, ZEND_FN( datefmt_localtime ), datefmt_parse_args ) + PHP_NAMED_FE( getErrorCode, ZEND_FN( datefmt_get_error_code ), arginfo_intldateformatter_getdatetype ) + PHP_NAMED_FE( getErrorMessage, ZEND_FN( datefmt_get_error_message ), arginfo_intldateformatter_getdatetype ) + PHP_FE_END +}; +/* }}} */ + +/* {{{ 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 ); + + memcpy(&IntlDateFormatter_handlers, zend_get_std_object_handlers(), + sizeof IntlDateFormatter_handlers); + IntlDateFormatter_handlers.clone_obj = IntlDateFormatter_object_clone; + + /* 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 100644 index 0000000..d58abe4 --- /dev/null +++ b/ext/intl/dateformat/dateformat_class.h @@ -0,0 +1,52 @@ +/* + +----------------------------------------------------------------------+ + | 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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_CLASS_H +#define DATE_FORMAT_CLASS_H + +#include <php.h> + +#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, dfo) +#define DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(IntlDateFormatter, dfo) +#define DATE_FORMAT_METHOD_FETCH_OBJECT \ + DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; \ + if (dfo->datef_data.udatf == NULL) \ + { \ + intl_errors_set(&dfo->datef_data.error, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed IntlDateFormatter", 0 TSRMLS_CC); \ + RETURN_FALSE; \ + } + +#define DATE_FORMAT_OBJECT(dfo) (dfo)->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 100644 index 0000000..33451e1 --- /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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#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 100644 index 0000000..cde9e36 --- /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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_DATA_H +#define DATE_FORMAT_DATA_H + +#include <php.h> + +#include <unicode/udat.h> + +#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 100644 index 0000000..4d03d92 --- /dev/null +++ b/ext/intl/dateformat/dateformat_format.c @@ -0,0 +1,194 @@ +/* + +----------------------------------------------------------------------+ + | 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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/ustring.h> +#include <unicode/ucal.h> + +#include "php_intl.h" +#include "intl_convert.h" +#include "dateformat.h" +#include "dateformat_class.h" +#include "dateformat_format.h" +#include "dateformat_data.h" +#include "ext/date/php_date.h" + +/* {{{ + * Internal function which calls the udat_format +*/ +static void internal_format(IntlDateFormatter_object *dfo, UDate timestamp, zval *return_value TSRMLS_DC) +{ + UChar* formatted = NULL; + int32_t resultlengthneeded =0 ; + + resultlengthneeded=udat_format( DATE_FORMAT_OBJECT(dfo), timestamp, NULL, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(dfo)); + if(INTL_DATA_ERROR_CODE(dfo)==U_BUFFER_OVERFLOW_ERROR) + { + INTL_DATA_ERROR_CODE(dfo)=U_ZERO_ERROR; + formatted=(UChar*)emalloc(sizeof(UChar) * resultlengthneeded); + udat_format( DATE_FORMAT_OBJECT(dfo), timestamp, formatted, resultlengthneeded, NULL, &INTL_DATA_ERROR_CODE(dfo)); + } + + if (formatted && U_FAILURE( INTL_DATA_ERROR_CODE(dfo) ) ) { + efree(formatted); + } + + INTL_METHOD_CHECK_STATUS( dfo, "Date formatting failed" ); + INTL_METHOD_RETVAL_UTF8( dfo, 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 *dfo, 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 sets UCalendar from the passed array and retrieves timestamp +*/ +static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, HashTable* hash_arr 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; + UCalendar *pcal; + + /* Fetch values from the incoming array */ + year = internal_get_arr_ele( dfo, 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( dfo, hash_arr, CALENDAR_MON TSRMLS_CC); + hour = internal_get_arr_ele( dfo, hash_arr, CALENDAR_HOUR TSRMLS_CC); + minute = internal_get_arr_ele( dfo, hash_arr, CALENDAR_MIN TSRMLS_CC); + second = internal_get_arr_ele( dfo, hash_arr, CALENDAR_SEC TSRMLS_CC); + wday = internal_get_arr_ele( dfo, hash_arr, CALENDAR_WDAY TSRMLS_CC); + yday = internal_get_arr_ele( dfo, hash_arr, CALENDAR_YDAY TSRMLS_CC); + isInDST = internal_get_arr_ele( dfo, hash_arr, CALENDAR_ISDST TSRMLS_CC); + /* For the ucal_setDateTime() function, this is the 'date' value */ + mday = internal_get_arr_ele( dfo, hash_arr, CALENDAR_MDAY TSRMLS_CC); + + pcal = udat_getCalendar(DATE_FORMAT_OBJECT(dfo)); + /* set the incoming values for the calendar */ + ucal_setDateTime( pcal, year, month, mday, hour, minute, second, &INTL_DATA_ERROR_CODE(dfo)); + if( INTL_DATA_ERROR_CODE(dfo) != U_ZERO_ERROR){ + return 0; + } + + /* Fetch the timestamp from the UCalendar */ + return ucal_getMillis(pcal, &INTL_DATA_ERROR_CODE(dfo) ); +} + + +/* {{{ 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; + 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; + + timestamp = internal_get_timestamp(dfo, hash_arr TSRMLS_CC); + INTL_METHOD_CHECK_STATUS( dfo, "datefmt_format: Date formatting failed" ) + break; + case IS_OBJECT: { + zend_class_entry *date_ce = php_date_get_date_ce(); + zval retval; + zval *zfuncname; + if(!instanceof_function(Z_OBJCE_P(zarg), date_ce TSRMLS_CC)) { + intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: object must be an instance of DateTime", 0 TSRMLS_CC ); + RETURN_FALSE; + } + INIT_ZVAL(retval); + MAKE_STD_ZVAL(zfuncname); + ZVAL_STRING(zfuncname, "getTimestamp", 1); + if(call_user_function(NULL, &zarg, zfuncname, &retval, 0, NULL TSRMLS_CC) != SUCCESS || Z_TYPE(retval) != IS_LONG) { + intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: cannot get timestamp", 0 TSRMLS_CC ); + zval_ptr_dtor(&zfuncname); + RETURN_FALSE; + } + zval_ptr_dtor(&zfuncname); + p_timestamp = Z_LVAL(retval); + timestamp = p_timestamp*1000; + } + break; + default: + intl_errors_set( INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_format: takes either an array or an integer timestamp value or a DateTime object", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + internal_format( dfo, timestamp, return_value TSRMLS_CC); + +} + +/* }}} */ + diff --git a/ext/intl/dateformat/dateformat_format.h b/ext/intl/dateformat/dateformat_format.h new file mode 100644 index 0000000..49f34c6 --- /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 <stas@zend.com> | + +----------------------------------------------------------------------+ + */ + +#ifndef DATE_FORMAT_FORMAT_H +#define DATE_FORMAT_FORMAT_H + +#include <php.h> + +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 100644 index 0000000..4193e89 --- /dev/null +++ b/ext/intl/dateformat/dateformat_parse.c @@ -0,0 +1,199 @@ +/* + +----------------------------------------------------------------------+ + | 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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unicode/ustring.h> +#include <math.h> + +#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 *dfo, char* text_to_parse, int32_t text_len, int32_t *parse_pos, zval *return_value TSRMLS_DC) +{ + double 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(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); + + timestamp = udat_parse( DATE_FORMAT_OBJECT(dfo), text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); + if( text_utf16 ){ + efree(text_utf16); + } + + INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" ); + + /* Since return is in sec. */ + result = (double)timestamp / U_MILLIS_PER_SECOND; + if(result > LONG_MAX || result < -LONG_MAX) { + ZVAL_DOUBLE(return_value, result<0?ceil(result):floor(result)); + } else { + ZVAL_LONG(return_value, (long)result); + } +} +/* }}} */ + +static void add_to_localtime_arr( IntlDateFormatter_object *dfo, 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(dfo)); + INTL_METHOD_CHECK_STATUS( dfo, "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 *dfo, char* text_to_parse, int32_t text_len, int32_t *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(dfo)); + INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" ); + + parsed_calendar = udat_getCalendar(DATE_FORMAT_OBJECT(dfo)); + udat_parseCalendar( DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo)); + + if (text_utf16) { + efree(text_utf16); + } + + INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" ); + + + array_init( return_value ); + /* Add entries from various fields of the obtained parsed_calendar */ + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_SECOND, CALENDAR_SEC TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MINUTE, CALENDAR_MIN TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_HOUR_OF_DAY, CALENDAR_HOUR TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_YEAR, CALENDAR_YEAR TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_MONTH, CALENDAR_MDAY TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_WEEK, CALENDAR_WDAY TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_YEAR, CALENDAR_YDAY TSRMLS_CC); + add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MONTH, CALENDAR_MON TSRMLS_CC); + + /* Is in DST? */ + isInDST = ucal_inDaylightTime(parsed_calendar , &INTL_DATA_ERROR_CODE(dfo)); + INTL_METHOD_CHECK_STATUS( dfo, "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; + zval* z_parse_pos = NULL; + int32_t parse_pos = -1; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|z!", + &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_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; + + if (z_parse_pos) { + convert_to_long(z_parse_pos); + parse_pos = (int32_t)Z_LVAL_P(z_parse_pos); + if(parse_pos > text_len) { + RETURN_FALSE; + } + } + internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value TSRMLS_CC); + if(z_parse_pos) { + zval_dtor(z_parse_pos); + ZVAL_LONG(z_parse_pos, parse_pos); + } +} +/* }}} */ + +/* {{{ 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; + zval* z_parse_pos = NULL; + int32_t parse_pos = -1; + + DATE_FORMAT_METHOD_INIT_VARS; + + /* Parse parameters. */ + if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|z!", + &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_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; + + if(z_parse_pos) { + convert_to_long(z_parse_pos); + parse_pos = (int32_t)Z_LVAL_P(z_parse_pos); + if(parse_pos > text_len) { + RETURN_FALSE; + } + } + internal_parse_to_localtime( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value TSRMLS_CC); + if(z_parse_pos) { + zval_dtor(z_parse_pos); + ZVAL_LONG(z_parse_pos, parse_pos); + } +} +/* }}} */ + diff --git a/ext/intl/dateformat/dateformat_parse.h b/ext/intl/dateformat/dateformat_parse.h new file mode 100644 index 0000000..c74a3d5 --- /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 <kirtig@yahoo-inc.com> | + +----------------------------------------------------------------------+ +*/ +#ifndef DATE_FORMAT_PARSE_H +#define DATE_FORMAT_PARSE_H + +#include <php.h> + +PHP_FUNCTION( datefmt_parse ); +PHP_FUNCTION( datefmt_localtime ); + +#endif // DATE_FORMAT_PARSE_H |