mirror of
https://github.com/php/php-src.git
synced 2024-11-29 04:46:07 +08:00
Added IntlCodePointBreakIterator.
Objects of this class can be instantiated with IntlBreakIterator::createCodePointInstance() The method does not take a locale, as it would not make sense in this context. This class has one additional method: long IntlCodePointIterator::getLastCodePoint() which returns either -1 or the last code point we moved over, if any (and discounting any movement before the last call to IntlBreakIterator::first() or IntlBreakIterator::last()).
This commit is contained in:
parent
cee31091a9
commit
0a7ae87e91
@ -20,6 +20,7 @@
|
||||
|
||||
#include <unicode/brkiter.h>
|
||||
#include <unicode/rbbi.h>
|
||||
#include "codepointiterator_internal.h"
|
||||
|
||||
#include "breakiterator_iterators.h"
|
||||
|
||||
@ -30,14 +31,18 @@ extern "C" {
|
||||
#include "breakiterator_class.h"
|
||||
#include "breakiterator_methods.h"
|
||||
#include "rulebasedbreakiterator_methods.h"
|
||||
#include "codepointiterator_methods.h"
|
||||
#include <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;
|
||||
/* }}} */
|
||||
|
||||
@ -49,6 +54,8 @@ U_CFUNC void breakiterator_object_create(zval *object,
|
||||
|
||||
if (classId == RuleBasedBreakIterator::getStaticClassID()) {
|
||||
ce = RuleBasedBreakIterator_ce_ptr;
|
||||
} else if (classId == CodePointBreakIterator::getStaticClassID()) {
|
||||
ce = CodePointBreakIterator_ce_ptr;
|
||||
} else {
|
||||
ce = BreakIterator_ce_ptr;
|
||||
}
|
||||
@ -274,6 +281,7 @@ static const zend_function_entry BreakIterator_class_functions[] = {
|
||||
PHP_ME_MAPPING(createCharacterInstance, breakiter_create_character_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(createSentenceInstance, breakiter_create_sentence_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(createTitleInstance, breakiter_create_title_instance, ainfo_biter_locale, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(createCodePointInstance, breakiter_create_code_point_instance, ainfo_biter_void, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(getText, breakiter_get_text, ainfo_biter_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(setText, breakiter_set_text, ainfo_biter_setText, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(first, breakiter_first, ainfo_biter_void, ZEND_ACC_PUBLIC)
|
||||
@ -305,6 +313,14 @@ static const zend_function_entry RuleBasedBreakIterator_class_functions[] = {
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ CodePointBreakIterator_class_functions
|
||||
*/
|
||||
static const zend_function_entry CodePointBreakIterator_class_functions[] = {
|
||||
PHP_ME_MAPPING(getLastCodePoint, cpbi_get_last_code_point, ainfo_biter_void, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ breakiterator_register_BreakIterator_class
|
||||
* Initialize 'BreakIterator' class
|
||||
@ -364,6 +380,12 @@ void breakiterator_register_BreakIterator_class(TSRMLS_D)
|
||||
INIT_CLASS_ENTRY(ce, "IntlRuleBasedBreakIterator",
|
||||
RuleBasedBreakIterator_class_functions);
|
||||
RuleBasedBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce,
|
||||
BreakIterator_ce_ptr, NULL TSRMLS_CC);
|
||||
BreakIterator_ce_ptr, NULL TSRMLS_CC);
|
||||
|
||||
/* Create and register 'CodePointBreakIterator' class. */
|
||||
INIT_CLASS_ENTRY(ce, "IntlCodePointBreakIterator",
|
||||
CodePointBreakIterator_class_functions);
|
||||
CodePointBreakIterator_ce_ptr = zend_register_internal_class_ex(&ce,
|
||||
BreakIterator_ce_ptr, NULL TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#endif
|
||||
|
||||
#include <unicode/brkiter.h>
|
||||
#include "codepointiterator_internal.h"
|
||||
|
||||
#include "breakiterator_iterators.h"
|
||||
|
||||
@ -29,6 +30,8 @@ extern "C" {
|
||||
#include <zend_exceptions.h>
|
||||
}
|
||||
|
||||
using PHP::CodePointBreakIterator;
|
||||
|
||||
U_CFUNC PHP_METHOD(BreakIterator, __construct)
|
||||
{
|
||||
zend_throw_exception( NULL,
|
||||
@ -107,6 +110,21 @@ U_CFUNC PHP_FUNCTION(breakiter_create_title_instance)
|
||||
INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
}
|
||||
|
||||
U_CFUNC PHP_FUNCTION(breakiter_create_code_point_instance)
|
||||
{
|
||||
UErrorCode status = UErrorCode();
|
||||
intl_error_reset(NULL TSRMLS_CC);
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
"breakiter_create_code_point_instance: bad arguments", 0 TSRMLS_CC);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
CodePointBreakIterator *cpbi = new CodePointBreakIterator();
|
||||
breakiterator_object_create(return_value, cpbi TSRMLS_CC);
|
||||
}
|
||||
|
||||
U_CFUNC PHP_FUNCTION(breakiter_get_text)
|
||||
{
|
||||
BREAKITER_METHOD_INIT_VARS;
|
||||
|
@ -31,6 +31,8 @@ PHP_FUNCTION(breakiter_create_sentence_instance);
|
||||
|
||||
PHP_FUNCTION(breakiter_create_title_instance);
|
||||
|
||||
PHP_FUNCTION(breakiter_create_code_point_instance);
|
||||
|
||||
PHP_FUNCTION(breakiter_get_text);
|
||||
|
||||
PHP_FUNCTION(breakiter_set_text);
|
||||
|
286
ext/intl/breakiterator/codepointiterator_internal.cpp
Normal file
286
ext/intl/breakiterator/codepointiterator_internal.cpp
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "codepointiterator_internal.h"
|
||||
#include <unicode/uchriter.h>
|
||||
|
||||
//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);
|
||||
|
||||
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;
|
||||
}
|
98
ext/intl/breakiterator/codepointiterator_internal.h
Normal file
98
ext/intl/breakiterator/codepointiterator_internal.h
Normal 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
|
44
ext/intl/breakiterator/codepointiterator_methods.cpp
Normal file
44
ext/intl/breakiterator/codepointiterator_methods.cpp
Normal 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());
|
||||
}
|
24
ext/intl/breakiterator/codepointiterator_methods.h
Normal file
24
ext/intl/breakiterator/codepointiterator_methods.h
Normal 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
|
@ -79,6 +79,8 @@ if test "$PHP_INTL" != "no"; then
|
||||
breakiterator/breakiterator_iterators.cpp \
|
||||
breakiterator/breakiterator_methods.cpp \
|
||||
breakiterator/rulebasedbreakiterator_methods.cpp \
|
||||
breakiterator/codepointiterator_internal.cpp \
|
||||
breakiterator/codepointiterator_methods.cpp \
|
||||
idn/idn.c \
|
||||
$icu_spoof_src, $ext_shared,,$ICU_INCS -Wno-write-strings)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/collator)
|
||||
@ -95,4 +97,5 @@ if test "$PHP_INTL" != "no"; then
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/calendar)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/idn)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/spoofchecker)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/breakiterator)
|
||||
fi
|
||||
|
@ -107,7 +107,9 @@ if (PHP_INTL != "no") {
|
||||
breakiterator_class.cpp \
|
||||
breakiterator_methods.cpp \
|
||||
breakiterator_iterators.cpp \
|
||||
rulebasedbreakiterator_methods.cpp",
|
||||
rulebasedbreakiterator_methods.cpp \
|
||||
codepointiterator_internal.cpp \
|
||||
codepointiterator_methods.cpp ",
|
||||
"intl");
|
||||
|
||||
ADD_FLAG("LIBS_INTL", "icudt.lib icuin.lib icuio.lib icule.lib iculx.lib");
|
||||
|
43
ext/intl/tests/breakiter_createCodePointInstance_basic.phpt
Normal file
43
ext/intl/tests/breakiter_createCodePointInstance_basic.phpt
Normal 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==
|
18
ext/intl/tests/breakiter_createCodePointInstance_error.phpt
Normal file
18
ext/intl/tests/breakiter_createCodePointInstance_error.phpt
Normal 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
|
||||
|
33
ext/intl/tests/cpbi_clone_equality.phpt
Normal file
33
ext/intl/tests/cpbi_clone_equality.phpt
Normal 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==
|
82
ext/intl/tests/cpbi_getLastCodePoint_basic.phpt
Normal file
82
ext/intl/tests/cpbi_getLastCodePoint_basic.phpt
Normal 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==
|
19
ext/intl/tests/cpbi_getLastCodePoint_error.phpt
Normal file
19
ext/intl/tests/cpbi_getLastCodePoint_error.phpt
Normal 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)
|
||||
|
40
ext/intl/tests/cpbi_parts_iterator.phpt
Normal file
40
ext/intl/tests/cpbi_parts_iterator.phpt
Normal 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==
|
Loading…
Reference in New Issue
Block a user