Commit:    0a7ae87e91368fe17c52767cfb31dabf3a94e38f
Author:    Gustavo André dos Santos Lopes <cataphr...@php.net>         Fri, 22 
Jun 2012 18:19:54 +0200
Parents:   cee31091a960014ce5315008fc64437d04174caf
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=0a7ae87e91368fe17c52767cfb31dabf3a94e38f

Log:
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()).

Changed paths:
  M  ext/intl/breakiterator/breakiterator_class.cpp
  M  ext/intl/breakiterator/breakiterator_methods.cpp
  M  ext/intl/breakiterator/breakiterator_methods.h
  A  ext/intl/breakiterator/codepointiterator_internal.cpp
  A  ext/intl/breakiterator/codepointiterator_internal.h
  A  ext/intl/breakiterator/codepointiterator_methods.cpp
  A  ext/intl/breakiterator/codepointiterator_methods.h
  M  ext/intl/config.m4
  M  ext/intl/config.w32
  A  ext/intl/tests/breakiter_createCodePointInstance_basic.phpt
  A  ext/intl/tests/breakiter_createCodePointInstance_error.phpt
  A  ext/intl/tests/cpbi_clone_equality.phpt
  A  ext/intl/tests/cpbi_getLastCodePoint_basic.phpt
  A  ext/intl/tests/cpbi_getLastCodePoint_error.phpt
  A  ext/intl/tests/cpbi_parts_iterator.phpt

diff --git a/ext/intl/breakiterator/breakiterator_class.cpp 
b/ext/intl/breakiterator/breakiterator_class.cpp
index 8c25314..6335502 100644
--- a/ext/intl/breakiterator/breakiterator_class.cpp
+++ b/ext/intl/breakiterator/breakiterator_class.cpp
@@ -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);
 }
 /* }}} */
diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp 
b/ext/intl/breakiterator/breakiterator_methods.cpp
index 5b8f859..e9e6b19 100644
--- a/ext/intl/breakiterator/breakiterator_methods.cpp
+++ b/ext/intl/breakiterator/breakiterator_methods.cpp
@@ -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;
diff --git a/ext/intl/breakiterator/breakiterator_methods.h 
b/ext/intl/breakiterator/breakiterator_methods.h
index e0d13b0..a479ac9 100644
--- a/ext/intl/breakiterator/breakiterator_methods.h
+++ b/ext/intl/breakiterator/breakiterator_methods.h
@@ -31,6 +31,8 @@ PHP_FUNCTION(breakiter_create_sentence_instance);
 
 PHP_FUNCTION(breakiter_create_title_instance);
 
+PHP_FUNCTION(breakiter_create_code_point_instance);
+
 PHP_FUNCTION(breakiter_get_text);
 
 PHP_FUNCTION(breakiter_set_text);
diff --git a/ext/intl/breakiterator/codepointiterator_internal.cpp 
b/ext/intl/breakiterator/codepointiterator_internal.cpp
new file mode 100644
index 0000000..2dfae1a
--- /dev/null
+++ b/ext/intl/breakiterator/codepointiterator_internal.cpp
@@ -0,0 +1,286 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Gustavo Lopes <cataphr...@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;
+}
\ No newline at end of file
diff --git a/ext/intl/breakiterator/codepointiterator_internal.h 
b/ext/intl/breakiterator/codepointiterator_internal.h
new file mode 100644
index 0000000..988b91c
--- /dev/null
+++ b/ext/intl/breakiterator/codepointiterator_internal.h
@@ -0,0 +1,98 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Gustavo Lopes <cataphr...@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
\ No newline at end of file
diff --git a/ext/intl/breakiterator/codepointiterator_methods.cpp 
b/ext/intl/breakiterator/codepointiterator_methods.cpp
new file mode 100644
index 0000000..ae7e526
--- /dev/null
+++ b/ext/intl/breakiterator/codepointiterator_methods.cpp
@@ -0,0 +1,44 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Gustavo Lopes <cataphr...@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());
+}
\ No newline at end of file
diff --git a/ext/intl/breakiterator/codepointiterator_methods.h 
b/ext/intl/breakiterator/codepointiterator_methods.h
new file mode 100644
index 0000000..d34e5b6
--- /dev/null
+++ b/ext/intl/breakiterator/codepointiterator_methods.h
@@ -0,0 +1,24 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Gustavo Lopes <cataphr...@php.net>                          |
+   +----------------------------------------------------------------------+
+ */
+
+#ifndef CODEPOINTITERATOR_METHODS_H
+#define CODEPOINTITERATOR_METHODS_H
+
+#include <php.h>
+
+PHP_FUNCTION(cpbi_get_last_code_point);
+
+#endif
\ No newline at end of file
diff --git a/ext/intl/config.m4 b/ext/intl/config.m4
index 2273683..d7eacbc 100755
--- a/ext/intl/config.m4
+++ b/ext/intl/config.m4
@@ -79,6 +79,8 @@ if test "$PHP_INTL" != "no"; then
     breakiterator/breakiterator_iterators.cpp \
     breakiterator/breakiterator_methods.cpp \
     breakiterator/rulebasedbreakiterator_methods.cpp \
+    breakiterator/codepointiterator_internal.cpp \
+    breakiterator/codepointiterator_methods.cpp \
     idn/idn.c \
     $icu_spoof_src, $ext_shared,,$ICU_INCS -Wno-write-strings)
   PHP_ADD_BUILD_DIR($ext_builddir/collator)
@@ -95,4 +97,5 @@ if test "$PHP_INTL" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/calendar)
   PHP_ADD_BUILD_DIR($ext_builddir/idn)
   PHP_ADD_BUILD_DIR($ext_builddir/spoofchecker)
+  PHP_ADD_BUILD_DIR($ext_builddir/breakiterator)
 fi
diff --git a/ext/intl/config.w32 b/ext/intl/config.w32
index 6b7d15d..a223505 100755
--- a/ext/intl/config.w32
+++ b/ext/intl/config.w32
@@ -107,7 +107,9 @@ if (PHP_INTL != "no") {
                                breakiterator_class.cpp \
                                breakiterator_methods.cpp \
                                breakiterator_iterators.cpp \
-                               rulebasedbreakiterator_methods.cpp",
+                               rulebasedbreakiterator_methods.cpp \
+                               codepointiterator_internal.cpp \
+                               codepointiterator_methods.cpp ",
                                "intl");
                
                ADD_FLAG("LIBS_INTL", "icudt.lib icuin.lib icuio.lib icule.lib 
iculx.lib");
diff --git a/ext/intl/tests/breakiter_createCodePointInstance_basic.phpt 
b/ext/intl/tests/breakiter_createCodePointInstance_basic.phpt
new file mode 100644
index 0000000..a43e827
--- /dev/null
+++ b/ext/intl/tests/breakiter_createCodePointInstance_basic.phpt
@@ -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==
diff --git a/ext/intl/tests/breakiter_createCodePointInstance_error.phpt 
b/ext/intl/tests/breakiter_createCodePointInstance_error.phpt
new file mode 100644
index 0000000..90228e1
--- /dev/null
+++ b/ext/intl/tests/breakiter_createCodePointInstance_error.phpt
@@ -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
+
diff --git a/ext/intl/tests/cpbi_clone_equality.phpt 
b/ext/intl/tests/cpbi_clone_equality.phpt
new file mode 100644
index 0000000..c62b452
--- /dev/null
+++ b/ext/intl/tests/cpbi_clone_equality.phpt
@@ -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==
diff --git a/ext/intl/tests/cpbi_getLastCodePoint_basic.phpt 
b/ext/intl/tests/cpbi_getLastCodePoint_basic.phpt
new file mode 100644
index 0000000..74a07a6
--- /dev/null
+++ b/ext/intl/tests/cpbi_getLastCodePoint_basic.phpt
@@ -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==
diff --git a/ext/intl/tests/cpbi_getLastCodePoint_error.phpt 
b/ext/intl/tests/cpbi_getLastCodePoint_error.phpt
new file mode 100644
index 0000000..78bd216
--- /dev/null
+++ b/ext/intl/tests/cpbi_getLastCodePoint_error.phpt
@@ -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)
+
diff --git a/ext/intl/tests/cpbi_parts_iterator.phpt 
b/ext/intl/tests/cpbi_parts_iterator.phpt
new file mode 100644
index 0000000..4754c12
--- /dev/null
+++ b/ext/intl/tests/cpbi_parts_iterator.phpt
@@ -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==
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to