Skip to content

Commit

Permalink
use std::aligned_storage instead of std::array as a static_buf in Str…
Browse files Browse the repository at this point in the history
…ingLibContext
  • Loading branch information
apolyakov committed Jan 31, 2025
1 parent 7d80b66 commit 19214f4
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 48 deletions.
13 changes: 9 additions & 4 deletions runtime-common/stdlib/string/string-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

#include <array>
#include <cstdint>
#include <memory>
#include <string_view>
#include <type_traits>

#include "common/mixin/not_copyable.h"
#include "common/php-functions.h"
Expand All @@ -30,13 +32,16 @@ inline constexpr std::string_view PERCENT_ = "%";

}; // namespace string_context_impl_

class StringLibContext final : vk::not_copyable {
struct StringLibContext final : vk::not_copyable {
static constexpr int32_t STATIC_BUFFER_LENGTH = 1U << 23U;

private:
static constexpr int32_t MASK_BUFFER_LENGTH = 256;

public:
static constexpr int32_t STATIC_BUFFER_LENGTH = 1U << 23U;
std::aligned_storage<STATIC_BUFFER_LENGTH + 1> storage;

std::array<char, STATIC_BUFFER_LENGTH + 1> static_buf{};
public:
char *static_buf{reinterpret_cast<char *>(std::addressof(storage))};
std::array<char, MASK_BUFFER_LENGTH> mask_buffer{};

int64_t str_replace_count_dummy{};
Expand Down
34 changes: 17 additions & 17 deletions runtime-common/stdlib/string/string-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ string f$nl2br(const string &str, bool is_xhtml) noexcept {
}

string f$number_format(double number, int64_t decimals, const string &dec_point, const string &thousands_sep) noexcept {
char *result_begin = StringLibContext::get().static_buf.data() + StringLibContext::STATIC_BUFFER_LENGTH;
char *result_begin = StringLibContext::get().static_buf + StringLibContext::STATIC_BUFFER_LENGTH;

if (decimals < 0 || decimals > 100) {
php_warning("Wrong parameter decimals (%" PRIi64 ") in function number_format", decimals);
Expand All @@ -607,7 +607,7 @@ string f$number_format(double number, int64_t decimals, const string &dec_point,
frac = round(frac * mul + 1e-9);

int64_t old_decimals = decimals;
while (result_begin > StringLibContext::get().static_buf.data() && decimals--) {
while (result_begin > StringLibContext::get().static_buf && decimals--) {
double x = floor(frac * 0.1 + 0.05);
auto y = static_cast<int32_t>(frac - x * 10 + 0.05);
if (static_cast<unsigned int>(y) >= 10U) {
Expand All @@ -621,7 +621,7 @@ string f$number_format(double number, int64_t decimals, const string &dec_point,

if (old_decimals > 0) {
string::size_type i = dec_point.size();
while (result_begin > StringLibContext::get().static_buf.data() && i > 0) {
while (result_begin > StringLibContext::get().static_buf && i > 0) {
*--result_begin = dec_point[--i];
}
}
Expand All @@ -630,13 +630,13 @@ string f$number_format(double number, int64_t decimals, const string &dec_point,
do {
if (digits && digits % 3 == 0) {
string::size_type i = thousands_sep.size();
while (result_begin > StringLibContext::get().static_buf.data() && i > 0) {
while (result_begin > StringLibContext::get().static_buf && i > 0) {
*--result_begin = thousands_sep[--i];
}
}
digits++;

if (result_begin > StringLibContext::get().static_buf.data()) {
if (result_begin > StringLibContext::get().static_buf) {
double x = floor(number * 0.1 + 0.05);
auto y = static_cast<int32_t>((number - x * 10 + 0.05));
if (static_cast<unsigned int>(y) >= 10U) {
Expand All @@ -646,18 +646,18 @@ string f$number_format(double number, int64_t decimals, const string &dec_point,

*--result_begin = static_cast<char>(y + '0');
}
} while (result_begin > StringLibContext::get().static_buf.data() && number > 0.5);
} while (result_begin > StringLibContext::get().static_buf && number > 0.5);

if (result_begin > StringLibContext::get().static_buf.data() && negative) {
if (result_begin > StringLibContext::get().static_buf && negative) {
*--result_begin = '-';
}

if (result_begin <= StringLibContext::get().static_buf.data()) {
if (result_begin <= StringLibContext::get().static_buf) {
php_critical_error("maximum length of result (%d) exceeded", StringLibContext::STATIC_BUFFER_LENGTH);
return {};
}

return {result_begin, static_cast<string::size_type>(StringLibContext::get().static_buf.data() + StringLibContext::STATIC_BUFFER_LENGTH - result_begin)};
return {result_begin, static_cast<string::size_type>(StringLibContext::get().static_buf + StringLibContext::STATIC_BUFFER_LENGTH - result_begin)};
}

static uint64_t float64_bits(double f) {
Expand Down Expand Up @@ -1000,7 +1000,7 @@ string f$sprintf(const string &format, const array<mixed> &a) noexcept {
StringLibContext::get().static_buf[--cur_pos] = static_cast<char>((arg_int & 1) + '0');
arg_int >>= 1;
} while (arg_int > 0);
piece.assign(StringLibContext::get().static_buf.data() + cur_pos, 70 - cur_pos);
piece.assign(StringLibContext::get().static_buf + cur_pos, 70 - cur_pos);
break;
}
case 'c': {
Expand All @@ -1027,7 +1027,7 @@ string f$sprintf(const string &format, const array<mixed> &a) noexcept {
StringLibContext::get().static_buf[--cur_pos] = static_cast<char>(arg_int % 10 + '0');
arg_int /= 10;
} while (arg_int > 0);
piece.assign(StringLibContext::get().static_buf.data() + cur_pos, 70 - cur_pos);
piece.assign(StringLibContext::get().static_buf + cur_pos, 70 - cur_pos);
break;
}
case 'e':
Expand All @@ -1047,13 +1047,13 @@ string f$sprintf(const string &format, const array<mixed> &a) noexcept {
}
static_SB << format[i];

int len = snprintf(StringLibContext::get().static_buf.data(), StringLibContext::STATIC_BUFFER_LENGTH, static_SB.c_str(), arg_float);
int len = snprintf(StringLibContext::get().static_buf, StringLibContext::STATIC_BUFFER_LENGTH, static_SB.c_str(), arg_float);
if (len >= StringLibContext::STATIC_BUFFER_LENGTH) {
error_too_big = true;
break;
}

piece.assign(StringLibContext::get().static_buf.data(), len);
piece.assign(StringLibContext::get().static_buf, len);
break;
}
case 'o': {
Expand All @@ -1063,7 +1063,7 @@ string f$sprintf(const string &format, const array<mixed> &a) noexcept {
StringLibContext::get().static_buf[--cur_pos] = static_cast<char>((arg_int & 7) + '0');
arg_int >>= 3;
} while (arg_int > 0);
piece.assign(StringLibContext::get().static_buf.data() + cur_pos, 70 - cur_pos);
piece.assign(StringLibContext::get().static_buf + cur_pos, 70 - cur_pos);
break;
}
case 's': {
Expand All @@ -1075,13 +1075,13 @@ string f$sprintf(const string &format, const array<mixed> &a) noexcept {
}
static_SB << 's';

int len = snprintf(StringLibContext::get().static_buf.data(), StringLibContext::STATIC_BUFFER_LENGTH, static_SB.c_str(), arg_string.c_str());
int len = snprintf(StringLibContext::get().static_buf, StringLibContext::STATIC_BUFFER_LENGTH, static_SB.c_str(), arg_string.c_str());
if (len >= StringLibContext::STATIC_BUFFER_LENGTH) {
error_too_big = true;
break;
}

piece.assign(StringLibContext::get().static_buf.data(), len);
piece.assign(StringLibContext::get().static_buf, len);
break;
}
case 'x':
Expand All @@ -1094,7 +1094,7 @@ string f$sprintf(const string &format, const array<mixed> &a) noexcept {
StringLibContext::get().static_buf[--cur_pos] = hex_digits[arg_int & 15];
arg_int >>= 4;
} while (arg_int > 0);
piece.assign(StringLibContext::get().static_buf.data() + cur_pos, 70 - cur_pos);
piece.assign(StringLibContext::get().static_buf + cur_pos, 70 - cur_pos);
break;
}
default:
Expand Down
2 changes: 1 addition & 1 deletion runtime-light/stdlib/zlib/zlib-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ voidpf zlib_static_alloc(voidpf opaque, uInt items, uInt size) noexcept {
return Z_NULL;
}

auto *mem{std::next(StringInstanceState::get().static_buf.data(), *buf_pos_ptr)};
auto *mem{std::next(StringInstanceState::get().static_buf, *buf_pos_ptr)};
*buf_pos_ptr += required_mem;
return mem;
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/datetime/datetime_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,11 @@ string f$strftime(const string &format, int64_t timestamp) {
time_t timestamp_t = timestamp;
localtime_r(&timestamp_t, &t);

if (!strftime(StringLibContext::get().static_buf.data(), StringLibContext::STATIC_BUFFER_LENGTH, format.c_str(), &t)) {
if (!strftime(StringLibContext::get().static_buf, StringLibContext::STATIC_BUFFER_LENGTH, format.c_str(), &t)) {
return {};
}

return string(StringLibContext::get().static_buf.data());
return string(StringLibContext::get().static_buf);
}

Optional<int64_t> f$strtotime(const string &time_str, int64_t timestamp) {
Expand Down
8 changes: 4 additions & 4 deletions runtime/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ bool f$copy(const string &from, const string &to) {
size_t size = stat_buf.st_size;
while (size > 0) {
size_t len = min(size, (size_t)StringLibContext::STATIC_BUFFER_LENGTH);
if (read_safe(read_fd, StringLibContext::get().static_buf.data(), len, from) < (ssize_t)len) {
if (read_safe(read_fd, StringLibContext::get().static_buf, len, from) < (ssize_t)len) {
break;
}
if (write_safe(write_fd, StringLibContext::get().static_buf.data(), len, to) < (ssize_t)len) {
if (write_safe(write_fd, StringLibContext::get().static_buf, len, to) < (ssize_t)len) {
break;
}
size -= len;
Expand Down Expand Up @@ -781,13 +781,13 @@ static Optional<int64_t> file_fpassthru(const Stream &stream) {
dl::enter_critical_section();//OK
while (!feof(f)) {
clearerr(f);
size_t res_size = fread(StringLibContext::get().static_buf.data(), 1, StringLibContext::STATIC_BUFFER_LENGTH, f);
size_t res_size = fread(StringLibContext::get().static_buf, 1, StringLibContext::STATIC_BUFFER_LENGTH, f);
if (ferror(f)) {
dl::leave_critical_section();
php_warning("Error happened during fpassthru from file \"%s\"", stream.to_string().c_str());
return false;
}
print(StringLibContext::get().static_buf.data(), res_size);
print(StringLibContext::get().static_buf, res_size);
result += static_cast<int64_t>(res_size);
}
dl::leave_critical_section();
Expand Down
4 changes: 2 additions & 2 deletions runtime/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ class post_reader {
buf_pos(0),
boundary(boundary) {
if (post == nullptr) {
buf = StringLibContext::get().static_buf.data();
buf = StringLibContext::get().static_buf;
buf_len = 0;
} else {
buf = (char *)post;
Expand Down Expand Up @@ -1699,7 +1699,7 @@ static void init_superglobals_impl(const http_query_data &http_data, const rpc_q
int loaded = 0;
while (loaded < http_data.post_len) {
int to_load = min(StringLibContext::STATIC_BUFFER_LENGTH, http_data.post_len - loaded);
http_load_long_query(StringLibContext::get().static_buf.data(), to_load, to_load);
http_load_long_query(StringLibContext::get().static_buf, to_load, to_load);
loaded += to_load;
}
}
Expand Down
24 changes: 12 additions & 12 deletions runtime/openssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,14 @@ Optional<string> f$md5_file(const string &file_name, bool raw_output) {
size_t size = stat_buf.st_size;
while (size > 0) {
size_t len = min(size, (size_t)StringLibContext::STATIC_BUFFER_LENGTH);
if (read_safe(read_fd, StringLibContext::get().static_buf.data(), len, file_name) < (ssize_t)len) {
if (read_safe(read_fd, StringLibContext::get().static_buf, len, file_name) < (ssize_t)len) {
break;
}
php_assert (MD5_Update(&c, static_cast <const void *> (StringLibContext::get().static_buf.data()), (unsigned long)len) == 1);
php_assert (MD5_Update(&c, static_cast <const void *> (StringLibContext::get().static_buf), (unsigned long)len) == 1);
size -= len;
}
close(read_fd);
php_assert (MD5_Final(reinterpret_cast <unsigned char *> (StringLibContext::get().static_buf.data()), &c) == 1);
php_assert (MD5_Final(reinterpret_cast <unsigned char *> (StringLibContext::get().static_buf), &c) == 1);
critical_section.leave_critical_section();

if (size > 0) {
Expand All @@ -188,12 +188,12 @@ Optional<string> f$md5_file(const string &file_name, bool raw_output) {
if (!raw_output) {
string res(32, false);
for (int i = 15; i >= 0; i--) {
res[2 * i + 1] = StringLibConstants::get().lhex_digits[StringLibContext::get().static_buf.data()[i] & 15];
res[2 * i] = StringLibConstants::get().lhex_digits[(StringLibContext::get().static_buf.data()[i] >> 4) & 15];
res[2 * i + 1] = StringLibConstants::get().lhex_digits[StringLibContext::get().static_buf[i] & 15];
res[2 * i] = StringLibConstants::get().lhex_digits[(StringLibContext::get().static_buf[i] >> 4) & 15];
}
return res;
} else {
return string(StringLibContext::get().static_buf.data(), 16);
return string(StringLibContext::get().static_buf, 16);
}
}

Expand Down Expand Up @@ -224,10 +224,10 @@ int64_t f$crc32_file(const string &file_name) {
size_t size = stat_buf.st_size;
while (size > 0) {
size_t len = min(size, (size_t)StringLibContext::STATIC_BUFFER_LENGTH);
if (read_safe(read_fd, StringLibContext::get().static_buf.data(), len, file_name) < (ssize_t)len) {
if (read_safe(read_fd, StringLibContext::get().static_buf, len, file_name) < (ssize_t)len) {
break;
}
res = crc32_partial(StringLibContext::get().static_buf.data(), (int)len, res);
res = crc32_partial(StringLibContext::get().static_buf, (int)len, res);
size -= len;
}
close(read_fd);
Expand Down Expand Up @@ -364,7 +364,7 @@ bool f$openssl_public_encrypt(const string &data, string &result, const string &

RSA_ptr rsa{EVP_PKEY_get1_RSA(pkey)};
if (RSA_public_encrypt(static_cast<int>(data.size()), reinterpret_cast<const unsigned char *>(data.c_str()),
reinterpret_cast<unsigned char *>(StringLibContext::get().static_buf.data()), rsa.get(), RSA_PKCS1_PADDING) != key_size) {
reinterpret_cast<unsigned char *>(StringLibContext::get().static_buf), rsa.get(), RSA_PKCS1_PADDING) != key_size) {
if (!from_cache) {
EVP_PKEY_free(pkey);
}
Expand All @@ -376,7 +376,7 @@ bool f$openssl_public_encrypt(const string &data, string &result, const string &
if (!from_cache) {
EVP_PKEY_free(pkey);
}
result = string(StringLibContext::get().static_buf.data(), key_size);
result = string(StringLibContext::get().static_buf, key_size);
return true;
}

Expand Down Expand Up @@ -414,7 +414,7 @@ bool f$openssl_private_decrypt(const string &data, string &result, const string

RSA_ptr rsa{EVP_PKEY_get1_RSA(pkey)};
int len = RSA_private_decrypt(static_cast<int>(data.size()), reinterpret_cast<const unsigned char *>(data.c_str()),
reinterpret_cast<unsigned char *>(StringLibContext::get().static_buf.data()), rsa.get(), RSA_PKCS1_PADDING);
reinterpret_cast<unsigned char *>(StringLibContext::get().static_buf), rsa.get(), RSA_PKCS1_PADDING);
if (!from_cache) {
EVP_PKEY_free(pkey);
}
Expand All @@ -424,7 +424,7 @@ bool f$openssl_private_decrypt(const string &data, string &result, const string
return false;
}

result.assign(StringLibContext::get().static_buf.data(), len);
result.assign(StringLibContext::get().static_buf, len);
return true;
}

Expand Down
8 changes: 4 additions & 4 deletions runtime/zlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ voidpf zlib_static_alloc(voidpf opaque, uInt items, uInt size) {
int pos = *buf_pos;
*buf_pos += items * size;
php_assert (*buf_pos <= StringLibContext::STATIC_BUFFER_LENGTH);
return StringLibContext::get().static_buf.data() + pos;
return StringLibContext::get().static_buf + pos;
}

void zlib_static_free(voidpf opaque __attribute__((unused)), voidpf address __attribute__((unused))) {}
Expand Down Expand Up @@ -249,7 +249,7 @@ static string::size_type zlib_decode_raw(vk::string_view s, int encoding) {
strm.avail_in = s.size();
strm.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(s.data()));
strm.avail_out = StringLibContext::STATIC_BUFFER_LENGTH;
strm.next_out = reinterpret_cast<Bytef *>(StringLibContext::get().static_buf.data());
strm.next_out = reinterpret_cast<Bytef *>(StringLibContext::get().static_buf);

int ret = inflateInit2(&strm, encoding);
if (ret != Z_OK) {
Expand Down Expand Up @@ -292,15 +292,15 @@ const char *gzuncompress_raw(vk::string_view s, string::size_type *result_len) {
return "";
}
*result_len = len;
return StringLibContext::get().static_buf.data();
return StringLibContext::get().static_buf;
}

string zlib_decode(const string &s, int encoding) {
int len = zlib_decode_raw({s.c_str(), s.size()}, encoding);
if (len == -1u) {
return {};
}
return {StringLibContext::get().static_buf.data(), static_cast<string::size_type>(len)};
return {StringLibContext::get().static_buf, static_cast<string::size_type>(len)};
}

string f$gzdecode(const string &s) {
Expand Down
4 changes: 2 additions & 2 deletions runtime/zstd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Optional<string> zstd_compress_impl(const string &data, int64_t level = DEFAULT_
}

php_assert(ZSTD_CStreamOutSize() <= StringLibContext::STATIC_BUFFER_LENGTH);
ZSTD_outBuffer out{StringLibContext::get().static_buf.data(), StringLibContext::STATIC_BUFFER_LENGTH, 0};
ZSTD_outBuffer out{StringLibContext::get().static_buf, StringLibContext::STATIC_BUFFER_LENGTH, 0};
ZSTD_inBuffer in{data.c_str(), data.size(), 0};

string encoded_string;
Expand Down Expand Up @@ -105,7 +105,7 @@ Optional<string> zstd_uncompress_impl(const string &data, const string &dict = s

php_assert(ZSTD_DStreamOutSize() <= StringLibContext::STATIC_BUFFER_LENGTH);
ZSTD_inBuffer in{data.c_str(), data.size(), 0};
ZSTD_outBuffer out{StringLibContext::get().static_buf.data(), StringLibContext::STATIC_BUFFER_LENGTH, 0};
ZSTD_outBuffer out{StringLibContext::get().static_buf, StringLibContext::STATIC_BUFFER_LENGTH, 0};

string decoded_string;
while (in.pos < in.size) {
Expand Down

0 comments on commit 19214f4

Please sign in to comment.