From 239868719c3509d7f8fdc0589ac71ee9d8450bbe Mon Sep 17 00:00:00 2001 From: Alexander Polyakov Date: Tue, 10 Dec 2024 12:45:56 +0300 Subject: [PATCH] Move hexdec & dechex builtins to runtime-common (#1181) --- builtin-functions/kphp-light/math.txt | 12 +++-- .../kphp-light/unsupported/misc.txt | 6 --- runtime-common/stdlib/math/math-functions.cpp | 50 +++++++++++++++++++ runtime-common/stdlib/math/math-functions.h | 17 +++++++ runtime-common/stdlib/stdlib.cmake | 5 +- runtime/math_functions.cpp | 47 +---------------- runtime/math_functions.h | 5 -- tests/phpt/dl/435_base64_encode.php | 2 +- tests/phpt/dl/455_inc_xor_str.php | 2 +- tests/phpt/dl/488_ipv6.php | 2 +- tests/phpt/dl/489_hexdec.php | 2 +- 11 files changed, 83 insertions(+), 67 deletions(-) create mode 100644 runtime-common/stdlib/math/math-functions.cpp diff --git a/builtin-functions/kphp-light/math.txt b/builtin-functions/kphp-light/math.txt index c701b249ae..8671d0e826 100644 --- a/builtin-functions/kphp-light/math.txt +++ b/builtin-functions/kphp-light/math.txt @@ -20,13 +20,17 @@ define('M_SQRT1_2', 0.70710678118654752440); define('M_LNPI', 1.14472988584940017414); define('M_EULER', 0.57721566490153286061); -function mt_rand ($l ::: int = TODO_OVERLOAD, $r ::: int = TODO_OVERLOAD) ::: int; +function mt_rand ($l ::: int = TODO_OVERLOAD, $r ::: int = TODO_OVERLOAD): int; -function mt_getrandmax() ::: int; +function mt_getrandmax(): int; -function mt_srand ($seed ::: int = PHP_INT_MIN) ::: void; +function mt_srand ($seed ::: int = PHP_INT_MIN): void; -function rand ($l ::: int = TODO_OVERLOAD, $r ::: int = TODO_OVERLOAD) ::: int; +function rand ($l ::: int = TODO_OVERLOAD, $r ::: int = TODO_OVERLOAD): int; + +function dechex ($number ::: int): string; + +function hexdec ($number ::: string): int; // === UNSUPPORTED === diff --git a/builtin-functions/kphp-light/unsupported/misc.txt b/builtin-functions/kphp-light/unsupported/misc.txt index c5a9db3348..64f2080653 100644 --- a/builtin-functions/kphp-light/unsupported/misc.txt +++ b/builtin-functions/kphp-light/unsupported/misc.txt @@ -13,12 +13,6 @@ function bindec ($number ::: string) ::: int; /** @kphp-extern-func-info generate-stub */ function decbin ($number ::: int) ::: string; -/** @kphp-extern-func-info generate-stub */ -function dechex ($number ::: int) ::: string; - -/** @kphp-extern-func-info generate-stub */ -function hexdec ($number ::: string) ::: int; - /** @kphp-extern-func-info generate-stub */ function crc32 ($s ::: string) ::: int; diff --git a/runtime-common/stdlib/math/math-functions.cpp b/runtime-common/stdlib/math/math-functions.cpp new file mode 100644 index 0000000000..5ffca12848 --- /dev/null +++ b/runtime-common/stdlib/math/math-functions.cpp @@ -0,0 +1,50 @@ +// Compiler for PHP (aka KPHP) +// Copyright (c) 2020 LLC «V Kontakte» +// Distributed under the GPL v3 License, see LICENSE.notice.txt + +#include "runtime-common/stdlib/math/math-functions.h" + +#include + +#include "runtime-common/core/runtime-core.h" +#include "runtime-common/stdlib/string/string-context.h" +#include "runtime-common/stdlib/string/string-functions.h" + +string f$dechex(int64_t number) noexcept { + auto v = static_cast(number); + + char s[17]; + int i = 16; + + const auto &lhex_digits{StringLibConstants::get().lhex_digits}; + do { + s[--i] = lhex_digits[v & 15]; + v >>= 4; + } while (v > 0); + + return {s + i, static_cast(16 - i)}; +} + +int64_t f$hexdec(const string &number) noexcept { + uint64_t v = 0; + bool bad_str_param = number.empty(); + bool overflow = false; + for (string::size_type i = 0; i < number.size(); i++) { + const uint8_t d = hex_to_int(number[i]); + if (unlikely(d == 16)) { + bad_str_param = true; + } else { + v = math_functions_impl_::mult_and_add<16>(v, d, overflow); + } + } + + if (unlikely(bad_str_param)) { + php_warning("Wrong parameter \"%s\" in function hexdec", number.c_str()); + } + if (unlikely(overflow)) { + php_warning("Integer overflow on converting '%s' in function hexdec, " + "the result will be different from PHP", + number.c_str()); + } + return v; +} diff --git a/runtime-common/stdlib/math/math-functions.h b/runtime-common/stdlib/math/math-functions.h index 19d8365e84..99708d485d 100644 --- a/runtime-common/stdlib/math/math-functions.h +++ b/runtime-common/stdlib/math/math-functions.h @@ -5,10 +5,23 @@ #pragma once #include +#include #include +#include #include "runtime-common/core/runtime-core.h" +namespace math_functions_impl_ { + +template +uint64_t mult_and_add(uint64_t x, uint8_t y, bool &overflow) noexcept { + const uint64_t r = x * M + y; + overflow = overflow || r < x || r > static_cast(std::numeric_limits::max()); + return r; +} + +} // namespace math_functions_impl_ + inline double f$ceil(double v) noexcept; inline double f$cos(double v) noexcept; @@ -177,3 +190,7 @@ inline double f$sqrt(double v) noexcept { } return sqrt(v); } + +int64_t f$hexdec(const string &number) noexcept; + +string f$dechex(int64_t number) noexcept; diff --git a/runtime-common/stdlib/stdlib.cmake b/runtime-common/stdlib/stdlib.cmake index a3b2ac1f4e..3fe2a6da34 100644 --- a/runtime-common/stdlib/stdlib.cmake +++ b/runtime-common/stdlib/stdlib.cmake @@ -1,9 +1,10 @@ prepend(STDLIB_ARRAY stdlib/array/ array-functions.cpp) +prepend(STDLIB_MATH stdlib/math/ math-functions.cpp) prepend(STDLIB_SERIALIZATION stdlib/serialization/ json-functions.cpp json-writer.cpp serialize-functions.cpp) prepend(STDLIB_STRING stdlib/string/ mbstring-functions.cpp string-functions.cpp) prepend(STDLIB_SERVER stdlib/server/ url-functions.cpp) -set(STDLIB_SRC ${STDLIB_ARRAY} ${STDLIB_SERIALIZATION} ${STDLIB_STRING} - ${STDLIB_SERVER}) +set(STDLIB_SRC ${STDLIB_ARRAY} ${STDLIB_MATH} ${STDLIB_SERIALIZATION} + ${STDLIB_STRING} ${STDLIB_SERVER}) diff --git a/runtime/math_functions.cpp b/runtime/math_functions.cpp index a9083cd312..5c756344ff 100644 --- a/runtime/math_functions.cpp +++ b/runtime/math_functions.cpp @@ -19,19 +19,11 @@ #include "common/cycleclock.h" #include "runtime-common/stdlib/string/string-context.h" #include "runtime-common/stdlib/math/random-functions.h" -#include "runtime-common/stdlib/string/string-functions.h" #include "runtime/allocator.h" #include "runtime/critical_section.h" #include "server/php-engine-vars.h" namespace { - template - uint64_t mult_and_add(uint64_t x, uint8_t y, bool &overflow) noexcept { - const uint64_t r = x * M + y; - overflow = overflow || r < x || r > static_cast(std::numeric_limits::max()); - return r; - } - int64_t secure_rand_buf(char * const buf, int64_t length) noexcept { #if defined(__APPLE__) arc4random_buf(static_cast(buf), static_cast(length)); @@ -49,7 +41,7 @@ int64_t f$bindec(const string &number) noexcept { for (string::size_type i = 0; i < number.size(); i++) { const char c = number[i]; if (likely(vk::any_of_equal(c, '0', '1'))) { - v = mult_and_add<2>(v, static_cast(c - '0'), overflow); + v = math_functions_impl_::mult_and_add<2>(v, static_cast(c - '0'), overflow); } else { bad_str_param = true; } @@ -79,43 +71,6 @@ string f$decbin(int64_t number) noexcept { return {s + i, static_cast(65 - i)}; } -string f$dechex(int64_t number) noexcept { - auto v = static_cast(number); - - char s[17]; - int i = 16; - - do { - s[--i] = StringLibConstants::get().lhex_digits[v & 15]; - v >>= 4; - } while (v > 0); - - return {s + i, static_cast(16 - i)}; -} - -int64_t f$hexdec(const string &number) noexcept { - uint64_t v = 0; - bool bad_str_param = number.empty(); - bool overflow = false; - for (string::size_type i = 0; i < number.size(); i++) { - const uint8_t d = hex_to_int(number[i]); - if (unlikely(d == 16)) { - bad_str_param = true; - } else { - v = mult_and_add<16>(v, d, overflow); - } - } - - if (unlikely(bad_str_param)) { - php_warning("Wrong parameter \"%s\" in function hexdec", number.c_str()); - } - if (unlikely(overflow)) { - php_warning("Integer overflow on converting '%s' in function hexdec, " - "the result will be different from PHP", number.c_str()); - } - return v; -} - double f$lcg_value() { dl::enter_critical_section();//OK diff --git a/runtime/math_functions.h b/runtime/math_functions.h index 8e56fbf08c..d6514db87b 100644 --- a/runtime/math_functions.h +++ b/runtime/math_functions.h @@ -11,13 +11,8 @@ int64_t f$bindec(const string &number) noexcept; string f$decbin(int64_t number) noexcept; -string f$dechex(int64_t number) noexcept; - -int64_t f$hexdec(const string &number) noexcept; - double f$lcg_value(); - void f$mt_srand(int64_t seed = std::numeric_limits::min()) noexcept; int64_t f$mt_rand(int64_t l, int64_t r) noexcept; diff --git a/tests/phpt/dl/435_base64_encode.php b/tests/phpt/dl/435_base64_encode.php index 98ad8b49df..0f3ccc10c6 100644 --- a/tests/phpt/dl/435_base64_encode.php +++ b/tests/phpt/dl/435_base64_encode.php @@ -1,4 +1,4 @@ -@ok k2_skip +@ok