From f5b421621d89c3e87c498ee228c421e67719fbc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Thu, 31 May 2012 12:11:44 +0200 Subject: [PATCH 01/13] BreakIterator and RuleBasedBreakiterator added This commit adds wrappers for the classes BreakIterator and RuleBasedbreakIterator. The C++ ICU classes are described here: Additionally, a tutorial is available at: This implementation wraps UTF-8 text in a UText. The text is iterated without any copying or conversion to UTF-16. There is also no validation that the input is actually UTF-8; where there are malformed sequences, the UText will simply U+FFFD. The class BreakIterator cannot be instantiated directly (has a private constructor). It provides the interface exposed by the ICU abstract class with the same name. The PHP class is not abstract because we may use it to wrap native subclasses of BreakIterator that we don't know how to wrap. This class includes methods to move the iterator position to the beginning (first()), to the end (last()), forward (next()), backwards (previous()), to the boundary preceding a certain position (preceding()) and following a certain position (following()) and to obtain the current position (current()). next() can also be used to advance or recede an arbitrary number of positions. BreakIterator also exposes other native methods: getAvailableLocales(), getLocale() and factory methods to build several predefined types of BreakIterators: createWordInstance() for word boundaries, createCharacterInstance() for locale dependent notions of "characters", createSentenceInstance() for sentences, createLineInstance() and createTitleInstance() -- for title casing breaks. These factories currently return RuleBasedbreakIterators where the names of the rule sets are found in the ICU data, observing the passed locale (although the locale is taken into considering there are very few exceptions to the root rules). The clone and compare_object PHP object handlers are also implemented, though the comparison does not yield meaningful results when used with >, <, >= and <=. Note that BreakIterator is an iterator only in the sense of the first 'Iterator' in 'IteratorIterator', i.e., it does not implement the Iterator interface. The reason is that there is no sensible implementation for Iterator::key(). Using it for an ordinal of the current boundary is not feasible because we are allowed to move to any boundary at any time. It we were to determine the current ordinal when last() is called we'd have to traverse the whole input text to find out how many breaks there were before. Therefore, BreakIterator implements only Traversable. It can be wrapped in an IteratorIterator, but the usual warnings apply. Finally, I added a convenience method to BreakIterator: getPartsIterator(). This provides an IntlIterator, backed by the BreakIterator PHP object (i.e. moving the pointer or changing the text in BreakIterator affects the iterator and also moving the iterator affects the backing BreakIterator), which allows traversing the text between each boundary. This iterator uses the original text to retrieve the text between two positions, not the code points returned by the wrapping UText. Therefore, if the text includes invalid code unit sequences, these invalid sequences will be in the output of this iterator, not U+FFFD code points. The class RuleBasedIterator exposes a constructor that allows building an iterator from arbitrary compiled or non-compiled rules. The form of these rules in described in the tutorial linked above. The rest of the methods allow retrieving the rules -- getRules() and getCompiledRules() --, a hash code of the rule set (hashCode()) and the rules statuses (getRuleStatus() and getRuleStatusVec()). Because the RuleBasedBreakIterator constructor may return parse errors, I reuse the UParseError to text function that was in the transliterator files. Therefore, I move that function to intl_error.c. common_enum.cpp was also changed, mainly to expose previously static functions. This avoided code duplication when implementing the BreakIterator iterator and the IntlIterator returned by BreakIterator::getPartsIterator(). --- .../breakiterator/breakiterator_class.cpp | 342 ++++++++++++++ ext/intl/breakiterator/breakiterator_class.h | 71 +++ .../breakiterator/breakiterator_iterators.cpp | 218 +++++++++ .../breakiterator/breakiterator_iterators.h | 39 ++ .../breakiterator/breakiterator_methods.cpp | 442 ++++++++++++++++++ .../breakiterator/breakiterator_methods.h | 64 +++ .../rulebasedbreakiterator_methods.cpp | 227 +++++++++ .../rulebasedbreakiterator_methods.h | 34 ++ ext/intl/common/common_enum.cpp | 49 +- ext/intl/common/common_enum.h | 38 ++ ext/intl/config.m4 | 4 + ext/intl/config.w32 | 7 + ext/intl/intl_error.c | 78 +++- ext/intl/intl_error.h | 5 + ext/intl/php_intl.c | 5 + ext/intl/transliterator/transliterator.c | 79 ---- .../transliterator/transliterator_methods.c | 2 +- 17 files changed, 1583 insertions(+), 121 deletions(-) create mode 100644 ext/intl/breakiterator/breakiterator_class.cpp create mode 100644 ext/intl/breakiterator/breakiterator_class.h create mode 100644 ext/intl/breakiterator/breakiterator_iterators.cpp create mode 100644 ext/intl/breakiterator/breakiterator_iterators.h create mode 100644 ext/intl/breakiterator/breakiterator_methods.cpp create mode 100644 ext/intl/breakiterator/breakiterator_methods.h create mode 100644 ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp create mode 100644 ext/intl/breakiterator/rulebasedbreakiterator_methods.h diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp new file mode 100644 index 00000000000..47e5fb52df1 --- /dev/null +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -0,0 +1,342 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "breakiterator_iterators.h" + +#include + +extern "C" { +#define USE_BREAKITERATOR_POINTER 1 +#include "breakiterator_class.h" +#include "breakiterator_methods.h" +#include "rulebasedbreakiterator_methods.h" +#include +#include +#include +} + +/* {{{ Global variables */ +zend_class_entry *BreakIterator_ce_ptr; +zend_class_entry *RuleBasedBreakIterator_ce_ptr; +zend_object_handlers BreakIterator_handlers; +/* }}} */ + +U_CFUNC void breakiterator_object_create(zval *object, + BreakIterator *biter TSRMLS_DC) +{ + UClassID classId = biter->getDynamicClassID(); + zend_class_entry *ce; + + if (classId == RuleBasedBreakIterator::getStaticClassID()) { + ce = RuleBasedBreakIterator_ce_ptr; + } else { + ce = BreakIterator_ce_ptr; + } + + object_init_ex(object, ce); + breakiterator_object_construct(object, biter TSRMLS_CC); +} + +U_CFUNC void breakiterator_object_construct(zval *object, + BreakIterator *biter TSRMLS_DC) +{ + BreakIterator_object *bio; + + BREAKITER_METHOD_FETCH_OBJECT_NO_CHECK; //populate to from object + assert(bio->biter == NULL); + bio->biter = biter; +} + +/* {{{ compare handler for BreakIterator */ +static int BreakIterator_compare_objects(zval *object1, + zval *object2 TSRMLS_DC) +{ + BreakIterator_object *bio1, + *bio2; + + bio1 = (BreakIterator_object*)zend_object_store_get_object(object1 TSRMLS_CC); + bio2 = (BreakIterator_object*)zend_object_store_get_object(object2 TSRMLS_CC); + + if (bio1->biter == NULL || bio2->biter == NULL) { + return bio1->biter == bio2->biter ? 0 : 1; + } + + return *bio1->biter == *bio2->biter ? 0 : 1; +} +/* }}} */ + +/* {{{ clone handler for BreakIterator */ +static zend_object_value BreakIterator_clone_obj(zval *object TSRMLS_DC) +{ + BreakIterator_object *bio_orig, + *bio_new; + zend_object_value ret_val; + + bio_orig = (BreakIterator_object*)zend_object_store_get_object(object TSRMLS_CC); + intl_errors_reset(INTL_DATA_ERROR_P(bio_orig) TSRMLS_CC); + + ret_val = BreakIterator_ce_ptr->create_object(Z_OBJCE_P(object) TSRMLS_CC); + bio_new = (BreakIterator_object*)zend_object_store_get_object_by_handle( + ret_val.handle TSRMLS_CC); + + zend_objects_clone_members(&bio_new->zo, ret_val, + &bio_orig->zo, Z_OBJ_HANDLE_P(object) TSRMLS_CC); + + if (bio_orig->biter != NULL) { + BreakIterator *new_biter; + + new_biter = bio_orig->biter->clone(); + if (!new_biter) { + char *err_msg; + intl_errors_set_code(BREAKITER_ERROR_P(bio_orig), + U_MEMORY_ALLOCATION_ERROR TSRMLS_CC); + intl_errors_set_custom_msg(BREAKITER_ERROR_P(bio_orig), + "Could not clone BreakIterator", 0 TSRMLS_CC); + err_msg = intl_error_get_message(BREAKITER_ERROR_P(bio_orig) TSRMLS_CC); + zend_throw_exception(NULL, err_msg, 0 TSRMLS_CC); + efree(err_msg); + } else { + bio_new->biter = new_biter; + bio_new->text = bio_orig->text; + if (bio_new->text) { + zval_add_ref(&bio_new->text); + } + } + } else { + zend_throw_exception(NULL, "Cannot clone unconstructed BreakIterator", 0 TSRMLS_CC); + } + + return ret_val; +} +/* }}} */ + +/* {{{ get_debug_info handler for BreakIterator */ +static HashTable *BreakIterator_get_debug_info(zval *object, int *is_temp TSRMLS_DC) +{ + zval zv = zval_used_for_init; + BreakIterator_object *bio; + const BreakIterator *biter; + + *is_temp = 1; + + array_init_size(&zv, 8); + + bio = (BreakIterator_object*)zend_object_store_get_object(object TSRMLS_CC); + biter = bio->biter; + + if (biter == NULL) { + add_assoc_bool_ex(&zv, "valid", sizeof("valid"), 0); + return Z_ARRVAL(zv); + } + add_assoc_bool_ex(&zv, "valid", sizeof("valid"), 1); + + if (bio->text == NULL) { + add_assoc_null_ex(&zv, "text", sizeof("text")); + } else { + zval_add_ref(&bio->text); + add_assoc_zval_ex(&zv, "text", sizeof("text"), bio->text); + } + + add_assoc_string_ex(&zv, "type", sizeof("type"), + const_cast(typeid(*biter).name()), 1); + + return Z_ARRVAL(zv); +} +/* }}} */ + +/* {{{ void breakiterator_object_init(BreakIterator_object* to) + * Initialize internals of BreakIterator_object not specific to zend standard objects. + */ +static void breakiterator_object_init(BreakIterator_object *bio TSRMLS_DC) +{ + intl_error_init(BREAKITER_ERROR_P(bio) TSRMLS_CC); + bio->biter = NULL; + bio->text = NULL; +} +/* }}} */ + +/* {{{ BreakIterator_objects_dtor */ +static void BreakIterator_objects_dtor(void *object, + zend_object_handle handle TSRMLS_DC) +{ + zend_objects_destroy_object((zend_object*)object, handle TSRMLS_CC); +} +/* }}} */ + +/* {{{ BreakIterator_objects_free */ +static void BreakIterator_objects_free(zend_object *object TSRMLS_DC) +{ + BreakIterator_object* bio = (BreakIterator_object*) object; + + if (bio->text) { + zval_ptr_dtor(&bio->text); + } + if (bio->biter) { + delete bio->biter; + bio->biter = NULL; + } + intl_error_reset(BREAKITER_ERROR_P(bio) TSRMLS_CC); + + zend_object_std_dtor(&bio->zo TSRMLS_CC); + + efree(bio); +} +/* }}} */ + +/* {{{ BreakIterator_object_create */ +static zend_object_value BreakIterator_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + BreakIterator_object* intern; + + intern = (BreakIterator_object*)ecalloc(1, sizeof(BreakIterator_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 + breakiterator_object_init(intern TSRMLS_CC); + + retval.handle = zend_objects_store_put( + intern, + BreakIterator_objects_dtor, + (zend_objects_free_object_storage_t) BreakIterator_objects_free, + NULL TSRMLS_CC); + + retval.handlers = &BreakIterator_handlers; + + return retval; +} +/* }}} */ + +/* {{{ BreakIterator/RuleBasedBreakIterator methods arguments info */ + +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_void, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_locale, 0, 0, 0) + ZEND_ARG_INFO(0, "locale") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_setText, 0, 0, 1) + ZEND_ARG_INFO(0, "text") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_next, 0, 0, 0) + ZEND_ARG_INFO(0, "offset") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_offset, 0, 0, 1) + ZEND_ARG_INFO(0, "offset") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_get_locale, 0, 0, 1) + ZEND_ARG_INFO(0, "locale_type") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(ainfo_rbbi___construct, 0, 0, 1) + ZEND_ARG_INFO(0, "rules") + ZEND_ARG_INFO(0, "areCompiled") +ZEND_END_ARG_INFO() + +/* }}} */ + +/* {{{ BreakIterator_class_functions + * Every 'BreakIterator' class method has an entry in this table + */ +static const zend_function_entry BreakIterator_class_functions[] = { + PHP_ME(BreakIterator, __construct, ainfo_biter_void, ZEND_ACC_PRIVATE) + PHP_ME_MAPPING(createWordInstance, breakiter_create_word_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(createLineInstance, breakiter_create_line_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(createCharacterInstance, breakiter_create_character_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(createSentenceInstance, breakiter_create_sentence_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(createTitleInstance, breakiter_create_title_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getAvailableLocales, breakiter_get_available_locales, ainfo_biter_void, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getText, breakiter_get_text, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(setText, breakiter_set_text, ainfo_biter_setText, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(first, breakiter_first, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(last, breakiter_last, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(previous, breakiter_previous, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(next, breakiter_next, ainfo_biter_next, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(current, breakiter_current, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(following, breakiter_following, ainfo_biter_offset, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(preceding, breakiter_preceding, ainfo_biter_offset, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(isBoundary, breakiter_is_boundary, ainfo_biter_offset, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getLocale, breakiter_get_locale, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getPartsIterator, breakiter_get_parts_iterator, ainfo_biter_void, ZEND_ACC_PUBLIC) + + PHP_ME_MAPPING(getErrorCode, breakiter_get_error_code, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getErrorMessage, breakiter_get_error_message, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_FE_END +}; +/* }}} */ + +/* {{{ RuleBasedBreakIterator_class_functions + */ +static const zend_function_entry RuleBasedBreakIterator_class_functions[] = { + PHP_ME(RuleBasedBreakIterator, __construct, ainfo_rbbi___construct, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(hashCode, rbbi_hash_code, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getRules, rbbi_get_rules, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getRuleStatus, rbbi_get_rule_status, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getRuleStatusVec, rbbi_get_rule_status_vec, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getBinaryRules, rbbi_get_binary_rules, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_FE_END +}; +/* }}} */ + + +/* {{{ breakiterator_register_BreakIterator_class + * Initialize 'BreakIterator' class + */ +void breakiterator_register_BreakIterator_class(TSRMLS_D) +{ + zend_class_entry ce; + + /* Create and register 'BreakIterator' class. */ + INIT_CLASS_ENTRY(ce, "BreakIterator", BreakIterator_class_functions); + ce.create_object = BreakIterator_object_create; + ce.get_iterator = _breakiterator_get_iterator; + BreakIterator_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); + + memcpy( &BreakIterator_handlers, zend_get_std_object_handlers(), + sizeof BreakIterator_handlers); + BreakIterator_handlers.compare_objects = BreakIterator_compare_objects; + BreakIterator_handlers.clone_obj = BreakIterator_clone_obj; + BreakIterator_handlers.get_debug_info = BreakIterator_get_debug_info; + + zend_class_implements(BreakIterator_ce_ptr TSRMLS_CC, 1, + zend_ce_traversable); + + zend_declare_class_constant_long(BreakIterator_ce_ptr, + "DONE", sizeof("DONE") - 1, BreakIterator::DONE TSRMLS_CC ); + + /* Create and register 'RuleBasedBreakIterator' class. */ + INIT_CLASS_ENTRY(ce, "RuleBasedBreakIterator", + RuleBasedBreakIterator_class_functions); + RuleBasedBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce, + BreakIterator_ce_ptr, NULL TSRMLS_CC); +} +/* }}} */ diff --git a/ext/intl/breakiterator/breakiterator_class.h b/ext/intl/breakiterator/breakiterator_class.h new file mode 100644 index 00000000000..a3872662832 --- /dev/null +++ b/ext/intl/breakiterator/breakiterator_class.h @@ -0,0 +1,71 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#ifndef BREAKITERATOR_CLASS_H +#define BREAKITERATOR_CLASS_H + +//redefinition of inline in PHP headers causes problems, so include this before +#include + +#include +#include "../intl_error.h" +#include "../intl_data.h" + +#ifndef USE_BREAKITERATOR_POINTER +typedef void BreakIterator; +#endif + +typedef struct { + zend_object zo; + + // error handling + intl_error err; + + // ICU break iterator + BreakIterator* biter; + + // current text + zval *text; +} BreakIterator_object; + +#define BREAKITER_ERROR(bio) (bio)->err +#define BREAKITER_ERROR_P(bio) &(BREAKITER_ERROR(bio)) + +#define BREAKITER_ERROR_CODE(bio) INTL_ERROR_CODE(BREAKITER_ERROR(bio)) +#define BREAKITER_ERROR_CODE_P(bio) &(INTL_ERROR_CODE(BREAKITER_ERROR(bio))) + +#define BREAKITER_METHOD_INIT_VARS INTL_METHOD_INIT_VARS(BreakIterator, bio) +#define BREAKITER_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(BreakIterator, bio) +#define BREAKITER_METHOD_FETCH_OBJECT \ + BREAKITER_METHOD_FETCH_OBJECT_NO_CHECK; \ + if (bio->biter == NULL) \ + { \ + intl_errors_set(&bio->err, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed BreakIterator", 0 TSRMLS_CC); \ + RETURN_FALSE; \ + } + +void breakiterator_object_create(zval *object, BreakIterator *break_iter TSRMLS_DC); + +void breakiterator_object_construct(zval *object, BreakIterator *break_iter TSRMLS_DC); + +void breakiterator_register_BreakIterator_class(TSRMLS_D); + +extern zend_class_entry *BreakIterator_ce_ptr, + *RuleBasedBreakIterator_ce_ptr; + +extern zend_object_handlers BreakIterator_handlers; + +#endif /* #ifndef BREAKITERATOR_CLASS_H */ diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp new file mode 100644 index 00000000000..4a0cf1da80c --- /dev/null +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -0,0 +1,218 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "breakiterator_iterators.h" + +extern "C" { +#define USE_BREAKITERATOR_POINTER +#include "breakiterator_class.h" +#include "../intl_convert.h" +#include "../locale/locale.h" +#include +} + +/* BreakIterator's iterator */ + +inline BreakIterator *_breakiter_prolog(zend_object_iterator *iter TSRMLS_DC) +{ + BreakIterator_object *bio; + bio = (BreakIterator_object*)zend_object_store_get_object( + (const zval*)iter->data TSRMLS_CC); + intl_errors_reset(BREAKITER_ERROR_P(bio) TSRMLS_CC); + if (bio->biter == NULL) { + intl_errors_set(BREAKITER_ERROR_P(bio), U_INVALID_STATE_ERROR, + "The BreakIterator object backing the PHP iterator is not " + "properly constructed", 0 TSRMLS_CC); + } + return bio->biter; +} + +static void _breakiterator_destroy_it(zend_object_iterator *iter TSRMLS_DC) +{ + zval_ptr_dtor((zval**)&iter->data); +} + +static void _breakiterator_move_forward(zend_object_iterator *iter TSRMLS_DC) +{ + BreakIterator *biter = _breakiter_prolog(iter TSRMLS_CC); + zoi_with_current *zoi_iter = (zoi_with_current*)iter; + + iter->funcs->invalidate_current(iter TSRMLS_CC); + + if (biter == NULL) { + return; + } + + int32_t pos = biter->next(); + if (pos != BreakIterator::DONE) { + MAKE_STD_ZVAL(zoi_iter->current); + ZVAL_LONG(zoi_iter->current, (long)pos); + } //else we've reached the end of the enum, nothing more is required +} + +static void _breakiterator_rewind(zend_object_iterator *iter TSRMLS_DC) +{ + BreakIterator *biter = _breakiter_prolog(iter TSRMLS_CC); + zoi_with_current *zoi_iter = (zoi_with_current*)iter; + + int32_t pos = biter->first(); + MAKE_STD_ZVAL(zoi_iter->current); + ZVAL_LONG(zoi_iter->current, (long)pos); +} + +static zend_object_iterator_funcs breakiterator_iterator_funcs = { + zoi_with_current_dtor, + zoi_with_current_valid, + zoi_with_current_get_current_data, + NULL, + _breakiterator_move_forward, + _breakiterator_rewind, + zoi_with_current_invalidate_current +}; + +U_CFUNC zend_object_iterator *_breakiterator_get_iterator( + zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) +{ + BreakIterator_object *bio; + if (by_ref) { + zend_throw_exception(NULL, + "Iteration by reference is not supported", 0 TSRMLS_CC); + return NULL; + } + + bio = (BreakIterator_object*)zend_object_store_get_object(object TSRMLS_CC); + BreakIterator *biter = bio->biter; + + if (biter == NULL) { + zend_throw_exception(NULL, + "The BreakIterator is not properly constructed", 0 TSRMLS_CC); + return NULL; + } + + zoi_with_current *zoi_iter = + static_cast(emalloc(sizeof *zoi_iter)); + zoi_iter->zoi.data = static_cast(object); + zoi_iter->zoi.funcs = &breakiterator_iterator_funcs; + zoi_iter->zoi.index = 0; + zoi_iter->destroy_it = _breakiterator_destroy_it; + zoi_iter->wrapping_obj = NULL; /* not used; object is in zoi.data */ + zoi_iter->current = NULL; + + zval_add_ref(&object); + + return reinterpret_cast(zoi_iter); +} + +/* BreakIterator parts iterator */ + +typedef struct zoi_break_iter_parts { + zoi_with_current zoi_cur; + BreakIterator_object *bio; /* so we don't have to fetch it all the time */ +} zoi_break_iter_parts; + +static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC) +{ + zval_ptr_dtor(reinterpret_cast(&iter->data)); +} + +static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_DC) +{ + zoi_break_iter_parts *zoi_bit = (zoi_break_iter_parts*)iter; + BreakIterator_object *bio = zoi_bit->bio; + + iter->funcs->invalidate_current(iter TSRMLS_CC); + + int32_t cur, + next; + + cur = bio->biter->current(); + if (cur == BreakIterator::DONE) { + return; + } + next = bio->biter->next(); + if (next == BreakIterator::DONE) { + return; + } + + const char *s = Z_STRVAL_P(bio->text); + int32_t slen = Z_STRLEN_P(bio->text), + len; + char *res; + + if (next == BreakIterator::DONE) { + next = slen; + } + assert(next <= slen && next >= cur); + len = next - cur; + res = static_cast(emalloc(len + 1)); + + memcpy(res, &s[cur], len); + res[len] = '\0'; + + MAKE_STD_ZVAL(zoi_bit->zoi_cur.current); + ZVAL_STRINGL(zoi_bit->zoi_cur.current, res, len, 0); +} + +static void _breakiterator_parts_rewind(zend_object_iterator *iter TSRMLS_DC) +{ + zoi_break_iter_parts *zoi_bit = (zoi_break_iter_parts*)iter; + BreakIterator_object *bio = zoi_bit->bio; + + if (zoi_bit->zoi_cur.current) { + iter->funcs->invalidate_current(iter TSRMLS_CC); + } + + bio->biter->first(); + + iter->funcs->move_forward(iter TSRMLS_CC); +} + +static zend_object_iterator_funcs breakiterator_parts_it_funcs = { + zoi_with_current_dtor, + zoi_with_current_valid, + zoi_with_current_get_current_data, + NULL, + _breakiterator_parts_move_forward, + _breakiterator_parts_rewind, + zoi_with_current_invalidate_current +}; + +void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, + zval *object TSRMLS_DC) +{ + IntlIterator_object *ii; + + zval_add_ref(&break_iter_zv); + + 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_break_iter_parts)); + ii->iterator->data = break_iter_zv; + ii->iterator->funcs = &breakiterator_parts_it_funcs; + ii->iterator->index = 0; + ((zoi_with_current*)ii->iterator)->destroy_it = _breakiterator_parts_destroy_it; + ((zoi_with_current*)ii->iterator)->wrapping_obj = object; + ((zoi_with_current*)ii->iterator)->current = NULL; + + ((zoi_break_iter_parts*)ii->iterator)->bio = (BreakIterator_object*) + zend_object_store_get_object(break_iter_zv TSRMLS_CC); + assert(((zoi_break_iter_parts*)ii->iterator)->bio->biter != NULL); +} diff --git a/ext/intl/breakiterator/breakiterator_iterators.h b/ext/intl/breakiterator/breakiterator_iterators.h new file mode 100644 index 00000000000..4ef5a2f4eff --- /dev/null +++ b/ext/intl/breakiterator/breakiterator_iterators.h @@ -0,0 +1,39 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ +#ifndef INTL_BREAKITERATOR_ITERATORS_H +#define INTL_BREAKITERATOR_ITERATORS_H + +#ifndef __cplusplus +#error Header for C++ only +#endif + +#include +#include + +#include "../common/common_enum.h" + +extern "C" { +#include +#include +} + +void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, + zval *object TSRMLS_DC); + +U_CFUNC zend_object_iterator *_breakiterator_get_iterator( + zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); + +#endif \ No newline at end of file diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp new file mode 100644 index 00000000000..4aca6ef23f5 --- /dev/null +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -0,0 +1,442 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "breakiterator_iterators.h" + +extern "C" { +#define USE_BREAKITERATOR_POINTER 1 +#include "breakiterator_class.h" +#include "../locale/locale.h" +#include +} + +U_CFUNC PHP_METHOD(BreakIterator, __construct) +{ + zend_throw_exception( NULL, + "An object of this type cannot be created with the new operator", + 0 TSRMLS_CC ); +} + +static void _breakiter_factory(const char *func_name, + BreakIterator *(*func)(const Locale&, UErrorCode&), + INTERNAL_FUNCTION_PARAMETERS) +{ + BreakIterator *biter; + const char *locale_str = NULL; + int dummy; + char *msg; + UErrorCode status = UErrorCode(); + intl_error_reset(NULL TSRMLS_CC); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", + &locale_str, &dummy) == FAILURE) { + spprintf(&msg, NULL, "%s: bad arguments", func_name); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); + efree(msg); + RETURN_NULL(); + } + + if (locale_str == NULL) { + locale_str = intl_locale_get_default(TSRMLS_C); + } + + biter = func(Locale::createFromName(locale_str), status); + intl_error_set_code(NULL, status TSRMLS_CC); + if (U_FAILURE(status)) { + spprintf(&msg, NULL, "%s: error creating BreakIterator", + func_name); + intl_error_set_custom_msg(NULL, msg, 1 TSRMLS_CC); + efree(msg); + RETURN_NULL(); + } + + breakiterator_object_create(return_value, biter TSRMLS_CC); +} + +U_CFUNC PHP_FUNCTION(breakiter_create_word_instance) +{ + _breakiter_factory("breakiter_create_word_instance", + &BreakIterator::createWordInstance, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_create_line_instance) +{ + _breakiter_factory("breakiter_create_line_instance", + &BreakIterator::createLineInstance, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_create_character_instance) +{ + _breakiter_factory("breakiter_create_character_instance", + &BreakIterator::createCharacterInstance, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_create_sentence_instance) +{ + _breakiter_factory("breakiter_create_sentence_instance", + &BreakIterator::createSentenceInstance, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_create_title_instance) +{ + _breakiter_factory("breakiter_create_title_instance", + &BreakIterator::createTitleInstance, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_get_available_locales) +{ + intl_error_reset(NULL TSRMLS_CC); + + if (zend_parse_parameters_none() == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_available_locales: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + const Locale *locales; + int32_t count; + + locales = BreakIterator::getAvailableLocales(count); + array_init_size(return_value, (uint)count); + for (int i = 0; i < count; i++) { + Locale locale = locales[i]; + add_next_index_string(return_value, locale.getName(), 1); + } +} + +U_CFUNC PHP_FUNCTION(breakiter_get_text) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_text: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + if (bio->text == NULL) { + RETURN_NULL(); + } else { + RETURN_ZVAL(bio->text, 1, 0); + } +} + +U_CFUNC PHP_FUNCTION(breakiter_set_text) +{ + char *text; + int text_len; + UText *ut = NULL; + zval **textzv; + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", + &object, BreakIterator_ce_ptr, &text, &text_len) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_set_text: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + int res = zend_get_parameters_ex(1, &textzv); + assert(res == SUCCESS); + + BREAKITER_METHOD_FETCH_OBJECT; + + /* assert it's safe to use text and text_len because zpp changes the + * arguments in the stack */ + assert(text == Z_STRVAL_PP(textzv)); + + ut = utext_openUTF8(ut, text, text_len, BREAKITER_ERROR_CODE_P(bio)); + INTL_CTOR_CHECK_STATUS(bio, "breakiter_set_text: error opening UText"); + + bio->biter->setText(ut, BREAKITER_ERROR_CODE(bio)); + utext_close(ut); /* ICU shallow clones the UText */ + INTL_CTOR_CHECK_STATUS(bio, "breakiter_set_text: error calling " + "BreakIterator::setText()"); + + /* When ICU clones the UText, it does not copy the buffer, so we have to + * keep the string buffer around by holding a reference to its zval. This + * also allows a faste implementation of getText() */ + if (bio->text != NULL) { + zval_ptr_dtor(&bio->text); + } + bio->text = *textzv; + zval_add_ref(&bio->text); + + RETURN_TRUE; +} + +static void _breakiter_no_args_ret_int32( + const char *func_name, + int32_t (BreakIterator::*func)(), + INTERNAL_FUNCTION_PARAMETERS) +{ + char *msg; + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + spprintf(&msg, NULL, "%s: bad arguments", func_name); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); + efree(msg); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + int32_t res = (bio->biter->*func)(); + + RETURN_LONG((long)res); +} + +static void _breakiter_int32_ret_int32( + const char *func_name, + int32_t (BreakIterator::*func)(int32_t), + INTERNAL_FUNCTION_PARAMETERS) +{ + char *msg; + long arg; + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, BreakIterator_ce_ptr, &arg) == FAILURE) { + spprintf(&msg, NULL, "%s: bad arguments", func_name); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); + efree(msg); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + if (arg < INT32_MIN || arg > INT32_MAX) { + spprintf(&msg, NULL, "%s: offset argument is outside bounds of " + "a 32-bit wide integer", func_name); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); + efree(msg); + RETURN_FALSE; + } + + int32_t res = (bio->biter->*func)((int32_t)arg); + + RETURN_LONG((long)res); +} + +U_CFUNC PHP_FUNCTION(breakiter_first) +{ + _breakiter_no_args_ret_int32("breakiter_first", + &BreakIterator::first, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_last) +{ + _breakiter_no_args_ret_int32("breakiter_last", + &BreakIterator::last, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_previous) +{ + _breakiter_no_args_ret_int32("breakiter_previous", + &BreakIterator::previous, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_next) +{ + bool no_arg_version = false; + + if (ZEND_NUM_ARGS() == 0) { + no_arg_version = true; + } else if (ZEND_NUM_ARGS() == 1) { + zval **arg; + int res = zend_get_parameters_ex(1, &arg); + assert(res == SUCCESS); + if (Z_TYPE_PP(arg) == IS_NULL) { + no_arg_version = true; + ht = 0; /* pretend we don't have any argument */ + } else { + no_arg_version = false; + } + } + + if (no_arg_version) { + _breakiter_no_args_ret_int32("breakiter_next", + &BreakIterator::next, + INTERNAL_FUNCTION_PARAM_PASSTHRU); + } else { + _breakiter_int32_ret_int32("breakiter_next", + &BreakIterator::next, + INTERNAL_FUNCTION_PARAM_PASSTHRU); + } +} + +U_CFUNC PHP_FUNCTION(breakiter_current) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_current: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + int32_t res = bio->biter->current(); + + RETURN_LONG((long)res); +} + +U_CFUNC PHP_FUNCTION(breakiter_following) +{ + _breakiter_int32_ret_int32("breakiter_following", + &BreakIterator::following, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_preceding) +{ + _breakiter_int32_ret_int32("breakiter_preceding", + &BreakIterator::preceding, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +U_CFUNC PHP_FUNCTION(breakiter_is_boundary) +{ + long offset; + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", + &object, BreakIterator_ce_ptr, &offset) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_is_boundary: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + if (offset < INT32_MIN || offset > INT32_MAX) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_is_boundary: offset argument is outside bounds of " + "a 32-bit wide integer", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + UBool res = bio->biter->isBoundary((int32_t)offset); + + RETURN_BOOL((long)res); +} + +U_CFUNC PHP_FUNCTION(breakiter_get_locale) +{ + long locale_type; + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), + "Ol", &object, BreakIterator_ce_ptr, &locale_type) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_locale: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + if (locale_type != ULOC_ACTUAL_LOCALE && locale_type != ULOC_VALID_LOCALE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_locale: invalid locale type", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + Locale locale = bio->biter->getLocale((ULocDataLocaleType)locale_type, + BREAKITER_ERROR_CODE(bio)); + INTL_METHOD_CHECK_STATUS(bio, + "breakiter_get_locale: Call to ICU method has failed"); + + RETURN_STRING(locale.getName(), 1); +} + +U_CFUNC PHP_FUNCTION(breakiter_get_parts_iterator) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_parts_iterator: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + IntlIterator_from_BreakIterator_parts(object, return_value TSRMLS_CC); +} + +U_CFUNC PHP_FUNCTION(breakiter_get_error_code) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_error_code: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + /* Fetch the object (without resetting its last error code ). */ + bio = (BreakIterator_object*)zend_object_store_get_object(object TSRMLS_CC); + if (bio == NULL) + RETURN_FALSE; + + RETURN_LONG((long)BREAKITER_ERROR_CODE(bio)); +} + +U_CFUNC PHP_FUNCTION(breakiter_get_error_message) +{ + const char* message = NULL; + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_error_message: bad arguments", 0 TSRMLS_CC ); + RETURN_FALSE; + } + + + /* Fetch the object (without resetting its last error code ). */ + bio = (BreakIterator_object*)zend_object_store_get_object(object TSRMLS_CC); + if (bio == NULL) + RETURN_FALSE; + + /* Return last error message. */ + message = intl_error_get_message(BREAKITER_ERROR_P(bio) TSRMLS_CC); + RETURN_STRING(message, 0); +} diff --git a/ext/intl/breakiterator/breakiterator_methods.h b/ext/intl/breakiterator/breakiterator_methods.h new file mode 100644 index 00000000000..42a6f3a1b30 --- /dev/null +++ b/ext/intl/breakiterator/breakiterator_methods.h @@ -0,0 +1,64 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#ifndef BREAKITERATOR_METHODS_H +#define BREAKITERATOR_METHODS_H + +#include + +PHP_METHOD(BreakIterator, __construct); + +PHP_FUNCTION(breakiter_create_word_instance); + +PHP_FUNCTION(breakiter_create_line_instance); + +PHP_FUNCTION(breakiter_create_character_instance); + +PHP_FUNCTION(breakiter_create_sentence_instance); + +PHP_FUNCTION(breakiter_create_title_instance); + +PHP_FUNCTION(breakiter_get_available_locales); + +PHP_FUNCTION(breakiter_get_text); + +PHP_FUNCTION(breakiter_set_text); + +PHP_FUNCTION(breakiter_first); + +PHP_FUNCTION(breakiter_last); + +PHP_FUNCTION(breakiter_previous); + +PHP_FUNCTION(breakiter_next); + +PHP_FUNCTION(breakiter_current); + +PHP_FUNCTION(breakiter_following); + +PHP_FUNCTION(breakiter_preceding); + +PHP_FUNCTION(breakiter_is_boundary); + +PHP_FUNCTION(breakiter_get_locale); + +PHP_FUNCTION(breakiter_get_parts_iterator); + +PHP_FUNCTION(breakiter_get_error_code); + +PHP_FUNCTION(breakiter_get_error_message); + +#endif \ No newline at end of file diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp new file mode 100644 index 00000000000..5ccef90707c --- /dev/null +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -0,0 +1,227 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#include + +extern "C" { +#define USE_BREAKITERATOR_POINTER 1 +#include "breakiterator_class.h" +#include +#include +} + +#include "../intl_convertcpp.h" + +static inline RuleBasedBreakIterator *fetch_rbbi(BreakIterator_object *bio) { + return (RuleBasedBreakIterator*)bio->biter; +} + +static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *object = getThis(); + char *rules; + int rules_len; + zend_bool compiled = 0; + UErrorCode status = U_ZERO_ERROR; + intl_error_reset(NULL TSRMLS_CC); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", + &rules, &rules_len, &compiled) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_create_instance: bad arguments", 0 TSRMLS_CC); + RETURN_NULL(); + } + + // instantiation of ICU object + RuleBasedBreakIterator *rbbi; + + if (!compiled) { + UnicodeString rulesStr; + UParseError parseError = UParseError(); + if (intl_stringFromChar(rulesStr, rules, rules_len, &status) + == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_create_instance: rules were not a valid UTF-8 string", + 0 TSRMLS_CC); + RETURN_NULL(); + } + + rbbi = new RuleBasedBreakIterator(rulesStr, parseError, status); + intl_error_set_code(NULL, status TSRMLS_CC); + if (U_FAILURE(status)) { + char *msg; + smart_str parse_error_str; + parse_error_str = intl_parse_error_to_string(&parseError); + spprintf(&msg, 0, "rbbi_create_instance: unable to create " + "RuleBasedBreakIterator from rules (%s)", parse_error_str.c); + smart_str_free(&parse_error_str); + intl_error_set_custom_msg(NULL, msg, 1 TSRMLS_CC); + efree(msg); + RETURN_NULL(); + } + } else { // compiled + rbbi = new RuleBasedBreakIterator((uint8_t*)rules, rules_len, status); + if (U_FAILURE(status)) { + intl_error_set(NULL, status, "rbbi_create_instance: unable to " + "creaete instance from compiled rules", 0 TSRMLS_CC); + RETURN_NULL(); + } + } + + breakiterator_object_create(return_value, rbbi TSRMLS_CC); +} + +U_CFUNC PHP_METHOD(RuleBasedBreakIterator, __construct) +{ + zval orig_this = *getThis(); + + return_value = getThis(); + //changes this to IS_NULL (without first destroying) if there's an error + _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAM_PASSTHRU); + + if (Z_TYPE_P(return_value) == IS_NULL) { + zend_object_store_ctor_failed(&orig_this TSRMLS_CC); + zval_dtor(&orig_this); + } +} + +U_CFUNC PHP_FUNCTION(rbbi_hash_code) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_hash_code: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + RETURN_LONG(fetch_rbbi(bio)->hashCode()); +} + +U_CFUNC PHP_FUNCTION(rbbi_get_rules) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_hash_code: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + const UnicodeString rules = fetch_rbbi(bio)->getRules(); + + Z_TYPE_P(return_value) = IS_STRING; + if (intl_charFromString(rules, &Z_STRVAL_P(return_value), + &Z_STRLEN_P(return_value), BREAKITER_ERROR_CODE_P(bio)) == FAILURE) + { + intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), + "rbbi_hash_code: Error converting result to UTF-8 string", + 0 TSRMLS_CC); + RETURN_FALSE; + } +} + +U_CFUNC PHP_FUNCTION(rbbi_get_rule_status) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_get_rule_status: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + RETURN_LONG(fetch_rbbi(bio)->getRuleStatus()); +} + +U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_get_rule_status_vec: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + int32_t num_rules = fetch_rbbi(bio)->getRuleStatusVec(NULL, 0, + BREAKITER_ERROR_CODE(bio)); + if (BREAKITER_ERROR_CODE(bio) == U_BUFFER_OVERFLOW_ERROR) { + BREAKITER_ERROR_CODE(bio) = U_ZERO_ERROR; + } else { + // should not happen + INTL_METHOD_CHECK_STATUS(bio, "rbbi_get_rule_status_vec: failed " + " determining the number of status values"); + } + int32_t *rules = new int32_t[num_rules]; + num_rules = fetch_rbbi(bio)->getRuleStatusVec(rules, num_rules, + BREAKITER_ERROR_CODE(bio)); + if (U_FAILURE(BREAKITER_ERROR_CODE(bio))) { + delete[] rules; + intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), + "rbbi_get_rule_status_vec: failed obtaining the status values", + 0 TSRMLS_CC); + RETURN_FALSE; + } + + array_init_size(return_value, num_rules); + for (int32_t i = 0; i < num_rules; i++) { + add_next_index_long(return_value, rules[i]); + } + delete[] rules; +} + +U_CFUNC PHP_FUNCTION(rbbi_get_binary_rules) +{ + BREAKITER_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, BreakIterator_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "rbbi_get_binary_rules: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + uint32_t rules_len; + const uint8_t *rules = fetch_rbbi(bio)->getBinaryRules(rules_len); + + if (rules_len > INT_MAX - 1) { + intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), + "rbbi_get_binary_rules: the rules are too large", + 0 TSRMLS_CC); + RETURN_FALSE; + } + + char *ret_rules = static_cast(emalloc(rules_len + 1)); + memcpy(ret_rules, rules, rules_len); + ret_rules[rules_len] = '\0'; + + RETURN_STRINGL(ret_rules, rules_len, 0); +} diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.h b/ext/intl/breakiterator/rulebasedbreakiterator_methods.h new file mode 100644 index 00000000000..b645e0c1cc7 --- /dev/null +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.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: Gustavo Lopes | + +----------------------------------------------------------------------+ + */ + +#ifndef RULEBASEDBREAKITERATOR_METHODS_H +#define RULEBASEDBREAKITERATOR_METHODS_H + +#include + +PHP_METHOD(RuleBasedBreakIterator, __construct); + +PHP_FUNCTION(rbbi_hash_code); + +PHP_FUNCTION(rbbi_get_rules); + +PHP_FUNCTION(rbbi_get_rule_status); + +PHP_FUNCTION(rbbi_get_rule_status_vec); + +PHP_FUNCTION(rbbi_get_binary_rules); + +#endif \ No newline at end of file diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp index a0e346061a7..6dfacd7e3a7 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -26,45 +26,14 @@ #include "common_enum.h" extern "C" { -#include "intl_error.h" -#include "intl_data.h" #include #include } -static zend_class_entry *IntlIterator_ce_ptr; +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) +void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC) { zoi_with_current *zoiwc = (zoi_with_current*)iter; @@ -84,22 +53,22 @@ static void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC) * 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); + zoiwc->destroy_it(iter TSRMLS_CC); efree(iter); } } -static int zoi_with_current_valid(zend_object_iterator *iter TSRMLS_DC) +U_CFUNC 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) +U_CFUNC 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) +U_CFUNC 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) { @@ -155,7 +124,7 @@ static void string_enum_rewind(zend_object_iterator *iter TSRMLS_DC) } } -static void string_enum_destroy_free_it(zend_object_iterator *iter TSRMLS_DC) +static void string_enum_destroy_it(zend_object_iterator *iter TSRMLS_DC) { delete (StringEnumeration*)iter->data; } @@ -179,7 +148,7 @@ U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *ob 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)->destroy_it = string_enum_destroy_it; ((zoi_with_current*)ii->iterator)->wrapping_obj = object; ((zoi_with_current*)ii->iterator)->current = NULL; } @@ -331,7 +300,7 @@ static PHP_METHOD(IntlIterator, rewind) if (ii->iterator->funcs->rewind) { ii->iterator->funcs->rewind(ii->iterator TSRMLS_CC); } else { - intl_error_set(NULL, U_UNSUPPORTED_ERROR, + intl_errors_set(INTLITERATOR_ERROR_P(ii), U_UNSUPPORTED_ERROR, "IntlIterator::rewind: rewind not supported", 0 TSRMLS_CC); } } diff --git a/ext/intl/common/common_enum.h b/ext/intl/common/common_enum.h index f3c8bfcead8..bcd9f447968 100644 --- a/ext/intl/common/common_enum.h +++ b/ext/intl/common/common_enum.h @@ -25,10 +25,48 @@ extern "C" { #include #endif #include +#include "../intl_error.h" +#include "../intl_data.h" #ifdef __cplusplus } #endif +#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 zo; + intl_error err; + zend_object_iterator *iterator; +} IntlIterator_object; + +typedef struct { + zend_object_iterator zoi; + zval *current; + zval *wrapping_obj; + void (*destroy_it)(zend_object_iterator *iterator TSRMLS_DC); +} zoi_with_current; + +extern zend_class_entry *IntlIterator_ce_ptr; + +U_CFUNC void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC); +U_CFUNC int zoi_with_current_valid(zend_object_iterator *iter TSRMLS_DC); +U_CFUNC void zoi_with_current_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC); +U_CFUNC void zoi_with_current_invalidate_current(zend_object_iterator *iter TSRMLS_DC); + #ifdef __cplusplus U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *object TSRMLS_DC); #endif diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index 431deeb7d29..227368334df 100755 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -75,6 +75,10 @@ if test "$PHP_INTL" != "no"; then calendar/calendar_class.cpp \ calendar/calendar_methods.cpp \ calendar/gregoriancalendar_methods.cpp \ + breakiterator/breakiterator_class.cpp \ + breakiterator/breakiterator_iterators.cpp \ + breakiterator/breakiterator_methods.cpp \ + breakiterator/rulebasedbreakiterator_methods.cpp \ idn/idn.c \ $icu_spoof_src, $ext_shared,,$ICU_INCS -Wno-write-strings) PHP_ADD_BUILD_DIR($ext_builddir/collator) diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index 735749ab438..6b7d15d56d8 100755 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -102,6 +102,13 @@ if (PHP_INTL != "no") { gregoriancalendar_methods.cpp \ calendar_class.cpp", "intl"); + + ADD_SOURCES(configure_module_dirname + "/breakiterator", "\ + breakiterator_class.cpp \ + breakiterator_methods.cpp \ + breakiterator_iterators.cpp \ + rulebasedbreakiterator_methods.cpp", + "intl"); ADD_FLAG("LIBS_INTL", "icudt.lib icuin.lib icuio.lib icule.lib iculx.lib"); AC_DEFINE("HAVE_INTL", 1, "Internationalization support enabled"); diff --git a/ext/intl/intl_error.c b/ext/intl/intl_error.c index 2c7066b0817..99b1c6001cd 100755 --- a/ext/intl/intl_error.c +++ b/ext/intl/intl_error.c @@ -25,6 +25,7 @@ #include "php_intl.h" #include "intl_error.h" +#include "intl_convert.h" ZEND_EXTERN_MODULE_GLOBALS( intl ) @@ -242,7 +243,82 @@ void intl_register_IntlException_class( TSRMLS_D ) default_exception_ce, NULL TSRMLS_CC ); IntlException_ce_ptr->create_object = default_exception_ce->create_object; } -/* }}} */ + +smart_str intl_parse_error_to_string( UParseError* pe ) +{ + smart_str ret = {0}; + char *buf; + int u8len; + UErrorCode status; + int any = 0; + + assert( pe != NULL ); + + smart_str_appends( &ret, "parse error " ); + if( pe->line > 0 ) + { + smart_str_appends( &ret, "on line " ); + smart_str_append_long( &ret, (long ) pe->line ); + any = 1; + } + if( pe->offset >= 0 ) { + if( any ) + smart_str_appends( &ret, ", " ); + else + smart_str_appends( &ret, "at " ); + + smart_str_appends( &ret, "offset " ); + smart_str_append_long( &ret, (long ) pe->offset ); + any = 1; + } + + if (pe->preContext[0] != 0 ) { + if( any ) + smart_str_appends( &ret, ", " ); + + smart_str_appends( &ret, "after \"" ); + intl_convert_utf16_to_utf8( &buf, &u8len, pe->preContext, -1, &status ); + if( U_FAILURE( status ) ) + { + smart_str_appends( &ret, "(could not convert parser error pre-context to UTF-8)" ); + } + else { + smart_str_appendl( &ret, buf, u8len ); + efree( buf ); + } + smart_str_appends( &ret, "\"" ); + any = 1; + } + + if( pe->postContext[0] != 0 ) + { + if( any ) + smart_str_appends( &ret, ", " ); + + smart_str_appends( &ret, "before or at \"" ); + intl_convert_utf16_to_utf8( &buf, &u8len, pe->postContext, -1, &status ); + if( U_FAILURE( status ) ) + { + smart_str_appends( &ret, "(could not convert parser error post-context to UTF-8)" ); + } + else + { + smart_str_appendl( &ret, buf, u8len ); + efree( buf ); + } + smart_str_appends( &ret, "\"" ); + any = 1; + } + + if( !any ) + { + smart_str_free( &ret ); + smart_str_appends( &ret, "no parse error" ); + } + + smart_str_0( &ret ); + return ret; +} /* * Local variables: diff --git a/ext/intl/intl_error.h b/ext/intl/intl_error.h index b5000a15de6..4d8eb79327f 100755 --- a/ext/intl/intl_error.h +++ b/ext/intl/intl_error.h @@ -20,6 +20,8 @@ #define INTL_ERROR_H #include +#include +#include #define INTL_ERROR_CODE(e) (e).code @@ -44,6 +46,9 @@ void intl_errors_set_custom_msg( intl_error* err, char* msg, int copyMsg void intl_errors_set_code( intl_error* err, UErrorCode err_code TSRMLS_DC ); void intl_errors_set( intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC ); +// Other error helpers +smart_str intl_parse_error_to_string( UParseError* pe ); + // exported to be called on extension MINIT void intl_register_IntlException_class( TSRMLS_D ); diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 59272db7127..5d8aa6be957 100755 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -78,6 +78,8 @@ #include "calendar/calendar_methods.h" #include "calendar/gregoriancalendar_methods.h" +#include "breakiterator/breakiterator_class.h" + #include "idn/idn.h" #if U_ICU_VERSION_MAJOR_NUM > 3 && U_ICU_VERSION_MINOR_NUM >=2 @@ -958,6 +960,9 @@ PHP_MINIT_FUNCTION( intl ) /* Register 'IntlIterator' PHP class */ intl_register_IntlIterator_class( TSRMLS_C ); + /* Register 'BreakIterator' class */ + breakiterator_register_BreakIterator_class( TSRMLS_C ); + /* Global error handling. */ intl_error_init( NULL TSRMLS_CC ); diff --git a/ext/intl/transliterator/transliterator.c b/ext/intl/transliterator/transliterator.c index 75c9eaabdaa..8ee49e1e51b 100644 --- a/ext/intl/transliterator/transliterator.c +++ b/ext/intl/transliterator/transliterator.c @@ -49,85 +49,6 @@ void transliterator_register_constants( INIT_FUNC_ARGS ) } /* }}} */ -/* {{{ transliterator_parse_error_to_string - * Transforms parse errors in strings. - */ -smart_str transliterator_parse_error_to_string( UParseError* pe ) -{ - smart_str ret = {0}; - char *buf; - int u8len; - UErrorCode status; - int any = 0; - - assert( pe != NULL ); - - smart_str_appends( &ret, "parse error " ); - if( pe->line > 0 ) - { - smart_str_appends( &ret, "on line " ); - smart_str_append_long( &ret, (long ) pe->line ); - any = 1; - } - if( pe->offset >= 0 ) { - if( any ) - smart_str_appends( &ret, ", " ); - else - smart_str_appends( &ret, "at " ); - - smart_str_appends( &ret, "offset " ); - smart_str_append_long( &ret, (long ) pe->offset ); - any = 1; - } - - if (pe->preContext[0] != 0 ) { - if( any ) - smart_str_appends( &ret, ", " ); - - smart_str_appends( &ret, "after \"" ); - intl_convert_utf16_to_utf8( &buf, &u8len, pe->preContext, -1, &status ); - if( U_FAILURE( status ) ) - { - smart_str_appends( &ret, "(could not convert parser error pre-context to UTF-8)" ); - } - else { - smart_str_appendl( &ret, buf, u8len ); - efree( buf ); - } - smart_str_appends( &ret, "\"" ); - any = 1; - } - - if( pe->postContext[0] != 0 ) - { - if( any ) - smart_str_appends( &ret, ", " ); - - smart_str_appends( &ret, "before or at \"" ); - intl_convert_utf16_to_utf8( &buf, &u8len, pe->postContext, -1, &status ); - if( U_FAILURE( status ) ) - { - smart_str_appends( &ret, "(could not convert parser error post-context to UTF-8)" ); - } - else - { - smart_str_appendl( &ret, buf, u8len ); - efree( buf ); - } - smart_str_appends( &ret, "\"" ); - any = 1; - } - - if( !any ) - { - smart_str_free( &ret ); - smart_str_appends( &ret, "no parse error" ); - } - - smart_str_0( &ret ); - return ret; -} - /* * Local variables: * tab-width: 4 diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c index d0cfb9790d9..1aa39c54b98 100644 --- a/ext/intl/transliterator/transliterator_methods.c +++ b/ext/intl/transliterator/transliterator_methods.c @@ -183,7 +183,7 @@ PHP_FUNCTION( transliterator_create_from_rules ) { char *msg = NULL; smart_str parse_error_str; - parse_error_str = transliterator_parse_error_to_string( &parse_error ); + parse_error_str = intl_parse_error_to_string( &parse_error ); spprintf( &msg, 0, "transliterator_create_from_rules: unable to " "create ICU transliterator from rules (%s)", parse_error_str.c ); smart_str_free( &parse_error_str ); From 036b1eb2912872ade10e35f26daf10c65cc3cdea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Thu, 31 May 2012 13:02:02 +0200 Subject: [PATCH 02/13] Tests for (RuleBased)BreakIterator. --- ext/intl/tests/breakiter___construct.phpt | 13 +++++ .../tests/breakiter___construct_error.phpt | 35 ++++++++++++ ext/intl/tests/breakiter_clone_basic.phpt | 23 ++++++++ ext/intl/tests/breakiter_current_basic.phpt | 24 ++++++++ ext/intl/tests/breakiter_factories_basic.phpt | 45 +++++++++++++++ ext/intl/tests/breakiter_factories_error.phpt | 39 +++++++++++++ ext/intl/tests/breakiter_first_basic.phpt | 21 +++++++ ...ter_first_last_previous_current_error.phpt | 35 ++++++++++++ ext/intl/tests/breakiter_following_basic.phpt | 20 +++++++ ..._following_preceding_isBoundary_error.phpt | 47 ++++++++++++++++ .../breakiter_getAvailableLocales_basic.phpt | 12 ++++ .../breakiter_getAvailableLocales_error.phpt | 14 +++++ ext/intl/tests/breakiter_getLocale_basic.phpt | 17 ++++++ ext/intl/tests/breakiter_getLocale_error.phpt | 29 ++++++++++ .../breakiter_getPartsIterator_basic.phpt | 29 ++++++++++ ext/intl/tests/breakiter_getText_basic.phpt | 16 ++++++ ext/intl/tests/breakiter_getText_error.phpt | 15 +++++ .../tests/breakiter_isBoundary_basic.phpt | 24 ++++++++ ext/intl/tests/breakiter_last_basic.phpt | 19 +++++++ ext/intl/tests/breakiter_next_basic.phpt | 26 +++++++++ ext/intl/tests/breakiter_next_error.phpt | 23 ++++++++ ext/intl/tests/breakiter_preceding_basic.phpt | 20 +++++++ ext/intl/tests/breakiter_previous_basic.phpt | 18 ++++++ ext/intl/tests/breakiter_setText_basic.phpt | 35 ++++++++++++ ext/intl/tests/breakiter_setText_error.phpt | 40 ++++++++++++++ ext/intl/tests/rbbiter___construct_basic.phpt | 27 +++++++++ .../tests/rbbiter_getBinaryRules_basic.phpt | 36 ++++++++++++ .../tests/rbbiter_getRuleStatusVec_basic.phpt | 55 +++++++++++++++++++ .../tests/rbbiter_getRuleStatus_basic.phpt | 42 ++++++++++++++ ext/intl/tests/rbbiter_getRules_basic.phpt | 28 ++++++++++ ext/intl/tests/rbbiter_hashCode_basic.phpt | 15 +++++ 31 files changed, 842 insertions(+) create mode 100644 ext/intl/tests/breakiter___construct.phpt create mode 100644 ext/intl/tests/breakiter___construct_error.phpt create mode 100644 ext/intl/tests/breakiter_clone_basic.phpt create mode 100644 ext/intl/tests/breakiter_current_basic.phpt create mode 100644 ext/intl/tests/breakiter_factories_basic.phpt create mode 100644 ext/intl/tests/breakiter_factories_error.phpt create mode 100644 ext/intl/tests/breakiter_first_basic.phpt create mode 100644 ext/intl/tests/breakiter_first_last_previous_current_error.phpt create mode 100644 ext/intl/tests/breakiter_following_basic.phpt create mode 100644 ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt create mode 100644 ext/intl/tests/breakiter_getAvailableLocales_basic.phpt create mode 100644 ext/intl/tests/breakiter_getAvailableLocales_error.phpt create mode 100644 ext/intl/tests/breakiter_getLocale_basic.phpt create mode 100644 ext/intl/tests/breakiter_getLocale_error.phpt create mode 100644 ext/intl/tests/breakiter_getPartsIterator_basic.phpt create mode 100644 ext/intl/tests/breakiter_getText_basic.phpt create mode 100644 ext/intl/tests/breakiter_getText_error.phpt create mode 100644 ext/intl/tests/breakiter_isBoundary_basic.phpt create mode 100644 ext/intl/tests/breakiter_last_basic.phpt create mode 100644 ext/intl/tests/breakiter_next_basic.phpt create mode 100644 ext/intl/tests/breakiter_next_error.phpt create mode 100644 ext/intl/tests/breakiter_preceding_basic.phpt create mode 100644 ext/intl/tests/breakiter_previous_basic.phpt create mode 100644 ext/intl/tests/breakiter_setText_basic.phpt create mode 100644 ext/intl/tests/breakiter_setText_error.phpt create mode 100644 ext/intl/tests/rbbiter___construct_basic.phpt create mode 100644 ext/intl/tests/rbbiter_getBinaryRules_basic.phpt create mode 100644 ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt create mode 100644 ext/intl/tests/rbbiter_getRuleStatus_basic.phpt create mode 100644 ext/intl/tests/rbbiter_getRules_basic.phpt create mode 100644 ext/intl/tests/rbbiter_hashCode_basic.phpt diff --git a/ext/intl/tests/breakiter___construct.phpt b/ext/intl/tests/breakiter___construct.phpt new file mode 100644 index 00000000000..a379b19f92e --- /dev/null +++ b/ext/intl/tests/breakiter___construct.phpt @@ -0,0 +1,13 @@ +--TEST-- +BreakIterator::__construct() should not be callable +--SKIPIF-- +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +--FILE-- +setText('foobar'); +$bi_clone = clone $bi; +var_dump(get_class($bi), get_class($bi_clone)); +var_dump($bi == $bi_clone); + +--EXPECT-- +string(22) "RuleBasedBreakIterator" +string(22) "RuleBasedBreakIterator" +bool(true) +string(22) "RuleBasedBreakIterator" +string(22) "RuleBasedBreakIterator" +bool(true) diff --git a/ext/intl/tests/breakiter_current_basic.phpt b/ext/intl/tests/breakiter_current_basic.phpt new file mode 100644 index 00000000000..26f1d5f46e2 --- /dev/null +++ b/ext/intl/tests/breakiter_current_basic.phpt @@ -0,0 +1,24 @@ +--TEST-- +BreakIterator::current(): basic test +--FILE-- +current()); +$bi->setText('foo bar trans zoo bee'); + +var_dump($bi->first()); +var_dump($bi->current()); +var_dump($bi->next()); +var_dump($bi->current()); +?> +==DONE== +--EXPECT-- +int(0) +int(0) +int(0) +int(3) +int(3) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_factories_basic.phpt b/ext/intl/tests/breakiter_factories_basic.phpt new file mode 100644 index 00000000000..30fb312cd55 --- /dev/null +++ b/ext/intl/tests/breakiter_factories_basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +BreakIterator factories: basic tests +--SKIPIF-- +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +--FILE-- +setText('foo bar trans'); + +var_dump($bi->current()); +var_dump($bi->next()); +var_dump($bi->first()); +var_dump($bi->current()); +--EXPECT-- +int(0) +int(3) +int(0) +int(0) diff --git a/ext/intl/tests/breakiter_first_last_previous_current_error.phpt b/ext/intl/tests/breakiter_first_last_previous_current_error.phpt new file mode 100644 index 00000000000..a56228e284f --- /dev/null +++ b/ext/intl/tests/breakiter_first_last_previous_current_error.phpt @@ -0,0 +1,35 @@ +--TEST-- +BreakIterator::first()/last()/previous()/current(): arg errors +--FILE-- +setText("\x80sdfé\x90d888 dfsa9"); + +var_dump($bi->first(1)); +var_dump($bi->last(1)); +var_dump($bi->previous(1)); +var_dump($bi->current(1)); + +--EXPECTF-- + +Warning: BreakIterator::first() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: BreakIterator::first(): breakiter_first: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::last() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: BreakIterator::last(): breakiter_last: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::previous() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: BreakIterator::previous(): breakiter_previous: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::current() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: BreakIterator::current(): breakiter_current: bad arguments in %s on line %d +bool(false) diff --git a/ext/intl/tests/breakiter_following_basic.phpt b/ext/intl/tests/breakiter_following_basic.phpt new file mode 100644 index 00000000000..f460ecbf7ad --- /dev/null +++ b/ext/intl/tests/breakiter_following_basic.phpt @@ -0,0 +1,20 @@ +--TEST-- +BreakIterator::following(): basic test +--FILE-- +setText('foo bar trans zoo bee'); + +var_dump($bi->following(5)); +var_dump($bi->following(50)); +var_dump($bi->following(-1)); +?> +==DONE== +--EXPECT-- +int(7) +int(-1) +int(0) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt b/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt new file mode 100644 index 00000000000..016db6441e3 --- /dev/null +++ b/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt @@ -0,0 +1,47 @@ +--TEST-- +BreakIterator::following()/preceding()/isBoundary(): arg errors +--FILE-- +setText("\x80sdfé\x90d888 dfsa9"); + +var_dump($bi->following(1, 2)); +var_dump($bi->following(array())); +var_dump($bi->preceding(1, 2)); +var_dump($bi->preceding(array())); +var_dump($bi->isBoundary(1, 2)); +var_dump($bi->isBoundary(array())); + +--EXPECTF-- + +Warning: BreakIterator::following() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: BreakIterator::following(): breakiter_following: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::following() expects parameter 1 to be long, array given in %s on line %d + +Warning: BreakIterator::following(): breakiter_following: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::preceding() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: BreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::preceding() expects parameter 1 to be long, array given in %s on line %d + +Warning: BreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::isBoundary() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: BreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::isBoundary() expects parameter 1 to be long, array given in %s on line %d + +Warning: BreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d +bool(false) diff --git a/ext/intl/tests/breakiter_getAvailableLocales_basic.phpt b/ext/intl/tests/breakiter_getAvailableLocales_basic.phpt new file mode 100644 index 00000000000..5cba4c548f7 --- /dev/null +++ b/ext/intl/tests/breakiter_getAvailableLocales_basic.phpt @@ -0,0 +1,12 @@ +--TEST-- +BreakIterator::getAvailableLocales(): basic test +--SKIPIF-- +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +--FILE-- + 150); +--EXPECT-- +bool(true) diff --git a/ext/intl/tests/breakiter_getAvailableLocales_error.phpt b/ext/intl/tests/breakiter_getAvailableLocales_error.phpt new file mode 100644 index 00000000000..4772e8ae2bf --- /dev/null +++ b/ext/intl/tests/breakiter_getAvailableLocales_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +BreakIterator::getAvailableLocales(): arg errors +--FILE-- +getLocale(0)); +var_dump($bi->getLocale(1)); +?> +==DONE== +--EXPECT-- +string(4) "root" +string(4) "root" +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_getLocale_error.phpt b/ext/intl/tests/breakiter_getLocale_error.phpt new file mode 100644 index 00000000000..7d822ab5630 --- /dev/null +++ b/ext/intl/tests/breakiter_getLocale_error.phpt @@ -0,0 +1,29 @@ +--TEST-- +BreakIterator::getLocale(): arg errors +--FILE-- +setText("\x80sdfé\x90d888 dfsa9"); + +var_dump($bi->getLocale(1, 2)); +var_dump($bi->getLocale(array())); +var_dump($bi->getLocale()); + +--EXPECTF-- + +Warning: BreakIterator::getLocale() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: BreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::getLocale() expects parameter 1 to be long, array given in %s on line %d + +Warning: BreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::getLocale() expects exactly 1 parameter, 0 given in %s on line %d + +Warning: BreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d +bool(false) diff --git a/ext/intl/tests/breakiter_getPartsIterator_basic.phpt b/ext/intl/tests/breakiter_getPartsIterator_basic.phpt new file mode 100644 index 00000000000..5c23bfdfa7a --- /dev/null +++ b/ext/intl/tests/breakiter_getPartsIterator_basic.phpt @@ -0,0 +1,29 @@ +--TEST-- +BreakIterator::getPartsIterator(): basic test +--FILE-- +getPartsIterator(); +var_dump(get_class($pi)); +print_r(iterator_to_array($pi)); + +$bi->setText("foo bar"); +$pi = $bi->getPartsIterator(); +print_r(iterator_to_array($pi)); +?> +==DONE== +--EXPECT-- +string(12) "IntlIterator" +Array +( +) +Array +( + [0] => foo + [1] => + [2] => bar +) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_getText_basic.phpt b/ext/intl/tests/breakiter_getText_basic.phpt new file mode 100644 index 00000000000..60801ccc453 --- /dev/null +++ b/ext/intl/tests/breakiter_getText_basic.phpt @@ -0,0 +1,16 @@ +--TEST-- +BreakIterator::getText(): basic test +--SKIPIF-- +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +--FILE-- +getText()); +$bi->setText('foo bar'); +var_dump($bi->getText()); +--EXPECTF-- +NULL +string(7) "foo bar" diff --git a/ext/intl/tests/breakiter_getText_error.phpt b/ext/intl/tests/breakiter_getText_error.phpt new file mode 100644 index 00000000000..79d152831cf --- /dev/null +++ b/ext/intl/tests/breakiter_getText_error.phpt @@ -0,0 +1,15 @@ +--TEST-- +BreakIterator::getText(): arg errors +--FILE-- +getText(array())); + +--EXPECTF-- + +Warning: BreakIterator::getText() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: BreakIterator::getText(): breakiter_get_text: bad arguments in %s on line %d +bool(false) diff --git a/ext/intl/tests/breakiter_isBoundary_basic.phpt b/ext/intl/tests/breakiter_isBoundary_basic.phpt new file mode 100644 index 00000000000..5e8a9f04ecd --- /dev/null +++ b/ext/intl/tests/breakiter_isBoundary_basic.phpt @@ -0,0 +1,24 @@ +--TEST-- +BreakIterator::isBoundary(): basic test +--FILE-- +setText('foo bar trans zoo bee'); + +var_dump($bi->isBoundary(0)); +var_dump($bi->isBoundary(7)); +var_dump($bi->isBoundary(-1)); +var_dump($bi->isBoundary(1)); +var_dump($bi->isBoundary(50)); +?> +==DONE== +--EXPECT-- +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_last_basic.phpt b/ext/intl/tests/breakiter_last_basic.phpt new file mode 100644 index 00000000000..9e260594d9e --- /dev/null +++ b/ext/intl/tests/breakiter_last_basic.phpt @@ -0,0 +1,19 @@ +--TEST-- +BreakIterator::last(): basic test +--SKIPIF-- +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +--FILE-- +setText('foo bar trans'); + +var_dump($bi->current()); +var_dump($bi->last()); +var_dump($bi->current()); +--EXPECTF-- +int(0) +int(13) +int(13) diff --git a/ext/intl/tests/breakiter_next_basic.phpt b/ext/intl/tests/breakiter_next_basic.phpt new file mode 100644 index 00000000000..8e4827e2d4d --- /dev/null +++ b/ext/intl/tests/breakiter_next_basic.phpt @@ -0,0 +1,26 @@ +--TEST-- +BreakIterator::next(): basic test +--FILE-- +setText('foo bar trans zoo bee'); + +var_dump($bi->first()); +var_dump($bi->next()); +var_dump($bi->next(2)); +var_dump($bi->next(-1)); +var_dump($bi->next(0)); +var_dump($bi->next(NULL)); +?> +==DONE== +--EXPECT-- +int(0) +int(3) +int(7) +int(4) +int(4) +int(7) +==DONE== diff --git a/ext/intl/tests/breakiter_next_error.phpt b/ext/intl/tests/breakiter_next_error.phpt new file mode 100644 index 00000000000..08e4aa4c32b --- /dev/null +++ b/ext/intl/tests/breakiter_next_error.phpt @@ -0,0 +1,23 @@ +--TEST-- +BreakIterator::next(): arg errors +--FILE-- +setText("\x80sdfé\x90d888 dfsa9"); + +var_dump($bi->next(1, 2)); +var_dump($bi->next(array())); + +--EXPECTF-- + +Warning: BreakIterator::next() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: BreakIterator::next(): breakiter_next: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::next() expects parameter 1 to be long, array given in %s on line %d + +Warning: BreakIterator::next(): breakiter_next: bad arguments in %s on line %d +bool(false) diff --git a/ext/intl/tests/breakiter_preceding_basic.phpt b/ext/intl/tests/breakiter_preceding_basic.phpt new file mode 100644 index 00000000000..5a321b6f3cc --- /dev/null +++ b/ext/intl/tests/breakiter_preceding_basic.phpt @@ -0,0 +1,20 @@ +--TEST-- +BreakIterator::preceding(): basic test +--FILE-- +setText('foo bar trans zoo bee'); + +var_dump($bi->preceding(5)); +var_dump($bi->preceding(50)); +var_dump($bi->preceding(-1)); +?> +==DONE== +--EXPECT-- +int(4) +int(21) +int(0) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_previous_basic.phpt b/ext/intl/tests/breakiter_previous_basic.phpt new file mode 100644 index 00000000000..2d0e71656d0 --- /dev/null +++ b/ext/intl/tests/breakiter_previous_basic.phpt @@ -0,0 +1,18 @@ +--TEST-- +BreakIterator::previous(): basic test +--FILE-- +setText('foo bar trans'); + +var_dump($bi->last()); +var_dump($bi->previous()); +?> +==DONE== +--EXPECT-- +int(13) +int(8) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/breakiter_setText_basic.phpt b/ext/intl/tests/breakiter_setText_basic.phpt new file mode 100644 index 00000000000..72ea48371b4 --- /dev/null +++ b/ext/intl/tests/breakiter_setText_basic.phpt @@ -0,0 +1,35 @@ +--TEST-- +BreakIterator::setText(): basic test +--SKIPIF-- +if (!extension_loaded('intl')) + die('skip intl extension not enabled'); +--FILE-- +setText('foo bar')); +var_dump($bi->getText()); +var_dump($bi->setText(1)); +var_dump($bi->getText()); +var_dump($bi->setText(new A)); +var_dump($bi->getText()); + +/* setText resets the pointer */ +var_dump($bi->next()); +var_dump($bi->setText('foo bar')); +var_dump($bi->current()); +--EXPECT-- +bool(true) +string(7) "foo bar" +bool(true) +string(1) "1" +bool(true) +string(3) "aaa" +int(3) +bool(true) +int(0) diff --git a/ext/intl/tests/breakiter_setText_error.phpt b/ext/intl/tests/breakiter_setText_error.phpt new file mode 100644 index 00000000000..08d69070a50 --- /dev/null +++ b/ext/intl/tests/breakiter_setText_error.phpt @@ -0,0 +1,40 @@ +--TEST-- +BreakIterator::setText(): arg errors +--FILE-- +setText()); +var_dump($bi->setText(array())); +var_dump($bi->setText(1,2)); + +class A { +function __destruct() { var_dump('destructed'); throw new Exception('e'); } +function __tostring() { return 'foo'; } +} + +try { +var_dump($bi->setText(new A)); +} catch (Exception $e) { +var_dump($e->getMessage()); +} + +--EXPECTF-- + +Warning: BreakIterator::setText() expects exactly 1 parameter, 0 given in %s on line %d + +Warning: BreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::setText() expects parameter 1 to be string, array given in %s on line %d + +Warning: BreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d +bool(false) + +Warning: BreakIterator::setText() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: BreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d +bool(false) +string(10) "destructed" +string(1) "e" diff --git a/ext/intl/tests/rbbiter___construct_basic.phpt b/ext/intl/tests/rbbiter___construct_basic.phpt new file mode 100644 index 00000000000..567a09fa2de --- /dev/null +++ b/ext/intl/tests/rbbiter___construct_basic.phpt @@ -0,0 +1,27 @@ +--TEST-- +RuleBasedBreakIterator::__construct: basic test +--FILE-- + +==DONE== +--EXPECT-- +string(22) "RuleBasedBreakIterator" +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt b/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt new file mode 100644 index 00000000000..815c711cfcb --- /dev/null +++ b/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt @@ -0,0 +1,36 @@ +--TEST-- +RuleBasedBreakIterator::getBinaryRules(): basic test +--FILE-- +setText('sdfkjsdf88á.... ,;');; + +$br = $rbbi->getBinaryRules(); + +$rbbi2 = new RuleBasedBreakIterator($br, true); + +var_dump($rbbi->getRules(), $rbbi2->getRules()); +var_dump($rbbi->getRules() == $rbbi2->getRules()); +?> +==DONE== +--EXPECT-- +string(128) "$LN = [[:letter:] [:number:]];$S = [.;,:];!!forward;$LN+ {1};$S+ {42};!!reverse;$LN+ {1};$S+ {42};!!safe_forward;!!safe_reverse;" +string(128) "$LN = [[:letter:] [:number:]];$S = [.;,:];!!forward;$LN+ {1};$S+ {42};!!reverse;$LN+ {1};$S+ {42};!!safe_forward;!!safe_reverse;" +bool(true) +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt b/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt new file mode 100644 index 00000000000..bbc00e9b48a --- /dev/null +++ b/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt @@ -0,0 +1,55 @@ +--TEST-- +RuleBasedBreakIterator::getRuleStatusVec(): basic test +--FILE-- +setText('sdfkjsdf88á.... ,;');; + +do { + var_dump($rbbi->current(), $rbbi->getRuleStatusVec()); +} while ($rbbi->next() != BreakIterator::DONE); + +?> +==DONE== +--EXPECT-- +int(0) +array(1) { + [0]=> + int(0) +} +int(12) +array(2) { + [0]=> + int(1) + [1]=> + int(4) +} +int(16) +array(1) { + [0]=> + int(42) +} +int(19) +array(1) { + [0]=> + int(4) +} +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt b/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt new file mode 100644 index 00000000000..1bce102489f --- /dev/null +++ b/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt @@ -0,0 +1,42 @@ +--TEST-- +RuleBasedBreakIterator::getRuleStatus(): basic test +--FILE-- +setText('sdfkjsdf88á.... ,;'); + +do { + echo "pos : {$rbbi->current()}\n", + "rule status: {$rbbi->getRuleStatus()}\n"; +} while ($rbbi->next() != BreakIterator::DONE); + +?> +==DONE== +--EXPECT-- +pos : 0 +rule status: 0 +pos : 12 +rule status: 1 +pos : 16 +rule status: 42 +pos : 17 +rule status: 0 +pos : 19 +rule status: 42 +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/rbbiter_getRules_basic.phpt b/ext/intl/tests/rbbiter_getRules_basic.phpt new file mode 100644 index 00000000000..7f510484be9 --- /dev/null +++ b/ext/intl/tests/rbbiter_getRules_basic.phpt @@ -0,0 +1,28 @@ +--TEST-- +RuleBasedBreakIterator::getRules(): basic test +--FILE-- +getRules()); + +?> +==DONE== +--EXPECT-- +string(128) "$LN = [[:letter:] [:number:]];$S = [.;,:];!!forward;$LN+ {1};$S+ {42};!!reverse;$LN+ {1};$S+ {42};!!safe_forward;!!safe_reverse;" +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/rbbiter_hashCode_basic.phpt b/ext/intl/tests/rbbiter_hashCode_basic.phpt new file mode 100644 index 00000000000..83155b5c97b --- /dev/null +++ b/ext/intl/tests/rbbiter_hashCode_basic.phpt @@ -0,0 +1,15 @@ +--TEST-- +RuleBasedBreakIterator::hashCode(): basic test +--FILE-- +hashCode()); + +?> +==DONE== +--EXPECTF-- +int(%d) +==DONE== \ No newline at end of file From c6593a0e9b3ea1a6045f8a52a1b9d8bce4d63773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Mon, 4 Jun 2012 23:09:10 +0200 Subject: [PATCH 03/13] BreakIterator: add rules status constants --- .../breakiterator/breakiterator_class.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index 47e5fb52df1..f273a2f74ae 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -333,6 +333,35 @@ void breakiterator_register_BreakIterator_class(TSRMLS_D) zend_declare_class_constant_long(BreakIterator_ce_ptr, "DONE", sizeof("DONE") - 1, BreakIterator::DONE TSRMLS_CC ); + /* Declare constants that are defined in the C header */ +#define BREAKITER_DECL_LONG_CONST(name) \ + zend_declare_class_constant_long(BreakIterator_ce_ptr, #name, \ + sizeof(#name) - 1, UBRK_ ## name TSRMLS_CC) + + BREAKITER_DECL_LONG_CONST(WORD_NONE); + BREAKITER_DECL_LONG_CONST(WORD_NONE_LIMIT); + BREAKITER_DECL_LONG_CONST(WORD_NUMBER); + BREAKITER_DECL_LONG_CONST(WORD_NUMBER_LIMIT); + BREAKITER_DECL_LONG_CONST(WORD_LETTER); + BREAKITER_DECL_LONG_CONST(WORD_LETTER_LIMIT); + BREAKITER_DECL_LONG_CONST(WORD_KANA); + BREAKITER_DECL_LONG_CONST(WORD_KANA_LIMIT); + BREAKITER_DECL_LONG_CONST(WORD_IDEO); + BREAKITER_DECL_LONG_CONST(WORD_IDEO_LIMIT); + + BREAKITER_DECL_LONG_CONST(LINE_SOFT); + BREAKITER_DECL_LONG_CONST(LINE_SOFT_LIMIT); + BREAKITER_DECL_LONG_CONST(LINE_HARD); + BREAKITER_DECL_LONG_CONST(LINE_HARD_LIMIT); + + BREAKITER_DECL_LONG_CONST(SENTENCE_TERM); + BREAKITER_DECL_LONG_CONST(SENTENCE_TERM_LIMIT); + BREAKITER_DECL_LONG_CONST(SENTENCE_SEP); + BREAKITER_DECL_LONG_CONST(SENTENCE_SEP_LIMIT); + +#undef BREAKITER_DECL_LONG_CONST + + /* Create and register 'RuleBasedBreakIterator' class. */ INIT_CLASS_ENTRY(ce, "RuleBasedBreakIterator", RuleBasedBreakIterator_class_functions); From 4ec75539dba8cefef16e56f02c62755a9aa9c60b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Thu, 7 Jun 2012 15:20:00 +0200 Subject: [PATCH 04/13] Change in BreakIterator::getPartsIterator() BreakIterator::getPartsIterator() now returns an IntlIterator subclass with a special method, getBreakIterator(), that returns the associated BreakIterator. Any call to getRuleStatus() is forwarded to the BreakIterator. --- .../breakiterator/breakiterator_iterators.cpp | 99 ++++++++++++++++++- .../breakiterator/breakiterator_iterators.h | 16 ++- ext/intl/common/common_enum.cpp | 2 +- ext/intl/common/common_enum.h | 1 + ext/intl/php_intl.c | 4 + .../breakiter_getPartsIterator_basic.phpt | 6 +- 6 files changed, 115 insertions(+), 13 deletions(-) diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp index 4a0cf1da80c..66f42922596 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.cpp +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -18,7 +18,10 @@ #include "config.h" #endif +#include + #include "breakiterator_iterators.h" +#include "../common/common_enum.h" extern "C" { #define USE_BREAKITERATOR_POINTER @@ -28,6 +31,9 @@ extern "C" { #include } +static zend_class_entry *IntlPartsIterator_ce_ptr; +static zend_object_handlers IntlPartsIterator_handlers; + /* BreakIterator's iterator */ inline BreakIterator *_breakiter_prolog(zend_object_iterator *iter TSRMLS_DC) @@ -201,7 +207,7 @@ void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, zval_add_ref(&break_iter_zv); - object_init_ex(object, IntlIterator_ce_ptr); + object_init_ex(object, IntlPartsIterator_ce_ptr); ii = (IntlIterator_object*)zend_object_store_get_object(object TSRMLS_CC); ii->iterator = (zend_object_iterator*)emalloc(sizeof(zoi_break_iter_parts)); @@ -216,3 +222,94 @@ void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, zend_object_store_get_object(break_iter_zv TSRMLS_CC); assert(((zoi_break_iter_parts*)ii->iterator)->bio->biter != NULL); } + +U_CFUNC zend_object_value IntlPartsIterator_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + + retval = IntlIterator_ce_ptr->create_object(ce TSRMLS_CC); + retval.handlers = &IntlPartsIterator_handlers; + + return retval; +} + +U_CFUNC zend_function *IntlPartsIterator_get_method(zval **object_ptr, + char *method, int method_len, const zend_literal *key TSRMLS_DC) +{ + zend_literal local_literal = {0}; + zend_function *ret; + ALLOCA_FLAG(use_heap) + + if (key == NULL) { + Z_STRVAL(local_literal.constant) = static_cast( + do_alloca(method_len + 1, use_heap)); + zend_str_tolower_copy(Z_STRVAL(local_literal.constant), + method, method_len); + local_literal.hash_value = zend_hash_func( + Z_STRVAL(local_literal.constant), method_len + 1); + key = &local_literal; + } + + if ((key->hash_value & 0xFFFFFFFF) == 0xA2B486A1 /* hash of getrulestatus\0 */ + && method_len == sizeof("getrulestatus") - 1 + && memcmp("getrulestatus", Z_STRVAL(key->constant), method_len) == 0) { + IntlIterator_object *obj = (IntlIterator_object*) + zend_object_store_get_object(*object_ptr TSRMLS_CC); + if (obj->iterator && obj->iterator->data) { + zval *break_iter_zv = static_cast(obj->iterator->data); + *object_ptr = break_iter_zv; + ret = Z_OBJ_HANDLER_P(break_iter_zv, get_method)(object_ptr, + method, method_len, key TSRMLS_CC); + goto end; + } + } + + ret = std_object_handlers.get_method(object_ptr, + method, method_len, key TSRMLS_CC); + +end: + if (key == &local_literal) { + free_alloca(Z_STRVAL(local_literal.constant), use_heap); + } + + return ret; +} + +U_CFUNC PHP_METHOD(IntlPartsIterator, getBreakIterator) +{ + INTLITERATOR_METHOD_INIT_VARS; + + if (zend_parse_parameters_none() == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "IntlPartsIterator::getBreakIterator: bad arguments", 0 TSRMLS_CC); + return; + } + + INTLITERATOR_METHOD_FETCH_OBJECT; + + zval *biter_zval = static_cast(ii->iterator->data); + RETURN_ZVAL(biter_zval, 1, 0); +} + +ZEND_BEGIN_ARG_INFO_EX(ainfo_parts_it_void, 0, 0, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry IntlPartsIterator_class_functions[] = { + PHP_ME(IntlPartsIterator, getBreakIterator, ainfo_parts_it_void, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D) +{ + zend_class_entry ce; + + /* Create and register 'BreakIterator' class. */ + INIT_CLASS_ENTRY(ce, "IntlPartsIterator", IntlPartsIterator_class_functions); + IntlPartsIterator_ce_ptr = zend_register_internal_class_ex(&ce, + IntlIterator_ce_ptr, NULL TSRMLS_CC); + IntlPartsIterator_ce_ptr->create_object = IntlPartsIterator_object_create; + + memcpy(&IntlPartsIterator_handlers, &IntlIterator_handlers, + sizeof IntlPartsIterator_handlers); + IntlPartsIterator_handlers.get_method = IntlPartsIterator_get_method; +} \ No newline at end of file diff --git a/ext/intl/breakiterator/breakiterator_iterators.h b/ext/intl/breakiterator/breakiterator_iterators.h index 4ef5a2f4eff..855246ff77e 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.h +++ b/ext/intl/breakiterator/breakiterator_iterators.h @@ -16,24 +16,20 @@ #ifndef INTL_BREAKITERATOR_ITERATORS_H #define INTL_BREAKITERATOR_ITERATORS_H -#ifndef __cplusplus -#error Header for C++ only -#endif - -#include #include -#include "../common/common_enum.h" - -extern "C" { +U_CDECL_BEGIN #include #include -} +U_CDECL_END +#ifdef __cplusplus void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, zval *object TSRMLS_DC); +#endif U_CFUNC zend_object_iterator *_breakiterator_get_iterator( - zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); + zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); +U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D); #endif \ No newline at end of file diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp index 6dfacd7e3a7..da47a437a67 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -31,7 +31,7 @@ extern "C" { } zend_class_entry *IntlIterator_ce_ptr; -static zend_object_handlers IntlIterator_handlers; +zend_object_handlers IntlIterator_handlers; void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC) { diff --git a/ext/intl/common/common_enum.h b/ext/intl/common/common_enum.h index bcd9f447968..4c6abdb8f54 100644 --- a/ext/intl/common/common_enum.h +++ b/ext/intl/common/common_enum.h @@ -61,6 +61,7 @@ typedef struct { } zoi_with_current; extern zend_class_entry *IntlIterator_ce_ptr; +extern zend_object_handlers IntlIterator_handlers; U_CFUNC void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC); U_CFUNC int zoi_with_current_valid(zend_object_iterator *iter TSRMLS_DC); diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 5d8aa6be957..c023ba93414 100755 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -79,6 +79,7 @@ #include "calendar/gregoriancalendar_methods.h" #include "breakiterator/breakiterator_class.h" +#include "breakiterator/breakiterator_iterators.h" #include "idn/idn.h" @@ -963,6 +964,9 @@ PHP_MINIT_FUNCTION( intl ) /* Register 'BreakIterator' class */ breakiterator_register_BreakIterator_class( TSRMLS_C ); + /* Register 'IntlPartsIterator' class */ + breakiterator_register_IntlPartsIterator_class( TSRMLS_C ); + /* Global error handling. */ intl_error_init( NULL TSRMLS_CC ); diff --git a/ext/intl/tests/breakiter_getPartsIterator_basic.phpt b/ext/intl/tests/breakiter_getPartsIterator_basic.phpt index 5c23bfdfa7a..7a8c3162584 100644 --- a/ext/intl/tests/breakiter_getPartsIterator_basic.phpt +++ b/ext/intl/tests/breakiter_getPartsIterator_basic.phpt @@ -12,18 +12,22 @@ print_r(iterator_to_array($pi)); $bi->setText("foo bar"); $pi = $bi->getPartsIterator(); +var_dump(get_class($pi->getBreakIterator())); print_r(iterator_to_array($pi)); +var_dump($pi->getRuleStatus()); ?> ==DONE== --EXPECT-- -string(12) "IntlIterator" +string(17) "IntlPartsIterator" Array ( ) +string(22) "RuleBasedBreakIterator" Array ( [0] => foo [1] => [2] => bar ) +int(0) ==DONE== \ No newline at end of file From afed66bb9efc0a8838f2061c4a3aa0befec0f98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Sat, 9 Jun 2012 23:59:26 +0200 Subject: [PATCH 05/13] BreakIter: Removed getAvailableLocales/getHashCode --- .../breakiterator/breakiterator_class.cpp | 2 -- .../breakiterator/breakiterator_methods.cpp | 21 ------------------- .../breakiterator/breakiterator_methods.h | 2 -- .../rulebasedbreakiterator_methods.cpp | 16 -------------- .../rulebasedbreakiterator_methods.h | 2 -- .../breakiter_getAvailableLocales_basic.phpt | 12 ----------- .../breakiter_getAvailableLocales_error.phpt | 14 ------------- ext/intl/tests/rbbiter_hashCode_basic.phpt | 15 ------------- 8 files changed, 84 deletions(-) delete mode 100644 ext/intl/tests/breakiter_getAvailableLocales_basic.phpt delete mode 100644 ext/intl/tests/breakiter_getAvailableLocales_error.phpt delete mode 100644 ext/intl/tests/rbbiter_hashCode_basic.phpt diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index f273a2f74ae..f9ea794d41f 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -274,7 +274,6 @@ static const zend_function_entry BreakIterator_class_functions[] = { PHP_ME_MAPPING(createCharacterInstance, breakiter_create_character_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) PHP_ME_MAPPING(createSentenceInstance, breakiter_create_sentence_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) PHP_ME_MAPPING(createTitleInstance, breakiter_create_title_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) - PHP_ME_MAPPING(getAvailableLocales, breakiter_get_available_locales, ainfo_biter_void, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getText, breakiter_get_text, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(setText, breakiter_set_text, ainfo_biter_setText, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(first, breakiter_first, ainfo_biter_void, ZEND_ACC_PUBLIC) @@ -298,7 +297,6 @@ static const zend_function_entry BreakIterator_class_functions[] = { */ static const zend_function_entry RuleBasedBreakIterator_class_functions[] = { PHP_ME(RuleBasedBreakIterator, __construct, ainfo_rbbi___construct, ZEND_ACC_PUBLIC) - PHP_ME_MAPPING(hashCode, rbbi_hash_code, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRules, rbbi_get_rules, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRuleStatus, rbbi_get_rule_status, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRuleStatusVec, rbbi_get_rule_status_vec, ainfo_biter_void, ZEND_ACC_PUBLIC) diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp index 4aca6ef23f5..28551051c3f 100644 --- a/ext/intl/breakiterator/breakiterator_methods.cpp +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -107,27 +107,6 @@ U_CFUNC PHP_FUNCTION(breakiter_create_title_instance) INTERNAL_FUNCTION_PARAM_PASSTHRU); } -U_CFUNC PHP_FUNCTION(breakiter_get_available_locales) -{ - intl_error_reset(NULL TSRMLS_CC); - - if (zend_parse_parameters_none() == FAILURE) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "breakiter_get_available_locales: bad arguments", 0 TSRMLS_CC); - RETURN_FALSE; - } - - const Locale *locales; - int32_t count; - - locales = BreakIterator::getAvailableLocales(count); - array_init_size(return_value, (uint)count); - for (int i = 0; i < count; i++) { - Locale locale = locales[i]; - add_next_index_string(return_value, locale.getName(), 1); - } -} - U_CFUNC PHP_FUNCTION(breakiter_get_text) { BREAKITER_METHOD_INIT_VARS; diff --git a/ext/intl/breakiterator/breakiterator_methods.h b/ext/intl/breakiterator/breakiterator_methods.h index 42a6f3a1b30..e0d13b0f45e 100644 --- a/ext/intl/breakiterator/breakiterator_methods.h +++ b/ext/intl/breakiterator/breakiterator_methods.h @@ -31,8 +31,6 @@ PHP_FUNCTION(breakiter_create_sentence_instance); PHP_FUNCTION(breakiter_create_title_instance); -PHP_FUNCTION(breakiter_get_available_locales); - PHP_FUNCTION(breakiter_get_text); PHP_FUNCTION(breakiter_set_text); diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index 5ccef90707c..85eceb3f307 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -98,22 +98,6 @@ U_CFUNC PHP_METHOD(RuleBasedBreakIterator, __construct) } } -U_CFUNC PHP_FUNCTION(rbbi_hash_code) -{ - BREAKITER_METHOD_INIT_VARS; - - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "rbbi_hash_code: bad arguments", 0 TSRMLS_CC); - RETURN_FALSE; - } - - BREAKITER_METHOD_FETCH_OBJECT; - - RETURN_LONG(fetch_rbbi(bio)->hashCode()); -} - U_CFUNC PHP_FUNCTION(rbbi_get_rules) { BREAKITER_METHOD_INIT_VARS; diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.h b/ext/intl/breakiterator/rulebasedbreakiterator_methods.h index b645e0c1cc7..29cf3db7d57 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.h +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.h @@ -21,8 +21,6 @@ PHP_METHOD(RuleBasedBreakIterator, __construct); -PHP_FUNCTION(rbbi_hash_code); - PHP_FUNCTION(rbbi_get_rules); PHP_FUNCTION(rbbi_get_rule_status); diff --git a/ext/intl/tests/breakiter_getAvailableLocales_basic.phpt b/ext/intl/tests/breakiter_getAvailableLocales_basic.phpt deleted file mode 100644 index 5cba4c548f7..00000000000 --- a/ext/intl/tests/breakiter_getAvailableLocales_basic.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -BreakIterator::getAvailableLocales(): basic test ---SKIPIF-- -if (!extension_loaded('intl')) - die('skip intl extension not enabled'); ---FILE-- - 150); ---EXPECT-- -bool(true) diff --git a/ext/intl/tests/breakiter_getAvailableLocales_error.phpt b/ext/intl/tests/breakiter_getAvailableLocales_error.phpt deleted file mode 100644 index 4772e8ae2bf..00000000000 --- a/ext/intl/tests/breakiter_getAvailableLocales_error.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -BreakIterator::getAvailableLocales(): arg errors ---FILE-- -hashCode()); - -?> -==DONE== ---EXPECTF-- -int(%d) -==DONE== \ No newline at end of file From a4925fae9b89dcd7912dce5852b4170a978e1bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Sun, 10 Jun 2012 00:23:09 +0200 Subject: [PATCH 06/13] Replaced zend_parse_method_params with plain zpp --- .../breakiterator/breakiterator_methods.cpp | 42 ++++++++++--------- .../rulebasedbreakiterator_methods.cpp | 18 ++++---- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp index 28551051c3f..6777f9005fe 100644 --- a/ext/intl/breakiterator/breakiterator_methods.cpp +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -110,9 +110,9 @@ U_CFUNC PHP_FUNCTION(breakiter_create_title_instance) U_CFUNC PHP_FUNCTION(breakiter_get_text) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_get_text: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -134,9 +134,10 @@ U_CFUNC PHP_FUNCTION(breakiter_set_text) UText *ut = NULL; zval **textzv; BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", - &object, BreakIterator_ce_ptr, &text, &text_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", + &text, &text_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_set_text: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -178,9 +179,9 @@ static void _breakiter_no_args_ret_int32( { char *msg; BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { spprintf(&msg, NULL, "%s: bad arguments", func_name); intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); efree(msg); @@ -202,9 +203,9 @@ static void _breakiter_int32_ret_int32( char *msg; long arg; BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", - &object, BreakIterator_ce_ptr, &arg) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg) == FAILURE) { spprintf(&msg, NULL, "%s: bad arguments", func_name); intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); efree(msg); @@ -279,9 +280,9 @@ U_CFUNC PHP_FUNCTION(breakiter_next) U_CFUNC PHP_FUNCTION(breakiter_current) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_current: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -312,9 +313,10 @@ U_CFUNC PHP_FUNCTION(breakiter_is_boundary) { long offset; BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", - &object, BreakIterator_ce_ptr, &offset) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", + &offset) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_is_boundary: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -338,9 +340,9 @@ U_CFUNC PHP_FUNCTION(breakiter_get_locale) { long locale_type; BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), - "Ol", &object, BreakIterator_ce_ptr, &locale_type) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &locale_type) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_get_locale: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -365,9 +367,9 @@ U_CFUNC PHP_FUNCTION(breakiter_get_locale) U_CFUNC PHP_FUNCTION(breakiter_get_parts_iterator) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_get_parts_iterator: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -381,9 +383,9 @@ U_CFUNC PHP_FUNCTION(breakiter_get_parts_iterator) U_CFUNC PHP_FUNCTION(breakiter_get_error_code) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_get_error_code: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -401,9 +403,9 @@ U_CFUNC PHP_FUNCTION(breakiter_get_error_message) { const char* message = NULL; BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_get_error_message: bad arguments", 0 TSRMLS_CC ); RETURN_FALSE; diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index 85eceb3f307..4e96450d283 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -101,11 +101,11 @@ U_CFUNC PHP_METHOD(RuleBasedBreakIterator, __construct) U_CFUNC PHP_FUNCTION(rbbi_get_rules) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "rbbi_hash_code: bad arguments", 0 TSRMLS_CC); + "rbbi_get_rules: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } @@ -127,9 +127,9 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rules) U_CFUNC PHP_FUNCTION(rbbi_get_rule_status) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "rbbi_get_rule_status: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -143,9 +143,9 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rule_status) U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "rbbi_get_rule_status_vec: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; @@ -183,9 +183,9 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec) U_CFUNC PHP_FUNCTION(rbbi_get_binary_rules) { BREAKITER_METHOD_INIT_VARS; + object = getThis(); - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", - &object, BreakIterator_ce_ptr) == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "rbbi_get_binary_rules: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; From 87dd0269ba262649402bf00207f80aede181f1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Sun, 10 Jun 2012 13:26:28 +0200 Subject: [PATCH 07/13] Remove trailing space --- .../breakiterator/breakiterator_class.cpp | 16 ++--- ext/intl/breakiterator/breakiterator_class.h | 2 +- .../breakiterator/breakiterator_iterators.cpp | 8 +-- .../breakiterator/breakiterator_methods.cpp | 70 +++++++++---------- .../rulebasedbreakiterator_methods.cpp | 28 ++++---- 5 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index f9ea794d41f..05b876665a6 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -76,11 +76,11 @@ static int BreakIterator_compare_objects(zval *object1, bio1 = (BreakIterator_object*)zend_object_store_get_object(object1 TSRMLS_CC); bio2 = (BreakIterator_object*)zend_object_store_get_object(object2 TSRMLS_CC); - + if (bio1->biter == NULL || bio2->biter == NULL) { return bio1->biter == bio2->biter ? 0 : 1; } - + return *bio1->biter == *bio2->biter ? 0 : 1; } /* }}} */ @@ -136,9 +136,9 @@ static HashTable *BreakIterator_get_debug_info(zval *object, int *is_temp TSRMLS zval zv = zval_used_for_init; BreakIterator_object *bio; const BreakIterator *biter; - + *is_temp = 1; - + array_init_size(&zv, 8); bio = (BreakIterator_object*)zend_object_store_get_object(object TSRMLS_CC); @@ -149,14 +149,14 @@ static HashTable *BreakIterator_get_debug_info(zval *object, int *is_temp TSRMLS return Z_ARRVAL(zv); } add_assoc_bool_ex(&zv, "valid", sizeof("valid"), 1); - + if (bio->text == NULL) { add_assoc_null_ex(&zv, "text", sizeof("text")); } else { zval_add_ref(&bio->text); add_assoc_zval_ex(&zv, "text", sizeof("text"), bio->text); } - + add_assoc_string_ex(&zv, "type", sizeof("type"), const_cast(typeid(*biter).name()), 1); @@ -210,7 +210,7 @@ static zend_object_value BreakIterator_object_create(zend_class_entry *ce TSRMLS BreakIterator_object* intern; intern = (BreakIterator_object*)ecalloc(1, sizeof(BreakIterator_object)); - + zend_object_std_init(&intern->zo, ce TSRMLS_CC); #if PHP_VERSION_ID < 50399 zend_hash_copy(intern->zo.properties, &(ce->default_properties), @@ -324,7 +324,7 @@ void breakiterator_register_BreakIterator_class(TSRMLS_D) BreakIterator_handlers.compare_objects = BreakIterator_compare_objects; BreakIterator_handlers.clone_obj = BreakIterator_clone_obj; BreakIterator_handlers.get_debug_info = BreakIterator_get_debug_info; - + zend_class_implements(BreakIterator_ce_ptr TSRMLS_CC, 1, zend_ce_traversable); diff --git a/ext/intl/breakiterator/breakiterator_class.h b/ext/intl/breakiterator/breakiterator_class.h index a3872662832..cc5d51256f9 100644 --- a/ext/intl/breakiterator/breakiterator_class.h +++ b/ext/intl/breakiterator/breakiterator_class.h @@ -36,7 +36,7 @@ typedef struct { // ICU break iterator BreakIterator* biter; - + // current text zval *text; } BreakIterator_object; diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp index 66f42922596..d3ad050299f 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.cpp +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -226,10 +226,10 @@ void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, U_CFUNC zend_object_value IntlPartsIterator_object_create(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; - + retval = IntlIterator_ce_ptr->create_object(ce TSRMLS_CC); retval.handlers = &IntlPartsIterator_handlers; - + return retval; } @@ -263,7 +263,7 @@ U_CFUNC zend_function *IntlPartsIterator_get_method(zval **object_ptr, goto end; } } - + ret = std_object_handlers.get_method(object_ptr, method, method_len, key TSRMLS_CC); @@ -286,7 +286,7 @@ U_CFUNC PHP_METHOD(IntlPartsIterator, getBreakIterator) } INTLITERATOR_METHOD_FETCH_OBJECT; - + zval *biter_zval = static_cast(ii->iterator->data); RETURN_ZVAL(biter_zval, 1, 0); } diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp index 6777f9005fe..5b8f859d527 100644 --- a/ext/intl/breakiterator/breakiterator_methods.cpp +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -46,7 +46,7 @@ static void _breakiter_factory(const char *func_name, char *msg; UErrorCode status = UErrorCode(); intl_error_reset(NULL TSRMLS_CC); - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &locale_str, &dummy) == FAILURE) { spprintf(&msg, NULL, "%s: bad arguments", func_name); @@ -54,11 +54,11 @@ static void _breakiter_factory(const char *func_name, efree(msg); RETURN_NULL(); } - + if (locale_str == NULL) { locale_str = intl_locale_get_default(TSRMLS_C); } - + biter = func(Locale::createFromName(locale_str), status); intl_error_set_code(NULL, status TSRMLS_CC); if (U_FAILURE(status)) { @@ -68,7 +68,7 @@ static void _breakiter_factory(const char *func_name, efree(msg); RETURN_NULL(); } - + breakiterator_object_create(return_value, biter TSRMLS_CC); } @@ -117,9 +117,9 @@ U_CFUNC PHP_FUNCTION(breakiter_get_text) "breakiter_get_text: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + if (bio->text == NULL) { RETURN_NULL(); } else { @@ -135,31 +135,31 @@ U_CFUNC PHP_FUNCTION(breakiter_set_text) zval **textzv; BREAKITER_METHOD_INIT_VARS; object = getThis(); - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_set_text: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + int res = zend_get_parameters_ex(1, &textzv); assert(res == SUCCESS); - + BREAKITER_METHOD_FETCH_OBJECT; - + /* assert it's safe to use text and text_len because zpp changes the * arguments in the stack */ assert(text == Z_STRVAL_PP(textzv)); - + ut = utext_openUTF8(ut, text, text_len, BREAKITER_ERROR_CODE_P(bio)); INTL_CTOR_CHECK_STATUS(bio, "breakiter_set_text: error opening UText"); - + bio->biter->setText(ut, BREAKITER_ERROR_CODE(bio)); utext_close(ut); /* ICU shallow clones the UText */ INTL_CTOR_CHECK_STATUS(bio, "breakiter_set_text: error calling " "BreakIterator::setText()"); - + /* When ICU clones the UText, it does not copy the buffer, so we have to * keep the string buffer around by holding a reference to its zval. This * also allows a faste implementation of getText() */ @@ -168,7 +168,7 @@ U_CFUNC PHP_FUNCTION(breakiter_set_text) } bio->text = *textzv; zval_add_ref(&bio->text); - + RETURN_TRUE; } @@ -180,18 +180,18 @@ static void _breakiter_no_args_ret_int32( char *msg; BREAKITER_METHOD_INIT_VARS; object = getThis(); - + if (zend_parse_parameters_none() == FAILURE) { spprintf(&msg, NULL, "%s: bad arguments", func_name); intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); efree(msg); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + int32_t res = (bio->biter->*func)(); - + RETURN_LONG((long)res); } @@ -204,16 +204,16 @@ static void _breakiter_int32_ret_int32( long arg; BREAKITER_METHOD_INIT_VARS; object = getThis(); - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg) == FAILURE) { spprintf(&msg, NULL, "%s: bad arguments", func_name); intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC); efree(msg); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + if (arg < INT32_MIN || arg > INT32_MAX) { spprintf(&msg, NULL, "%s: offset argument is outside bounds of " "a 32-bit wide integer", func_name); @@ -221,9 +221,9 @@ static void _breakiter_int32_ret_int32( efree(msg); RETURN_FALSE; } - + int32_t res = (bio->biter->*func)((int32_t)arg); - + RETURN_LONG((long)res); } @@ -251,7 +251,7 @@ U_CFUNC PHP_FUNCTION(breakiter_previous) U_CFUNC PHP_FUNCTION(breakiter_next) { bool no_arg_version = false; - + if (ZEND_NUM_ARGS() == 0) { no_arg_version = true; } else if (ZEND_NUM_ARGS() == 1) { @@ -265,7 +265,7 @@ U_CFUNC PHP_FUNCTION(breakiter_next) no_arg_version = false; } } - + if (no_arg_version) { _breakiter_no_args_ret_int32("breakiter_next", &BreakIterator::next, @@ -281,17 +281,17 @@ U_CFUNC PHP_FUNCTION(breakiter_current) { BREAKITER_METHOD_INIT_VARS; object = getThis(); - + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_current: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + int32_t res = bio->biter->current(); - + RETURN_LONG((long)res); } @@ -314,25 +314,25 @@ U_CFUNC PHP_FUNCTION(breakiter_is_boundary) long offset; BREAKITER_METHOD_INIT_VARS; object = getThis(); - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &offset) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_is_boundary: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + if (offset < INT32_MIN || offset > INT32_MAX) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_is_boundary: offset argument is outside bounds of " "a 32-bit wide integer", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + UBool res = bio->biter->isBoundary((int32_t)offset); - + RETURN_BOOL((long)res); } @@ -368,7 +368,7 @@ U_CFUNC PHP_FUNCTION(breakiter_get_parts_iterator) { BREAKITER_METHOD_INIT_VARS; object = getThis(); - + if (zend_parse_parameters_none() == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "breakiter_get_parts_iterator: bad arguments", 0 TSRMLS_CC); diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index 4e96450d283..f0f680355b8 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -44,7 +44,7 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS) "rbbi_create_instance: bad arguments", 0 TSRMLS_CC); RETURN_NULL(); } - + // instantiation of ICU object RuleBasedBreakIterator *rbbi; @@ -108,11 +108,11 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rules) "rbbi_get_rules: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + const UnicodeString rules = fetch_rbbi(bio)->getRules(); - + Z_TYPE_P(return_value) = IS_STRING; if (intl_charFromString(rules, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), BREAKITER_ERROR_CODE_P(bio)) == FAILURE) @@ -134,9 +134,9 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rule_status) "rbbi_get_rule_status: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + RETURN_LONG(fetch_rbbi(bio)->getRuleStatus()); } @@ -150,9 +150,9 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec) "rbbi_get_rule_status_vec: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + int32_t num_rules = fetch_rbbi(bio)->getRuleStatusVec(NULL, 0, BREAKITER_ERROR_CODE(bio)); if (BREAKITER_ERROR_CODE(bio) == U_BUFFER_OVERFLOW_ERROR) { @@ -172,7 +172,7 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec) 0 TSRMLS_CC); RETURN_FALSE; } - + array_init_size(return_value, num_rules); for (int32_t i = 0; i < num_rules; i++) { add_next_index_long(return_value, rules[i]); @@ -190,22 +190,22 @@ U_CFUNC PHP_FUNCTION(rbbi_get_binary_rules) "rbbi_get_binary_rules: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } - + BREAKITER_METHOD_FETCH_OBJECT; - + uint32_t rules_len; const uint8_t *rules = fetch_rbbi(bio)->getBinaryRules(rules_len); - + if (rules_len > INT_MAX - 1) { intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), "rbbi_get_binary_rules: the rules are too large", 0 TSRMLS_CC); RETURN_FALSE; } - + char *ret_rules = static_cast(emalloc(rules_len + 1)); memcpy(ret_rules, rules, rules_len); ret_rules[rules_len] = '\0'; - + RETURN_STRINGL(ret_rules, rules_len, 0); } From cee31091a960014ce5315008fc64437d04174caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Sun, 10 Jun 2012 22:42:38 +0200 Subject: [PATCH 08/13] Add Intl prefix to BreakIterator/RuleBasedBI --- .../breakiterator/breakiterator_class.cpp | 8 ++--- .../rulebasedbreakiterator_methods.cpp | 2 +- .../rulebasedbreakiterator_methods.h | 2 +- ext/intl/tests/breakiter___construct.phpt | 6 ++-- .../tests/breakiter___construct_error.phpt | 28 ++++++++-------- ext/intl/tests/breakiter_clone_basic.phpt | 12 +++---- ext/intl/tests/breakiter_current_basic.phpt | 4 +-- ext/intl/tests/breakiter_factories_basic.phpt | 6 ++-- ext/intl/tests/breakiter_factories_error.phpt | 32 +++++++++---------- ext/intl/tests/breakiter_first_basic.phpt | 4 +-- ...ter_first_last_previous_current_error.phpt | 20 ++++++------ ext/intl/tests/breakiter_following_basic.phpt | 4 +-- ..._following_preceding_isBoundary_error.phpt | 28 ++++++++-------- ext/intl/tests/breakiter_getLocale_basic.phpt | 4 +-- ext/intl/tests/breakiter_getLocale_error.phpt | 16 +++++----- .../breakiter_getPartsIterator_basic.phpt | 6 ++-- ext/intl/tests/breakiter_getText_basic.phpt | 4 +-- ext/intl/tests/breakiter_getText_error.phpt | 8 ++--- .../tests/breakiter_isBoundary_basic.phpt | 4 +-- ext/intl/tests/breakiter_last_basic.phpt | 4 +-- ext/intl/tests/breakiter_next_basic.phpt | 4 +-- ext/intl/tests/breakiter_next_error.phpt | 12 +++---- ext/intl/tests/breakiter_preceding_basic.phpt | 4 +-- ext/intl/tests/breakiter_previous_basic.phpt | 4 +-- ext/intl/tests/breakiter_setText_basic.phpt | 4 +-- ext/intl/tests/breakiter_setText_error.phpt | 16 +++++----- ext/intl/tests/rbbiter___construct_basic.phpt | 6 ++-- .../tests/rbbiter_getBinaryRules_basic.phpt | 6 ++-- .../tests/rbbiter_getRuleStatusVec_basic.phpt | 6 ++-- .../tests/rbbiter_getRuleStatus_basic.phpt | 6 ++-- ext/intl/tests/rbbiter_getRules_basic.phpt | 4 +-- 31 files changed, 137 insertions(+), 137 deletions(-) diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index 05b876665a6..8c25314a4a8 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -296,7 +296,7 @@ static const zend_function_entry BreakIterator_class_functions[] = { /* {{{ RuleBasedBreakIterator_class_functions */ static const zend_function_entry RuleBasedBreakIterator_class_functions[] = { - PHP_ME(RuleBasedBreakIterator, __construct, ainfo_rbbi___construct, ZEND_ACC_PUBLIC) + PHP_ME(IntlRuleBasedBreakIterator, __construct, ainfo_rbbi___construct, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRules, rbbi_get_rules, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRuleStatus, rbbi_get_rule_status, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRuleStatusVec, rbbi_get_rule_status_vec, ainfo_biter_void, ZEND_ACC_PUBLIC) @@ -314,12 +314,12 @@ void breakiterator_register_BreakIterator_class(TSRMLS_D) zend_class_entry ce; /* Create and register 'BreakIterator' class. */ - INIT_CLASS_ENTRY(ce, "BreakIterator", BreakIterator_class_functions); + INIT_CLASS_ENTRY(ce, "IntlBreakIterator", BreakIterator_class_functions); ce.create_object = BreakIterator_object_create; ce.get_iterator = _breakiterator_get_iterator; BreakIterator_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC); - memcpy( &BreakIterator_handlers, zend_get_std_object_handlers(), + memcpy(&BreakIterator_handlers, zend_get_std_object_handlers(), sizeof BreakIterator_handlers); BreakIterator_handlers.compare_objects = BreakIterator_compare_objects; BreakIterator_handlers.clone_obj = BreakIterator_clone_obj; @@ -361,7 +361,7 @@ void breakiterator_register_BreakIterator_class(TSRMLS_D) /* Create and register 'RuleBasedBreakIterator' class. */ - INIT_CLASS_ENTRY(ce, "RuleBasedBreakIterator", + INIT_CLASS_ENTRY(ce, "IntlRuleBasedBreakIterator", RuleBasedBreakIterator_class_functions); RuleBasedBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce, BreakIterator_ce_ptr, NULL TSRMLS_CC); diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index f0f680355b8..288179a7859 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -84,7 +84,7 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS) breakiterator_object_create(return_value, rbbi TSRMLS_CC); } -U_CFUNC PHP_METHOD(RuleBasedBreakIterator, __construct) +U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, __construct) { zval orig_this = *getThis(); diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.h b/ext/intl/breakiterator/rulebasedbreakiterator_methods.h index 29cf3db7d57..edea4ea2a69 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.h +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.h @@ -19,7 +19,7 @@ #include -PHP_METHOD(RuleBasedBreakIterator, __construct); +PHP_METHOD(IntlRuleBasedBreakIterator, __construct); PHP_FUNCTION(rbbi_get_rules); diff --git a/ext/intl/tests/breakiter___construct.phpt b/ext/intl/tests/breakiter___construct.phpt index a379b19f92e..9ea6a9cf118 100644 --- a/ext/intl/tests/breakiter___construct.phpt +++ b/ext/intl/tests/breakiter___construct.phpt @@ -1,5 +1,5 @@ --TEST-- -BreakIterator::__construct() should not be callable +IntlBreakIterator::__construct() should not be callable --SKIPIF-- if (!extension_loaded('intl')) die('skip intl extension not enabled'); @@ -7,7 +7,7 @@ if (!extension_loaded('intl')) current()); $bi->setText('foo bar trans zoo bee'); diff --git a/ext/intl/tests/breakiter_factories_basic.phpt b/ext/intl/tests/breakiter_factories_basic.phpt index 30fb312cd55..333023a2538 100644 --- a/ext/intl/tests/breakiter_factories_basic.phpt +++ b/ext/intl/tests/breakiter_factories_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -BreakIterator factories: basic tests +IntlBreakIterator factories: basic tests --SKIPIF-- if (!extension_loaded('intl')) die('skip intl extension not enabled'); @@ -16,9 +16,9 @@ $t = 'Frase 1... Frase 2'. $o1 = $o2 = null; foreach ($m as $method) { echo "===== $method =====\n"; - $o1 = call_user_func(array('Breakiterator', $method), 'ja'); + $o1 = call_user_func(array('IntlBreakIterator', $method), 'ja'); var_dump($o1 == $o2); - $o2 = call_user_func(array('Breakiterator', $method), NULL); + $o2 = call_user_func(array('IntlBreakIterator', $method), NULL); var_dump($o1 == $o2); echo "\n"; } diff --git a/ext/intl/tests/breakiter_factories_error.phpt b/ext/intl/tests/breakiter_factories_error.phpt index d172143ad1f..6001946ad29 100644 --- a/ext/intl/tests/breakiter_factories_error.phpt +++ b/ext/intl/tests/breakiter_factories_error.phpt @@ -1,39 +1,39 @@ --TEST-- -BreakIterator factory methods: argument errors +IntlBreakIterator factory methods: argument errors --FILE-- setText('foo bar trans'); var_dump($bi->current()); diff --git a/ext/intl/tests/breakiter_first_last_previous_current_error.phpt b/ext/intl/tests/breakiter_first_last_previous_current_error.phpt index a56228e284f..9865cdec58f 100644 --- a/ext/intl/tests/breakiter_first_last_previous_current_error.phpt +++ b/ext/intl/tests/breakiter_first_last_previous_current_error.phpt @@ -1,10 +1,10 @@ --TEST-- -BreakIterator::first()/last()/previous()/current(): arg errors +IntlBreakIterator::first()/last()/previous()/current(): arg errors --FILE-- setText("\x80sdfé\x90d888 dfsa9"); var_dump($bi->first(1)); @@ -14,22 +14,22 @@ var_dump($bi->current(1)); --EXPECTF-- -Warning: BreakIterator::first() expects exactly 0 parameters, 1 given in %s on line %d +Warning: IntlBreakIterator::first() expects exactly 0 parameters, 1 given in %s on line %d -Warning: BreakIterator::first(): breakiter_first: bad arguments in %s on line %d +Warning: IntlBreakIterator::first(): breakiter_first: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::last() expects exactly 0 parameters, 1 given in %s on line %d +Warning: IntlBreakIterator::last() expects exactly 0 parameters, 1 given in %s on line %d -Warning: BreakIterator::last(): breakiter_last: bad arguments in %s on line %d +Warning: IntlBreakIterator::last(): breakiter_last: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::previous() expects exactly 0 parameters, 1 given in %s on line %d +Warning: IntlBreakIterator::previous() expects exactly 0 parameters, 1 given in %s on line %d -Warning: BreakIterator::previous(): breakiter_previous: bad arguments in %s on line %d +Warning: IntlBreakIterator::previous(): breakiter_previous: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::current() expects exactly 0 parameters, 1 given in %s on line %d +Warning: IntlBreakIterator::current() expects exactly 0 parameters, 1 given in %s on line %d -Warning: BreakIterator::current(): breakiter_current: bad arguments in %s on line %d +Warning: IntlBreakIterator::current(): breakiter_current: bad arguments in %s on line %d bool(false) diff --git a/ext/intl/tests/breakiter_following_basic.phpt b/ext/intl/tests/breakiter_following_basic.phpt index f460ecbf7ad..967ccafb621 100644 --- a/ext/intl/tests/breakiter_following_basic.phpt +++ b/ext/intl/tests/breakiter_following_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::following(): basic test +IntlBreakIterator::following(): basic test --FILE-- setText('foo bar trans zoo bee'); var_dump($bi->following(5)); diff --git a/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt b/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt index 016db6441e3..a4b60857aba 100644 --- a/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt +++ b/ext/intl/tests/breakiter_following_preceding_isBoundary_error.phpt @@ -1,10 +1,10 @@ --TEST-- -BreakIterator::following()/preceding()/isBoundary(): arg errors +IntlBreakIterator::following()/preceding()/isBoundary(): arg errors --FILE-- setText("\x80sdfé\x90d888 dfsa9"); var_dump($bi->following(1, 2)); @@ -16,32 +16,32 @@ var_dump($bi->isBoundary(array())); --EXPECTF-- -Warning: BreakIterator::following() expects exactly 1 parameter, 2 given in %s on line %d +Warning: IntlBreakIterator::following() expects exactly 1 parameter, 2 given in %s on line %d -Warning: BreakIterator::following(): breakiter_following: bad arguments in %s on line %d +Warning: IntlBreakIterator::following(): breakiter_following: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::following() expects parameter 1 to be long, array given in %s on line %d +Warning: IntlBreakIterator::following() expects parameter 1 to be long, array given in %s on line %d -Warning: BreakIterator::following(): breakiter_following: bad arguments in %s on line %d +Warning: IntlBreakIterator::following(): breakiter_following: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::preceding() expects exactly 1 parameter, 2 given in %s on line %d +Warning: IntlBreakIterator::preceding() expects exactly 1 parameter, 2 given in %s on line %d -Warning: BreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d +Warning: IntlBreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::preceding() expects parameter 1 to be long, array given in %s on line %d +Warning: IntlBreakIterator::preceding() expects parameter 1 to be long, array given in %s on line %d -Warning: BreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d +Warning: IntlBreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::isBoundary() expects exactly 1 parameter, 2 given in %s on line %d +Warning: IntlBreakIterator::isBoundary() expects exactly 1 parameter, 2 given in %s on line %d -Warning: BreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d +Warning: IntlBreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::isBoundary() expects parameter 1 to be long, array given in %s on line %d +Warning: IntlBreakIterator::isBoundary() expects parameter 1 to be long, array given in %s on line %d -Warning: BreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d +Warning: IntlBreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d bool(false) diff --git a/ext/intl/tests/breakiter_getLocale_basic.phpt b/ext/intl/tests/breakiter_getLocale_basic.phpt index eeed6e802c6..499316c1692 100644 --- a/ext/intl/tests/breakiter_getLocale_basic.phpt +++ b/ext/intl/tests/breakiter_getLocale_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::getLocale(): basic test +IntlBreakIterator::getLocale(): basic test --FILE-- getLocale(0)); var_dump($bi->getLocale(1)); diff --git a/ext/intl/tests/breakiter_getLocale_error.phpt b/ext/intl/tests/breakiter_getLocale_error.phpt index 7d822ab5630..1dec56db080 100644 --- a/ext/intl/tests/breakiter_getLocale_error.phpt +++ b/ext/intl/tests/breakiter_getLocale_error.phpt @@ -1,10 +1,10 @@ --TEST-- -BreakIterator::getLocale(): arg errors +IntlBreakIterator::getLocale(): arg errors --FILE-- setText("\x80sdfé\x90d888 dfsa9"); var_dump($bi->getLocale(1, 2)); @@ -13,17 +13,17 @@ var_dump($bi->getLocale()); --EXPECTF-- -Warning: BreakIterator::getLocale() expects exactly 1 parameter, 2 given in %s on line %d +Warning: IntlBreakIterator::getLocale() expects exactly 1 parameter, 2 given in %s on line %d -Warning: BreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d +Warning: IntlBreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::getLocale() expects parameter 1 to be long, array given in %s on line %d +Warning: IntlBreakIterator::getLocale() expects parameter 1 to be long, array given in %s on line %d -Warning: BreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d +Warning: IntlBreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::getLocale() expects exactly 1 parameter, 0 given in %s on line %d +Warning: IntlBreakIterator::getLocale() expects exactly 1 parameter, 0 given in %s on line %d -Warning: BreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d +Warning: IntlBreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d bool(false) diff --git a/ext/intl/tests/breakiter_getPartsIterator_basic.phpt b/ext/intl/tests/breakiter_getPartsIterator_basic.phpt index 7a8c3162584..794bab30148 100644 --- a/ext/intl/tests/breakiter_getPartsIterator_basic.phpt +++ b/ext/intl/tests/breakiter_getPartsIterator_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::getPartsIterator(): basic test +IntlBreakIterator::getPartsIterator(): basic test --FILE-- getPartsIterator(); var_dump(get_class($pi)); print_r(iterator_to_array($pi)); @@ -22,7 +22,7 @@ string(17) "IntlPartsIterator" Array ( ) -string(22) "RuleBasedBreakIterator" +string(26) "IntlRuleBasedBreakIterator" Array ( [0] => foo diff --git a/ext/intl/tests/breakiter_getText_basic.phpt b/ext/intl/tests/breakiter_getText_basic.phpt index 60801ccc453..57f3e32aa38 100644 --- a/ext/intl/tests/breakiter_getText_basic.phpt +++ b/ext/intl/tests/breakiter_getText_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -BreakIterator::getText(): basic test +IntlBreakIterator::getText(): basic test --SKIPIF-- if (!extension_loaded('intl')) die('skip intl extension not enabled'); @@ -7,7 +7,7 @@ if (!extension_loaded('intl')) getText()); $bi->setText('foo bar'); var_dump($bi->getText()); diff --git a/ext/intl/tests/breakiter_getText_error.phpt b/ext/intl/tests/breakiter_getText_error.phpt index 79d152831cf..f222002374b 100644 --- a/ext/intl/tests/breakiter_getText_error.phpt +++ b/ext/intl/tests/breakiter_getText_error.phpt @@ -1,15 +1,15 @@ --TEST-- -BreakIterator::getText(): arg errors +IntlBreakIterator::getText(): arg errors --FILE-- getText(array())); --EXPECTF-- -Warning: BreakIterator::getText() expects exactly 0 parameters, 1 given in %s on line %d +Warning: IntlBreakIterator::getText() expects exactly 0 parameters, 1 given in %s on line %d -Warning: BreakIterator::getText(): breakiter_get_text: bad arguments in %s on line %d +Warning: IntlBreakIterator::getText(): breakiter_get_text: bad arguments in %s on line %d bool(false) diff --git a/ext/intl/tests/breakiter_isBoundary_basic.phpt b/ext/intl/tests/breakiter_isBoundary_basic.phpt index 5e8a9f04ecd..87d82273520 100644 --- a/ext/intl/tests/breakiter_isBoundary_basic.phpt +++ b/ext/intl/tests/breakiter_isBoundary_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::isBoundary(): basic test +IntlBreakIterator::isBoundary(): basic test --FILE-- setText('foo bar trans zoo bee'); var_dump($bi->isBoundary(0)); diff --git a/ext/intl/tests/breakiter_last_basic.phpt b/ext/intl/tests/breakiter_last_basic.phpt index 9e260594d9e..0d3aead232f 100644 --- a/ext/intl/tests/breakiter_last_basic.phpt +++ b/ext/intl/tests/breakiter_last_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -BreakIterator::last(): basic test +IntlBreakIterator::last(): basic test --SKIPIF-- if (!extension_loaded('intl')) die('skip intl extension not enabled'); @@ -7,7 +7,7 @@ if (!extension_loaded('intl')) setText('foo bar trans'); var_dump($bi->current()); diff --git a/ext/intl/tests/breakiter_next_basic.phpt b/ext/intl/tests/breakiter_next_basic.phpt index 8e4827e2d4d..3d535443b8a 100644 --- a/ext/intl/tests/breakiter_next_basic.phpt +++ b/ext/intl/tests/breakiter_next_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::next(): basic test +IntlBreakIterator::next(): basic test --FILE-- setText('foo bar trans zoo bee'); var_dump($bi->first()); diff --git a/ext/intl/tests/breakiter_next_error.phpt b/ext/intl/tests/breakiter_next_error.phpt index 08e4aa4c32b..40d8f5813b1 100644 --- a/ext/intl/tests/breakiter_next_error.phpt +++ b/ext/intl/tests/breakiter_next_error.phpt @@ -1,10 +1,10 @@ --TEST-- -BreakIterator::next(): arg errors +IntlBreakIterator::next(): arg errors --FILE-- setText("\x80sdfé\x90d888 dfsa9"); var_dump($bi->next(1, 2)); @@ -12,12 +12,12 @@ var_dump($bi->next(array())); --EXPECTF-- -Warning: BreakIterator::next() expects exactly 1 parameter, 2 given in %s on line %d +Warning: IntlBreakIterator::next() expects exactly 1 parameter, 2 given in %s on line %d -Warning: BreakIterator::next(): breakiter_next: bad arguments in %s on line %d +Warning: IntlBreakIterator::next(): breakiter_next: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::next() expects parameter 1 to be long, array given in %s on line %d +Warning: IntlBreakIterator::next() expects parameter 1 to be long, array given in %s on line %d -Warning: BreakIterator::next(): breakiter_next: bad arguments in %s on line %d +Warning: IntlBreakIterator::next(): breakiter_next: bad arguments in %s on line %d bool(false) diff --git a/ext/intl/tests/breakiter_preceding_basic.phpt b/ext/intl/tests/breakiter_preceding_basic.phpt index 5a321b6f3cc..60695209ccd 100644 --- a/ext/intl/tests/breakiter_preceding_basic.phpt +++ b/ext/intl/tests/breakiter_preceding_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::preceding(): basic test +IntlBreakIterator::preceding(): basic test --FILE-- setText('foo bar trans zoo bee'); var_dump($bi->preceding(5)); diff --git a/ext/intl/tests/breakiter_previous_basic.phpt b/ext/intl/tests/breakiter_previous_basic.phpt index 2d0e71656d0..6d4f3bce5fe 100644 --- a/ext/intl/tests/breakiter_previous_basic.phpt +++ b/ext/intl/tests/breakiter_previous_basic.phpt @@ -1,11 +1,11 @@ --TEST-- -BreakIterator::previous(): basic test +IntlBreakIterator::previous(): basic test --FILE-- setText('foo bar trans'); var_dump($bi->last()); diff --git a/ext/intl/tests/breakiter_setText_basic.phpt b/ext/intl/tests/breakiter_setText_basic.phpt index 72ea48371b4..7b3fa2a6e5e 100644 --- a/ext/intl/tests/breakiter_setText_basic.phpt +++ b/ext/intl/tests/breakiter_setText_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -BreakIterator::setText(): basic test +IntlBreakIterator::setText(): basic test --SKIPIF-- if (!extension_loaded('intl')) die('skip intl extension not enabled'); @@ -11,7 +11,7 @@ class A { function __tostring() { return 'aaa'; } } -$bi = BreakIterator::createWordInstance('pt'); +$bi = IntlBreakIterator::createWordInstance('pt'); var_dump($bi->setText('foo bar')); var_dump($bi->getText()); var_dump($bi->setText(1)); diff --git a/ext/intl/tests/breakiter_setText_error.phpt b/ext/intl/tests/breakiter_setText_error.phpt index 08d69070a50..bfcda8ddaab 100644 --- a/ext/intl/tests/breakiter_setText_error.phpt +++ b/ext/intl/tests/breakiter_setText_error.phpt @@ -1,10 +1,10 @@ --TEST-- -BreakIterator::setText(): arg errors +IntlBreakIterator::setText(): arg errors --FILE-- setText()); var_dump($bi->setText(array())); var_dump($bi->setText(1,2)); @@ -22,19 +22,19 @@ var_dump($e->getMessage()); --EXPECTF-- -Warning: BreakIterator::setText() expects exactly 1 parameter, 0 given in %s on line %d +Warning: IntlBreakIterator::setText() expects exactly 1 parameter, 0 given in %s on line %d -Warning: BreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d +Warning: IntlBreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::setText() expects parameter 1 to be string, array given in %s on line %d +Warning: IntlBreakIterator::setText() expects parameter 1 to be string, array given in %s on line %d -Warning: BreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d +Warning: IntlBreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d bool(false) -Warning: BreakIterator::setText() expects exactly 1 parameter, 2 given in %s on line %d +Warning: IntlBreakIterator::setText() expects exactly 1 parameter, 2 given in %s on line %d -Warning: BreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d +Warning: IntlBreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d bool(false) string(10) "destructed" string(1) "e" diff --git a/ext/intl/tests/rbbiter___construct_basic.phpt b/ext/intl/tests/rbbiter___construct_basic.phpt index 567a09fa2de..2b14d826e37 100644 --- a/ext/intl/tests/rbbiter___construct_basic.phpt +++ b/ext/intl/tests/rbbiter___construct_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -RuleBasedBreakIterator::__construct: basic test +IntlRuleBasedBreakIterator::__construct: basic test --FILE-- ==DONE== --EXPECT-- -string(22) "RuleBasedBreakIterator" +string(26) "IntlRuleBasedBreakIterator" ==DONE== \ No newline at end of file diff --git a/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt b/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt index 815c711cfcb..7bc02188460 100644 --- a/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt +++ b/ext/intl/tests/rbbiter_getBinaryRules_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -RuleBasedBreakIterator::getBinaryRules(): basic test +IntlRuleBasedBreakIterator::getBinaryRules(): basic test --FILE-- setText('sdfkjsdf88á.... ,;');; $br = $rbbi->getBinaryRules(); -$rbbi2 = new RuleBasedBreakIterator($br, true); +$rbbi2 = new IntlRuleBasedBreakIterator($br, true); var_dump($rbbi->getRules(), $rbbi2->getRules()); var_dump($rbbi->getRules() == $rbbi2->getRules()); diff --git a/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt b/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt index bbc00e9b48a..a4f3352f9a2 100644 --- a/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt +++ b/ext/intl/tests/rbbiter_getRuleStatusVec_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -RuleBasedBreakIterator::getRuleStatusVec(): basic test +IntlRuleBasedBreakIterator::getRuleStatusVec(): basic test --FILE-- setText('sdfkjsdf88á.... ,;');; do { var_dump($rbbi->current(), $rbbi->getRuleStatusVec()); -} while ($rbbi->next() != BreakIterator::DONE); +} while ($rbbi->next() != IntlBreakIterator::DONE); ?> ==DONE== diff --git a/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt b/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt index 1bce102489f..6199fdee7c2 100644 --- a/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt +++ b/ext/intl/tests/rbbiter_getRuleStatus_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -RuleBasedBreakIterator::getRuleStatus(): basic test +IntlRuleBasedBreakIterator::getRuleStatus(): basic test --FILE-- setText('sdfkjsdf88á.... ,;'); do { echo "pos : {$rbbi->current()}\n", "rule status: {$rbbi->getRuleStatus()}\n"; -} while ($rbbi->next() != BreakIterator::DONE); +} while ($rbbi->next() != IntlBreakIterator::DONE); ?> ==DONE== diff --git a/ext/intl/tests/rbbiter_getRules_basic.phpt b/ext/intl/tests/rbbiter_getRules_basic.phpt index 7f510484be9..e115e9b9e2a 100644 --- a/ext/intl/tests/rbbiter_getRules_basic.phpt +++ b/ext/intl/tests/rbbiter_getRules_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -RuleBasedBreakIterator::getRules(): basic test +IntlRuleBasedBreakIterator::getRules(): basic test --FILE-- getRules()); ?> From 0a7ae87e91368fe17c52767cfb31dabf3a94e38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Fri, 22 Jun 2012 18:19:54 +0200 Subject: [PATCH 09/13] Added IntlCodePointBreakIterator. Objects of this class can be instantiated with IntlBreakIterator::createCodePointInstance() The method does not take a locale, as it would not make sense in this context. This class has one additional method: long IntlCodePointIterator::getLastCodePoint() which returns either -1 or the last code point we moved over, if any (and discounting any movement before the last call to IntlBreakIterator::first() or IntlBreakIterator::last()). --- .../breakiterator/breakiterator_class.cpp | 24 +- .../breakiterator/breakiterator_methods.cpp | 18 ++ .../breakiterator/breakiterator_methods.h | 2 + .../codepointiterator_internal.cpp | 286 ++++++++++++++++++ .../codepointiterator_internal.h | 98 ++++++ .../codepointiterator_methods.cpp | 44 +++ .../breakiterator/codepointiterator_methods.h | 24 ++ ext/intl/config.m4 | 3 + ext/intl/config.w32 | 4 +- ...eakiter_createCodePointInstance_basic.phpt | 43 +++ ...eakiter_createCodePointInstance_error.phpt | 18 ++ ext/intl/tests/cpbi_clone_equality.phpt | 33 ++ .../tests/cpbi_getLastCodePoint_basic.phpt | 82 +++++ .../tests/cpbi_getLastCodePoint_error.phpt | 19 ++ ext/intl/tests/cpbi_parts_iterator.phpt | 40 +++ 15 files changed, 736 insertions(+), 2 deletions(-) create mode 100644 ext/intl/breakiterator/codepointiterator_internal.cpp create mode 100644 ext/intl/breakiterator/codepointiterator_internal.h create mode 100644 ext/intl/breakiterator/codepointiterator_methods.cpp create mode 100644 ext/intl/breakiterator/codepointiterator_methods.h create mode 100644 ext/intl/tests/breakiter_createCodePointInstance_basic.phpt create mode 100644 ext/intl/tests/breakiter_createCodePointInstance_error.phpt create mode 100644 ext/intl/tests/cpbi_clone_equality.phpt create mode 100644 ext/intl/tests/cpbi_getLastCodePoint_basic.phpt create mode 100644 ext/intl/tests/cpbi_getLastCodePoint_error.phpt create mode 100644 ext/intl/tests/cpbi_parts_iterator.phpt diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index 8c25314a4a8..633550203b8 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -20,6 +20,7 @@ #include #include +#include "codepointiterator_internal.h" #include "breakiterator_iterators.h" @@ -30,14 +31,18 @@ extern "C" { #include "breakiterator_class.h" #include "breakiterator_methods.h" #include "rulebasedbreakiterator_methods.h" +#include "codepointiterator_methods.h" #include #include #include } +using PHP::CodePointBreakIterator; + /* {{{ Global variables */ zend_class_entry *BreakIterator_ce_ptr; zend_class_entry *RuleBasedBreakIterator_ce_ptr; +zend_class_entry *CodePointBreakIterator_ce_ptr; zend_object_handlers BreakIterator_handlers; /* }}} */ @@ -49,6 +54,8 @@ U_CFUNC void breakiterator_object_create(zval *object, if (classId == RuleBasedBreakIterator::getStaticClassID()) { ce = RuleBasedBreakIterator_ce_ptr; + } else if (classId == CodePointBreakIterator::getStaticClassID()) { + ce = CodePointBreakIterator_ce_ptr; } else { ce = BreakIterator_ce_ptr; } @@ -274,6 +281,7 @@ static const zend_function_entry BreakIterator_class_functions[] = { PHP_ME_MAPPING(createCharacterInstance, breakiter_create_character_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) PHP_ME_MAPPING(createSentenceInstance, breakiter_create_sentence_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) PHP_ME_MAPPING(createTitleInstance, breakiter_create_title_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(createCodePointInstance, breakiter_create_code_point_instance, ainfo_biter_void, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getText, breakiter_get_text, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(setText, breakiter_set_text, ainfo_biter_setText, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(first, breakiter_first, ainfo_biter_void, ZEND_ACC_PUBLIC) @@ -305,6 +313,14 @@ static const zend_function_entry RuleBasedBreakIterator_class_functions[] = { }; /* }}} */ +/* {{{ CodePointBreakIterator_class_functions + */ +static const zend_function_entry CodePointBreakIterator_class_functions[] = { + PHP_ME_MAPPING(getLastCodePoint, cpbi_get_last_code_point, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_FE_END +}; +/* }}} */ + /* {{{ breakiterator_register_BreakIterator_class * Initialize 'BreakIterator' class @@ -364,6 +380,12 @@ void breakiterator_register_BreakIterator_class(TSRMLS_D) INIT_CLASS_ENTRY(ce, "IntlRuleBasedBreakIterator", RuleBasedBreakIterator_class_functions); RuleBasedBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce, - BreakIterator_ce_ptr, NULL TSRMLS_CC); + BreakIterator_ce_ptr, NULL TSRMLS_CC); + + /* Create and register 'CodePointBreakIterator' class. */ + INIT_CLASS_ENTRY(ce, "IntlCodePointBreakIterator", + CodePointBreakIterator_class_functions); + CodePointBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce, + BreakIterator_ce_ptr, NULL TSRMLS_CC); } /* }}} */ diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp index 5b8f859d527..e9e6b19ba3b 100644 --- a/ext/intl/breakiterator/breakiterator_methods.cpp +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -19,6 +19,7 @@ #endif #include +#include "codepointiterator_internal.h" #include "breakiterator_iterators.h" @@ -29,6 +30,8 @@ extern "C" { #include } +using PHP::CodePointBreakIterator; + U_CFUNC PHP_METHOD(BreakIterator, __construct) { zend_throw_exception( NULL, @@ -107,6 +110,21 @@ U_CFUNC PHP_FUNCTION(breakiter_create_title_instance) INTERNAL_FUNCTION_PARAM_PASSTHRU); } +U_CFUNC PHP_FUNCTION(breakiter_create_code_point_instance) +{ + UErrorCode status = UErrorCode(); + intl_error_reset(NULL TSRMLS_CC); + + if (zend_parse_parameters_none() == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_create_code_point_instance: bad arguments", 0 TSRMLS_CC); + RETURN_NULL(); + } + + CodePointBreakIterator *cpbi = new CodePointBreakIterator(); + breakiterator_object_create(return_value, cpbi TSRMLS_CC); +} + U_CFUNC PHP_FUNCTION(breakiter_get_text) { BREAKITER_METHOD_INIT_VARS; diff --git a/ext/intl/breakiterator/breakiterator_methods.h b/ext/intl/breakiterator/breakiterator_methods.h index e0d13b0f45e..a479ac92e85 100644 --- a/ext/intl/breakiterator/breakiterator_methods.h +++ b/ext/intl/breakiterator/breakiterator_methods.h @@ -31,6 +31,8 @@ PHP_FUNCTION(breakiter_create_sentence_instance); PHP_FUNCTION(breakiter_create_title_instance); +PHP_FUNCTION(breakiter_create_code_point_instance); + PHP_FUNCTION(breakiter_get_text); PHP_FUNCTION(breakiter_set_text); diff --git a/ext/intl/breakiterator/codepointiterator_internal.cpp b/ext/intl/breakiterator/codepointiterator_internal.cpp new file mode 100644 index 00000000000..2dfae1aa4ff --- /dev/null +++ b/ext/intl/breakiterator/codepointiterator_internal.cpp @@ -0,0 +1,286 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#include "codepointiterator_internal.h" +#include + +//copied from cmemory.h, which is not public +typedef union { + long t1; + double t2; + void *t3; +} UAlignedMemory; + +#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask)) +#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1) +#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr)) + +using namespace PHP; + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CodePointBreakIterator); + +CodePointBreakIterator::CodePointBreakIterator() +: BreakIterator(), fCharIter(NULL), lastCodePoint(U_SENTINEL) +{ + UErrorCode uec = UErrorCode(); + this->fText = utext_openUChars(NULL, NULL, 0, &uec); +} + +CodePointBreakIterator::CodePointBreakIterator(const PHP::CodePointBreakIterator &other) +: BreakIterator(other), fText(NULL), fCharIter(NULL), lastCodePoint(U_SENTINEL) +{ + *this = other; +} + +CodePointBreakIterator& CodePointBreakIterator::operator=(const CodePointBreakIterator& that) +{ + UErrorCode uec = UErrorCode(); + UText *ut_clone = NULL; + + if (this == &that) { + return *this; + } + + this->fText = utext_clone(this->fText, that.fText, FALSE, TRUE, &uec); + + //don't bother copying the character iterator, getText() is deprecated + clearCurrentCharIter(); + + this->lastCodePoint = that.lastCodePoint; + return *this; +} + +CodePointBreakIterator::~CodePointBreakIterator() +{ + if (this->fText) { + utext_close(this->fText); + } + clearCurrentCharIter(); +} + +UBool CodePointBreakIterator::operator==(const BreakIterator& that) const +{ + if (typeid(*this) != typeid(that)) { + return FALSE; + } + + const CodePointBreakIterator& that2 = + static_cast(that); + + if (!utext_equals(this->fText, that2.fText)) { + return FALSE; + } + + return TRUE; +} + +CodePointBreakIterator* CodePointBreakIterator::clone(void) const +{ + return new CodePointBreakIterator(*this); +} + +CharacterIterator& CodePointBreakIterator::getText(void) const +{ + if (this->fCharIter == NULL) { + //this method is deprecated anyway; setup bogus iterator + static const UChar c = 0; + this->fCharIter = new UCharCharacterIterator(&c, 0); + } + + return *this->fCharIter; +} + +UText *CodePointBreakIterator::getUText(UText *fillIn, UErrorCode &status) const +{ + return utext_clone(fillIn, this->fText, FALSE, TRUE, &status); +} + +void CodePointBreakIterator::setText(const UnicodeString &text) +{ + UErrorCode uec = UErrorCode(); + + //this closes the previous utext, if any + this->fText = utext_openConstUnicodeString(this->fText, &text, &uec); + + clearCurrentCharIter(); +} + +void CodePointBreakIterator::setText(UText *text, UErrorCode &status) +{ + if (U_FAILURE(status)) { + return; + } + + this->fText = utext_clone(this->fText, text, FALSE, TRUE, &status); + + clearCurrentCharIter(); +} + +void CodePointBreakIterator::adoptText(CharacterIterator* it) +{ + UErrorCode uec = UErrorCode(); + clearCurrentCharIter(); + + this->fCharIter = it; + this->fText = utext_openCharacterIterator(this->fText, it, &uec); +} + +int32_t CodePointBreakIterator::first(void) +{ + UTEXT_SETNATIVEINDEX(this->fText, 0); + this->lastCodePoint = U_SENTINEL; + + return 0; +} + +int32_t CodePointBreakIterator::last(void) +{ + int32_t pos = (int32_t)utext_nativeLength(this->fText); + UTEXT_SETNATIVEINDEX(this->fText, pos); + this->lastCodePoint = U_SENTINEL; + + return pos; +} + +int32_t CodePointBreakIterator::previous(void) +{ + this->lastCodePoint = UTEXT_PREVIOUS32(this->fText); + if (this->lastCodePoint == U_SENTINEL) { + return BreakIterator::DONE; + } + + return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); +} + +int32_t CodePointBreakIterator::next(void) +{ + this->lastCodePoint = UTEXT_NEXT32(this->fText); + if (this->lastCodePoint == U_SENTINEL) { + return BreakIterator::DONE; + } + + return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); +} + +int32_t CodePointBreakIterator::current(void) const +{ + return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); +} + +int32_t CodePointBreakIterator::following(int32_t offset) +{ + this->lastCodePoint = utext_next32From(this->fText, offset); + if (this->lastCodePoint == U_SENTINEL) { + return BreakIterator::DONE; + } + + return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); +} + +int32_t CodePointBreakIterator::preceding(int32_t offset) +{ + this->lastCodePoint = utext_previous32From(this->fText, offset); + if (this->lastCodePoint == U_SENTINEL) { + return BreakIterator::DONE; + } + + return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); +} + +UBool CodePointBreakIterator::isBoundary(int32_t offset) +{ + //this function has side effects, and it's supposed to + utext_setNativeIndex(this->fText, offset); + return (offset == utext_getNativeIndex(this->fText)); +} + +int32_t CodePointBreakIterator::next(int32_t n) +{ + UBool res = utext_moveIndex32(this->fText, n); + + if (res) { + this->lastCodePoint = UTEXT_CURRENT32(this->fText); + return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); + } else { + this->lastCodePoint = U_SENTINEL; + return BreakIterator::DONE; + } +} + +CodePointBreakIterator *CodePointBreakIterator::createBufferClone( + void *stackBuffer, int32_t &bufferSize, UErrorCode &status) +{ + //see implementation of RuleBasedBreakIterator::createBufferClone() + if (U_FAILURE(status)) { + return NULL; + } + + if (bufferSize <= 0) { + bufferSize = sizeof(CodePointBreakIterator) + U_ALIGNMENT_OFFSET_UP(0); + return NULL; + } + + char *buf = (char*)stackBuffer; + uint32_t s = bufferSize; + + if (stackBuffer == NULL) { + s = 0; + } + + if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) { + uint32_t offsetUp = (uint32_t)U_ALIGNMENT_OFFSET_UP(buf); + s -= offsetUp; + buf += offsetUp; + } + + if (s < sizeof(CodePointBreakIterator)) { + CodePointBreakIterator *clonedBI = new CodePointBreakIterator(*this); + if (clonedBI == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + } else { + status = U_SAFECLONE_ALLOCATED_WARNING; + } + + return clonedBI; + } + + return new(buf) CodePointBreakIterator(*this); +} + +CodePointBreakIterator &CodePointBreakIterator::refreshInputText(UText *input, UErrorCode &status) +{ + //see implementation of RuleBasedBreakIterator::createBufferClone() + if (U_FAILURE(status)) { + return *this; + } + if (input == NULL) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return *this; + } + + int64_t pos = utext_getNativeIndex(this->fText); + this->fText = utext_clone(this->fText, input, FALSE, TRUE, &status); + if (U_FAILURE(status)) { + return *this; + } + + utext_setNativeIndex(this->fText, pos); + if (utext_getNativeIndex(fText) != pos) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } + + return *this; +} \ No newline at end of file diff --git a/ext/intl/breakiterator/codepointiterator_internal.h b/ext/intl/breakiterator/codepointiterator_internal.h new file mode 100644 index 00000000000..988b91c2009 --- /dev/null +++ b/ext/intl/breakiterator/codepointiterator_internal.h @@ -0,0 +1,98 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#ifndef CODEPOINTITERATOR_INTERNAL_H +#define CODEPOINTITERATOR_INTERNAL_H + +#include + +using U_ICU_NAMESPACE::BreakIterator; + +namespace PHP { + + class CodePointBreakIterator : public BreakIterator { + + public: + static UClassID getStaticClassID(); + + CodePointBreakIterator(); + + CodePointBreakIterator(const CodePointBreakIterator &other); + + CodePointBreakIterator& operator=(const CodePointBreakIterator& that); + + virtual ~CodePointBreakIterator(); + + virtual UBool operator==(const BreakIterator& that) const; + + virtual CodePointBreakIterator* clone(void) const; + + virtual UClassID getDynamicClassID(void) const; + + virtual CharacterIterator& getText(void) const; + + virtual UText *getUText(UText *fillIn, UErrorCode &status) const; + + virtual void setText(const UnicodeString &text); + + virtual void setText(UText *text, UErrorCode &status); + + virtual void adoptText(CharacterIterator* it); + + virtual int32_t first(void); + + virtual int32_t last(void); + + virtual int32_t previous(void); + + virtual int32_t next(void); + + virtual int32_t current(void) const; + + virtual int32_t following(int32_t offset); + + virtual int32_t preceding(int32_t offset); + + virtual UBool isBoundary(int32_t offset); + + virtual int32_t next(int32_t n); + + virtual CodePointBreakIterator *createBufferClone(void *stackBuffer, + int32_t &BufferSize, + UErrorCode &status); + + virtual CodePointBreakIterator &refreshInputText(UText *input, UErrorCode &status); + + inline UChar32 getLastCodePoint() + { + return this->lastCodePoint; + } + + private: + UText *fText; + UChar32 lastCodePoint; + mutable CharacterIterator *fCharIter; + + inline void clearCurrentCharIter() + { + delete this->fCharIter; + this->fCharIter = NULL; + this->lastCodePoint = U_SENTINEL; + } + }; +} + +#endif \ No newline at end of file diff --git a/ext/intl/breakiterator/codepointiterator_methods.cpp b/ext/intl/breakiterator/codepointiterator_methods.cpp new file mode 100644 index 00000000000..ae7e526eada --- /dev/null +++ b/ext/intl/breakiterator/codepointiterator_methods.cpp @@ -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: Gustavo Lopes | + +----------------------------------------------------------------------+ + */ + +#include "codepointiterator_internal.h" + +extern "C" { +#define USE_BREAKITERATOR_POINTER 1 +#include "breakiterator_class.h" +} + +using PHP::CodePointBreakIterator; + +static inline CodePointBreakIterator *fetch_cpbi(BreakIterator_object *bio) { + return (CodePointBreakIterator*)bio->biter; +} + +U_CFUNC PHP_FUNCTION(cpbi_get_last_code_point) +{ + BREAKITER_METHOD_INIT_VARS; + object = getThis(); + + if (zend_parse_parameters_none() == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "cpbi_get_last_code_point: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + BREAKITER_METHOD_FETCH_OBJECT; + + RETURN_LONG(fetch_cpbi(bio)->getLastCodePoint()); +} \ No newline at end of file diff --git a/ext/intl/breakiterator/codepointiterator_methods.h b/ext/intl/breakiterator/codepointiterator_methods.h new file mode 100644 index 00000000000..d34e5b61e22 --- /dev/null +++ b/ext/intl/breakiterator/codepointiterator_methods.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: Gustavo Lopes | + +----------------------------------------------------------------------+ + */ + +#ifndef CODEPOINTITERATOR_METHODS_H +#define CODEPOINTITERATOR_METHODS_H + +#include + +PHP_FUNCTION(cpbi_get_last_code_point); + +#endif \ No newline at end of file diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index 227368334df..d7eacbc0b41 100755 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -79,6 +79,8 @@ if test "$PHP_INTL" != "no"; then breakiterator/breakiterator_iterators.cpp \ breakiterator/breakiterator_methods.cpp \ breakiterator/rulebasedbreakiterator_methods.cpp \ + breakiterator/codepointiterator_internal.cpp \ + breakiterator/codepointiterator_methods.cpp \ idn/idn.c \ $icu_spoof_src, $ext_shared,,$ICU_INCS -Wno-write-strings) PHP_ADD_BUILD_DIR($ext_builddir/collator) @@ -95,4 +97,5 @@ if test "$PHP_INTL" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/calendar) PHP_ADD_BUILD_DIR($ext_builddir/idn) PHP_ADD_BUILD_DIR($ext_builddir/spoofchecker) + PHP_ADD_BUILD_DIR($ext_builddir/breakiterator) fi diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index 6b7d15d56d8..a223505f8c9 100755 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -107,7 +107,9 @@ if (PHP_INTL != "no") { breakiterator_class.cpp \ breakiterator_methods.cpp \ breakiterator_iterators.cpp \ - rulebasedbreakiterator_methods.cpp", + rulebasedbreakiterator_methods.cpp \ + codepointiterator_internal.cpp \ + codepointiterator_methods.cpp ", "intl"); ADD_FLAG("LIBS_INTL", "icudt.lib icuin.lib icuio.lib icule.lib iculx.lib"); diff --git a/ext/intl/tests/breakiter_createCodePointInstance_basic.phpt b/ext/intl/tests/breakiter_createCodePointInstance_basic.phpt new file mode 100644 index 00000000000..a43e82760cc --- /dev/null +++ b/ext/intl/tests/breakiter_createCodePointInstance_basic.phpt @@ -0,0 +1,43 @@ +--TEST-- +IntlBreakIterator::createCodePointInstance(): basic test +--SKIPIF-- +setText($text); + +print_r(iterator_to_array($codepoint_it)); + +?> +==DONE== +--EXPECT-- +string(26) "IntlCodePointBreakIterator" +Array +( + [0] => 0 + [1] => 3 + [2] => 6 + [3] => 9 + [4] => 12 + [5] => 15 + [6] => 18 + [7] => 21 + [8] => 24 + [9] => 27 + [10] => 30 + [11] => 33 + [12] => 36 + [13] => 39 + [14] => 42 + [15] => 45 +) +==DONE== diff --git a/ext/intl/tests/breakiter_createCodePointInstance_error.phpt b/ext/intl/tests/breakiter_createCodePointInstance_error.phpt new file mode 100644 index 00000000000..90228e128f6 --- /dev/null +++ b/ext/intl/tests/breakiter_createCodePointInstance_error.phpt @@ -0,0 +1,18 @@ +--TEST-- +IntlBreakIterator::createCodePointInstance(): bad arguments +--SKIPIF-- +setText($text); + +$it_clone = clone $it; +var_dump($it == $it_clone); + +$it->setText($text2 ); +var_dump($it == $it_clone); + +$it_clone->setText($text2); +var_dump($it == $it_clone); + +?> +==DONE== +--EXPECT-- +bool(true) +bool(false) +bool(true) +==DONE== diff --git a/ext/intl/tests/cpbi_getLastCodePoint_basic.phpt b/ext/intl/tests/cpbi_getLastCodePoint_basic.phpt new file mode 100644 index 00000000000..74a07a62922 --- /dev/null +++ b/ext/intl/tests/cpbi_getLastCodePoint_basic.phpt @@ -0,0 +1,82 @@ +--TEST-- +IntlCodepointBreakIterator::getLastCodePoint(): basic test +--SKIPIF-- +setText($text); + +var_dump($codepoint_it->getLastCodePoint()); +//first() and last() don't read codepoint and set the last code point var to -1 +//The pointer is after the last read codepoint if moving forward and +//before the last read codepoint is moving backwards +$p = $codepoint_it->first(); +while ($p != IntlBreakIterator::DONE) { + $c = $codepoint_it->getLastCodePoint(); + if ($c > 0) + var_dump(sprintf('U+%04X', $codepoint_it->getLastCodePoint())); + else + var_dump($c); + //it's a post-increment operation as to the codepoint, i.e., it gives the codepoint + //starting at the initial position and only then moves the pointer forward + $p = $codepoint_it->next(); +} + +echo "Now backwards\n"; +$p = $codepoint_it->last(); +while ($p != IntlBreakIterator::DONE) { + $c = $codepoint_it->getLastCodePoint(); + if ($c > 0) + var_dump(sprintf('U+%04X', $codepoint_it->getLastCodePoint())); + else + var_dump($c); + $p = $codepoint_it->previous(); +} + + +?> +==DONE== +--EXPECT-- +int(-1) +int(-1) +string(6) "U+0E15" +string(6) "U+0E31" +string(6) "U+0E27" +string(6) "U+0E2D" +string(6) "U+0E22" +string(6) "U+0E48" +string(6) "U+0E32" +string(6) "U+0E07" +string(6) "U+0E02" +string(6) "U+0E49" +string(6) "U+0E2D" +string(6) "U+0E04" +string(6) "U+0E27" +string(6) "U+0E32" +string(6) "U+0E21" +Now backwards +int(-1) +string(6) "U+0E21" +string(6) "U+0E32" +string(6) "U+0E27" +string(6) "U+0E04" +string(6) "U+0E2D" +string(6) "U+0E49" +string(6) "U+0E02" +string(6) "U+0E07" +string(6) "U+0E32" +string(6) "U+0E48" +string(6) "U+0E22" +string(6) "U+0E2D" +string(6) "U+0E27" +string(6) "U+0E31" +string(6) "U+0E15" +==DONE== diff --git a/ext/intl/tests/cpbi_getLastCodePoint_error.phpt b/ext/intl/tests/cpbi_getLastCodePoint_error.phpt new file mode 100644 index 00000000000..78bd216629b --- /dev/null +++ b/ext/intl/tests/cpbi_getLastCodePoint_error.phpt @@ -0,0 +1,19 @@ +--TEST-- +IntlBreakIterator::getLastCodePoint(): bad args +--SKIPIF-- +getLastCodePoint(array())); +--EXPECTF-- + +Warning: IntlCodePointBreakIterator::getLastCodePoint() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: IntlCodePointBreakIterator::getLastCodePoint(): cpbi_get_last_code_point: bad arguments in %s on line %d +bool(false) + diff --git a/ext/intl/tests/cpbi_parts_iterator.phpt b/ext/intl/tests/cpbi_parts_iterator.phpt new file mode 100644 index 00000000000..4754c123710 --- /dev/null +++ b/ext/intl/tests/cpbi_parts_iterator.phpt @@ -0,0 +1,40 @@ +--TEST-- +IntlCodepointBreakIterator's part iterator +--SKIPIF-- +getPartsIterator(); +$it->getBreakIterator()->setText($text); + +foreach ($it as $k => $v) { + echo "$k. $v (" . sprintf("U+%04X", $it->getBreakIterator()->getLastCodePoint()) . + ") at {$it->getBreakIterator()->current()}\r\n"; +} + +?> +==DONE== +--EXPECT-- +0. ต (U+0E15) at 3 +1. ั (U+0E31) at 6 +2. ว (U+0E27) at 9 +3. อ (U+0E2D) at 12 +4. ย (U+0E22) at 15 +5. ่ (U+0E48) at 18 +6. า (U+0E32) at 21 +7. ง (U+0E07) at 24 +8. ข (U+0E02) at 27 +9. ้ (U+0E49) at 30 +10. อ (U+0E2D) at 33 +11. ค (U+0E04) at 36 +12. ว (U+0E27) at 39 +13. า (U+0E32) at 42 +14. ม (U+0E21) at 45 +==DONE== From 77daa3482d5592181560e0e6076c1e3291620e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Fri, 22 Jun 2012 18:28:19 +0200 Subject: [PATCH 10/13] BreakIterator::getPartsIterator: new optional arg Can take one of: * IntlPartsIterator::KEY_SEQUENTIAL (keys are 0, 1, ...) * IntlPartsIterator::KEY_LEFT (keys are left boundaries) * IntlPartsIterator::KEY_LEFT (keys are right boundaries) The default is IntlPartsIterator::KEY_SEQUENTIAL (the previous behavior). --- .../breakiterator/breakiterator_class.cpp | 6 +- .../breakiterator/breakiterator_iterators.cpp | 35 ++++++++++- .../breakiterator/breakiterator_iterators.h | 9 ++- .../breakiterator/breakiterator_methods.cpp | 16 ++++- .../breakiter_getPartsIterator_error.phpt | 33 ++++++++++ .../breakiter_getPartsIterator_var1.phpt | 60 +++++++++++++++++++ 6 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 ext/intl/tests/breakiter_getPartsIterator_error.phpt create mode 100644 ext/intl/tests/breakiter_getPartsIterator_var1.phpt diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index 633550203b8..d193fc44577 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -264,6 +264,10 @@ ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_get_locale, 0, 0, 1) ZEND_ARG_INFO(0, "locale_type") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(ainfo_biter_getPartsIterator, 0, 0, 0) + ZEND_ARG_INFO(0, "key_type") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(ainfo_rbbi___construct, 0, 0, 1) ZEND_ARG_INFO(0, "rules") ZEND_ARG_INFO(0, "areCompiled") @@ -293,7 +297,7 @@ static const zend_function_entry BreakIterator_class_functions[] = { PHP_ME_MAPPING(preceding, breakiter_preceding, ainfo_biter_offset, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(isBoundary, breakiter_is_boundary, ainfo_biter_offset, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getLocale, breakiter_get_locale, ainfo_biter_void, ZEND_ACC_PUBLIC) - PHP_ME_MAPPING(getPartsIterator, breakiter_get_parts_iterator, ainfo_biter_void, ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(getPartsIterator, breakiter_get_parts_iterator, ainfo_biter_getPartsIterator, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorCode, breakiter_get_error_code, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorMessage, breakiter_get_error_message, ainfo_biter_void, ZEND_ACC_PUBLIC) diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp index d3ad050299f..d88ad8a712d 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.cpp +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -130,6 +130,7 @@ U_CFUNC zend_object_iterator *_breakiterator_get_iterator( typedef struct zoi_break_iter_parts { zoi_with_current zoi_cur; + parts_iter_key_type key_type; BreakIterator_object *bio; /* so we don't have to fetch it all the time */ } zoi_break_iter_parts; @@ -138,6 +139,16 @@ static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC zval_ptr_dtor(reinterpret_cast(&iter->data)); } +static int _breakiterator_parts_get_current_key(zend_object_iterator *iter, + char **str_key, + uint *str_key_len, + ulong *int_key TSRMLS_DC) +{ + /* the actual work is done in move_forward and rewind */ + *int_key = iter->index; + return HASH_KEY_IS_LONG; +} + static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_DC) { zoi_break_iter_parts *zoi_bit = (zoi_break_iter_parts*)iter; @@ -157,6 +168,14 @@ static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_ return; } + if (zoi_bit->key_type == PARTS_ITERATOR_KEY_LEFT) { + iter->index = cur; + } else if (zoi_bit->key_type == PARTS_ITERATOR_KEY_RIGHT) { + iter->index = next; + } + /* else zoi_bit->key_type == PARTS_ITERATOR_KEY_SEQUENTIAL + * No need to do anything, the engine increments ->index */ + const char *s = Z_STRVAL_P(bio->text); int32_t slen = Z_STRLEN_P(bio->text), len; @@ -194,14 +213,15 @@ static zend_object_iterator_funcs breakiterator_parts_it_funcs = { zoi_with_current_dtor, zoi_with_current_valid, zoi_with_current_get_current_data, - NULL, + _breakiterator_parts_get_current_key, _breakiterator_parts_move_forward, _breakiterator_parts_rewind, zoi_with_current_invalidate_current }; void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, - zval *object TSRMLS_DC) + zval *object, + parts_iter_key_type key_type TSRMLS_DC) { IntlIterator_object *ii; @@ -221,6 +241,7 @@ void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, ((zoi_break_iter_parts*)ii->iterator)->bio = (BreakIterator_object*) zend_object_store_get_object(break_iter_zv TSRMLS_CC); assert(((zoi_break_iter_parts*)ii->iterator)->bio->biter != NULL); + ((zoi_break_iter_parts*)ii->iterator)->key_type = key_type; } U_CFUNC zend_object_value IntlPartsIterator_object_create(zend_class_entry *ce TSRMLS_DC) @@ -312,4 +333,14 @@ U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D) memcpy(&IntlPartsIterator_handlers, &IntlIterator_handlers, sizeof IntlPartsIterator_handlers); IntlPartsIterator_handlers.get_method = IntlPartsIterator_get_method; + +#define PARTSITER_DECL_LONG_CONST(name) \ + zend_declare_class_constant_long(IntlPartsIterator_ce_ptr, #name, \ + sizeof(#name) - 1, PARTS_ITERATOR_ ## name TSRMLS_CC) + + PARTSITER_DECL_LONG_CONST(KEY_SEQUENTIAL); + PARTSITER_DECL_LONG_CONST(KEY_LEFT); + PARTSITER_DECL_LONG_CONST(KEY_RIGHT); + +#undef PARTSITER_DECL_LONG_CONST } \ No newline at end of file diff --git a/ext/intl/breakiterator/breakiterator_iterators.h b/ext/intl/breakiterator/breakiterator_iterators.h index 855246ff77e..71620724147 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.h +++ b/ext/intl/breakiterator/breakiterator_iterators.h @@ -23,9 +23,16 @@ U_CDECL_BEGIN #include U_CDECL_END +typedef enum { + PARTS_ITERATOR_KEY_SEQUENTIAL, + PARTS_ITERATOR_KEY_LEFT, + PARTS_ITERATOR_KEY_RIGHT, +} parts_iter_key_type; + #ifdef __cplusplus void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv, - zval *object TSRMLS_DC); + zval *object, + parts_iter_key_type key_type TSRMLS_DC); #endif U_CFUNC zend_object_iterator *_breakiterator_get_iterator( diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp index e9e6b19ba3b..7b502528f3e 100644 --- a/ext/intl/breakiterator/breakiterator_methods.cpp +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -384,18 +384,28 @@ U_CFUNC PHP_FUNCTION(breakiter_get_locale) U_CFUNC PHP_FUNCTION(breakiter_get_parts_iterator) { + long key_type = 0; BREAKITER_METHOD_INIT_VARS; object = getThis(); - if (zend_parse_parameters_none() == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &key_type) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "breakiter_get_parts_iterator: bad arguments", 0 TSRMLS_CC); + "breakiter_get_parts_iterator: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + if (key_type != PARTS_ITERATOR_KEY_SEQUENTIAL + && key_type != PARTS_ITERATOR_KEY_LEFT + && key_type != PARTS_ITERATOR_KEY_RIGHT) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "breakiter_get_parts_iterator: bad key type", 0 TSRMLS_CC); RETURN_FALSE; } BREAKITER_METHOD_FETCH_OBJECT; - IntlIterator_from_BreakIterator_parts(object, return_value TSRMLS_CC); + IntlIterator_from_BreakIterator_parts( + object, return_value, (parts_iter_key_type)key_type TSRMLS_CC); } U_CFUNC PHP_FUNCTION(breakiter_get_error_code) diff --git a/ext/intl/tests/breakiter_getPartsIterator_error.phpt b/ext/intl/tests/breakiter_getPartsIterator_error.phpt new file mode 100644 index 00000000000..97376180338 --- /dev/null +++ b/ext/intl/tests/breakiter_getPartsIterator_error.phpt @@ -0,0 +1,33 @@ +--TEST-- +IntlBreakIterator::getPartsIterator(): bad args +--SKIPIF-- +getPartsIterator(array())); +var_dump($it->getPartsIterator(1, 2)); +var_dump($it->getPartsIterator(-1)); + +?> +==DONE== +--EXPECTF-- + +Warning: IntlBreakIterator::getPartsIterator() expects parameter 1 to be long, array given in %s on line %d + +Warning: IntlBreakIterator::getPartsIterator(): breakiter_get_parts_iterator: bad arguments in %s on line %d +bool(false) + +Warning: IntlBreakIterator::getPartsIterator() expects at most 1 parameter, 2 given in %s on line %d + +Warning: IntlBreakIterator::getPartsIterator(): breakiter_get_parts_iterator: bad arguments in %s on line %d +bool(false) + +Warning: IntlBreakIterator::getPartsIterator(): breakiter_get_parts_iterator: bad key type in %s on line %d +bool(false) +==DONE== diff --git a/ext/intl/tests/breakiter_getPartsIterator_var1.phpt b/ext/intl/tests/breakiter_getPartsIterator_var1.phpt new file mode 100644 index 00000000000..7bbd27ea451 --- /dev/null +++ b/ext/intl/tests/breakiter_getPartsIterator_var1.phpt @@ -0,0 +1,60 @@ +--TEST-- +IntlBreakIterator::getPartsIterator(): argument variations +--SKIPIF-- +setText($text); + +var_dump(iterator_to_array($it->getPartsIterator(IntlPartsIterator::KEY_SEQUENTIAL))); +var_dump(iterator_to_array($it->getPartsIterator(IntlPartsIterator::KEY_LEFT))); +var_dump(iterator_to_array($it->getPartsIterator(IntlPartsIterator::KEY_RIGHT))); + +?> +==DONE== +--EXPECT-- +array(5) { + [0]=> + string(3) "foo" + [1]=> + string(1) " " + [2]=> + string(3) "bar" + [3]=> + string(1) " " + [4]=> + string(3) "tao" +} +array(5) { + [0]=> + string(3) "foo" + [4]=> + string(1) " " + [5]=> + string(3) "bar" + [8]=> + string(1) " " + [9]=> + string(3) "tao" +} +array(5) { + [3]=> + string(3) "foo" + [5]=> + string(1) " " + [8]=> + string(3) "bar" + [9]=> + string(1) " " + [12]=> + string(3) "tao" +} +==DONE== From 5a9dca458a517f62fc596c57594a02c363c5a3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Mon, 25 Jun 2012 11:53:20 +0200 Subject: [PATCH 11/13] Fix build error one ext/intl --- ext/intl/breakiterator/codepointiterator_internal.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/intl/breakiterator/codepointiterator_internal.cpp b/ext/intl/breakiterator/codepointiterator_internal.cpp index 2dfae1aa4ff..e88f2eaf6b8 100644 --- a/ext/intl/breakiterator/codepointiterator_internal.cpp +++ b/ext/intl/breakiterator/codepointiterator_internal.cpp @@ -16,6 +16,7 @@ #include "codepointiterator_internal.h" #include +#include //copied from cmemory.h, which is not public typedef union { @@ -283,4 +284,4 @@ CodePointBreakIterator &CodePointBreakIterator::refreshInputText(UText *input, U } return *this; -} \ No newline at end of file +} From d8b067e66f4b458108821df512090ede623df214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Mon, 25 Jun 2012 12:03:27 +0200 Subject: [PATCH 12/13] BreakIterator: fix compat with old ICU versions --- ext/intl/breakiterator/breakiterator_class.cpp | 4 +++- ext/intl/breakiterator/codepointiterator_internal.cpp | 4 ++++ ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp | 8 ++++++++ ext/intl/tests/breakiter___construct_error.phpt | 3 +++ ext/intl/tests/rbbiter_getBinaryRules_basic.phpt | 5 ++++- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index d193fc44577..de4bfbb7b0d 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -312,7 +312,9 @@ static const zend_function_entry RuleBasedBreakIterator_class_functions[] = { PHP_ME_MAPPING(getRules, rbbi_get_rules, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRuleStatus, rbbi_get_rule_status, ainfo_biter_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getRuleStatusVec, rbbi_get_rule_status_vec, ainfo_biter_void, ZEND_ACC_PUBLIC) +#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48 PHP_ME_MAPPING(getBinaryRules, rbbi_get_binary_rules, ainfo_biter_void, ZEND_ACC_PUBLIC) +#endif PHP_FE_END }; /* }}} */ @@ -329,7 +331,7 @@ static const zend_function_entry CodePointBreakIterator_class_functions[] = { /* {{{ breakiterator_register_BreakIterator_class * Initialize 'BreakIterator' class */ -void breakiterator_register_BreakIterator_class(TSRMLS_D) +U_CFUNC void breakiterator_register_BreakIterator_class(TSRMLS_D) { zend_class_entry ce; diff --git a/ext/intl/breakiterator/codepointiterator_internal.cpp b/ext/intl/breakiterator/codepointiterator_internal.cpp index e88f2eaf6b8..bf9239d531f 100644 --- a/ext/intl/breakiterator/codepointiterator_internal.cpp +++ b/ext/intl/breakiterator/codepointiterator_internal.cpp @@ -212,6 +212,10 @@ int32_t CodePointBreakIterator::next(int32_t n) { UBool res = utext_moveIndex32(this->fText, n); +#ifndef UTEXT_CURRENT32 +#define UTEXT_CURRENT32 utext_current32 +#endif + if (res) { this->lastCodePoint = UTEXT_CURRENT32(this->fText); return (int32_t)UTEXT_GETNATIVEINDEX(this->fText); diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index 288179a7859..41ebfe5e0f5 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -73,12 +73,18 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS) RETURN_NULL(); } } else { // compiled +#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48 rbbi = new RuleBasedBreakIterator((uint8_t*)rules, rules_len, status); if (U_FAILURE(status)) { intl_error_set(NULL, status, "rbbi_create_instance: unable to " "creaete instance from compiled rules", 0 TSRMLS_CC); RETURN_NULL(); } +#else + intl_error_set(NULL, U_UNSUPPORTED_ERROR, "rbbi_create_instance: " + "compiled rules require ICU >= 4.8", 0 TSRMLS_CC); + RETURN_NULL(); +#endif } breakiterator_object_create(return_value, rbbi TSRMLS_CC); @@ -180,6 +186,7 @@ U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec) delete[] rules; } +#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48 U_CFUNC PHP_FUNCTION(rbbi_get_binary_rules) { BREAKITER_METHOD_INIT_VARS; @@ -209,3 +216,4 @@ U_CFUNC PHP_FUNCTION(rbbi_get_binary_rules) RETURN_STRINGL(ret_rules, rules_len, 0); } +#endif diff --git a/ext/intl/tests/breakiter___construct_error.phpt b/ext/intl/tests/breakiter___construct_error.phpt index e96086de567..8d6a7181ed5 100644 --- a/ext/intl/tests/breakiter___construct_error.phpt +++ b/ext/intl/tests/breakiter___construct_error.phpt @@ -1,5 +1,8 @@ --TEST-- IntlRuleBasedBreakIterator::__construct(): arg errors +--SKIPIF-- + += 4.8 only'; ?> --FILE-- += 4.8 only'; ?> --FILE-- getRules() == $rbbi2->getRules()); string(128) "$LN = [[:letter:] [:number:]];$S = [.;,:];!!forward;$LN+ {1};$S+ {42};!!reverse;$LN+ {1};$S+ {42};!!safe_forward;!!safe_reverse;" string(128) "$LN = [[:letter:] [:number:]];$S = [.;,:];!!forward;$LN+ {1};$S+ {42};!!reverse;$LN+ {1};$S+ {42};!!safe_forward;!!safe_reverse;" bool(true) -==DONE== \ No newline at end of file +==DONE== From 0df73a85e19d71612ab3a0ba03061123453ff2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Mon, 25 Jun 2012 12:06:31 +0200 Subject: [PATCH 13/13] Fix typo in error message --- ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp | 2 +- ext/intl/tests/breakiter___construct_error.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index 41ebfe5e0f5..f2a39ba0225 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -77,7 +77,7 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS) rbbi = new RuleBasedBreakIterator((uint8_t*)rules, rules_len, status); if (U_FAILURE(status)) { intl_error_set(NULL, status, "rbbi_create_instance: unable to " - "creaete instance from compiled rules", 0 TSRMLS_CC); + "create instance from compiled rules", 0 TSRMLS_CC); RETURN_NULL(); } #else diff --git a/ext/intl/tests/breakiter___construct_error.phpt b/ext/intl/tests/breakiter___construct_error.phpt index 8d6a7181ed5..770f1403c71 100644 --- a/ext/intl/tests/breakiter___construct_error.phpt +++ b/ext/intl/tests/breakiter___construct_error.phpt @@ -34,5 +34,5 @@ Warning: IntlRuleBasedBreakIterator::__construct() expects parameter 2 to be boo Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: bad arguments in %s on line %d NULL -Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: unable to creaete instance from compiled rules in %s on line %d +Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: unable to create instance from compiled rules in %s on line %d NULL