32
32
ZEND_DECLARE_MODULE_GLOBALS (bcmath )
33
33
static PHP_GINIT_FUNCTION (bcmath );
34
34
static PHP_GSHUTDOWN_FUNCTION (bcmath );
35
+ static PHP_RINIT_FUNCTION (bcmath );
36
+ static PHP_RSHUTDOWN_FUNCTION (bcmath );
35
37
static PHP_MINIT_FUNCTION (bcmath );
36
38
static PHP_MSHUTDOWN_FUNCTION (bcmath );
37
39
static PHP_MINFO_FUNCTION (bcmath );
@@ -42,8 +44,8 @@ zend_module_entry bcmath_module_entry = {
42
44
ext_functions ,
43
45
PHP_MINIT (bcmath ),
44
46
PHP_MSHUTDOWN (bcmath ),
45
- NULL ,
46
- NULL ,
47
+ PHP_RINIT ( bcmath ) ,
48
+ PHP_RSHUTDOWN ( bcmath ) ,
47
49
PHP_MINFO (bcmath ),
48
50
PHP_BCMATH_VERSION ,
49
51
PHP_MODULE_GLOBALS (bcmath ),
@@ -82,6 +84,93 @@ PHP_INI_BEGIN()
82
84
PHP_INI_END ()
83
85
/* }}} */
84
86
87
+ static void bcmath_destroy_lru_entry (php_bc_lru_entry * entry )
88
+ {
89
+ /* No need to clean up str as that reference is held by the table. */
90
+ bc_free_num (& entry -> num );
91
+ }
92
+
93
+ static void bcmath_lru_init (php_bc_lru_cache * cache )
94
+ {
95
+ cache -> head = cache -> tail = NULL ;
96
+ zend_hash_init (& cache -> table , PHP_BCMATH_LRU_SIZE , NULL , NULL , false);
97
+ zend_hash_real_init_mixed (& cache -> table );
98
+ }
99
+
100
+ static void bcmath_lru_destroy (php_bc_lru_cache * cache )
101
+ {
102
+ php_bc_lru_entry * entry ;
103
+ ZEND_HASH_MAP_FOREACH_PTR (& cache -> table , entry ) {
104
+ bcmath_destroy_lru_entry (entry );
105
+ efree (entry );
106
+ } ZEND_HASH_FOREACH_END ();
107
+ zend_hash_destroy (& cache -> table );
108
+ }
109
+
110
+ static void bcmath_lru_new_entry (php_bc_lru_cache * cache , zend_string * str , bc_num num )
111
+ {
112
+ php_bc_lru_entry * entry = emalloc (sizeof (* entry ));
113
+ entry -> str = str ;
114
+ entry -> num = num ;
115
+
116
+ entry -> next = cache -> head ;
117
+ entry -> prev = NULL ;
118
+
119
+ if (cache -> head ) {
120
+ cache -> head -> prev = entry ;
121
+ } else {
122
+ cache -> tail = entry ;
123
+ }
124
+
125
+ cache -> head = entry ;
126
+
127
+ zend_hash_add_new_ptr (& cache -> table , str , entry );
128
+ }
129
+
130
+ static void bcmath_lru_move_to_head (php_bc_lru_cache * cache , php_bc_lru_entry * entry )
131
+ {
132
+ if (entry == cache -> head ) {
133
+ return ;
134
+ }
135
+
136
+ if (entry == cache -> tail ) {
137
+ cache -> tail = entry -> prev ;
138
+ }
139
+
140
+ if (entry -> prev ) {
141
+ entry -> prev -> next = entry -> next ;
142
+ }
143
+
144
+ if (entry -> next ) {
145
+ entry -> next -> prev = entry -> prev ;
146
+ }
147
+
148
+ entry -> next = cache -> head ;
149
+ entry -> prev = NULL ;
150
+
151
+ cache -> head -> prev = entry ;
152
+ cache -> head = entry ;
153
+ }
154
+
155
+ static void bcmath_lru_evict_oldest_and_reuse (php_bc_lru_cache * cache , zend_string * str , bc_num num )
156
+ {
157
+ zend_hash_del (& cache -> table , cache -> tail -> str );
158
+ bcmath_destroy_lru_entry (cache -> tail );
159
+ cache -> tail -> str = str ;
160
+ cache -> tail -> num = num ;
161
+ zend_hash_add_new_ptr (& cache -> table , str , cache -> tail );
162
+ bcmath_lru_move_to_head (cache , cache -> tail );
163
+ }
164
+
165
+ static void bcmath_lru_add (php_bc_lru_cache * cache , zend_string * str , bc_num num )
166
+ {
167
+ if (zend_hash_num_elements (& cache -> table ) == PHP_BCMATH_LRU_SIZE ) {
168
+ bcmath_lru_evict_oldest_and_reuse (cache , str , num );
169
+ } else {
170
+ bcmath_lru_new_entry (cache , str , num );
171
+ }
172
+ }
173
+
85
174
/* {{{ PHP_GINIT_FUNCTION */
86
175
static PHP_GINIT_FUNCTION (bcmath )
87
176
{
@@ -102,6 +191,18 @@ static PHP_GSHUTDOWN_FUNCTION(bcmath)
102
191
}
103
192
/* }}} */
104
193
194
+ static PHP_RINIT_FUNCTION (bcmath )
195
+ {
196
+ bcmath_lru_init (& bcmath_globals .lru_cache );
197
+ return SUCCESS ;
198
+ }
199
+
200
+ static PHP_RSHUTDOWN_FUNCTION (bcmath )
201
+ {
202
+ bcmath_lru_destroy (& bcmath_globals .lru_cache );
203
+ return SUCCESS ;
204
+ }
205
+
105
206
/* {{{ PHP_MINIT_FUNCTION */
106
207
PHP_MINIT_FUNCTION (bcmath )
107
208
{
@@ -132,12 +233,22 @@ PHP_MINFO_FUNCTION(bcmath)
132
233
133
234
/* {{{ php_str2num
134
235
Convert to bc_num detecting scale */
135
- static zend_result php_str2num (bc_num * num , const zend_string * str )
236
+ static zend_result php_str2num (bc_num * num , zend_string * str )
136
237
{
238
+ php_bc_lru_cache * cache = & BCG (lru_cache );
239
+ php_bc_lru_entry * cache_entry = zend_hash_find_ptr (& cache -> table , str );
240
+ if (cache_entry ) {
241
+ bcmath_lru_move_to_head (cache , cache_entry );
242
+ * num = bc_copy_num (cache_entry -> num );
243
+ return SUCCESS ;
244
+ }
245
+
137
246
if (!bc_str2num (num , ZSTR_VAL (str ), ZSTR_VAL (str ) + ZSTR_LEN (str ), 0 , true)) {
138
247
return FAILURE ;
139
248
}
140
249
250
+ bcmath_lru_add (cache , str , bc_copy_num (* num ));
251
+
141
252
return SUCCESS ;
142
253
}
143
254
/* }}} */
0 commit comments