Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizations for <format> #3826

Merged
merged 9 commits into from
Jul 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions stl/inc/format
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ concept _Parse_spec_callbacks = _Parse_align_callbacks<_Ty, _CharT>
&& _Parse_precision_callbacks<_Ty, _CharT>
&& _Width_adapter_callbacks<_Ty, _CharT>
&& _Precision_adapter_callbacks<_Ty, _CharT>
&& requires(_Ty _At, basic_string_view<_CharT> _Sv, _Fmt_align _Aln, _Fmt_sign _Sgn) {
&& requires(_Ty _At, _Fmt_sign _Sgn) {
{ _At._On_sign(_Sgn) } -> same_as<void>;
{ _At._On_hash() } -> same_as<void>;
{ _At._On_zero() } -> same_as<void>;
Expand Down Expand Up @@ -2089,19 +2089,22 @@ public:
}

_NODISCARD size_t _Estimate_required_capacity() const noexcept {
using _CharT = typename _Context::char_type;
size_t _Result = 0;
const auto _Visitor = [&_Result]<class _ArgTy>(const _ArgTy _Arg) noexcept {
if constexpr (is_same_v<_ArgTy, basic_string_view<_CharT>>) {
_Result += _Arg.size();
} else if constexpr (is_same_v<_ArgTy, const _CharT*>) {
using _CharType = typename _Context::char_type;
size_t _Result = 0;

for (size_t _Idx = 0; _Idx < _Num_args; ++_Idx) {
const auto _Packed_index = _Index_array[_Idx];
const auto _Arg_type = _Packed_index._Type();
if (_Arg_type == _Basic_format_arg_type::_String_type) {
const auto _Arg_storage =
reinterpret_cast<const unsigned char*>(_Index_array + _Num_args) + _Packed_index._Index;
const auto _View = _Get_value_from_memory<basic_string_view<_CharType>>(_Arg_storage);
_Result += _View.size();
} else if (_Arg_type == _Basic_format_arg_type::_CString_type) {
_Result += 32; // estimate for length of null-terminated strings
} else {
_Result += 8; // estimate for length of all other arguments
}
};
for (size_t _Idx = 0; _Idx < _Num_args; ++_Idx) {
_STD visit_format_arg(_Visitor, get(_Idx));
}
return _Result;
}
Expand Down Expand Up @@ -2589,9 +2592,11 @@ _NODISCARD _OutputIt _Write_sign(_OutputIt _Out, const _Fmt_sign _Sgn, const boo
return _Out;
}

inline void _Buffer_to_uppercase(char* _First, const char* _Last) {
inline void _Buffer_to_uppercase(char* _First, const char* _Last) noexcept {
for (; _First != _Last; ++_First) {
*_First = static_cast<char>(_CSTD toupper(*_First));
if (*_First >= 'a' && *_First <= 'z') {
*_First -= 'a' - 'A';
}
}
}

Expand Down Expand Up @@ -2722,19 +2727,14 @@ _NODISCARD _OutputIt _Write_integral(
_Specs._Sgn = _Fmt_sign::_Minus;
}

int _Base = 10;
bool _To_upper = false;
int _Base = 10;

switch (_Specs._Type) {
case 'B':
_To_upper = true;
[[fallthrough]];
case 'b':
_Base = 2;
break;
case 'X':
_To_upper = true;
[[fallthrough]];
case 'x':
_Base = 16;
break;
Expand All @@ -2760,7 +2760,7 @@ _NODISCARD _OutputIt _Write_integral(
_Buffer_start += 1;
}

if (_To_upper) {
if (_Specs._Type == 'X') {
_Buffer_to_uppercase(_Buffer_start, _End);
}

Expand Down Expand Up @@ -2965,9 +2965,10 @@ _NODISCARD _OutputIt _Fmt_write(
}
}

_STL_INTERNAL_CHECK(_Exponent == 'e' || _Exponent == 'p');
if (_To_upper) {
_Buffer_to_uppercase(_Buffer_start, _Result.ptr);
_Exponent = static_cast<char>(_CSTD toupper(_Exponent));
_Exponent -= 'a' - 'A';
}

const auto _Is_finite = (_STD isfinite)(_Value);
Expand Down