Merge remote branch 'upstream/master' into hash_password

Conflicts:
	ext/standard/crypt.c
This commit is contained in:
Anthony Ferrara 2012-06-29 10:29:58 -04:00
commit 9e18e578f0
95 changed files with 4098 additions and 359 deletions

2
NEWS
View File

@ -12,6 +12,8 @@ PHP NEWS
(Nikita Popov)
- Core:
. Fixed bug #62443 (Crypt SHA256/512 Segfaults With Malformed
Salt). (Anthony Ferrara)
. Added boolval(). (Jille Timmermans).
. Fixed bug #61681 (Malformed grammar). (Nikita Popov, Etienne, Laruence).
. Fixed bug #61038 (unpack("a5", "str\0\0") does not work as expected).

View File

@ -188,6 +188,9 @@ PHP X.Y UPGRADE NOTES
- IntlCalendar
- IntlGregorianCalendar
- IntlTimeZone
- IntlBreakIterator
- IntlRuleBasedBreakIterator
- IntlCodePointBreakIterator
========================================
7. Removed Extensions

View File

@ -1206,7 +1206,7 @@ static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr)
if (LANG_SCNG(yy_text)[0] == 0 &&
LANG_SCNG(yy_leng) == 1 &&
memcmp(yystr, ZEND_STRL("\"end of file\"")) == 0) {
memcmp(yystr, "\"end of file\"", sizeof("\"end of file\"") - 1) == 0) {
yystpcpy(yyres, "end of file");
return sizeof("end of file")-1;
}

View File

@ -0,0 +1,397 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unicode/brkiter.h>
#include <unicode/rbbi.h>
#include "codepointiterator_internal.h"
#include "breakiterator_iterators.h"
#include <typeinfo>
extern "C" {
#define USE_BREAKITERATOR_POINTER 1
#include "breakiterator_class.h"
#include "breakiterator_methods.h"
#include "rulebasedbreakiterator_methods.h"
#include "codepointiterator_methods.h"
#include <zend_exceptions.h>
#include <zend_interfaces.h>
#include <assert.h>
}
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;
/* }}} */
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 if (classId == CodePointBreakIterator::getStaticClassID()) {
ce = CodePointBreakIterator_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<char*>(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_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")
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(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)
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_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)
PHP_FE_END
};
/* }}} */
/* {{{ RuleBasedBreakIterator_class_functions
*/
static const zend_function_entry RuleBasedBreakIterator_class_functions[] = {
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)
#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
};
/* }}} */
/* {{{ 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
*/
U_CFUNC void breakiterator_register_BreakIterator_class(TSRMLS_D)
{
zend_class_entry ce;
/* Create and register 'BreakIterator' class. */
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(),
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 );
/* 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, "IntlRuleBasedBreakIterator",
RuleBasedBreakIterator_class_functions);
RuleBasedBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce,
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);
}
/* }}} */

View File

@ -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 <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef BREAKITERATOR_CLASS_H
#define BREAKITERATOR_CLASS_H
//redefinition of inline in PHP headers causes problems, so include this before
#include <math.h>
#include <php.h>
#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 */

View File

@ -0,0 +1,346 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unicode/brkiter.h>
#include "breakiterator_iterators.h"
#include "../common/common_enum.h"
extern "C" {
#define USE_BREAKITERATOR_POINTER
#include "breakiterator_class.h"
#include "../intl_convert.h"
#include "../locale/locale.h"
#include <zend_exceptions.h>
}
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)
{
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<zoi_with_current*>(emalloc(sizeof *zoi_iter));
zoi_iter->zoi.data = static_cast<void*>(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<zend_object_iterator *>(zoi_iter);
}
/* BreakIterator parts 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;
static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC)
{
zval_ptr_dtor(reinterpret_cast<zval**>(&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;
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;
}
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;
char *res;
if (next == BreakIterator::DONE) {
next = slen;
}
assert(next <= slen && next >= cur);
len = next - cur;
res = static_cast<char*>(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,
_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,
parts_iter_key_type key_type TSRMLS_DC)
{
IntlIterator_object *ii;
zval_add_ref(&break_iter_zv);
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));
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);
((zoi_break_iter_parts*)ii->iterator)->key_type = key_type;
}
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<char*>(
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<zval*>(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<zval*>(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;
#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
}

View File

@ -0,0 +1,42 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef INTL_BREAKITERATOR_ITERATORS_H
#define INTL_BREAKITERATOR_ITERATORS_H
#include <unicode/umachine.h>
U_CDECL_BEGIN
#include <math.h>
#include <php.h>
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,
parts_iter_key_type key_type TSRMLS_DC);
#endif
U_CFUNC zend_object_iterator *_breakiterator_get_iterator(
zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D);
#endif

View File

@ -0,0 +1,452 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unicode/brkiter.h>
#include "codepointiterator_internal.h"
#include "breakiterator_iterators.h"
extern "C" {
#include "../php_intl.h"
#define USE_BREAKITERATOR_POINTER 1
#include "breakiterator_class.h"
#include "../locale/locale.h"
#include <zend_exceptions.h>
}
using PHP::CodePointBreakIterator;
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_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;
object = getThis();
if (zend_parse_parameters_none() == 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;
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() */
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;
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);
}
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;
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);
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;
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);
}
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;
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);
}
U_CFUNC PHP_FUNCTION(breakiter_get_locale)
{
long locale_type;
BREAKITER_METHOD_INIT_VARS;
object = getThis();
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;
}
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)
{
long key_type = 0;
BREAKITER_METHOD_INIT_VARS;
object = getThis();
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);
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, (parts_iter_key_type)key_type TSRMLS_CC);
}
U_CFUNC PHP_FUNCTION(breakiter_get_error_code)
{
BREAKITER_METHOD_INIT_VARS;
object = getThis();
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;
}
/* 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;
object = getThis();
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;
}
/* 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);
}

View File

@ -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 <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef BREAKITERATOR_METHODS_H
#define BREAKITERATOR_METHODS_H
#include <php.h>
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_create_code_point_instance);
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

View File

@ -0,0 +1,291 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#include "codepointiterator_internal.h"
#include <unicode/uchriter.h>
#include <typeinfo>
//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<const CodePointBreakIterator&>(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);
#ifndef UTEXT_CURRENT32
#define UTEXT_CURRENT32 utext_current32
#endif
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;
}

View File

@ -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 <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef CODEPOINTITERATOR_INTERNAL_H
#define CODEPOINTITERATOR_INTERNAL_H
#include <unicode/brkiter.h>
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

View File

@ -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 <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#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());
}

View File

@ -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 <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef CODEPOINTITERATOR_METHODS_H
#define CODEPOINTITERATOR_METHODS_H
#include <php.h>
PHP_FUNCTION(cpbi_get_last_code_point);
#endif

View File

@ -0,0 +1,219 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#include <unicode/rbbi.h>
extern "C" {
#define USE_BREAKITERATOR_POINTER 1
#include "breakiterator_class.h"
#include <zend_exceptions.h>
#include <limits.h>
}
#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
#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 "
"create 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);
}
U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, __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_get_rules)
{
BREAKITER_METHOD_INIT_VARS;
object = getThis();
if (zend_parse_parameters_none() == FAILURE) {
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
"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)
{
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;
object = getThis();
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;
}
BREAKITER_METHOD_FETCH_OBJECT;
RETURN_LONG(fetch_rbbi(bio)->getRuleStatus());
}
U_CFUNC PHP_FUNCTION(rbbi_get_rule_status_vec)
{
BREAKITER_METHOD_INIT_VARS;
object = getThis();
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;
}
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;
}
#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;
object = getThis();
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;
}
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<char*>(emalloc(rules_len + 1));
memcpy(ret_rules, rules, rules_len);
ret_rules[rules_len] = '\0';
RETURN_STRINGL(ret_rules, rules_len, 0);
}
#endif

View File

@ -0,0 +1,32 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef RULEBASEDBREAKITERATOR_METHODS_H
#define RULEBASEDBREAKITERATOR_METHODS_H
#include <php.h>
PHP_METHOD(IntlRuleBasedBreakIterator, __construct);
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

View File

@ -25,12 +25,12 @@
#include <unicode/ustring.h>
#include "../intl_convertcpp.h"
extern "C" {
#include "../php_intl.h"
#define USE_TIMEZONE_POINTER 1
#include "../timezone/timezone_class.h"
#define USE_CALENDAR_POINTER 1
#include "calendar_class.h"
#include "../intl_convert.h"
#include "../locale/locale.h"
#include <zend_exceptions.h>
#include <zend_interfaces.h>
#include <ext/date/php_date.h>

View File

@ -24,11 +24,11 @@
#include <unicode/calendar.h>
#include <unicode/gregocal.h>
extern "C" {
#include "../php_intl.h"
#define USE_TIMEZONE_POINTER 1
#include "../timezone/timezone_class.h"
#define USE_CALENDAR_POINTER 1
#include "calendar_class.h"
#include "../locale/locale.h"
#include <ext/date/php_date.h>
}

View File

@ -26,45 +26,14 @@
#include "common_enum.h"
extern "C" {
#include "intl_error.h"
#include "intl_data.h"
#include <zend_interfaces.h>
#include <zend_exceptions.h>
}
static zend_class_entry *IntlIterator_ce_ptr;
static zend_object_handlers IntlIterator_handlers;
zend_class_entry *IntlIterator_ce_ptr;
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);
}
}

View File

@ -25,10 +25,49 @@ extern "C" {
#include <math.h>
#endif
#include <php.h>
#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;
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);
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

View File

@ -75,6 +75,12 @@ 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 \
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)
@ -91,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

View File

@ -102,6 +102,15 @@ 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 \
codepointiterator_internal.cpp \
codepointiterator_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");

View File

@ -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:

View File

@ -20,6 +20,8 @@
#define INTL_ERROR_H
#include <unicode/utypes.h>
#include <unicode/parseerr.h>
#include <ext/standard/php_smart_str.h>
#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 );

View File

@ -22,8 +22,6 @@
#include <php.h>
void locale_register_constants( INIT_FUNC_ARGS );
const char *intl_locale_get_default( TSRMLS_D );
#define OPTION_DEFAULT NULL
#define LOC_LANG_TAG "language"

View File

@ -201,14 +201,6 @@ static int getSingletonPos(char* str)
}
/* }}} */
const char *intl_locale_get_default( TSRMLS_D )
{
if( INTL_G(default_locale) == NULL ) {
return uloc_getDefault();
}
return INTL_G(default_locale);
}
/* {{{ proto static string Locale::getDefault( )
Get default locale */
/* }}} */

View File

@ -78,6 +78,9 @@
#include "calendar/calendar_methods.h"
#include "calendar/gregoriancalendar_methods.h"
#include "breakiterator/breakiterator_class.h"
#include "breakiterator/breakiterator_iterators.h"
#include "idn/idn.h"
#if U_ICU_VERSION_MAJOR_NUM > 3 && U_ICU_VERSION_MINOR_NUM >=2
@ -109,6 +112,14 @@
ZEND_DECLARE_MODULE_GLOBALS( intl )
const char *intl_locale_get_default( TSRMLS_D )
{
if( INTL_G(default_locale) == NULL ) {
return uloc_getDefault();
}
return INTL_G(default_locale);
}
/* {{{ Arguments info */
ZEND_BEGIN_ARG_INFO_EX(collator_static_0_args, 0, 0, 0)
ZEND_END_ARG_INFO()
@ -958,6 +969,12 @@ PHP_MINIT_FUNCTION( intl )
/* Register 'IntlIterator' PHP class */
intl_register_IntlIterator_class( TSRMLS_C );
/* 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 );

View File

@ -69,6 +69,8 @@ PHP_RINIT_FUNCTION(intl);
PHP_RSHUTDOWN_FUNCTION(intl);
PHP_MINFO_FUNCTION(intl);
const char *intl_locale_get_default( TSRMLS_D );
#define PHP_INTL_VERSION "1.1.0"
#endif /* PHP_INTL_H */

View File

@ -78,13 +78,11 @@ static zend_object_value ResourceBundle_object_create( zend_class_entry *ce TSRM
/* {{{ ResourceBundle_ctor */
static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
{
char * bundlename;
int bundlename_len = 0;
char * locale;
int locale_len = 0;
zend_bool fallback = 1;
char * pbuf;
const char *bundlename;
int bundlename_len = 0;
const char *locale;
int locale_len = 0;
zend_bool fallback = 1;
zval *object = return_value;
ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC);
@ -116,6 +114,7 @@ static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING ||
INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
char *pbuf;
intl_errors_set_code(NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC);
spprintf(&pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource "
"'%s' without fallback from %s to %s",

View File

@ -0,0 +1,13 @@
--TEST--
IntlBreakIterator::__construct() should not be callable
--SKIPIF--
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
new IntlBreakIterator();
--EXPECTF--
Fatal error: Call to private IntlBreakIterator::__construct() from invalid context in %s on line %d

View File

@ -0,0 +1,38 @@
--TEST--
IntlRuleBasedBreakIterator::__construct(): arg errors
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0) print 'skip ICU >= 4.8 only'; ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
//missing ; at the end:
var_dump(new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+'));
var_dump(new IntlRuleBasedBreakIterator());
var_dump(new IntlRuleBasedBreakIterator(1,2,3));
var_dump(new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;', array()));
var_dump(new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;', true));
--EXPECTF--
Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: unable to create RuleBasedBreakIterator from rules (parse error on line 1, offset 31) in %s on line %d
NULL
Warning: IntlRuleBasedBreakIterator::__construct() expects at least 1 parameter, 0 given in %s on line %d
Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: bad arguments in %s on line %d
NULL
Warning: IntlRuleBasedBreakIterator::__construct() expects at most 2 parameters, 3 given in %s on line %d
Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: bad arguments in %s on line %d
NULL
Warning: IntlRuleBasedBreakIterator::__construct() expects parameter 2 to be boolean, array given in %s on line %d
Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: bad arguments in %s on line %d
NULL
Warning: IntlRuleBasedBreakIterator::__construct(): rbbi_create_instance: unable to create instance from compiled rules in %s on line %d
NULL

View File

@ -0,0 +1,23 @@
--TEST--
IntlBreakIterator: clone handler
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;');
$bi_clone = clone $bi;
var_dump(get_class($bi), get_class($bi_clone));
var_dump($bi == $bi_clone);
$bi->setText('foobar');
$bi_clone = clone $bi;
var_dump(get_class($bi), get_class($bi_clone));
var_dump($bi == $bi_clone);
--EXPECT--
string(26) "IntlRuleBasedBreakIterator"
string(26) "IntlRuleBasedBreakIterator"
bool(true)
string(26) "IntlRuleBasedBreakIterator"
string(26) "IntlRuleBasedBreakIterator"
bool(true)

View File

@ -0,0 +1,43 @@
--TEST--
IntlBreakIterator::createCodePointInstance(): basic test
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$text = 'ตัวอย่างข้อความ';
$codepoint_it = IntlBreakIterator::createCodePointInstance();
var_dump(get_class($codepoint_it));
$codepoint_it->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==

View File

@ -0,0 +1,18 @@
--TEST--
IntlBreakIterator::createCodePointInstance(): bad arguments
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
var_dump(IntlBreakIterator::createCodePointInstance(array()));
--EXPECTF--
Warning: IntlBreakIterator::createCodePointInstance() expects exactly 0 parameters, 1 given in %s on line %d
Warning: IntlBreakIterator::createCodePointInstance(): breakiter_create_code_point_instance: bad arguments in %s on line %d
NULL

View File

@ -0,0 +1,24 @@
--TEST--
IntlBreakIterator::current(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
var_dump($bi->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==

View File

@ -0,0 +1,45 @@
--TEST--
IntlBreakIterator factories: basic tests
--SKIPIF--
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "ja");
$m = array('createWordInstance', 'createLineInstance', 'createCharacterInstance',
'createSentenceInstance', 'createTitleInstance');
$t = 'Frase 1... Frase 2'.
$o1 = $o2 = null;
foreach ($m as $method) {
echo "===== $method =====\n";
$o1 = call_user_func(array('IntlBreakIterator', $method), 'ja');
var_dump($o1 == $o2);
$o2 = call_user_func(array('IntlBreakIterator', $method), NULL);
var_dump($o1 == $o2);
echo "\n";
}
--EXPECT--
===== createWordInstance =====
bool(false)
bool(true)
===== createLineInstance =====
bool(false)
bool(true)
===== createCharacterInstance =====
bool(false)
bool(true)
===== createSentenceInstance =====
bool(false)
bool(true)
===== createTitleInstance =====
bool(false)
bool(true)

View File

@ -0,0 +1,39 @@
--TEST--
IntlBreakIterator factory methods: argument errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
var_dump(IntlBreakIterator::createWordInstance(array()));
var_dump(IntlBreakIterator::createSentenceInstance(NULL, 2));
var_dump(IntlBreakIterator::createCharacterInstance(NULL, 2));
var_dump(IntlBreakIterator::createTitleInstance(NULL, 2));
var_dump(IntlBreakIterator::createLineInstance(NULL, 2));
--EXPECTF--
Warning: IntlBreakIterator::createWordInstance() expects parameter 1 to be string, array given in %s on line %d
Warning: IntlBreakIterator::createWordInstance(): breakiter_create_word_instance: bad arguments in %s on line %d
NULL
Warning: IntlBreakIterator::createSentenceInstance() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::createSentenceInstance(): breakiter_create_sentence_instance: bad arguments in %s on line %d
NULL
Warning: IntlBreakIterator::createCharacterInstance() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::createCharacterInstance(): breakiter_create_character_instance: bad arguments in %s on line %d
NULL
Warning: IntlBreakIterator::createTitleInstance() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::createTitleInstance(): breakiter_create_title_instance: bad arguments in %s on line %d
NULL
Warning: IntlBreakIterator::createLineInstance() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::createLineInstance(): breakiter_create_line_instance: bad arguments in %s on line %d
NULL

View File

@ -0,0 +1,21 @@
--TEST--
IntlBreakIterator::first(): basic test
--SKIPIF--
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->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)

View File

@ -0,0 +1,35 @@
--TEST--
IntlBreakIterator::first()/last()/previous()/current(): arg errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;');
$bi->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: IntlBreakIterator::first() expects exactly 0 parameters, 1 given in %s on line %d
Warning: IntlBreakIterator::first(): breakiter_first: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::last() expects exactly 0 parameters, 1 given in %s on line %d
Warning: IntlBreakIterator::last(): breakiter_last: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::previous() expects exactly 0 parameters, 1 given in %s on line %d
Warning: IntlBreakIterator::previous(): breakiter_previous: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::current() expects exactly 0 parameters, 1 given in %s on line %d
Warning: IntlBreakIterator::current(): breakiter_current: bad arguments in %s on line %d
bool(false)

View File

@ -0,0 +1,20 @@
--TEST--
IntlBreakIterator::following(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->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==

View File

@ -0,0 +1,47 @@
--TEST--
IntlBreakIterator::following()/preceding()/isBoundary(): arg errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;');
$bi->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: IntlBreakIterator::following() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::following(): breakiter_following: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::following() expects parameter 1 to be long, array given in %s on line %d
Warning: IntlBreakIterator::following(): breakiter_following: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::preceding() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::preceding() expects parameter 1 to be long, array given in %s on line %d
Warning: IntlBreakIterator::preceding(): breakiter_preceding: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::isBoundary() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::isBoundary() expects parameter 1 to be long, array given in %s on line %d
Warning: IntlBreakIterator::isBoundary(): breakiter_is_boundary: bad arguments in %s on line %d
bool(false)

View File

@ -0,0 +1,17 @@
--TEST--
IntlBreakIterator::getLocale(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createSentenceInstance('pt');
var_dump($bi->getLocale(0));
var_dump($bi->getLocale(1));
?>
==DONE==
--EXPECT--
string(4) "root"
string(4) "root"
==DONE==

View File

@ -0,0 +1,29 @@
--TEST--
IntlBreakIterator::getLocale(): arg errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;');
$bi->setText("\x80sdfé\x90d888 dfsa9");
var_dump($bi->getLocale(1, 2));
var_dump($bi->getLocale(array()));
var_dump($bi->getLocale());
--EXPECTF--
Warning: IntlBreakIterator::getLocale() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::getLocale() expects parameter 1 to be long, array given in %s on line %d
Warning: IntlBreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::getLocale() expects exactly 1 parameter, 0 given in %s on line %d
Warning: IntlBreakIterator::getLocale(): breakiter_get_locale: bad arguments in %s on line %d
bool(false)

View File

@ -0,0 +1,33 @@
--TEST--
IntlBreakIterator::getPartsIterator(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
$pi = $bi->getPartsIterator();
var_dump(get_class($pi));
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(17) "IntlPartsIterator"
Array
(
)
string(26) "IntlRuleBasedBreakIterator"
Array
(
[0] => foo
[1] =>
[2] => bar
)
int(0)
==DONE==

View File

@ -0,0 +1,33 @@
--TEST--
IntlBreakIterator::getPartsIterator(): bad args
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$it = IntlBreakIterator::createWordInstance(NULL);
var_dump($it->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==

View File

@ -0,0 +1,60 @@
--TEST--
IntlBreakIterator::getPartsIterator(): argument variations
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$text = 'foo bar tao';
$it = IntlBreakIterator::createWordInstance(NULL);
$it->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==

View File

@ -0,0 +1,16 @@
--TEST--
IntlBreakIterator::getText(): basic test
--SKIPIF--
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = IntlBreakIterator::createWordInstance('pt');
var_dump($bi->getText());
$bi->setText('foo bar');
var_dump($bi->getText());
--EXPECTF--
NULL
string(7) "foo bar"

View File

@ -0,0 +1,15 @@
--TEST--
IntlBreakIterator::getText(): arg errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}]+;');
var_dump($bi->getText(array()));
--EXPECTF--
Warning: IntlBreakIterator::getText() expects exactly 0 parameters, 1 given in %s on line %d
Warning: IntlBreakIterator::getText(): breakiter_get_text: bad arguments in %s on line %d
bool(false)

View File

@ -0,0 +1,24 @@
--TEST--
IntlBreakIterator::isBoundary(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->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==

View File

@ -0,0 +1,19 @@
--TEST--
IntlBreakIterator::last(): basic test
--SKIPIF--
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->setText('foo bar trans');
var_dump($bi->current());
var_dump($bi->last());
var_dump($bi->current());
--EXPECTF--
int(0)
int(13)
int(13)

View File

@ -0,0 +1,26 @@
--TEST--
IntlBreakIterator::next(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->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==

View File

@ -0,0 +1,23 @@
--TEST--
IntlBreakIterator::next(): arg errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;');
$bi->setText("\x80sdfé\x90d888 dfsa9");
var_dump($bi->next(1, 2));
var_dump($bi->next(array()));
--EXPECTF--
Warning: IntlBreakIterator::next() expects exactly 1 parameter, 2 given in %s on line %d
Warning: IntlBreakIterator::next(): breakiter_next: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::next() expects parameter 1 to be long, array given in %s on line %d
Warning: IntlBreakIterator::next(): breakiter_next: bad arguments in %s on line %d
bool(false)

View File

@ -0,0 +1,20 @@
--TEST--
IntlBreakIterator::preceding(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->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==

View File

@ -0,0 +1,18 @@
--TEST--
IntlBreakIterator::previous(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$bi = IntlBreakIterator::createWordInstance('pt');
$bi->setText('foo bar trans');
var_dump($bi->last());
var_dump($bi->previous());
?>
==DONE==
--EXPECT--
int(13)
int(8)
==DONE==

View File

@ -0,0 +1,35 @@
--TEST--
IntlBreakIterator::setText(): basic test
--SKIPIF--
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
class A {
function __tostring() { return 'aaa'; }
}
$bi = IntlBreakIterator::createWordInstance('pt');
var_dump($bi->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)

View File

@ -0,0 +1,40 @@
--TEST--
IntlBreakIterator::setText(): arg errors
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$bi = new IntlRuleBasedBreakIterator('[\p{Letter}]+;');
var_dump($bi->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: IntlBreakIterator::setText() expects exactly 1 parameter, 0 given in %s on line %d
Warning: IntlBreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::setText() expects parameter 1 to be string, array given in %s on line %d
Warning: IntlBreakIterator::setText(): breakiter_set_text: bad arguments in %s on line %d
bool(false)
Warning: IntlBreakIterator::setText() expects exactly 1 parameter, 2 given 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"

View File

@ -0,0 +1,33 @@
--TEST--
IntlCodePointBreakIterator: clone and equality
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$text = 'ตัวอย่างข้อความ';
$text2 = 'foo';
$it = IntlBreakIterator::createCodePointInstance();
$it->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==

View File

@ -0,0 +1,82 @@
--TEST--
IntlCodepointBreakIterator::getLastCodePoint(): basic test
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$text = 'ตัวอย่างข้อความ';
$codepoint_it = IntlBreakIterator::createCodePointInstance();
$codepoint_it->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==

View File

@ -0,0 +1,19 @@
--TEST--
IntlBreakIterator::getLastCodePoint(): bad args
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
$it = IntlBreakIterator::createCodePointInstance();
var_dump($it->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)

View File

@ -0,0 +1,40 @@
--TEST--
IntlCodepointBreakIterator's part iterator
--SKIPIF--
<?php
if (!extension_loaded('intl'))
die('skip intl extension not enabled');
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$text = 'ตัวอย่างข้อความ';
$it = IntlBreakIterator::createCodePointInstance()->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==

View File

@ -1,8 +1,8 @@
--TEST--
locale_get_display_script() icu >= 4.8
locale_get_display_script() icu = 4.8
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0 || version_compare(INTL_ICU_VERSION, '49') >= 0) print 'skip'; ?>
--FILE--
<?php

View File

@ -0,0 +1,275 @@
--TEST--
locale_get_display_script() icu >= 49
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '49') < 0) print 'skip'; ?>
--FILE--
<?php
/*
* Try getting the display_script for different locales
* with Procedural and Object methods.
*/
function ut_main()
{
$res_str = '';
$disp_locales=array('en','fr','de');
$locales = array(
'uk-ua_CALIFORNIA@currency=;currency=GRN',
'root',
'uk@currency=EURO',
'Hindi',
//Simple language subtag
'de',
'fr',
'ja',
'i-enochian', //(example of a grandfathered tag)
//Language subtag plus Script subtag:
'zh-Hant',
'zh-Hans',
'sr-Cyrl',
'sr-Latn',
//Language-Script-Region
'zh-Hans-CN',
'sr-Latn-CS',
//Language-Variant
'sl-rozaj',
'sl-nedis',
//Language-Region-Variant
'de-CH-1901',
'sl-IT-nedis',
//Language-Script-Region-Variant
'sl-Latn-IT-nedis',
//Language-Region:
'de-DE',
'en-US',
'es-419',
//Private use subtags:
'de-CH-x-phonebk',
'az-Arab-x-AZE-derbend',
//Extended language subtags
'zh-min',
'zh-min-nan-Hant-CN',
//Private use registry values
'x-whatever',
'qaa-Qaaa-QM-x-southern',
'sr-Latn-QM',
'sr-Qaaa-CS',
/*Tags that use extensions (examples ONLY: extensions MUST be defined
by revision or update to this document or by RFC): */
'en-US-u-islamCal',
'zh-CN-a-myExt-x-private',
'en-a-myExt-b-another',
//Some Invalid Tags:
'de-419-DE',
'a-DE',
'ar-a-aaa-b-bbb-a-ccc'
);
$res_str = '';
foreach( $locales as $locale )
{
$res_str .= "locale='$locale'\n";
foreach( $disp_locales as $disp_locale )
{
$scr = ut_loc_get_display_script( $locale ,$disp_locale );
$res_str .= "disp_locale=$disp_locale : display_script=$scr";
$res_str .= "\n";
}
$res_str .= "-----------------\n";
}
return $res_str;
}
include_once( 'ut_common.inc' );
ut_run();
?>
--EXPECT--
locale='uk-ua_CALIFORNIA@currency=;currency=GRN'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='root'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='uk@currency=EURO'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='Hindi'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='de'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='fr'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='ja'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='i-enochian'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='zh-Hant'
disp_locale=en : display_script=Traditional Han
disp_locale=fr : display_script=chinois traditionnel
disp_locale=de : display_script=Traditionelles Chinesisch
-----------------
locale='zh-Hans'
disp_locale=en : display_script=Simplified Han
disp_locale=fr : display_script=chinois simplifié
disp_locale=de : display_script=Vereinfachtes Chinesisch
-----------------
locale='sr-Cyrl'
disp_locale=en : display_script=Cyrillic
disp_locale=fr : display_script=cyrillique
disp_locale=de : display_script=Kyrillisch
-----------------
locale='sr-Latn'
disp_locale=en : display_script=Latin
disp_locale=fr : display_script=latin
disp_locale=de : display_script=Lateinisch
-----------------
locale='zh-Hans-CN'
disp_locale=en : display_script=Simplified Han
disp_locale=fr : display_script=chinois simplifié
disp_locale=de : display_script=Vereinfachtes Chinesisch
-----------------
locale='sr-Latn-CS'
disp_locale=en : display_script=Latin
disp_locale=fr : display_script=latin
disp_locale=de : display_script=Lateinisch
-----------------
locale='sl-rozaj'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='sl-nedis'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='de-CH-1901'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='sl-IT-nedis'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='sl-Latn-IT-nedis'
disp_locale=en : display_script=Latin
disp_locale=fr : display_script=latin
disp_locale=de : display_script=Lateinisch
-----------------
locale='de-DE'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='en-US'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='es-419'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='de-CH-x-phonebk'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='az-Arab-x-AZE-derbend'
disp_locale=en : display_script=Arabic
disp_locale=fr : display_script=arabe
disp_locale=de : display_script=Arabisch
-----------------
locale='zh-min'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='zh-min-nan-Hant-CN'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='x-whatever'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='qaa-Qaaa-QM-x-southern'
disp_locale=en : display_script=Qaaa
disp_locale=fr : display_script=Qaaa
disp_locale=de : display_script=Qaaa
-----------------
locale='sr-Latn-QM'
disp_locale=en : display_script=Latin
disp_locale=fr : display_script=latin
disp_locale=de : display_script=Lateinisch
-----------------
locale='sr-Qaaa-CS'
disp_locale=en : display_script=Qaaa
disp_locale=fr : display_script=Qaaa
disp_locale=de : display_script=Qaaa
-----------------
locale='en-US-u-islamCal'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='zh-CN-a-myExt-x-private'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='en-a-myExt-b-another'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='de-419-DE'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='a-DE'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------
locale='ar-a-aaa-b-bbb-a-ccc'
disp_locale=en : display_script=
disp_locale=fr : display_script=
disp_locale=de : display_script=
-----------------

View File

@ -0,0 +1,27 @@
--TEST--
IntlRuleBasedBreakIterator::__construct: basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$rules = <<<RULES
\$LN = [[:letter:] [:number:]];
\$S = [.;,:];
!!forward;
\$LN+ {1};
\$S+ {42};
!!reverse;
\$LN+ {1};
\$S+ {42};
!!safe_forward;
!!safe_reverse;
RULES;
$rbbi = new IntlRuleBasedBreakIterator($rules);
var_dump(get_class($rbbi));
?>
==DONE==
--EXPECT--
string(26) "IntlRuleBasedBreakIterator"
==DONE==

View File

@ -0,0 +1,39 @@
--TEST--
IntlRuleBasedBreakIterator::getBinaryRules(): basic test
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0) print 'skip ICU >= 4.8 only'; ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$rules = <<<RULES
\$LN = [[:letter:] [:number:]];
\$S = [.;,:];
!!forward;
\$LN+ {1};
\$S+ {42};
!!reverse;
\$LN+ {1};
\$S+ {42};
!!safe_forward;
!!safe_reverse;
RULES;
$rbbi = new IntlRuleBasedBreakIterator($rules);
$rbbi->setText('sdfkjsdf88á.... ,;');;
$br = $rbbi->getBinaryRules();
$rbbi2 = new IntlRuleBasedBreakIterator($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==

View File

@ -0,0 +1,55 @@
--TEST--
IntlRuleBasedBreakIterator::getRuleStatusVec(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$rules = <<<RULES
\$LN = [[:letter:] [:number:]];
\$S = [.;,:];
!!forward;
\$LN+ {1};
[^.]+ {4};
\$S+ {42};
!!reverse;
\$LN+ {1};
[^.]+ {4};
\$S+ {42};
!!safe_forward;
!!safe_reverse;
RULES;
$rbbi = new IntlRuleBasedBreakIterator($rules);
$rbbi->setText('sdfkjsdf88á.... ,;');;
do {
var_dump($rbbi->current(), $rbbi->getRuleStatusVec());
} while ($rbbi->next() != IntlBreakIterator::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==

View File

@ -0,0 +1,42 @@
--TEST--
IntlRuleBasedBreakIterator::getRuleStatus(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$rules = <<<RULES
\$LN = [[:letter:] [:number:]];
\$S = [.;,:];
!!forward;
\$LN+ {1};
\$S+ {42};
!!reverse;
\$LN+ {1};
\$S+ {42};
!!safe_forward;
!!safe_reverse;
RULES;
$rbbi = new IntlRuleBasedBreakIterator($rules);
$rbbi->setText('sdfkjsdf88á.... ,;');
do {
echo "pos : {$rbbi->current()}\n",
"rule status: {$rbbi->getRuleStatus()}\n";
} while ($rbbi->next() != IntlBreakIterator::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==

View File

@ -0,0 +1,28 @@
--TEST--
IntlRuleBasedBreakIterator::getRules(): basic test
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
ini_set("intl.default_locale", "pt_PT");
$rules = <<<RULES
\$LN = [[:letter:] [:number:]];
\$S = [.;,:];
!!forward;
\$LN+ {1};
\$S+ {42};
!!reverse;
\$LN+ {1};
\$S+ {42};
!!safe_forward;
!!safe_reverse;
RULES;
$rbbi = new IntlRuleBasedBreakIterator($rules);
var_dump($rbbi->getRules());
?>
==DONE==
--EXPECT--
string(128) "$LN = [[:letter:] [:number:]];$S = [.;,:];!!forward;$LN+ {1};$S+ {42};!!reverse;$LN+ {1};$S+ {42};!!safe_forward;!!safe_reverse;"
==DONE==

View File

@ -25,10 +25,10 @@
#include <unicode/ustring.h>
#include "intl_convertcpp.h"
extern "C" {
#include "../php_intl.h"
#define USE_TIMEZONE_POINTER 1
#include "timezone_class.h"
#include "intl_convert.h"
#include "../locale/locale.h"
#include <zend_exceptions.h>
#include <ext/date/php_date.h>
}

View File

@ -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

View File

@ -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 );

View File

@ -35,6 +35,7 @@ static PHP_MINFO_FUNCTION(json);
static PHP_FUNCTION(json_encode);
static PHP_FUNCTION(json_decode);
static PHP_FUNCTION(json_last_error);
static PHP_FUNCTION(json_last_error_msg);
static const char digits[] = "0123456789abcdef";
@ -57,6 +58,9 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_json_last_error_msg, 0)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ json_functions[] */
@ -64,6 +68,7 @@ static const zend_function_entry json_functions[] = {
PHP_FE(json_encode, arginfo_json_encode)
PHP_FE(json_decode, arginfo_json_decode)
PHP_FE(json_last_error, arginfo_json_last_error)
PHP_FE(json_last_error_msg, arginfo_json_last_error_msg)
PHP_FE_END
};
/* }}} */
@ -236,7 +241,6 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
if (myht && myht->nApplyCount > 1) {
JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
smart_str_appendl(buf, "null", 4);
return;
}
@ -378,7 +382,6 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
efree(tmp);
} else {
JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec", d);
smart_str_appendc(buf, '0');
}
}
@ -395,7 +398,6 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
}
if (ulen < 0) {
JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument");
smart_str_appendl(buf, "null", 4);
} else {
smart_str_appendl(buf, "\"\"", 2);
@ -527,7 +529,6 @@ static void json_encode_serializable_object(smart_str *buf, zval *val, int optio
if (myht && myht->nApplyCount > 1) {
JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
smart_str_appendl(buf, "null", 4);
return;
}
@ -592,7 +593,6 @@ PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_
efree(d);
} else {
JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec", dbl);
smart_str_appendc(buf, '0');
}
}
@ -614,7 +614,6 @@ PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_
default:
JSON_G(error_code) = PHP_JSON_ERROR_UNSUPPORTED_TYPE;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "type is unsupported");
smart_str_appendl(buf, "null", 4);
break;
}
@ -751,7 +750,7 @@ static PHP_FUNCTION(json_decode)
/* }}} */
/* {{{ proto int json_last_error()
Returns the error code of the last json_decode(). */
Returns the error code of the last json_encode() or json_decode() call. */
static PHP_FUNCTION(json_last_error)
{
if (zend_parse_parameters_none() == FAILURE) {
@ -762,6 +761,40 @@ static PHP_FUNCTION(json_last_error)
}
/* }}} */
/* {{{ proto string json_last_error_msg()
Returns the error string of the last json_encode() or json_decode() call. */
static PHP_FUNCTION(json_last_error_msg)
{
if (zend_parse_parameters_none() == FAILURE) {
return;
}
switch(JSON_G(error_code)) {
case PHP_JSON_ERROR_NONE:
RETURN_STRING("No error", 1);
case PHP_JSON_ERROR_DEPTH:
RETURN_STRING("Maximum stack depth exceeded", 1);
case PHP_JSON_ERROR_STATE_MISMATCH:
RETURN_STRING("State mismatch (invalid or malformed JSON)", 1);
case PHP_JSON_ERROR_CTRL_CHAR:
RETURN_STRING("Control character error, possibly incorrectly encoded", 1);
case PHP_JSON_ERROR_SYNTAX:
RETURN_STRING("Syntax error", 1);
case PHP_JSON_ERROR_UTF8:
RETURN_STRING("Malformed UTF-8 characters, possibly incorrectly encoded", 1);
case PHP_JSON_ERROR_RECURSION:
RETURN_STRING("Recursion detected", 1);
case PHP_JSON_ERROR_INF_OR_NAN:
RETURN_STRING("Inf and NaN cannot be JSON encoded", 1);
case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
RETURN_STRING("Type is not supported", 1);
default:
RETURN_STRING("Unknown error", 1);
}
}
/* }}} */
/*
* Local variables:
* tab-width: 4

View File

@ -10,11 +10,15 @@ $a[] = &$a;
var_dump($a);
echo "\n";
var_dump(json_encode($a));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
echo "\n";
var_dump(json_encode($a, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
echo "Done\n";
?>
@ -27,11 +31,11 @@ array(1) {
}
}
Warning: json_encode(): recursion detected in %s on line %d
bool(false)
int(6)
string(%d) "Recursion detected"
Warning: json_encode(): recursion detected in %s on line %d
string(8) "[[null]]"
int(6)
string(%d) "Recursion detected"
Done

View File

@ -10,11 +10,15 @@ $a->prop = $a;
var_dump($a);
echo "\n";
var_dump(json_encode($a));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
echo "\n";
var_dump(json_encode($a, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
echo "Done\n";
?>
@ -24,11 +28,11 @@ object(stdClass)#%d (1) {
*RECURSION*
}
Warning: json_encode(): recursion detected in %s on line %d
bool(false)
int(6)
string(%d) "Recursion detected"
Warning: json_encode(): recursion detected in %s on line %d
string(22) "{"prop":{"prop":null}}"
int(6)
string(%d) "Recursion detected"
Done

View File

@ -5,15 +5,15 @@ json_last_error() tests
--FILE--
<?php
var_dump(json_decode("[1]"));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_decode("[[1]]", false, 2));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_decode("[1}"));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_decode('["' . chr(0) . 'abcd"]'));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_decode("[1"));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
echo "Done\n";
@ -24,13 +24,17 @@ array(1) {
int(1)
}
int(0)
string(8) "No error"
NULL
int(1)
string(28) "Maximum stack depth exceeded"
NULL
int(2)
string(42) "State mismatch (invalid or malformed JSON)"
NULL
int(3)
string(53) "Control character error, possibly incorrectly encoded"
NULL
int(4)
string(12) "Syntax error"
Done

View File

@ -14,15 +14,7 @@ echo "Done\n";
?>
--EXPECTF--
string(5) ""abc""
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
bool(false)
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
string(4) "null"
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
string(17) "[null,null,"abc"]"
Done

View File

@ -12,9 +12,5 @@ var_dump(json_encode("ab\xE0", JSON_UNESCAPED_UNICODE));
--EXPECTF--
string(156) ""latin 1234 -\/ russian \u043c\u0430\u043c\u0430 \u043c\u044b\u043b\u0430 \u0440\u0430\u043c\u0443 specialchars \u0002 \b \n U+1D11E >\ud834\udd1e<""
string(100) ""latin 1234 -\/ russian мама мыла раму specialchars \u0002 \b \n U+1D11E >𝄞<""
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
bool(false)
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
bool(false)

View File

@ -8,36 +8,33 @@ Bug #54058 (json_last_error() invalid UTF-8 produces wrong error)
$bad_utf8 = quoted_printable_decode('=B0');
json_encode($bad_utf8);
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
$a = new stdclass;
$a->foo = quoted_printable_decode('=B0');
json_encode($a);
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
$b = new stdclass;
$b->foo = $bad_utf8;
$b->bar = 1;
json_encode($b);
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
$c = array(
'foo' => $bad_utf8,
'bar' => 1
);
json_encode($c);
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
?>
--EXPECTF--
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
int(5)
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
int(5)
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
int(5)
Warning: json_encode(): Invalid UTF-8 sequence in argument in %s on line %d
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

View File

@ -0,0 +1,39 @@
--TEST--
Bug #61537 (json_encode() incorrectly truncates/discards information)
--SKIPIF--
<?php if (!extension_loaded("json")) print "skip"; ?>
--FILE--
<?php
$invalid_utf8 = "\x9f";
var_dump(json_encode($invalid_utf8));
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_encode($invalid_utf8, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error(), json_last_error_msg());
echo "\n";
$invalid_utf8 = "an invalid sequen\xce in the middle of a string";
var_dump(json_encode($invalid_utf8));
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_encode($invalid_utf8, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error(), json_last_error_msg());
?>
--EXPECTF--
bool(false)
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
string(4) "null"
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
bool(false)
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
string(4) "null"
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

View File

@ -31,17 +31,13 @@ class JsonTest2 implements JsonSerializable {
$obj1 = new JsonTest1();
var_dump(json_encode($obj1, JSON_PARTIAL_OUTPUT_ON_ERROR));
echo "\n==\n";
echo "==\n";
$obj2 = new JsonTest2();
var_dump(json_encode($obj2, JSON_PARTIAL_OUTPUT_ON_ERROR));
?>
--EXPECTF--
Warning: json_encode(): recursion detected in %s on line %d
string(44) "{"test":"123","me":{"test":"123","me":null}}"
==
Warning: json_encode(): recursion detected in %s on line %d
string(44) "{"test":"123","me":{"test":"123","me":null}}"

View File

@ -1,5 +1,7 @@
--TEST--
An error is thrown when INF or NaN are encoded
--SKIPIF--
<?php if (!extension_loaded("json")) print "skip"; ?>
--FILE--
<?php
@ -8,37 +10,36 @@ $inf = INF;
var_dump($inf);
var_dump(json_encode($inf));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_encode($inf, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
echo "\n";
$nan = NAN;
var_dump($nan);
var_dump(json_encode($nan));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_encode($nan, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
?>
--EXPECTF--
float(INF)
Warning: json_encode(): double INF does not conform to the JSON spec in %s on line %d
bool(false)
int(7)
Warning: json_encode(): double INF does not conform to the JSON spec in %s on line %d
string(34) "Inf and NaN cannot be JSON encoded"
string(1) "0"
int(7)
string(34) "Inf and NaN cannot be JSON encoded"
float(NAN)
Warning: json_encode(): double NAN does not conform to the JSON spec in %s on line %d
bool(false)
int(7)
Warning: json_encode(): double NAN does not conform to the JSON spec in %s on line %d
string(34) "Inf and NaN cannot be JSON encoded"
string(1) "0"
int(7)
string(34) "Inf and NaN cannot be JSON encoded"

View File

@ -150,8 +150,6 @@ string(4) "null"
-- Iteration 25 --
string(4) "null"
-- Iteration 26 --
Warning: json_encode(): type is unsupported in %s on line %d
bool(false)
-- Iteration 27 --
string(82) "{"MyInt":99,"MyFloat":123.45,"MyBool":true,"MyNull":null,"MyString":"Hello World"}"

View File

@ -1,5 +1,7 @@
--TEST--
An error is thrown when an unsupported type is encoded
--SKIPIF--
<?php if (!extension_loaded("json")) print "skip"; ?>
--FILE--
<?php
@ -8,19 +10,17 @@ $resource = fopen(__FILE__, "r");
var_dump($resource);
var_dump(json_encode($resource));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
var_dump(json_encode($resource, JSON_PARTIAL_OUTPUT_ON_ERROR));
var_dump(json_last_error());
var_dump(json_last_error(), json_last_error_msg());
?>
--EXPECTF--
resource(5) of type (stream)
Warning: json_encode(): type is unsupported in %s on line %d
bool(false)
int(8)
Warning: json_encode(): type is unsupported in %s on line %d
string(21) "Type is not supported"
string(4) "null"
int(8)
string(21) "Type is not supported"

View File

@ -789,6 +789,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
conn->server_version = mnd_pestrdup(greet_packet->server_version, conn->persistent);
conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
if (!conn->greet_charset) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
"Server sent charset unknown to the client. Please, report to the developers");
goto err;
}
if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
greet_packet, conn->options, mysql_flags TSRMLS_CC))

View File

@ -262,8 +262,10 @@ PHPAPI void _mysqlnd_get_client_stats(zval *return_value TSRMLS_DC ZEND_FILE_L
ZEND_BEGIN_MODULE_GLOBALS(mysqlnd)
zend_bool collect_statistics;
zend_bool collect_memory_statistics;
char* debug; /* The actual string */
MYSQLND_DEBUG *dbg; /* The DBG object */
char * debug; /* The actual string */
char * trace_alloc_settings; /* The actual string */
MYSQLND_DEBUG * dbg; /* The DBG object for standard tracing */
MYSQLND_DEBUG * trace_alloc; /* The DBG object for allocation tracing */
long net_cmd_buffer_size;
long net_read_buffer_size;
long log_mask;

View File

@ -65,8 +65,8 @@ const char * mysqlnd_debug_std_no_trace_funcs[] =
#if ZEND_DEBUG
#else
#define __zend_filename "/unknown/unknown"
#define __zend_lineno 0
#define __zend_orig_filename "/unknown/unknown"
#define __zend_orig_lineno 0
#endif
#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
@ -81,15 +81,15 @@ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_emalloc_name);
TRACE_ALLOC_ENTER(mysqlnd_emalloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
#if PHP_DEBUG
/* -1 is also "true" */
if (*threshold) {
#endif
ret = emalloc(REAL_SIZE(size));
ret = _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#if PHP_DEBUG
--*threshold;
} else if (*threshold == 0) {
@ -97,13 +97,13 @@ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("size=%lu ptr=%p", size, ret);
TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
if (ret && collect_memory_statistics) {
*(size_t *) ret = size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -116,14 +116,15 @@ void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_pemalloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
TRACE_ALLOC_ENTER(mysqlnd_pemalloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d persistent=%u",
strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno,persistent);
#if PHP_DEBUG
/* -1 is also "true" */
if (*threshold) {
#endif
ret = pemalloc(REAL_SIZE(size), persistent);
ret = (persistent) ? __zend_malloc(REAL_SIZE(size)) : _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#if PHP_DEBUG
--*threshold;
} else if (*threshold == 0) {
@ -131,7 +132,7 @@ void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
TRACE_ALLOC_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
if (ret && collect_memory_statistics) {
enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
@ -140,7 +141,7 @@ void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -153,15 +154,15 @@ void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_ecalloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
TRACE_ALLOC_ENTER(mysqlnd_ecalloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
#if PHP_DEBUG
/* -1 is also "true" */
if (*threshold) {
#endif
ret = ecalloc(nmemb, REAL_SIZE(size));
ret = _ecalloc(nmemb, REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#if PHP_DEBUG
--*threshold;
} else if (*threshold == 0) {
@ -169,13 +170,13 @@ void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
DBG_INF_FMT("size=%lu ptr=%p", size, ret);
TRACE_ALLOC_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
if (ret && collect_memory_statistics) {
*(size_t *) ret = size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -188,14 +189,15 @@ void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent M
#if PHP_DEBUG
long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_pecalloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
TRACE_ALLOC_ENTER(mysqlnd_pecalloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d persistent=%u",
strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno, persistent);
#if PHP_DEBUG
/* -1 is also "true" */
if (*threshold) {
#endif
ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
ret = (persistent) ? __zend_calloc(nmemb, REAL_SIZE(size)) : _ecalloc(nmemb, REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#if PHP_DEBUG
--*threshold;
} else if (*threshold == 0) {
@ -203,7 +205,7 @@ void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent M
}
#endif
DBG_INF_FMT("size=%lu ptr=%p", size, ret);
TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
if (ret && collect_memory_statistics) {
enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
@ -212,7 +214,7 @@ void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent M
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -226,15 +228,15 @@ void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_erealloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
TRACE_ALLOC_ENTER(mysqlnd_erealloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
#if PHP_DEBUG
/* -1 is also "true" */
if (*threshold) {
#endif
ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
ret = _erealloc(REAL_PTR(ptr), REAL_SIZE(new_size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#if PHP_DEBUG
--*threshold;
} else if (*threshold == 0) {
@ -242,12 +244,12 @@ void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("new_ptr=%p", (char*)ret);
TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret);
if (ret && collect_memory_statistics) {
*(size_t *) ret = new_size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -261,9 +263,9 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL
#if PHP_DEBUG
long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_perealloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);
TRACE_ALLOC_ENTER(mysqlnd_perealloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);
#if PHP_DEBUG
/* -1 is also "true" */
@ -277,7 +279,7 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL
}
#endif
DBG_INF_FMT("new_ptr=%p", (char*)ret);
TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret);
if (ret && collect_memory_statistics) {
enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
@ -285,7 +287,7 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL
*(size_t *) ret = new_size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -295,22 +297,22 @@ void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
{
size_t free_amount = 0;
zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
DBG_ENTER(mysqlnd_efree_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p", ptr);
TRACE_ALLOC_ENTER(mysqlnd_efree_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
if (ptr) {
if (collect_memory_statistics) {
free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
}
efree(REAL_PTR(ptr));
_efree(REAL_PTR(ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
if (collect_memory_statistics) {
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
}
DBG_VOID_RETURN;
TRACE_ALLOC_VOID_RETURN;
}
/* }}} */
@ -320,24 +322,25 @@ void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
{
size_t free_amount = 0;
zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
DBG_ENTER(mysqlnd_pefree_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
TRACE_ALLOC_ENTER(mysqlnd_pefree_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
if (ptr) {
if (collect_memory_statistics) {
free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
}
pefree(REAL_PTR(ptr), persistent);
(persistent) ? free(REAL_PTR(ptr)) : _efree(REAL_PTR(ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
if (collect_memory_statistics) {
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
}
DBG_VOID_RETURN;
TRACE_ALLOC_VOID_RETURN;
}
/* }}} */
/* {{{ _mysqlnd_malloc */
@ -348,8 +351,8 @@ void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_malloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
TRACE_ALLOC_ENTER(mysqlnd_malloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
#if PHP_DEBUG
/* -1 is also "true" */
@ -363,12 +366,12 @@ void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("size=%lu ptr=%p", size, ret);
TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
if (ret && collect_memory_statistics) {
*(size_t *) ret = size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -381,8 +384,8 @@ void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_calloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
TRACE_ALLOC_ENTER(mysqlnd_calloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
#if PHP_DEBUG
/* -1 is also "true" */
@ -396,12 +399,12 @@ void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("size=%lu ptr=%p", size, ret);
TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
if (ret && collect_memory_statistics) {
*(size_t *) ret = size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -414,10 +417,10 @@ void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
#if PHP_DEBUG
long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
#endif
DBG_ENTER(mysqlnd_realloc_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
TRACE_ALLOC_ENTER(mysqlnd_realloc_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
#if PHP_DEBUG
/* -1 is also "true" */
@ -431,13 +434,13 @@ void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
}
#endif
DBG_INF_FMT("new_ptr=%p", (char*)ret);
TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret);
if (ret && collect_memory_statistics) {
*(size_t *) ret = new_size;
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -447,14 +450,14 @@ void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
{
size_t free_amount = 0;
zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
DBG_ENTER(mysqlnd_free_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p", ptr);
TRACE_ALLOC_ENTER(mysqlnd_free_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
if (ptr) {
if (collect_memory_statistics) {
free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
}
free(REAL_PTR(ptr));
}
@ -462,7 +465,7 @@ void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
if (collect_memory_statistics) {
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
}
DBG_VOID_RETURN;
TRACE_ALLOC_VOID_RETURN;
}
/* }}} */
@ -476,11 +479,11 @@ char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persi
{
char * ret;
zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
DBG_ENTER(mysqlnd_pestrndup_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p", ptr);
TRACE_ALLOC_ENTER(mysqlnd_pestrndup_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
ret = pemalloc(REAL_SIZE(length) + 1, persistent);
ret = (persistent) ? __zend_malloc(REAL_SIZE(length + 1)) : _emalloc(REAL_SIZE(length + 1) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
{
size_t l = length;
char * p = (char *) ptr;
@ -496,7 +499,7 @@ char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persi
MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
}
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -508,14 +511,14 @@ char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_ME
smart_str tmp_str = {0, 0, 0};
const char * p = ptr;
zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
DBG_ENTER(mysqlnd_pestrdup_name);
DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
DBG_INF_FMT("ptr=%p", ptr);
TRACE_ALLOC_ENTER(mysqlnd_pestrdup_name);
TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR) + 1, __zend_orig_lineno);
TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
do {
smart_str_appendc(&tmp_str, *p);
} while (*p++);
ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
ret = (persistent) ? __zend_malloc(tmp_str.len + sizeof(size_t)) : _emalloc(REAL_SIZE(tmp_str.len + sizeof(size_t)) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
if (ret && collect_memory_statistics) {
@ -524,7 +527,7 @@ char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_ME
}
smart_str_free(&tmp_str);
DBG_RETURN(FAKE_PTR(ret));
TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */
@ -549,7 +552,7 @@ PHPAPI void _mysqlnd_sprintf_free(char * p)
}
/* }}} */
/* {{{ _mysqlnd_vsprintf */
PHPAPI int _mysqlnd_vsprintf(char ** pbuf, size_t max_len, const char * format, va_list ap)
{
return vspprintf(pbuf, max_len, format, ap);

View File

@ -26,8 +26,8 @@
extern const char * mysqlnd_debug_std_no_trace_funcs[];
#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_ORIG_DC
#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC
struct st_mysqlnd_allocator_methods
{

View File

@ -450,20 +450,27 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 6, "hp8", "hp8_english_ci", 1, 1, "", NULL, NULL},
{ 7, "koi8r", "koi8r_general_ci", 1, 1, "", NULL, NULL},
{ 8, "latin1", "latin1_swedish_ci", 1, 1, "", NULL, NULL},
{ 5, "latin1", "latin1_german_ci", 1, 1, "", NULL, NULL}, /* should be after 0x9 because swedish_ci is the default collation */
{ 9, "latin2", "latin2_general_ci", 1, 1, "", NULL, NULL},
{ 2, "latin2", "latin2_czech_cs", 1, 1, "", NULL, NULL}, /* should be after 0x9 because general_ci is the default collation */
{ 10, "swe7", "swe7_swedish_ci", 1, 1, "", NULL, NULL},
{ 11, "ascii", "ascii_general_ci", 1, 1, "", NULL, NULL},
{ 12, "ujis", "ujis_japanese_ci", 1, 3, "", mysqlnd_mbcharlen_ujis, check_mb_ujis},
{ 13, "sjis", "sjis_japanese_ci", 1, 2, "", mysqlnd_mbcharlen_sjis, check_mb_sjis},
{ 16, "hebrew", "hebrew_general_ci", 1, 1, "", NULL, NULL},
{ 17, "filename", "filename", 1, 5, "", NULL, NULL},
{ 18, "tis620", "tis620_thai_ci", 1, 1, "", NULL, NULL},
{ 19, "euckr", "euckr_korean_ci", 1, 2, "", mysqlnd_mbcharlen_euckr, check_mb_euckr},
{ 21, "latin2", "latin2_hungarian_ci", 1, 1, "", NULL, NULL},
{ 27, "latin2", "latin2_croatian_ci", 1, 1, "", NULL, NULL},
{ 22, "koi8u", "koi8u_general_ci", 1, 1, "", NULL, NULL},
{ 24, "gb2312", "gb2312_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_gb2312, check_mb_gb2312},
{ 25, "greek", "greek_general_ci", 1, 1, "", NULL, NULL},
{ 26, "cp1250", "cp1250_general_ci", 1, 1, "", NULL, NULL},
{ 28, "gbk", "gbk_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_gbk, check_mb_gbk},
{ 30, "latin5", "latin5_turkish_ci", 1, 1, "", NULL, NULL},
{ 31, "latin1", "latin1_german2_ci", 1, 1, "", NULL, NULL},
{ 15, "latin1", "latin1_danish_ci", 1, 1, "", NULL, NULL},
{ 32, "armscii8", "armscii8_general_ci", 1, 1, "", NULL, NULL},
{ 33, UTF8_MB3, UTF8_MB3"_general_ci", 1, 3, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 35, "ucs2", "ucs2_general_ci", 2, 2, "UCS-2 Unicode", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
@ -473,22 +480,11 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 39, "macroman", "macroman_general_ci", 1, 1, "", NULL, NULL},
{ 40, "cp852", "cp852_general_ci", 1, 1, "", NULL, NULL},
{ 41, "latin7", "latin7_general_ci", 1, 1, "", NULL, NULL},
{ 51, "cp1251", "cp1251_general_ci", 1, 1, "", NULL, NULL},
{ 20, "latin7", "latin7_estonian_cs", 1, 1, "", NULL, NULL},
{ 57, "cp1256", "cp1256_general_ci", 1, 1, "", NULL, NULL},
{ 59, "cp1257", "cp1257_general_ci", 1, 1, "", NULL, NULL},
{ 63, "binary", "binary", 1, 1, "", NULL, NULL},
{ 92, "geostd8", "geostd8_general_ci", 1, 1, "", NULL, NULL},
{ 95, "cp932", "cp932_japanese_ci", 1, 2, "", mysqlnd_mbcharlen_cp932, check_mb_cp932},
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, "", mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
{ 2, "latin2", "latin2_czech_cs", 1, 1, "", NULL, NULL},
{ 5, "latin1", "latin1_german_ci", 1, 1, "", NULL, NULL},
{ 14, "cp1251", "cp1251_bulgarian_ci", 1, 1, "", NULL, NULL},
{ 15, "latin1", "latin1_danish_ci", 1, 1, "", NULL, NULL},
{ 17, "filename", "filename", 1, 5, "", NULL, NULL},
{ 20, "latin7", "latin7_estonian_cs", 1, 1, "", NULL, NULL},
{ 21, "latin2", "latin2_hungarian_ci", 1, 1, "", NULL, NULL},
{ 23, "cp1251", "cp1251_ukrainian_ci", 1, 1, "", NULL, NULL},
{ 27, "latin2", "latin2_croatian_ci", 1, 1, "", NULL, NULL},
{ 29, "cp1257", "cp1257_lithunian_ci", 1, 1, "", NULL, NULL},
{ 31, "latin1", "latin1_german2_ci", 1, 1, "", NULL, NULL},
{ 34, "cp1250", "cp1250_czech_cs", 1, 1, "", NULL, NULL},
@ -500,6 +496,9 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 47, "latin1", "latin1_bin", 1, 1, "", NULL, NULL},
{ 48, "latin1", "latin1_general_ci", 1, 1, "", NULL, NULL},
{ 49, "latin1", "latin1_general_cs", 1, 1, "", NULL, NULL},
{ 51, "cp1251", "cp1251_general_ci", 1, 1, "", NULL, NULL},
{ 14, "cp1251", "cp1251_bulgarian_ci", 1, 1, "", NULL, NULL},
{ 23, "cp1251", "cp1251_ukrainian_ci", 1, 1, "", NULL, NULL},
{ 50, "cp1251", "cp1251_bin", 1, 1, "", NULL, NULL},
{ 52, "cp1251", "cp1251_general_cs", 1, 1, "", NULL, NULL},
{ 53, "macroman", "macroman_bin", 1, 1, "", NULL, NULL},
@ -509,8 +508,8 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
#ifdef USED_TO_BE_SO_BEFORE_MYSQL_5_5
{ 60, "armascii8", "armascii8_bin", 1, 1, "", NULL, NULL},
#endif
{ 60, "utf32", "utf32_general_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
{ 61, "utf32", "utf32_bin", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*55*/{ 60, "utf32", "utf32_general_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*55*/{ 61, "utf32", "utf32_bin", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
{ 65, "ascii", "ascii_bin", 1, 1, "", NULL, NULL},
{ 66, "cp1250", "cp1250_bin", 1, 1, "", NULL, NULL},
{ 67, "cp1256", "cp1256_bin", 1, 1, "", NULL, NULL},
@ -528,7 +527,6 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 80, "cp850", "cp850_bin", 1, 1, "", NULL, NULL},
{ 81, "cp852", "cp852_bin", 1, 1, "", NULL, NULL},
{ 82, "swe7", "swe7_bin", 1, 1, "", NULL, NULL},
{ 93, "geostd8", "geostd8_bin", 1, 1, "", NULL, NULL},
{ 83, UTF8_MB3, UTF8_MB3"_bin", 1, 3, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 84, "big5", "big5_bin", 1, 2, "", mysqlnd_mbcharlen_big5, check_mb_big5},
{ 85, "euckr", "euckr_bin", 1, 2, "", mysqlnd_mbcharlen_euckr, check_mb_euckr},
@ -538,10 +536,14 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 89, "tis620", "tis620_bin", 1, 1, "", NULL, NULL},
{ 90, "ucs2", "ucs2_bin", 2, 2, "UCS-2 Unicode", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 91, "ujis", "ujis_bin", 1, 3, "", mysqlnd_mbcharlen_ujis, check_mb_ujis},
{ 92, "geostd8", "geostd8_general_ci", 1, 1, "", NULL, NULL},
{ 93, "geostd8", "geostd8_bin", 1, 1, "", NULL, NULL},
{ 94, "latin1", "latin1_spanish_ci", 1, 1, "", NULL, NULL},
{ 95, "cp932", "cp932_japanese_ci", 1, 2, "", mysqlnd_mbcharlen_cp932, check_mb_cp932},
{ 96, "cp932", "cp932_bin", 1, 2, "", mysqlnd_mbcharlen_cp932, check_mb_cp932},
{ 99, "cp1250", "cp1250_polish_ci", 1, 1, "", NULL, NULL},
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, "", mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
{ 98, "eucjpms", "eucjpms_bin", 1, 3, "", mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
{ 99, "cp1250", "cp1250_polish_ci", 1, 1, "", NULL, NULL},
{ 128, "ucs2", "ucs2_unicode_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 129, "ucs2", "ucs2_icelandic_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 130, "ucs2", "ucs2_latvian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
@ -562,7 +564,35 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 145, "ucs2", "ucs2_esperanto_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 146, "ucs2", "ucs2_hungarian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 147, "ucs2", "ucs2_sinhala_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 149, "ucs2", "ucs2_croatian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2}, /* MDB */
{ 148, "ucs2", "ucs2_german2_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 149, "ucs2", "ucs2_croatian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 150, "ucs2", "ucs2_unicode_520_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 151, "ucs2", "ucs2_vietnamese_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
/*56*/{160, "utf32", "utf32_unicode_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{161, "utf32", "utf32_icelandic_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{162, "utf32", "utf32_latvian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{163, "utf32", "utf32_romanian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{164, "utf32", "utf32_slovenian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{165, "utf32", "utf32_polish_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{166, "utf32", "utf32_estonian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{167, "utf32", "utf32_spanish_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{168, "utf32", "utf32_swedish_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{169, "utf32", "utf32_turkish_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{170, "utf32", "utf32_czech_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{171, "utf32", "utf32_danish_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{172, "utf32", "utf32_lithuanian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{173, "utf32", "utf32_slovak_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{174, "utf32", "utf32_spanish2_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{175, "utf32", "utf32_roman_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{176, "utf32", "utf32_persian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{177, "utf32", "utf32_esperanto_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{178, "utf32", "utf32_hungarian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{179, "utf32", "utf32_sinhala_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{180, "utf32", "utf32_german2_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{181, "utf32", "utf32_croatian_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{182, "utf32", "utf32_unicode_520_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{183, "utf32", "utf32_vietnamese_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
{ 192, UTF8_MB3, UTF8_MB3"_general_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 193, UTF8_MB3, UTF8_MB3"_icelandic_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
@ -571,7 +601,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 196, UTF8_MB3, UTF8_MB3"_slovenian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 197, UTF8_MB3, UTF8_MB3"_polish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 198, UTF8_MB3, UTF8_MB3"_estonian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 119, UTF8_MB3, UTF8_MB3"_spanish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 199, UTF8_MB3, UTF8_MB3"_spanish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 200, UTF8_MB3, UTF8_MB3"_swedish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 201, UTF8_MB3, UTF8_MB3"_turkish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 202, UTF8_MB3, UTF8_MB3"_czech_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
@ -584,7 +614,10 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 209, UTF8_MB3, UTF8_MB3"_esperanto_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 210, UTF8_MB3, UTF8_MB3"_hungarian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 211, UTF8_MB3, UTF8_MB3"_sinhala_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 213, UTF8_MB3, UTF8_MB3"_croatian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
{ 211, UTF8_MB3, UTF8_MB3"_german2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 213, UTF8_MB3, UTF8_MB3"_croatian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 214, UTF8_MB3, UTF8_MB3"_unicode_520_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 215, UTF8_MB3, UTF8_MB3"_vietnamese_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 224, UTF8_MB4, UTF8_MB4"_unicode_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 225, UTF8_MB4, UTF8_MB4"_icelandic_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
@ -606,6 +639,10 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 241, UTF8_MB4, UTF8_MB4"_esperanto_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 242, UTF8_MB4, UTF8_MB4"_hungarian_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 243, UTF8_MB4, UTF8_MB4"_sinhala_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 244, UTF8_MB4, UTF8_MB4"_german2_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 245, UTF8_MB4, UTF8_MB4"_croatian_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 246, UTF8_MB4, UTF8_MB4"_unicode_520_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 247, UTF8_MB4, UTF8_MB4"_vietnamese_ci", 1, 4, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 254, UTF8_MB3, UTF8_MB3"_general_cs", 1, 3, "", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 0, NULL, NULL, 0, 0, NULL, NULL, NULL}

View File

@ -745,21 +745,26 @@ mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
{
#if PHP_DEBUG
MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);
MYSQLND_DEBUG * dbg = MYSQLND_G(dbg);
if (!dbg) {
MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
if (!dbg) {
return;
struct st_mysqlnd_plugin_trace_log * trace_log_plugin = mysqlnd_plugin_find("debug_trace");
if (trace_log_plugin) {
dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
if (!dbg) {
return;
}
MYSQLND_G(dbg) = dbg;
}
}
dbg->m->close(dbg);
dbg->m->set_mode(dbg, mode);
while (zend_stack_count(&dbg->call_stack)) {
zend_stack_del_top(&dbg->call_stack);
}
while (zend_stack_count(&dbg->call_time_stack)) {
zend_stack_del_top(&dbg->call_time_stack);
if (dbg) {
dbg->m->close(dbg);
dbg->m->set_mode(dbg, mode);
while (zend_stack_count(&dbg->call_stack)) {
zend_stack_del_top(&dbg->call_stack);
}
while (zend_stack_count(&dbg->call_time_stack)) {
zend_stack_del_top(&dbg->call_time_stack);
}
}
#endif
}

View File

@ -101,44 +101,63 @@ PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
#define DBG_INF_FMT_EX(dbg_obj, ...) do { if (dbg_skip_trace == FALSE) (dbg_obj)->m->log_va((dbg_obj), __LINE__, __FILE__, -1, "info : ", __VA_ARGS__); } while (0)
#define DBG_ERR_FMT_EX(dbg_obj, ...) do { if (dbg_skip_trace == FALSE) (dbg_obj)->m->log_va((dbg_obj), __LINE__, __FILE__, -1, "error: ", __VA_ARGS__); } while (0)
#define DBG_BLOCK_ENTER_EX(dbg_obj, block_name) \
{ \
DBG_ENTER_EX(dbg_obj, (block_name));
#define DBG_BLOCK_ENTER_EX(dbg_obj, block_name) DBG_BLOCK_ENTER_EX2((dbg_obj), NULL, (block_name))
#define DBG_BLOCK_LEAVE_EX(dbg_obj) DBG_BLOCK_LEAVE_EX2((dbg_obj))
#define DBG_BLOCK_LEAVE_EX(dbg_obj) \
DBG_LEAVE_EX((dbg_obj), ;) \
#define DBG_BLOCK_ENTER_EX2(dbg_obj1, dbg_obj2, block_name) \
{ \
DBG_ENTER_EX2((dbg_obj1), (db_obj2), (block_name));
#define DBG_BLOCK_LEAVE_EX2(dbg_obj1, dbg_obj2) \
DBG_LEAVE_EX2((dbg_obj1), (dbg_obj2), ;) \
} \
#define DBG_ENTER_EX(dbg_obj, func_name) \
#define DBG_ENTER_EX(dbg_obj, func_name) DBG_ENTER_EX2((dbg_obj), (MYSQLND_DEBUG *) NULL, (func_name))
#define DBG_LEAVE_EX(dbg_obj, leave) DBG_LEAVE_EX2((dbg_obj), (MYSQLND_DEBUG *) NULL, leave)
#define DBG_ENTER_EX2(dbg_obj1, dbg_obj2, func_name) \
struct timeval __dbg_prof_tp = {0}; \
uint64_t __dbg_prof_start = 0; /* initialization is needed */ \
zend_bool dbg_skip_trace = TRUE; \
if ((dbg_obj)) { \
dbg_skip_trace = !(dbg_obj)->m->func_enter((dbg_obj), __LINE__, __FILE__, func_name, strlen(func_name)); \
if ((dbg_obj1)) { \
dbg_skip_trace = !(dbg_obj1)->m->func_enter((dbg_obj1), __LINE__, __FILE__, func_name, strlen(func_name)); \
} \
if (dbg_skip_trace); /* shut compiler's mouth */ \
if ((dbg_obj2)) { \
dbg_skip_trace = !(dbg_obj2)->m->func_enter((dbg_obj2), __LINE__, __FILE__, func_name, strlen(func_name)); \
} \
if (dbg_skip_trace); /* shut compiler's mouth */\
do { \
if ((dbg_obj) && (dbg_obj)->flags & MYSQLND_DEBUG_PROFILE_CALLS) { \
if (((dbg_obj1) && (dbg_obj1)->flags & MYSQLND_DEBUG_PROFILE_CALLS) || \
((dbg_obj2) && (dbg_obj2)->flags & MYSQLND_DEBUG_PROFILE_CALLS)) \
{ \
DBG_PROFILE_START_TIME(); \
} \
} while (0);
#define DBG_LEAVE_EX(dbg_obj, leave) \
#define DBG_LEAVE_EX2(dbg_obj1, dbg_obj2, leave) \
do {\
if ((dbg_obj)) { \
uint64_t this_call_duration = 0; \
if ((dbg_obj)->flags & MYSQLND_DEBUG_PROFILE_CALLS) { \
DBG_PROFILE_END_TIME(this_call_duration); \
} \
(dbg_obj)->m->func_leave((dbg_obj), __LINE__, __FILE__, this_call_duration); \
uint64_t this_call_duration = 0; \
if (((dbg_obj1) && (dbg_obj1)->flags & MYSQLND_DEBUG_PROFILE_CALLS) || \
((dbg_obj2) && (dbg_obj2)->flags & MYSQLND_DEBUG_PROFILE_CALLS)) \
{ \
DBG_PROFILE_END_TIME(this_call_duration); \
} \
if ((dbg_obj1)) { \
(dbg_obj1)->m->func_leave((dbg_obj1), __LINE__, __FILE__, this_call_duration); \
} \
if ((dbg_obj2)) { \
(dbg_obj2)->m->func_leave((dbg_obj2), __LINE__, __FILE__, this_call_duration); \
} \
leave \
} while (0);
#define DBG_RETURN_EX(dbg_obj, value) DBG_LEAVE_EX(dbg_obj, return (value);)
#define DBG_VOID_RETURN_EX(dbg_obj) DBG_LEAVE_EX(dbg_obj, return;)
#define DBG_RETURN_EX(dbg_obj, value) DBG_LEAVE_EX((dbg_obj), return (value);)
#define DBG_VOID_RETURN_EX(dbg_obj) DBG_LEAVE_EX((dbg_obj), return;)
#define DBG_RETURN_EX2(dbg_obj1, dbg_obj2, value) DBG_LEAVE_EX2((dbg_obj1), (dbg_obj2), return (value);)
#define DBG_VOID_RETURN_EX2(dbg_obj1, dbg_obj2) DBG_LEAVE_EX2((dbg_obj1), (dbg_obj2), return;)
@ -168,6 +187,18 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func
#define DBG_VOID_RETURN DBG_VOID_RETURN_EX(MYSQLND_G(dbg))
#define DBG_BLOCK_LEAVE DBG_BLOCK_LEAVE_EX(MYSQLND_G(dbg))
#define TRACE_ALLOC_INF(msg) DBG_INF_EX(MYSQLND_G(trace_alloc), (msg))
#define TRACE_ALLOC_ERR(msg) DBG_ERR_EX(MYSQLND_G(trace_alloc), (msg))
#define TRACE_ALLOC_INF_FMT(...) DBG_INF_FMT_EX(MYSQLND_G(trace_alloc), __VA_ARGS__)
#define TRACE_ALLOC_ERR_FMT(...) DBG_ERR_FMT_EX(MYSQLND_G(trace_alloc), __VA_ARGS__)
#define TRACE_ALLOC_ENTER(func_name) DBG_ENTER_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc), (func_name))
#define TRACE_ALLOC_BLOCK_ENTER(bname) DBG_BLOCK_ENTER_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc), (bname))
#define TRACE_ALLOC_RETURN(value) DBG_RETURN_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc), (value))
#define TRACE_ALLOC_VOID_RETURN DBG_VOID_RETURN_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc))
#define TRACE_ALLOC_BLOCK_LEAVE DBG_BLOCK_LEAVE_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc))
#elif MYSQLND_DBG_ENABLED == 0
static inline void DBG_INF(const char * const msg) {}
@ -176,10 +207,21 @@ static inline void DBG_INF_FMT(const char * const format, ...) {}
static inline void DBG_ERR_FMT(const char * const format, ...) {}
static inline void DBG_ENTER(const char * const func_name) {}
#define DBG_BLOCK_ENTER(bname) {
#define DBG_RETURN(value) return (value)
#define DBG_VOID_RETURN return
#define DBG_RETURN(value) return (value)
#define DBG_VOID_RETURN return
#define DBG_BLOCK_LEAVE }
static inline void TRACE_ALLOC_INF(const char * const msg) {}
static inline void TRACE_ALLOC_ERR(const char * const msg) {}
static inline void TRACE_ALLOC_INF_FMT(const char * const format, ...) {}
static inline void TRACE_ALLOC_ERR_FMT(const char * const format, ...) {}
static inline void TRACE_ALLOC_ENTER(const char * const func_name) {}
#define TRACE_ALLOC_BLOCK_ENTER(bname) {
#define TRACE_ALLOC_RETURN(value) return (value)
#define TRACE_ALLOC_VOID_RETURN return
#define TRACE_ALLOC_BLOCK_LEAVE }
#endif
#endif /* MYSQLND_DEBUG_H */

View File

@ -221,6 +221,8 @@ static PHP_GINIT_FUNCTION(mysqlnd)
mysqlnd_globals->collect_memory_statistics = FALSE;
mysqlnd_globals->debug = NULL; /* The actual string */
mysqlnd_globals->dbg = NULL; /* The DBG object*/
mysqlnd_globals->trace_alloc_settings = NULL;
mysqlnd_globals->trace_alloc = NULL;
mysqlnd_globals->net_cmd_buffer_size = MYSQLND_NET_CMD_BUFFER_MIN_SIZE;
mysqlnd_globals->net_read_buffer_size = 32768;
mysqlnd_globals->net_read_timeout = 31536000;
@ -253,6 +255,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("mysqlnd.collect_statistics", "1", PHP_INI_ALL, OnUpdateBool, collect_statistics, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_BOOLEAN("mysqlnd.collect_memory_statistics", "0", PHP_INI_SYSTEM, OnUpdateBool, collect_memory_statistics, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug", NULL, PHP_INI_SYSTEM, OnUpdateString, debug, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.trace_alloc", NULL, PHP_INI_SYSTEM, OnUpdateString, trace_alloc_settings, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.net_cmd_buffer_size", MYSQLND_NET_CMD_BUFFER_MIN_SIZE_STR, PHP_INI_ALL, OnUpdateNetCmdBufferSize, net_cmd_buffer_size, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.net_read_buffer_size", "32768",PHP_INI_ALL, OnUpdateLong, net_read_buffer_size, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.net_read_timeout", "31536000", PHP_INI_SYSTEM, OnUpdateLong, net_read_timeout, zend_mysqlnd_globals, mysqlnd_globals)
@ -306,11 +309,14 @@ static PHP_RINIT_FUNCTION(mysqlnd)
MYSQLND_G(dbg) = NULL;
if (trace_log_plugin) {
MYSQLND_DEBUG * dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
if (!dbg) {
MYSQLND_DEBUG * trace_alloc = trace_log_plugin->methods.trace_instance_init(NULL TSRMLS_CC);
if (!dbg || !trace_alloc) {
return FAILURE;
}
dbg->m->set_mode(dbg, MYSQLND_G(debug));
trace_alloc->m->set_mode(trace_alloc, MYSQLND_G(trace_alloc_settings));
MYSQLND_G(dbg) = dbg;
MYSQLND_G(trace_alloc) = trace_alloc;
}
}
return SUCCESS;
@ -324,13 +330,19 @@ static PHP_RINIT_FUNCTION(mysqlnd)
*/
static PHP_RSHUTDOWN_FUNCTION(mysqlnd)
{
MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);
MYSQLND_DEBUG * dbg = MYSQLND_G(dbg);
MYSQLND_DEBUG * trace_alloc = MYSQLND_G(trace_alloc);
DBG_ENTER("RSHUTDOWN");
if (dbg) {
dbg->m->close(dbg);
dbg->m->free_handle(dbg);
MYSQLND_G(dbg) = NULL;
}
if (trace_alloc) {
trace_alloc->m->close(trace_alloc);
trace_alloc->m->free_handle(trace_alloc);
MYSQLND_G(trace_alloc) = NULL;
}
return SUCCESS;
}
/* }}} */

View File

@ -59,14 +59,14 @@ PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, in
unsigned char *p;
unsigned char *result;
if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {
if (length < 0) {
if (ret_length != NULL) {
*ret_length = 0;
}
return NULL;
}
result = (unsigned char *)safe_emalloc(((length + 2) / 3) * 4, sizeof(char), 1);
result = (unsigned char *) safe_emalloc((length + 2) / 3, 4 * sizeof(char), 1);
p = result;
while (length > 2) { /* keep going until we have less than 24 bits */

View File

@ -171,7 +171,7 @@ PHPAPI int crypt_execute(const char *password, const int pass_len, const char *s
char *output;
int needed = (sizeof(sha512_salt_prefix) - 1
+ sizeof(sha512_rounds_prefix) + 9 + 1
+ PHP_MAX_SALT_LEN + 43 + 1);
+ salt_in_len + 1 + 86 + 1);
output = emalloc(needed);
crypt_res = php_sha512_crypt_r(password, salt, output, needed);
@ -189,7 +189,7 @@ PHPAPI int crypt_execute(const char *password, const int pass_len, const char *s
char *output;
int needed = (sizeof(sha256_salt_prefix) - 1
+ sizeof(sha256_rounds_prefix) + 9 + 1
+ PHP_MAX_SALT_LEN + 43 + 1);
+ salt_in_len + 1 + 43 + 1);
output = emalloc(needed);
crypt_res = php_sha256_crypt_r(password, salt, output, needed);

View File

@ -0,0 +1,25 @@
--TEST--
Bug #62373 (serialize() generates wrong reference to the object)
--FILE--
<?php
class A {}
class B {}
$size_of_ce = (((int)(log(PHP_INT_MAX) / log(2)) + 1 == 32 ? 368: 680) + 15) & ~15;
$dummy = array();
$b = new B();
$period = $size_of_ce << 5;
for ($i = 0; $i < $period * 3; $i++) {
$a = new A();
$s = unserialize(serialize(array($b, $a)));
if ($s[0] === $s[1]) {
echo "OOPS\n";
break;
}
$dummy[] = $a;
}
echo "OK\n";
?>
--EXPECT--
OK

View File

@ -0,0 +1,9 @@
--TEST--
Bug #62443 Crypt SHA256/512 Segfaults With Malformed Salt
--FILE--
<?php
crypt("foo", '$5$'.chr(0).'abc');
crypt("foo", '$6$'.chr(0).'abc');
echo "OK!";
--EXPECT--
OK!

View File

@ -541,12 +541,9 @@ static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old
/* relies on "(long)" being a perfect hash function for data pointers,
* however the actual identity of an object has had to be determined
* by its object handle and the class entry since 5.0. */
* by its object handle since 5.0. */
if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) {
p = smart_str_print_long(id + sizeof(id) - 1,
(((size_t)Z_OBJCE_P(var) << 5)
| ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5)))
+ (long) Z_OBJ_HANDLE_P(var));
p = smart_str_print_long(id + sizeof(id) - 1, (long) Z_OBJ_HANDLE_P(var));
*(--p) = 'O';
len = id + sizeof(id) - 1 - p;
} else {

View File

@ -1173,6 +1173,9 @@ out:
if (request_started) {
php_request_shutdown((void *) 0);
}
if (translated_path) {
free(translated_path);
}
return exit_status;
err:
sapi_deactivate(TSRMLS_C);