-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#pragma once | ||
#include <cstddef> | ||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
|
||
namespace iguana::detail { | ||
|
||
#if __cpp_lib_string_resize_and_overwrite >= 202110L | ||
template <typename ch> | ||
inline void resize(std::basic_string<ch> &str, std::size_t sz) { | ||
str.resize_and_overwrite(sz, [sz](ch *, std::size_t) { | ||
return sz; | ||
}); | ||
} | ||
#elif (defined(_MSC_VER) && _MSC_VER <= 1920) | ||
// old msvc don't support visit private, discard it. | ||
|
||
#else | ||
|
||
template <typename Function, Function func_ptr> | ||
class string_thief { | ||
public: | ||
friend void string_set_length_hacker(std::string &self, std::size_t sz) { | ||
#if defined(_MSVC_STL_VERSION) | ||
(self.*func_ptr)._Myval2._Mysize = sz; | ||
#else | ||
#if defined(_LIBCPP_VERSION) | ||
(self.*func_ptr)(sz); | ||
#else | ||
#if (_GLIBCXX_USE_CXX11_ABI == 0) && defined(__GLIBCXX__) | ||
(self.*func_ptr)()->_M_set_length_and_sharable(sz); | ||
#else | ||
#if defined(__GLIBCXX__) | ||
(self.*func_ptr)(sz); | ||
#endif | ||
#endif | ||
#endif | ||
#endif | ||
} | ||
}; | ||
|
||
#if defined(__GLIBCXX__) // libstdc++ | ||
#if (_GLIBCXX_USE_CXX11_ABI == 0) | ||
template class string_thief<decltype(&std::string::_M_rep), | ||
&std::string::_M_rep>; | ||
#else | ||
template class string_thief<decltype(&std::string::_M_set_length), | ||
&std::string::_M_set_length>; | ||
#endif | ||
#elif defined(_LIBCPP_VERSION) | ||
template class string_thief<decltype(&std::string::__set_size), | ||
&std::string::__set_size>; | ||
#elif defined(_MSVC_STL_VERSION) | ||
template class string_thief<decltype(&std::string::_Mypair), | ||
&std::string::_Mypair>; | ||
#endif | ||
|
||
void string_set_length_hacker(std::string &, std::size_t); | ||
|
||
template <typename ch> | ||
inline void resize(std::basic_string<ch> &raw_str, std::size_t sz) { | ||
std::string &str = *reinterpret_cast<std::string *>(&raw_str); | ||
#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || \ | ||
defined(_MSVC_STL_VERSION) | ||
if (sz > str.capacity()) { | ||
str.reserve(sz); | ||
} | ||
string_set_length_hacker(str, sz); | ||
str[sz] = '\0'; | ||
#else | ||
raw_str.resize(sz); | ||
#endif | ||
} | ||
|
||
#endif | ||
|
||
#if (defined(_MSC_VER) && _MSC_VER <= 1920) | ||
#else | ||
void vector_set_length_hacker(std::vector<char> &self, std::size_t sz); | ||
|
||
template <typename Function, Function func_ptr> | ||
class vector_thief { | ||
public: | ||
friend void vector_set_length_hacker(std::vector<char> &self, | ||
std::size_t sz) { | ||
#if defined(_MSVC_STL_VERSION) | ||
(self.*func_ptr)._Myval2._Mylast = self.data() + sz; | ||
#else | ||
#if defined(_LIBCPP_VERSION) | ||
#if _LIBCPP_VERSION < 14000 | ||
((*(std::__vector_base<char, std::allocator<char> > *)(&self)).*func_ptr) = | ||
self.data() + sz; | ||
#else | ||
(self.*func_ptr) = self.data() + sz; | ||
#endif | ||
#else | ||
#if defined(__GLIBCXX__) | ||
((*(std::_Vector_base<char, std::allocator<char> > *)(&self)).*func_ptr) | ||
._M_finish = self.data() + sz; | ||
#endif | ||
#endif | ||
#endif | ||
} | ||
}; | ||
|
||
#if defined(__GLIBCXX__) // libstdc++ | ||
template class vector_thief<decltype(&std::vector<char>::_M_impl), | ||
&std::vector<char>::_M_impl>; | ||
#elif defined(_LIBCPP_VERSION) | ||
template class vector_thief<decltype(&std::vector<char>::__end_), | ||
&std::vector<char>::__end_>; | ||
#elif defined(_MSVC_STL_VERSION) | ||
template class vector_thief<decltype(&std::vector<char>::_Mypair), | ||
&std::vector<char>::_Mypair>; | ||
#endif | ||
|
||
template <typename ch> | ||
inline void resize(std::vector<ch> &raw_vec, std::size_t sz) { | ||
#if defined(__GLIBCXX__) || \ | ||
(defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_ASAN)) || \ | ||
defined(_MSVC_STL_VERSION) | ||
std::vector<char> &vec = *reinterpret_cast<std::vector<char> *>(&raw_vec); | ||
vec.reserve(sz); | ||
vector_set_length_hacker(vec, sz); | ||
#else | ||
raw_vec.resize(sz); | ||
#endif | ||
} | ||
#endif | ||
}; // namespace iguana::detail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
#pragma once | ||
#include "pb_util.hpp" | ||
#include "detail/string_resize.hpp" | ||
|
||
namespace iguana { | ||
namespace detail { | ||
|