/**
* Copyright 2019 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* crc32c extension for PHP
*
* This file sets up the crc32c module, and provide the 'crc32c' function.
*/
#include "php_crc32c.h"
#include "ext/hash/php_hash.h"
#include "ext/standard/info.h"
#include "crc32c/crc32c.h"
extern const php_hash_ops crc32_ops;
static uint32_t byte2int(const uint8_t hash[4]) {
return (hash[0] << 24) | (hash[1] << 16) | (hash[2] << 8) | hash[3];
}
/* {{{ int crc32c( string $data [, int $crc ] )
*/
PHP_FUNCTION(crc32c)
{
char *data_arg = NULL;
size_t data_len = 0;
char *crc_arg = NULL;
size_t crc_len = 0;
#if PHP_API_VERSION >= 20151012 /* >= PHP 7.0 */
// fast_zpp is a faster way to parse paramters.
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STRING(data_arg, data_len)
Z_PARAM_OPTIONAL
Z_PARAM_STRING_EX(crc_arg, crc_len, /* check_null */ 1, 0)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#else
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &data_arg, &data_len, &crc_arg, &crc_len) == FAILURE) {
RETURN_BOOL(false);
}
#endif
uint32_t crc = 0;
if (crc_len == 4) {
crc = byte2int((uint8_t *)crc_arg);
} else if (crc_arg != NULL) {
zend_error(E_WARNING, "crc32c(): Supplied crc must be a 4 byte string");
RETURN_BOOL(false);
}
crc = crc32c_extend(crc, (const uint8_t *)data_arg, data_len);
uint8_t hash[4];
int2byte(crc, hash);
#if PHP_API_VERSION >= 20151012 /* >= PHP 7.0 */
RETURN_STRINGL((const char *)hash, sizeof(hash));
#else
RETURN_STRINGL((const char *)hash, sizeof(hash), /* dup */ 1);
#endif
}
/* }}}*/
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(crc32c)
{
#if PHP_VERSION_ID >= 70000
# if defined(ZTS) && defined(COMPILE_DL_CRC32C)
ZEND_TSRMLS_CACHE_UPDATE();
# endif
#endif
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(crc32c)
{
php_hash_register_algo("crc32c", &crc32_ops);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(crc32c)
{
// TODO Unregister php_hash_register_algo
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(crc32c)
{
php_info_print_table_start();
php_info_print_table_header(2, "Google CRC32C support", "enabled");
php_info_print_table_end();
}
/* }}} */
/* {{{ arginfo
*/
ZEND_BEGIN_ARG_INFO_EX(arginfo_crc32c, 0, 0, 1)
ZEND_ARG_INFO(0, str)
ZEND_ARG_INFO(0, crc)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ crc32c_functions[]
*/
static const zend_function_entry crc32c_functions[] = {
PHP_FE(crc32c, arginfo_crc32c)
PHP_FE_END
};
/* }}} */
/* {{{ crc32c_deps
*/
static const zend_module_dep crc32c_deps[] = {
ZEND_MOD_REQUIRED("hash")
ZEND_MOD_END
};
/* }}} */
/* {{{ crc32c_module_entry
*/
zend_module_entry crc32c_module_entry = {
STANDARD_MODULE_HEADER_EX, NULL,
crc32c_deps, /* Module dependencies */
"crc32c", /* Extension name */
crc32c_functions, /* zend_function_entry */
PHP_MINIT(crc32c), /* PHP_MINIT - Module initialization */
PHP_MSHUTDOWN(crc32c), /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(crc32c), /* PHP_RINIT - Request initialization */
NULL, /* PHP_RSHUTDOWN - Request shutdown */
PHP_MINFO(crc32c), /* PHP_MINFO - Module info */
PHP_CRC32C_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_CRC32C
# if PHP_VERSION_ID >= 70000
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
# endif /* PHP_VERSION_ID >= 70000 */
ZEND_GET_MODULE(crc32c)
#endif /* COMPILE_DL_CRC32C */