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 - Zend - zend_string.h (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 69 74 93.2 %
Date: 2014-10-22 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        | 
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Dmitry Stogov <dmitry@zend.com>                             |
      16             :    +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id: $ */
      20             : 
      21             : #ifndef ZEND_STRING_H
      22             : #define ZEND_STRING_H
      23             : 
      24             : #include "zend.h"
      25             : 
      26             : BEGIN_EXTERN_C()
      27             : 
      28             : ZEND_API extern zend_string *(*zend_new_interned_string)(zend_string *str TSRMLS_DC);
      29             : ZEND_API extern void (*zend_interned_strings_snapshot)(TSRMLS_D);
      30             : ZEND_API extern void (*zend_interned_strings_restore)(TSRMLS_D);
      31             : 
      32             : ZEND_API zend_ulong zend_hash_func(const char *str, size_t len);
      33             : void zend_interned_strings_init(TSRMLS_D);
      34             : void zend_interned_strings_dtor(TSRMLS_D);
      35             : 
      36             : END_EXTERN_C()
      37             : 
      38             : #define IS_INTERNED(s)                                  (GC_FLAGS(s) & IS_STR_INTERNED)
      39             : 
      40             : #define STR_EMPTY_ALLOC()                               CG(empty_string)
      41             : 
      42             : #define _STR_HEADER_SIZE XtOffsetOf(zend_string, val)
      43             : 
      44             : #define STR_ALLOCA_ALLOC(str, _len, use_heap) do { \
      45             :         (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + (_len) + 1), (use_heap)); \
      46             :         GC_REFCOUNT(str) = 1; \
      47             :         (str)->h = 0; \
      48             :         (str)->len = (_len); \
      49             : } while (0)
      50             : #define STR_ALLOCA_INIT(str, s, len, use_heap) do { \
      51             :         STR_ALLOCA_ALLOC(str, len, use_heap); \
      52             :         memcpy((str)->val, (s), (len)); \
      53             :         (str)->val[(len)] = '\0'; \
      54             : } while (0)
      55             : 
      56             : #define STR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap)
      57             : 
      58             : static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s)
      59             : {
      60   737818465 :         if (!s->h) {
      61   297269232 :                 s->h = zend_hash_func(s->val, s->len);
      62             :         }
      63   737818465 :         return s->h;
      64             : }
      65             : 
      66             : static zend_always_inline void zend_string_forget_hash_val(zend_string *s)
      67             : {
      68     6597875 :         s->h = 0;
      69             : }
      70             : 
      71             : static zend_always_inline uint32_t zend_string_refcount(zend_string *s)
      72             : {
      73             :         if (!IS_INTERNED(s)) {
      74             :                 return GC_REFCOUNT(s);
      75             :         }
      76             :         return 1;
      77             : }
      78             : 
      79             : static zend_always_inline uint32_t zend_string_addref(zend_string *s)
      80             : {
      81   278457354 :         if (!IS_INTERNED(s)) {
      82    94688271 :                 return ++GC_REFCOUNT(s);
      83             :         }
      84   183769083 :         return 1;
      85             : }
      86             : 
      87             : static zend_always_inline uint32_t zend_string_delref(zend_string *s)
      88             : {
      89             :         if (!IS_INTERNED(s)) {
      90             :                 return --GC_REFCOUNT(s);
      91             :         }
      92             :         return 1;
      93             : }
      94             : 
      95             : static zend_always_inline zend_string *zend_string_alloc(size_t len, int persistent)
      96             : {
      97   646531898 :         zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
      98             : 
      99   320509376 :         GC_REFCOUNT(ret) = 1;
     100             : #if 1
     101             :         /* optimized single assignment */
     102   320509376 :         GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
     103             : #else
     104             :         GC_TYPE(ret) = IS_STRING;
     105             :         GC_FLAGS(ret) = (persistent ? IS_STR_PERSISTENT : 0);
     106             :         GC_INFO(ret) = 0;
     107             : #endif
     108   320509376 :         ret->h = 0;
     109   320509376 :         ret->len = len;
     110   320509376 :         return ret;
     111             : }
     112             : 
     113             : static zend_always_inline zend_string *zend_string_safe_alloc(size_t n, size_t m, size_t l, int persistent)
     114             : {
     115      226133 :         zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
     116             : 
     117      226133 :         GC_REFCOUNT(ret) = 1;
     118             : #if 1
     119             :         /* optimized single assignment */
     120      226133 :         GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
     121             : #else
     122             :         GC_TYPE(ret) = IS_STRING;
     123             :         GC_FLAGS(ret) = (persistent ? IS_STR_PERSISTENT : 0);
     124             :         GC_INFO(ret) = 0;
     125             : #endif
     126      226133 :         ret->h = 0;
     127      226133 :         ret->len = (n * m) + l;
     128      226133 :         return ret;
     129             : }
     130             : 
     131             : static zend_always_inline zend_string *zend_string_init(const char *str, size_t len, int persistent)
     132             : {
     133   184973268 :         zend_string *ret = zend_string_alloc(len, persistent);
     134             : 
     135   184973268 :         memcpy(ret->val, str, len);
     136   184973268 :         ret->val[len] = '\0';
     137   184973268 :         return ret;
     138             : }
     139             : 
     140             : static zend_always_inline zend_string *zend_string_copy(zend_string *s)
     141             : {
     142     6049606 :         if (!IS_INTERNED(s)) {
     143     5145384 :                 GC_REFCOUNT(s)++;
     144             :         }
     145     6049606 :         return s;
     146             : }
     147             : 
     148             : static zend_always_inline zend_string *zend_string_dup(zend_string *s, int persistent)
     149             : {
     150     1193064 :         if (IS_INTERNED(s)) {
     151         154 :                 return s;
     152             :         } else {
     153     2385820 :                 return zend_string_init(s->val, s->len, persistent);
     154             :         }
     155             : }
     156             : 
     157             : static zend_always_inline zend_string *zend_string_realloc(zend_string *s, size_t len, int persistent)
     158             : {
     159             :         zend_string *ret;
     160             : 
     161     7729588 :         if (IS_INTERNED(s)) {
     162     1131745 :                 ret = zend_string_alloc(len, persistent);
     163     1131745 :                 memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
     164     6597843 :         } else if (EXPECTED(GC_REFCOUNT(s) == 1)) {
     165    13195606 :                 ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
     166     6597803 :                 ret->len = len;
     167             :                 zend_string_forget_hash_val(ret);
     168             :         } else {
     169          40 :                 ret = zend_string_alloc(len, persistent);
     170          40 :                 memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
     171          40 :                 GC_REFCOUNT(s)--;
     172             :         }
     173     7729588 :         return ret;
     174             : }
     175             : 
     176             : static zend_always_inline zend_string *zend_string_safe_realloc(zend_string *s, size_t n, size_t m, size_t l, int persistent)
     177             : {
     178             :         zend_string *ret;
     179             : 
     180           3 :         if (IS_INTERNED(s)) {
     181           0 :                 ret = zend_string_safe_alloc(n, m, l, persistent);
     182           0 :                 memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
     183           3 :         } else if (GC_REFCOUNT(s) == 1) {
     184           3 :                 ret = (zend_string *)safe_perealloc(s, n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
     185           3 :                 ret->len = (n * m) + l;
     186             :                 zend_string_forget_hash_val(ret);
     187             :         } else {
     188           0 :                 ret = zend_string_safe_alloc(n, m, l, persistent);
     189           0 :                 memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
     190           0 :                 GC_REFCOUNT(s)--;
     191             :         }
     192           3 :         return ret;
     193             : }
     194             : 
     195             : static zend_always_inline void zend_string_free(zend_string *s)
     196             : {
     197    62415027 :         if (!IS_INTERNED(s)) {
     198             :                 ZEND_ASSERT(GC_REFCOUNT(s) <= 1);
     199    62072135 :                 pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
     200             :         }
     201             : }
     202             : 
     203             : static zend_always_inline void zend_string_release(zend_string *s)
     204             : {
     205   710951963 :         if (!IS_INTERNED(s)) {
     206   357367973 :                 if (--GC_REFCOUNT(s) == 0) {
     207   258968785 :                         pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
     208             :                 }
     209             :         }
     210             : }
     211             : 
     212             : static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_string *s2)
     213             : {
     214        1641 :         return s1 == s2 || (s1->len == s2->len && !memcmp(s1->val, s2->val, s1->len));
     215             : }
     216             : 
     217             : #define zend_string_equals_literal_ci(str, c) \
     218             :         ((str)->len == sizeof(c) - 1 && !zend_binary_strcasecmp((str)->val, (str)->len, (c), sizeof(c) - 1))
     219             : 
     220             : #define zend_string_equals_literal(str, literal) \
     221             :         ((str)->len == sizeof(literal)-1 && !memcmp((str)->val, literal, sizeof(literal) - 1))
     222             : 
     223             : /*
     224             :  * DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
     225             :  *
     226             :  * This is Daniel J. Bernstein's popular `times 33' hash function as
     227             :  * posted by him years ago on comp.lang.c. It basically uses a function
     228             :  * like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best
     229             :  * known hash functions for strings. Because it is both computed very
     230             :  * fast and distributes very well.
     231             :  *
     232             :  * The magic of number 33, i.e. why it works better than many other
     233             :  * constants, prime or not, has never been adequately explained by
     234             :  * anyone. So I try an explanation: if one experimentally tests all
     235             :  * multipliers between 1 and 256 (as RSE did now) one detects that even
     236             :  * numbers are not useable at all. The remaining 128 odd numbers
     237             :  * (except for the number 1) work more or less all equally well. They
     238             :  * all distribute in an acceptable way and this way fill a hash table
     239             :  * with an average percent of approx. 86%. 
     240             :  *
     241             :  * If one compares the Chi^2 values of the variants, the number 33 not
     242             :  * even has the best value. But the number 33 and a few other equally
     243             :  * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great
     244             :  * advantage to the remaining numbers in the large set of possible
     245             :  * multipliers: their multiply operation can be replaced by a faster
     246             :  * operation based on just one shift plus either a single addition
     247             :  * or subtraction operation. And because a hash function has to both
     248             :  * distribute good _and_ has to be very fast to compute, those few
     249             :  * numbers should be preferred and seems to be the reason why Daniel J.
     250             :  * Bernstein also preferred it.
     251             :  *
     252             :  *
     253             :  *                  -- Ralf S. Engelschall <rse@engelschall.com>
     254             :  */
     255             : 
     256             : static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len)
     257             : {
     258   301441345 :         register zend_ulong hash = Z_UL(5381);
     259             : 
     260             :         /* variant with the hash unrolled eight times */
     261   388593357 :         for (; len >= 8; len -= 8) {
     262   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     263   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     264   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     265   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     266   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     267   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     268   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     269   388593357 :                 hash = ((hash << 5) + hash) + *str++;
     270             :         }
     271   301441345 :         switch (len) {
     272    38254126 :                 case 7: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
     273    72939876 :                 case 6: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
     274   116351726 :                 case 5: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
     275   154701866 :                 case 4: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
     276   198704010 :                 case 3: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
     277   232679146 :                 case 2: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
     278   268011071 :                 case 1: hash = ((hash << 5) + hash) + *str++; break;
     279             :                 case 0: break;
     280             : EMPTY_SWITCH_DEFAULT_CASE()
     281             :         }
     282   301441345 :         return hash;
     283             : }
     284             : 
     285             : static zend_always_inline void zend_interned_empty_string_init(zend_string **s TSRMLS_DC)
     286             : {
     287             :         zend_string *str;
     288             : 
     289             :         str = zend_string_alloc(sizeof("")-1, 1);
     290             :         str->val[0] = '\000';
     291             : 
     292             : #ifndef ZTS
     293             :         *s = zend_new_interned_string(str TSRMLS_CC);
     294             : #else
     295             :         zend_string_hash_val(str);
     296             :         str->gc.u.v.flags |= IS_STR_INTERNED;
     297             :         *s = str;
     298             : #endif
     299             : }
     300             : 
     301             : static zend_always_inline void zend_interned_empty_string_free(zend_string **s TSRMLS_DC)
     302             : {
     303             :         if (NULL != *s) {
     304             :                 free(*s);
     305             :                 *s = NULL;
     306             :         }
     307             : }
     308             : 
     309             : #endif /* ZEND_STRING_H */
     310             : 
     311             : /*
     312             :  * Local variables:
     313             :  * tab-width: 4
     314             :  * c-basic-offset: 4
     315             :  * indent-tabs-mode: t
     316             :  * End:
     317             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:44 +0000 (2 days ago)

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