}
/* }}} */
-int gmp_import_export_validate(long size, long options, int *order, int *endian TSRMLS_DC)
++int gmp_import_export_validate(zend_long size, zend_long options, int *order, int *endian TSRMLS_DC)
+ {
+ if (size < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Word size must be positive, %ld given", size);
+ return FAILURE;
+ }
+
+ switch (options & (GMP_LSW_FIRST | GMP_MSW_FIRST)) {
+ case GMP_LSW_FIRST:
+ *order = -1;
+ break;
+ case GMP_MSW_FIRST:
+ case 0: /* default */
+ *order = 1;
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Invalid options: Conflicting word orders");
+ return FAILURE;
+ }
+
+ switch (options & (GMP_LITTLE_ENDIAN | GMP_BIG_ENDIAN | GMP_NATIVE_ENDIAN)) {
+ case GMP_LITTLE_ENDIAN:
+ *endian = -1;
+ break;
+ case GMP_BIG_ENDIAN:
+ *endian = 1;
+ break;
+ case GMP_NATIVE_ENDIAN:
+ case 0: /* default */
+ *endian = 0;
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Invalid options: Conflicting word endianness");
+ return FAILURE;
+ }
+
+ return SUCCESS;
+ }
+
+ /* {{{ proto GMP gmp_import(string data [, int word_size = 1, int options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN])
+ Imports a GMP number from a binary string */
+ ZEND_FUNCTION(gmp_import)
+ {
+ char *data;
- int data_len;
- long size = 1;
- long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;;
++ size_t data_len;
++ zend_long size = 1;
++ zend_long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;;
+ int order, endian;
+ mpz_ptr gmpnumber;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &size, &options) == FAILURE) {
+ return;
+ }
+
+ if (gmp_import_export_validate(size, options, &order, &endian TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if ((data_len % size) != 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Input length must be a multiple of word size");
+ RETURN_FALSE;
+ }
+
+ INIT_GMP_RETVAL(gmpnumber);
+
+ mpz_import(gmpnumber, data_len / size, order, size, endian, 0, data);
+ }
+ /* }}} */
+
+ /* {{{ proto string gmp_export(GMP gmpnumber [, int word_size = 1, int options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN])
+ Exports a GMP number to a binary string */
+ ZEND_FUNCTION(gmp_export)
+ {
+ zval *gmpnumber_arg;
- long size = 1;
- long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;;
++ zend_long size = 1;
++ zend_long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;;
+ int order, endian;
+ mpz_ptr gmpnumber;
+ gmp_temp_t temp_a;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &gmpnumber_arg, &size, &options) == FAILURE) {
+ return;
+ }
+
+ if (gmp_import_export_validate(size, options, &order, &endian TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ FETCH_GMP_ZVAL(gmpnumber, gmpnumber_arg, temp_a);
+
+ if (mpz_sgn(gmpnumber) == 0) {
- ZVAL_STRING(return_value, "", 1);
++ RETURN_EMPTY_STRING();
+ } else {
+ size_t bits_per_word = size * 8;
+ size_t count = (mpz_sizeinbase(gmpnumber, 2) + bits_per_word - 1) / bits_per_word;
+ size_t out_len = count * size;
+
- char *out_string = emalloc(out_len + 1);
- mpz_export(out_string, NULL, order, size, endian, 0, gmpnumber);
- out_string[out_len] = '\0';
++ zend_string *out_string = zend_string_alloc(out_len, 0);
++ mpz_export(out_string->val, NULL, order, size, endian, 0, gmpnumber);
++ out_string->val[out_len] = '\0';
+
- ZVAL_STRINGL(return_value, out_string, out_len, 0);
++ RETURN_STR(out_string);
+ }
+
+ FREE_GMP_TEMP(temp_a);
+ }
+ /* }}} */
+
/* {{{ proto int gmp_intval(mixed gmpnumber)
Gets signed long value of GMP number */
ZEND_FUNCTION(gmp_intval)