@@ -165,21 +165,51 @@ const php_hash_ops php_hash_xxh3_64_ops = {
165
165
0
166
166
};
167
167
168
- PHP_HASH_API void PHP_XXH3_64_Init (PHP_XXH3_64_CTX * ctx , HashTable * args )
168
+ typedef XXH_errorcode (* xxh3_reset_with_secret_func_t )(XXH3_state_t * , const void * , size_t );
169
+ typedef XXH_errorcode (* xxh3_reset_with_seed_func_t )(XXH3_state_t * , XXH64_hash_t );
170
+
171
+ zend_always_inline static void _PHP_XXH3_Init (PHP_XXH3_64_CTX * ctx , HashTable * args ,
172
+ xxh3_reset_with_seed_func_t func_init_seed , xxh3_reset_with_secret_func_t func_init_secret , const char * algo_name )
169
173
{
170
- /* TODO integrate also XXH3_64bits_reset_withSecret(). */
171
- XXH64_hash_t seed = 0 ;
174
+ memset (& ctx -> s , 0 , sizeof ctx -> s );
172
175
173
176
if (args ) {
174
177
zval * _seed = zend_hash_str_find_deref (args , "seed" , sizeof ("seed" ) - 1 );
175
- /* This might be a bit too restrictive, but thinking that a seed might be set
176
- once and for all, it should be done a clean way. */
178
+ zval * _secret = zend_hash_str_find_deref (args , "secret" , sizeof ("secret" ) - 1 );
179
+
180
+ if (_seed && _secret ) {
181
+ zend_throw_error (NULL , "%s: Only one of seed or secret is to be passed for initialization" , algo_name );
182
+ return ;
183
+ }
184
+
177
185
if (_seed && IS_LONG == Z_TYPE_P (_seed )) {
178
- seed = (XXH64_hash_t )Z_LVAL_P (_seed );
186
+ /* This might be a bit too restrictive, but thinking that a seed might be set
187
+ once and for all, it should be done a clean way. */
188
+ func_init_seed (& ctx -> s , (XXH64_hash_t )Z_LVAL_P (_seed ));
189
+ return ;
190
+ } else if (_secret ) {
191
+ convert_to_string (_secret );
192
+ size_t len = Z_STRLEN_P (_secret );
193
+ if (len < PHP_XXH3_SECRET_SIZE_MIN ) {
194
+ zend_throw_error (NULL , "%s: Secret length must be >= %u bytes, %zu bytes passed" , algo_name , XXH3_SECRET_SIZE_MIN , len );
195
+ return ;
196
+ }
197
+ if (len > sizeof (ctx -> secret )) {
198
+ len = sizeof (ctx -> secret );
199
+ php_error_docref (NULL , E_WARNING , "%s: Secret content exceeding %zu bytes discarded" , algo_name , sizeof (ctx -> secret ));
200
+ }
201
+ memcpy ((unsigned char * )ctx -> secret , Z_STRVAL_P (_secret ), len );
202
+ func_init_secret (& ctx -> s , ctx -> secret , len );
203
+ return ;
179
204
}
180
205
}
181
206
182
- XXH3_64bits_reset_withSeed (& ctx -> s , seed );
207
+ func_init_seed (& ctx -> s , 0 );
208
+ }
209
+
210
+ PHP_HASH_API void PHP_XXH3_64_Init (PHP_XXH3_64_CTX * ctx , HashTable * args )
211
+ {
212
+ _PHP_XXH3_Init (ctx , args , XXH3_64bits_reset_withSeed , XXH3_64bits_reset_withSecret , "xxh3" );
183
213
}
184
214
185
215
PHP_HASH_API void PHP_XXH3_64_Update (PHP_XXH3_64_CTX * ctx , const unsigned char * in , size_t len )
@@ -238,19 +268,7 @@ const php_hash_ops php_hash_xxh3_128_ops = {
238
268
239
269
PHP_HASH_API void PHP_XXH3_128_Init (PHP_XXH3_128_CTX * ctx , HashTable * args )
240
270
{
241
- /* TODO integrate also XXH3_128__64bits_reset_withSecret(). */
242
- XXH64_hash_t seed = 0 ;
243
-
244
- if (args ) {
245
- zval * _seed = zend_hash_str_find_deref (args , "seed" , sizeof ("seed" ) - 1 );
246
- /* This might be a bit too restrictive, but thinking that a seed might be set
247
- once and for all, it should be done a clean way. */
248
- if (_seed && IS_LONG == Z_TYPE_P (_seed )) {
249
- seed = (XXH64_hash_t )Z_LVAL_P (_seed );
250
- }
251
- }
252
-
253
- XXH3_128bits_reset_withSeed (& ctx -> s , seed );
271
+ _PHP_XXH3_Init (ctx , args , XXH3_128bits_reset_withSeed , XXH3_128bits_reset_withSecret , "xxh128" );
254
272
}
255
273
256
274
PHP_HASH_API void PHP_XXH3_128_Update (PHP_XXH3_128_CTX * ctx , const unsigned char * in , size_t len )
0 commit comments