mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Initial checkin of calendar/timezone code.
This commit is contained in:
parent
6c891f33d7
commit
5e65205a8f
143 changed files with 8044 additions and 6 deletions
380
ext/intl/common/common_enum.cpp
Normal file
380
ext/intl/common/common_enum.cpp
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "common_enum.h"
|
||||
|
||||
extern "C" {
|
||||
#include "intl_error.h"
|
||||
#include "intl_data.h"
|
||||
#include <zend_interfaces.h>
|
||||
#include <zend_exceptions.h>
|
||||
}
|
||||
|
||||
static zend_class_entry *IntlIterator_ce_ptr;
|
||||
static zend_object_handlers IntlIterator_handlers;
|
||||
|
||||
typedef struct {
|
||||
zend_object zo;
|
||||
intl_error err;
|
||||
zend_object_iterator *iterator;
|
||||
} IntlIterator_object;
|
||||
|
||||
#define INTLITERATOR_ERROR(ii) (ii)->err
|
||||
#define INTLITERATOR_ERROR_P(ii) &(INTLITERATOR_ERROR(ii))
|
||||
|
||||
#define INTLITERATOR_ERROR_CODE(ii) INTL_ERROR_CODE(INTLITERATOR_ERROR(ii))
|
||||
#define INTLITERATOR_ERROR_CODE_P(ii) &(INTL_ERROR_CODE(INTLITERATOR_ERROR(ii)))
|
||||
|
||||
#define INTLITERATOR_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(IntlIterator, ii)
|
||||
#define INTLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(IntlIterator, ii)
|
||||
#define INTLITERATOR_METHOD_FETCH_OBJECT\
|
||||
object = getThis(); \
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; \
|
||||
if (ii->iterator == NULL) { \
|
||||
intl_errors_set(&ii->err, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed IntlIterator", 0 TSRMLS_CC); \
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
zend_object_iterator zoi;
|
||||
zval *current;
|
||||
zval *wrapping_obj;
|
||||
void (*destroy_free_it)(zend_object_iterator *iterator TSRMLS_DC);
|
||||
} zoi_with_current;
|
||||
|
||||
static void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
zoi_with_current *zoiwc = (zoi_with_current*)iter;
|
||||
|
||||
if (zoiwc->wrapping_obj) {
|
||||
/* we have to copy the pointer because zoiwc->wrapping_obj may be
|
||||
* changed midway the execution of zval_ptr_dtor() */
|
||||
zval *zwo = zoiwc->wrapping_obj;
|
||||
|
||||
/* object is still here, we can rely on it to call this again and
|
||||
* destroy this object */
|
||||
zval_ptr_dtor(&zwo);
|
||||
} else {
|
||||
/* Object not here anymore (we've been called by the object free handler)
|
||||
* Note that the iterator wrapper objects (that also depend on this
|
||||
* structure) call this function earlier, in the destruction phase, which
|
||||
* precedes the object free phase. Therefore there's no risk on this
|
||||
* function being called by the iterator wrapper destructor function and
|
||||
* not finding the memory of this iterator allocated anymore. */
|
||||
iter->funcs->invalidate_current(iter TSRMLS_CC);
|
||||
zoiwc->destroy_free_it(iter TSRMLS_CC);
|
||||
efree(iter);
|
||||
}
|
||||
}
|
||||
|
||||
static int zoi_with_current_valid(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
return ((zoi_with_current*)iter)->current != NULL ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
static void zoi_with_current_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
|
||||
{
|
||||
*data = &((zoi_with_current*)iter)->current;
|
||||
}
|
||||
|
||||
static void zoi_with_current_invalidate_current(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
zoi_with_current *zoi_iter = (zoi_with_current*)iter;
|
||||
if (zoi_iter->current) {
|
||||
zval_ptr_dtor(&zoi_iter->current);
|
||||
zoi_iter->current = NULL; //valid would return FAILURE now
|
||||
}
|
||||
}
|
||||
|
||||
static void string_enum_current_move_forward(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
zoi_with_current *zoi_iter = (zoi_with_current*)iter;
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
iter->funcs->invalidate_current(iter TSRMLS_CC);
|
||||
|
||||
object = zoi_iter->wrapping_obj;
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
|
||||
|
||||
int32_t result_length;
|
||||
const char *result = ((StringEnumeration*)iter->data)->next(
|
||||
&result_length, INTLITERATOR_ERROR_CODE(ii));
|
||||
|
||||
intl_error_set_code(NULL, INTLITERATOR_ERROR_CODE(ii) TSRMLS_CC);
|
||||
if (U_FAILURE(INTLITERATOR_ERROR_CODE(ii))) {
|
||||
intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii),
|
||||
"Error fetching next iteration element", 0 TSRMLS_CC);
|
||||
} else if (result) {
|
||||
MAKE_STD_ZVAL(zoi_iter->current);
|
||||
ZVAL_STRINGL(zoi_iter->current, result, result_length, 1);
|
||||
} //else we've reached the end of the enum, nothing more is required
|
||||
}
|
||||
|
||||
static void string_enum_rewind(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
zoi_with_current *zoi_iter = (zoi_with_current*)iter;
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
if (zoi_iter->current) {
|
||||
iter->funcs->invalidate_current(iter TSRMLS_CC);
|
||||
}
|
||||
|
||||
object = zoi_iter->wrapping_obj;
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
|
||||
|
||||
((StringEnumeration*)iter->data)->reset(INTLITERATOR_ERROR_CODE(ii));
|
||||
|
||||
intl_error_set_code(NULL, INTLITERATOR_ERROR_CODE(ii) TSRMLS_CC);
|
||||
if (U_FAILURE(INTLITERATOR_ERROR_CODE(ii))) {
|
||||
intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii),
|
||||
"Error resetting enumeration", 0 TSRMLS_CC);
|
||||
} else {
|
||||
iter->funcs->move_forward(iter TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static void string_enum_destroy_free_it(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
delete (StringEnumeration*)iter->data;
|
||||
}
|
||||
|
||||
static zend_object_iterator_funcs string_enum_object_iterator_funcs = {
|
||||
zoi_with_current_dtor,
|
||||
zoi_with_current_valid,
|
||||
zoi_with_current_get_current_data,
|
||||
NULL,
|
||||
string_enum_current_move_forward,
|
||||
string_enum_rewind,
|
||||
zoi_with_current_invalidate_current
|
||||
};
|
||||
|
||||
U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *object TSRMLS_DC)
|
||||
{
|
||||
IntlIterator_object *ii;
|
||||
object_init_ex(object, IntlIterator_ce_ptr);
|
||||
ii = (IntlIterator_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
ii->iterator = (zend_object_iterator*)emalloc(sizeof(zoi_with_current));
|
||||
ii->iterator->data = (void*)se;
|
||||
ii->iterator->funcs = &string_enum_object_iterator_funcs;
|
||||
ii->iterator->index = 0;
|
||||
((zoi_with_current*)ii->iterator)->destroy_free_it = string_enum_destroy_free_it;
|
||||
((zoi_with_current*)ii->iterator)->wrapping_obj = object;
|
||||
((zoi_with_current*)ii->iterator)->current = NULL;
|
||||
}
|
||||
|
||||
static void IntlIterator_objects_free(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
IntlIterator_object *ii = (IntlIterator_object*) object;
|
||||
|
||||
if (ii->iterator) {
|
||||
zval **wrapping_objp = &((zoi_with_current*)ii->iterator)->wrapping_obj;
|
||||
*wrapping_objp = NULL;
|
||||
ii->iterator->funcs->dtor(ii->iterator TSRMLS_CC);
|
||||
}
|
||||
intl_error_reset(INTLITERATOR_ERROR_P(ii) TSRMLS_CC);
|
||||
|
||||
zend_object_std_dtor(&ii->zo TSRMLS_CC);
|
||||
|
||||
efree(ii);
|
||||
}
|
||||
|
||||
static zend_object_iterator *IntlIterator_get_iterator(
|
||||
zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
|
||||
{
|
||||
if (by_ref) {
|
||||
zend_throw_exception(NULL,
|
||||
"Iteration by reference is not supported", 0 TSRMLS_CC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntlIterator_object *ii = (IntlIterator_object*)
|
||||
zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if (ii->iterator == NULL) {
|
||||
zend_throw_exception(NULL,
|
||||
"The IntlIterator is not properly constructed", 0 TSRMLS_CC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zval_add_ref(&object);
|
||||
|
||||
return ii->iterator;
|
||||
}
|
||||
|
||||
static zend_object_value IntlIterator_object_create(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
zend_object_value retval;
|
||||
IntlIterator_object *intern;
|
||||
|
||||
intern = (IntlIterator_object*)ecalloc(1, sizeof(IntlIterator_object));
|
||||
|
||||
zend_object_std_init(&intern->zo, ce TSRMLS_CC);
|
||||
#if PHP_VERSION_ID < 50399
|
||||
zend_hash_copy(intern->zo.properties, &(ce->default_properties),
|
||||
(copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*));
|
||||
#else
|
||||
object_properties_init((zend_object*) intern, ce);
|
||||
#endif
|
||||
intl_error_init(INTLITERATOR_ERROR_P(intern) TSRMLS_CC);
|
||||
intern->iterator = NULL;
|
||||
|
||||
retval.handle = zend_objects_store_put(
|
||||
intern,
|
||||
(zend_objects_store_dtor_t)zend_objects_destroy_object,
|
||||
(zend_objects_free_object_storage_t)IntlIterator_objects_free,
|
||||
NULL TSRMLS_CC);
|
||||
|
||||
retval.handlers = &IntlIterator_handlers;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static PHP_METHOD(IntlIterator, current)
|
||||
{
|
||||
zval **data;
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"IntlIterator::current: bad arguments", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT;
|
||||
ii->iterator->funcs->get_current_data(ii->iterator, &data TSRMLS_CC);
|
||||
if (data && *data) {
|
||||
RETURN_ZVAL(*data, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static PHP_METHOD(IntlIterator, key)
|
||||
{
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"IntlIterator::key: bad arguments", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT;
|
||||
|
||||
if (ii->iterator->funcs->get_current_key) {
|
||||
char *str_key;
|
||||
uint str_key_len;
|
||||
ulong int_key;
|
||||
|
||||
switch (ii->iterator->funcs->get_current_key(
|
||||
ii->iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
|
||||
case HASH_KEY_IS_LONG:
|
||||
RETURN_LONG(int_key);
|
||||
break;
|
||||
case HASH_KEY_IS_STRING:
|
||||
RETURN_STRINGL(str_key, str_key_len-1, 0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
RETURN_LONG(ii->iterator->index);
|
||||
}
|
||||
}
|
||||
|
||||
static PHP_METHOD(IntlIterator, next)
|
||||
{
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"IntlIterator::next: bad arguments", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT;
|
||||
ii->iterator->funcs->move_forward(ii->iterator TSRMLS_CC);
|
||||
/* foreach also advances the index after the last iteration,
|
||||
* so I see no problem in incrementing the index here unconditionally */
|
||||
ii->iterator->index++;
|
||||
}
|
||||
|
||||
static PHP_METHOD(IntlIterator, rewind)
|
||||
{
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"IntlIterator::rewind: bad arguments", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT;
|
||||
if (ii->iterator->funcs->rewind) {
|
||||
ii->iterator->funcs->rewind(ii->iterator TSRMLS_CC);
|
||||
} else {
|
||||
intl_error_set(NULL, U_UNSUPPORTED_ERROR,
|
||||
"IntlIterator::rewind: rewind not supported", 0 TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static PHP_METHOD(IntlIterator, valid)
|
||||
{
|
||||
INTLITERATOR_METHOD_INIT_VARS;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"IntlIterator::valid: bad arguments", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
INTLITERATOR_METHOD_FETCH_OBJECT;
|
||||
RETURN_BOOL(ii->iterator->funcs->valid(ii->iterator TSRMLS_CC) == SUCCESS);
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(ainfo_se_void, 0, 0, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static zend_function_entry IntlIterator_class_functions[] = {
|
||||
PHP_ME(IntlIterator, current, ainfo_se_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(IntlIterator, key, ainfo_se_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(IntlIterator, next, ainfo_se_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(IntlIterator, rewind, ainfo_se_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(IntlIterator, valid, ainfo_se_void, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
|
||||
/* {{{ intl_register_IntlIterator_class
|
||||
* Initialize 'IntlIterator' class
|
||||
*/
|
||||
U_CFUNC void intl_register_IntlIterator_class(TSRMLS_D)
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
/* Create and register 'IntlIterator' class. */
|
||||
INIT_CLASS_ENTRY(ce, "IntlIterator", IntlIterator_class_functions);
|
||||
ce.create_object = IntlIterator_object_create;
|
||||
IntlIterator_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
|
||||
IntlIterator_ce_ptr->get_iterator = IntlIterator_get_iterator;
|
||||
zend_class_implements(IntlIterator_ce_ptr TSRMLS_CC, 1,
|
||||
zend_ce_iterator);
|
||||
|
||||
memcpy(&IntlIterator_handlers, zend_get_std_object_handlers(),
|
||||
sizeof IntlIterator_handlers);
|
||||
IntlIterator_handlers.clone_obj = NULL;
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue