PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/intl/grapheme - grapheme_util.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 195 262 74.4 %
Date: 2014-04-18 Functions: 12 13 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | This source file is subject to version 3.01 of the PHP license,      |
       6             :    | that is bundled with this package in the file LICENSE, and is        |
       7             :    | available through the world-wide-web at the following url:           |
       8             :    | http://www.php.net/license/3_01.txt                                  |
       9             :    | If you did not receive a copy of the PHP license and are unable to   |
      10             :    | obtain it through the world-wide-web, please send a note to          |
      11             :    | license@php.net so we can mail you a copy immediately.               |
      12             :    +----------------------------------------------------------------------+
      13             :    | Author: Ed Batutis <ed@batutis.com>                                  |
      14             :    +----------------------------------------------------------------------+
      15             :  */
      16             : 
      17             : /* {{{ includes */
      18             : #ifdef HAVE_CONFIG_H
      19             : #include "config.h"
      20             : #endif
      21             : 
      22             : #include <php.h>
      23             : #include "grapheme.h"
      24             : #include "grapheme_util.h"
      25             : #include "intl_common.h"
      26             : 
      27             : #include <unicode/utypes.h>
      28             : #include <unicode/ucol.h>
      29             : #include <unicode/ustring.h>
      30             : #include <unicode/ubrk.h>
      31             : 
      32             : #include "ext/standard/php_string.h"
      33             : 
      34             : ZEND_EXTERN_MODULE_GLOBALS( intl )
      35             : 
      36             : /* }}} */
      37             : 
      38             : /* {{{ grapheme_close_global_iterator - clean up */
      39             : void
      40           1 : grapheme_close_global_iterator( TSRMLS_D )
      41             : {
      42           1 :         UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator );
      43             : 
      44           1 :         if ( NULL != global_break_iterator ) {
      45           1 :                 ubrk_close(global_break_iterator);
      46             :         }
      47           1 : }
      48             : /* }}} */
      49             : 
      50             : /* {{{ grapheme_intl_case_fold: convert string to lowercase */
      51             : void
      52         146 : grapheme_intl_case_fold(UChar** ptr_to_free, UChar **str, int32_t *str_len, UErrorCode *pstatus )
      53             : {
      54             :     UChar *dest;
      55             :     int32_t dest_len, size_required;
      56             : 
      57             :     /* allocate a destination string that is a bit larger than the src, hoping that is enough */
      58         146 :     dest_len = (*str_len) + ( *str_len / 10 );
      59         146 :     dest = (UChar*) eumalloc(dest_len);
      60             : 
      61         146 :     *pstatus = U_ZERO_ERROR;
      62         146 :     size_required = u_strFoldCase(dest, dest_len, *str, *str_len, U_FOLD_CASE_DEFAULT, pstatus);
      63             : 
      64         146 :     dest_len = size_required;
      65             : 
      66         146 :     if ( U_BUFFER_OVERFLOW_ERROR == *pstatus ) {
      67             : 
      68           0 :         dest = (UChar*) eurealloc(dest, dest_len);
      69             : 
      70           0 :         *pstatus = U_ZERO_ERROR;
      71           0 :         size_required = u_strFoldCase(dest, dest_len, *str, *str_len, U_FOLD_CASE_DEFAULT, pstatus);
      72             :     }
      73             : 
      74         146 :     if ( U_FAILURE(*pstatus) ) {
      75           0 :         return;
      76             :     }
      77             : 
      78         146 :     if ( NULL != ptr_to_free) {
      79         146 :         efree(*ptr_to_free);
      80         146 :         *ptr_to_free = dest;
      81             :     }
      82             : 
      83         146 :     *str = dest;
      84         146 :     *str_len = dest_len;
      85             : 
      86         146 :     return;
      87             : }
      88             : /* }}} */
      89             : 
      90             : /* {{{ grapheme_substr_ascii f='from' - starting point, l='length' */
      91             : void
      92           6 : grapheme_substr_ascii(char *str, int str_len, int f, int l, int argc, char **sub_str, int *sub_str_len)
      93             : {
      94           6 :     *sub_str = NULL;
      95             : 
      96           6 :     if (argc > 2) {
      97           4 :         if ((l < 0 && -l > str_len)) {
      98           0 :             return;
      99           4 :         } else if (l > str_len) {
     100           1 :             l = str_len;
     101             :         }
     102             :     } else {
     103           2 :         l = str_len;
     104             :     }
     105             : 
     106           6 :     if (f > str_len || (f < 0 && -f > str_len)) {
     107           0 :         return;
     108             :     }
     109             : 
     110           6 :     if (l < 0 && (l + str_len - f) < 0) {
     111           0 :         return;
     112             :     }
     113             : 
     114             :     /* if "from" position is negative, count start position from the end
     115             :      * of the string
     116             :      */
     117           6 :     if (f < 0) {
     118           0 :         f = str_len + f;
     119           0 :         if (f < 0) {
     120           0 :             f = 0;
     121             :         }
     122             :     }
     123             : 
     124             : 
     125             :     /* if "length" position is negative, set it to the length
     126             :      * needed to stop that many chars from the end of the string
     127             :      */
     128           6 :     if (l < 0) {
     129           0 :         l = (str_len - f) + l;
     130           0 :         if (l < 0) {
     131           0 :             l = 0;
     132             :         }
     133             :     }
     134             : 
     135           6 :     if (f >= str_len) {
     136           0 :         return;
     137             :     }
     138             : 
     139           6 :     if ((f + l) > str_len) {
     140           2 :         l = str_len - f;
     141             :     }
     142             : 
     143           6 :     *sub_str = str + f;
     144           6 :     *sub_str_len = l;
     145             : 
     146           6 :     return;
     147             : }
     148             : /* }}} */
     149             : 
     150             : /* {{{ grapheme_strrpos_utf16 - strrpos using utf16 */
     151             : int
     152          38 : grapheme_strrpos_utf16(unsigned char *haystack, int32_t haystack_len, unsigned char*needle, int32_t needle_len, int32_t offset, int f_ignore_case TSRMLS_DC)
     153             : {
     154             :     UChar *uhaystack, *puhaystack, *uhaystack_end, *uneedle;
     155             :     int32_t uhaystack_len, uneedle_len;
     156             :     UErrorCode status;
     157             :     unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
     158          38 :     UBreakIterator* bi = NULL;
     159             :     int ret_pos, pos;
     160             : 
     161             :     /* convert the strings to UTF-16. */
     162          38 :     uhaystack = NULL;
     163          38 :     uhaystack_len = 0;
     164          38 :     status = U_ZERO_ERROR;
     165          38 :     intl_convert_utf8_to_utf16(&uhaystack, &uhaystack_len, (char *) haystack, haystack_len, &status );
     166             : 
     167          38 :     if ( U_FAILURE( status ) ) {
     168             :         /* Set global error code. */
     169           0 :         intl_error_set_code( NULL, status TSRMLS_CC );
     170             : 
     171             :         /* Set error messages. */
     172           0 :         intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 TSRMLS_CC );
     173           0 :         if (uhaystack) {
     174           0 :                         efree( uhaystack );
     175             :                 }
     176           0 :         return -1;
     177             :     }
     178             : 
     179          38 :     if ( f_ignore_case ) {
     180          19 :         grapheme_intl_case_fold(&uhaystack, &uhaystack, &uhaystack_len, &status );
     181             :     }
     182             : 
     183             :     /* get a pointer to the haystack taking into account the offset */
     184          38 :     bi = NULL;
     185          38 :     status = U_ZERO_ERROR;
     186          38 :     bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status TSRMLS_CC );
     187             : 
     188          38 :     puhaystack = grapheme_get_haystack_offset(bi, uhaystack, uhaystack_len, offset);
     189             : 
     190          38 :     if ( NULL == puhaystack ) {
     191           0 :         intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
     192           0 :         if (uhaystack) {
     193           0 :                         efree( uhaystack );
     194             :                 }
     195           0 :         ubrk_close (bi);
     196           0 :         return -1;
     197             :     }
     198             : 
     199          38 :     uneedle = NULL;
     200          38 :     uneedle_len = 0;
     201          38 :     status = U_ZERO_ERROR;
     202          38 :     intl_convert_utf8_to_utf16(&uneedle, &uneedle_len, (char *) needle, needle_len, &status );
     203             : 
     204          38 :     if ( U_FAILURE( status ) ) {
     205             :         /* Set global error code. */
     206           0 :         intl_error_set_code( NULL, status TSRMLS_CC );
     207             : 
     208             :         /* Set error messages. */
     209           0 :         intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 TSRMLS_CC );
     210           0 :         if (uhaystack) {
     211           0 :                         efree( uhaystack );
     212             :                 }
     213           0 :                 if (uneedle) {
     214           0 :                         efree( uneedle );
     215             :                 }
     216           0 :         ubrk_close (bi);
     217           0 :         return -1;
     218             :     }
     219             : 
     220          38 :     if ( f_ignore_case ) {
     221          19 :         grapheme_intl_case_fold(&uneedle, &uneedle, &uneedle_len, &status );
     222             :     }
     223             : 
     224          38 :     ret_pos = -1;   /* -1 represents 'not found' */
     225             : 
     226             :     /* back up until there's needle_len characters to compare */
     227             : 
     228          38 :     uhaystack_end = uhaystack + uhaystack_len;
     229          38 :     pos = ubrk_last(bi);
     230          38 :     puhaystack = uhaystack + pos;
     231             : 
     232         166 :     while ( uhaystack_end - puhaystack < uneedle_len ) {
     233             : 
     234          94 :         pos = ubrk_previous(bi);
     235             : 
     236          94 :         if ( UBRK_DONE == pos ) {
     237           4 :             break;
     238             :         }
     239             : 
     240          90 :         puhaystack = uhaystack + pos;
     241             :     }
     242             : 
     243             :     /* is there enough haystack left to hold the needle? */
     244          38 :     if ( ( uhaystack_end - puhaystack ) < uneedle_len ) {
     245             :         /* not enough, not found */
     246           4 :         goto exit;
     247             :     }
     248             : 
     249         108 :     while ( UBRK_DONE != pos ) {
     250             : 
     251          66 :         if (!u_memcmp(uneedle, puhaystack, uneedle_len)) {  /* needle_len - 1 in zend memnstr? */
     252             : 
     253             :             /* does the grapheme in the haystack end at the same place as the last grapheme in the needle? */
     254             : 
     255          30 :             if ( ubrk_isBoundary(bi, pos + uneedle_len) ) {
     256             : 
     257             :                 /* found it, get grapheme count offset */
     258          26 :                 ret_pos = grapheme_count_graphemes(bi, uhaystack, pos);
     259          26 :                 break;
     260             :             }
     261             : 
     262             :             /* set position back */
     263           4 :             ubrk_isBoundary(bi, pos);
     264             :         }
     265             : 
     266          40 :         pos = ubrk_previous(bi);
     267          40 :         puhaystack = uhaystack + pos;
     268             :     }
     269             : 
     270             : exit:
     271          38 :         if (uhaystack) {
     272          38 :                 efree( uhaystack );
     273             :         }
     274          38 :         if (uneedle) {
     275          38 :                 efree( uneedle );
     276             :         }
     277          38 :     ubrk_close (bi);
     278             : 
     279          38 :     return ret_pos;
     280             : }
     281             : 
     282             : /* }}} */
     283             : 
     284             : /* {{{ grapheme_strpos_utf16 - strrpos using utf16*/
     285             : int
     286          88 : grapheme_strpos_utf16(unsigned char *haystack, int32_t haystack_len, unsigned char*needle, int32_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case TSRMLS_DC)
     287             : {
     288             :         UChar *uhaystack, *puhaystack, *uneedle;
     289             :         int32_t uhaystack_len, uneedle_len;
     290             :         int ret_pos;
     291             :         unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
     292             :         UBreakIterator* bi;
     293             :         UErrorCode status;
     294             : 
     295          88 :         *puchar_pos = -1;
     296             : 
     297             :         /* convert the strings to UTF-16. */
     298             : 
     299          88 :         uhaystack = NULL;
     300          88 :         uhaystack_len = 0;
     301          88 :         status = U_ZERO_ERROR;
     302          88 :         intl_convert_utf8_to_utf16(&uhaystack, &uhaystack_len, (char *) haystack, haystack_len, &status );
     303             : 
     304          88 :         if ( U_FAILURE( status ) ) {
     305             :                 /* Set global error code. */
     306           0 :                 intl_error_set_code( NULL, status TSRMLS_CC );
     307             : 
     308             :                 /* Set error messages. */
     309           0 :                 intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 TSRMLS_CC );
     310           0 :                 if (uhaystack) {
     311           0 :                         efree( uhaystack );
     312             :                 }
     313           0 :                 return -1;
     314             :         }
     315             : 
     316             :         /* get a pointer to the haystack taking into account the offset */
     317          88 :         bi = NULL;
     318          88 :         status = U_ZERO_ERROR;
     319          88 :         bi = grapheme_get_break_iterator(u_break_iterator_buffer, &status TSRMLS_CC );
     320             :         
     321          88 :         puhaystack = grapheme_get_haystack_offset(bi, uhaystack, uhaystack_len, offset);
     322          88 :         uhaystack_len = (uhaystack_len - ( puhaystack - uhaystack));
     323             : 
     324          88 :         if ( NULL == puhaystack ) {
     325             :         
     326           0 :                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_strpos: Offset not contained in string", 1 TSRMLS_CC );
     327           0 :                 if (uhaystack) {
     328           0 :                         efree( uhaystack );
     329             :                 }
     330           0 :                 ubrk_close (bi);
     331             :                                         
     332           0 :                 return -1;
     333             :         }
     334             : 
     335          88 :         if ( f_ignore_case ) {
     336          54 :                 grapheme_intl_case_fold(&uhaystack, &puhaystack, &uhaystack_len, &status );
     337             :         }
     338             : 
     339          88 :         uneedle = NULL;
     340          88 :         uneedle_len = 0;
     341          88 :         status = U_ZERO_ERROR;
     342          88 :         intl_convert_utf8_to_utf16(&uneedle, &uneedle_len, (char *) needle, needle_len, &status );
     343             : 
     344          88 :         if ( U_FAILURE( status ) ) {
     345             :                 /* Set global error code. */
     346           0 :                 intl_error_set_code( NULL, status TSRMLS_CC );
     347             : 
     348             :                 /* Set error messages. */
     349           0 :                 intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 TSRMLS_CC );
     350           0 :                 if (uhaystack) {
     351           0 :                         efree( uhaystack );
     352             :                 }
     353           0 :                 if (uneedle) {
     354           0 :                         efree( uneedle );
     355             :                 }
     356           0 :                 ubrk_close (bi);
     357             :                 
     358           0 :                 return -1;
     359             :         }
     360             : 
     361          88 :         if ( f_ignore_case ) {
     362          54 :                 grapheme_intl_case_fold(&uneedle, &uneedle, &uneedle_len, &status );
     363             :         }
     364             : 
     365          88 :         ret_pos = grapheme_memnstr_grapheme(bi, puhaystack, uneedle, uneedle_len, puhaystack + uhaystack_len );
     366             :         
     367          88 :         *puchar_pos = ubrk_current(bi);
     368             : 
     369          88 :         if (uhaystack) {
     370          88 :                 efree( uhaystack );
     371             :         }
     372          88 :         if (uneedle) {
     373          88 :                 efree( uneedle );
     374             :         }
     375          88 :         ubrk_close (bi);
     376             : 
     377          88 :         return ret_pos;
     378             : }
     379             : 
     380             : /* }}} */
     381             : 
     382             : /* {{{ grapheme_ascii_check: ASCII check */
     383         341 : int grapheme_ascii_check(const unsigned char *day, int32_t len)
     384             : {
     385         341 :         int ret_len = len;
     386        1465 :         while ( len-- ) {
     387         992 :         if ( *day++ > 0x7f )
     388         209 :                 return -1;
     389             :         }
     390             : 
     391         132 :         return ret_len;
     392             : }
     393             : 
     394             : /* }}} */
     395             : 
     396             : /* {{{ grapheme_split_string: find and optionally return grapheme boundaries */
     397           4 : int grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len TSRMLS_DC )
     398             : {
     399             :         unsigned char u_break_iterator_buffer[U_BRK_SAFECLONE_BUFFERSIZE];
     400           4 :         UErrorCode              status = U_ZERO_ERROR;
     401             :         int ret_len, pos;
     402             :         UBreakIterator* bi;
     403             : 
     404           4 :         bi = grapheme_get_break_iterator((void*)u_break_iterator_buffer, &status TSRMLS_CC );
     405             : 
     406           4 :         if( U_FAILURE(status) ) {
     407           0 :                 return -1;
     408             :         }
     409             :         
     410           4 :         ubrk_setText(bi, text, text_length,     &status);
     411             : 
     412           4 :         pos = 0;
     413             :         
     414          27 :         for ( ret_len = 0; pos != UBRK_DONE; ) {
     415             :         
     416          19 :                 pos = ubrk_next(bi);
     417             :                 
     418          19 :                 if ( pos != UBRK_DONE ) {
     419             :                 
     420          15 :                         if ( NULL != boundary_array && ret_len < boundary_array_len ) {
     421           0 :                                 boundary_array[ret_len] = pos;
     422             :                         }
     423             : 
     424          15 :                         ret_len++;
     425             :                 }
     426             :         }
     427             :                         
     428           4 :         ubrk_close(bi);
     429             :         
     430           4 :         return ret_len;
     431             : }
     432             : /* }}} */
     433             : 
     434             : /* {{{ grapheme_count_graphemes */
     435             : int32_t
     436          97 : grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len)
     437             : {
     438          97 :         int ret_len = 0;
     439          97 :         int pos = 0;
     440          97 :         UErrorCode              status = U_ZERO_ERROR;
     441             :         
     442          97 :         ubrk_setText(bi, string, string_len, &status);
     443             : 
     444             :         do {
     445             :         
     446         341 :                 pos = ubrk_next(bi);
     447             :                 
     448         341 :                 if ( UBRK_DONE != pos ) {
     449         244 :                         ret_len++;
     450             :                 }
     451             :                 
     452         341 :         } while ( UBRK_DONE != pos );
     453             :         
     454          97 :         return ret_len;
     455             : }
     456             : /* }}} */
     457             : 
     458             : /* {{{ grapheme_memnstr_grapheme: find needle in haystack using grapheme boundaries */
     459             : int32_t
     460          88 : grapheme_memnstr_grapheme(UBreakIterator *bi, UChar *haystack, UChar *needle, int32_t needle_len, UChar *end)
     461             : {
     462          88 :         UChar *p = haystack;
     463          88 :         UChar ne = needle[needle_len-1];
     464             :         UErrorCode status;
     465             :         int32_t grapheme_offset;
     466             :         
     467          88 :         end -= needle_len;
     468             : 
     469         232 :         while (p <= end) {
     470             : 
     471         142 :                 if ((p = u_memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
     472             : 
     473          89 :                         if (!u_memcmp(needle, p, needle_len - 1)) {  /* needle_len - 1 works because if needle_len is 1, we've already tested the char */
     474             : 
     475             :                                 /* does the grapheme end here? */
     476             : 
     477          89 :                                 status = U_ZERO_ERROR;
     478          89 :                                 ubrk_setText (bi, haystack, (end - haystack) + needle_len, &status);
     479             : 
     480          89 :                                 if ( ubrk_isBoundary (bi, (p - haystack) + needle_len) ) {
     481             : 
     482             :                                         /* found it, get grapheme count offset */
     483          71 :                                         grapheme_offset = grapheme_count_graphemes(bi, haystack, (p - haystack));
     484             : 
     485          71 :                                         return grapheme_offset;
     486             :                                 }
     487             :                         }
     488             :                 }
     489             : 
     490          71 :                 if (p == NULL) {
     491          15 :                         return -1;
     492             :                 }
     493             : 
     494          56 :                 p++;
     495             :         }
     496             : 
     497           2 :         return -1;
     498             : }
     499             : 
     500             : /* }}} */
     501             : 
     502             : /* {{{ grapheme_memrstr_grapheme: reverse find needle in haystack using grapheme boundaries */
     503           0 : inline void *grapheme_memrchr_grapheme(const void *s, int c, int32_t n)
     504             : {
     505             :         register unsigned char *e;
     506             : 
     507           0 :         if (n <= 0) {
     508           0 :                 return NULL;
     509             :         }
     510             : 
     511           0 :         for (e = (unsigned char *)s + n - 1; e >= (unsigned char *)s; e--) {
     512           0 :                 if (*e == (unsigned char)c) {
     513           0 :                         return (void *)e;
     514             :                 }
     515             :         }
     516             : 
     517           0 :         return NULL;
     518             : }
     519             : /* }}} */
     520             : 
     521             : /* {{{  grapheme_get_haystack_offset - bump the haystack pointer based on the grapheme count offset */
     522             : UChar *
     523         126 : grapheme_get_haystack_offset(UBreakIterator* bi, UChar *uhaystack, int32_t uhaystack_len, int32_t offset)
     524             : {
     525             :         UErrorCode              status;
     526             :         int32_t pos;
     527             :         int32_t (*iter_op)(UBreakIterator* bi);
     528             :         int iter_incr;
     529             : 
     530         126 :         if ( NULL != bi ) {
     531         126 :                 status = U_ZERO_ERROR;
     532         126 :                 ubrk_setText (bi, uhaystack, uhaystack_len, &status);
     533             :         }
     534             : 
     535         126 :         if ( 0 == offset ) {
     536         110 :                 return uhaystack;
     537             :         }
     538             :         
     539          16 :         if ( offset < 0 ) {
     540           0 :                 iter_op = ubrk_previous;
     541           0 :                 ubrk_last(bi); /* one past the end */
     542           0 :                 iter_incr = 1;
     543             :         }
     544             :         else {
     545          16 :                 iter_op = ubrk_next;
     546          16 :                 iter_incr = -1;
     547             :         }
     548             :         
     549          16 :         pos = 0;
     550             :         
     551          64 :         while ( pos != UBRK_DONE && offset != 0 ) {
     552             :         
     553          32 :                 pos = iter_op(bi);
     554             :                 
     555          32 :                 if ( UBRK_DONE != pos ) {
     556          32 :                         offset += iter_incr;
     557             :                 }
     558             :         }
     559             : 
     560          16 :         if ( offset != 0 ) {
     561           0 :                 return NULL;
     562             :         }
     563             :         
     564          16 :         return uhaystack + pos;
     565             : }
     566             : /* }}} */
     567             : 
     568             : /* {{{ grapheme_strrpos_ascii: borrowed from the php ext/standard/string.c */
     569             :  int32_t
     570          38 : grapheme_strrpos_ascii(unsigned char *haystack, int32_t haystack_len, unsigned char *needle, int32_t needle_len, int32_t offset)
     571             : {
     572             :         unsigned char *p, *e;
     573             : 
     574          38 :         if (offset >= 0) {
     575          38 :                 p = haystack + offset;
     576          38 :                 e = haystack + haystack_len - needle_len;
     577             :         } else {
     578           0 :                 p = haystack;
     579           0 :                 if (needle_len > -offset) {
     580           0 :                         e = haystack + haystack_len - needle_len;
     581             :                 } else {
     582           0 :                         e = haystack + haystack_len + offset;
     583             :                 }
     584             :         }
     585             : 
     586          38 :         if (needle_len == 1) {
     587             :                 /* Single character search can shortcut memcmps */
     588          52 :                 while (e >= p) {
     589          34 :                         if (*e == *needle) {
     590          10 :                                 return (e - p + (offset > 0 ? offset : 0));
     591             :                         }
     592          24 :                         e--;
     593             :                 }
     594           4 :                 return -1;
     595             :         }
     596             : 
     597          56 :         while (e >= p) {
     598          22 :                 if (memcmp(e, needle, needle_len) == 0) {
     599          14 :                         return (e - p + (offset > 0 ? offset : 0));
     600             :                 }
     601           8 :                 e--;
     602             :         }
     603             : 
     604          10 :         return -1;
     605             : }
     606             : 
     607             : /* }}} */
     608             : 
     609             : /* {{{ grapheme_get_break_iterator: get a clone of the global character break iterator */
     610             : UBreakIterator* 
     611         244 : grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status TSRMLS_DC )
     612             : {
     613             :         int32_t buffer_size;
     614             : 
     615         244 :         UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator );
     616             : 
     617         244 :         if ( NULL == global_break_iterator ) {
     618             : 
     619           1 :                 global_break_iterator = ubrk_open(UBRK_CHARACTER, 
     620             :                                                                                         NULL,   /* icu default locale - locale has no effect on this iterator */
     621             :                                                                                         NULL,   /* text not set in global iterator */
     622             :                                                                                         0,              /* text length = 0 */
     623             :                                                                                         status);
     624             : 
     625           1 :                 INTL_G(grapheme_iterator) = global_break_iterator;
     626             :         }
     627             : 
     628         244 :         buffer_size = U_BRK_SAFECLONE_BUFFERSIZE;
     629             : 
     630         244 :         return ubrk_safeClone(global_break_iterator, stack_buffer, &buffer_size, status);
     631             : }
     632             : /* }}} */
     633             : 
     634             : /*
     635             :  * Local variables:
     636             :  * tab-width: 4
     637             :  * c-basic-offset: 4
     638             :  * End:
     639             :  * vim600: fdm=marker
     640             :  * vim: noet sw=4 ts=4
     641             :  */
     642             : 

Generated by: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:28 +0000 (5 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.