epee: avoid string allocation when parsing a pod from string

This commit is contained in:
moneromooo-monero 2018-11-26 00:19:10 +00:00
parent e282e9fa40
commit 3a3858dc90
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
2 changed files with 14 additions and 38 deletions

View File

@ -117,16 +117,12 @@ namespace string_tools
return to_hex::string(to_byte_span(to_span(src))); return to_hex::string(to_byte_span(to_span(src)));
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template<class CharT> inline bool parse_hexstr_to_binbuff(const epee::span<const char> s, epee::span<char>& res)
bool parse_hexstr_to_binbuff(const std::basic_string<CharT>& s, std::basic_string<CharT>& res)
{ {
res.clear(); if (s.size() != res.size() * 2)
if (s.size() & 1)
return false; return false;
try
{ unsigned char *dst = (unsigned char *)&res[0];
res.resize(s.size() / 2);
unsigned char *dst = (unsigned char *)res.data();
const unsigned char *src = (const unsigned char *)s.data(); const unsigned char *src = (const unsigned char *)s.data();
for(size_t i = 0; i < s.size(); i += 2) for(size_t i = 0; i < s.size(); i += 2)
{ {
@ -141,27 +137,14 @@ namespace string_tools
return true; return true;
} }
catch(...)
{
return false;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template<class t_pod_type> inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res)
bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod)
{
static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string buf;
bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf);
if (!res || buf.size() != sizeof(t_pod_type))
{ {
if (s.size() & 1)
return false; return false;
} res.resize(s.size() / 2);
else epee::span<char> rspan((char*)&res[0], res.size());
{ return parse_hexstr_to_binbuff(epee::to_span(s), rspan);
buf.copy(reinterpret_cast<char *>(&t_pod), sizeof(t_pod_type));
return true;
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
PUSH_WARNINGS PUSH_WARNINGS
@ -360,17 +343,10 @@ POP_WARNINGS
bool hex_to_pod(const std::string& hex_str, t_pod_type& s) bool hex_to_pod(const std::string& hex_str, t_pod_type& s)
{ {
static_assert(std::is_pod<t_pod_type>::value, "expected pod type"); static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string hex_str_tr = trim(hex_str);
if(sizeof(s)*2 != hex_str.size()) if(sizeof(s)*2 != hex_str.size())
return false; return false;
std::string bin_buff; epee::span<char> rspan((char*)&s, sizeof(s));
if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff)) return parse_hexstr_to_binbuff(epee::to_span(hex_str), rspan);
return false;
if(bin_buff.size()!=sizeof(s))
return false;
s = *(t_pod_type*)bin_buff.data();
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template<class t_pod_type> template<class t_pod_type>

View File

@ -74,7 +74,7 @@ namespace cryptonote
bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str) bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str)
{ {
crypto::hash h = crypto::null_hash; crypto::hash h = crypto::null_hash;
bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h); bool r = epee::string_tools::hex_to_pod(hash_str, h);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!"); CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!");
// return false if adding at a height we already have AND the hash is different // return false if adding at a height we already have AND the hash is different
@ -292,7 +292,7 @@ namespace cryptonote
// parse the second part as crypto::hash, // parse the second part as crypto::hash,
// if this fails move on to the next record // if this fails move on to the next record
std::string hashStr = record.substr(pos + 1); std::string hashStr = record.substr(pos + 1);
if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash)) if (!epee::string_tools::hex_to_pod(hashStr, hash))
{ {
continue; continue;
} }