diff --git a/include/opendht/infohash.h b/include/opendht/infohash.h index 5e07ba1c44dc2f1a9d30ff98623fbce0907da86c..74186ed2e6309a2c97ac14a797c4e182aaf9bfda 100644 --- a/include/opendht/infohash.h +++ b/include/opendht/infohash.h @@ -278,6 +278,8 @@ public: OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const InfoHash& h); OPENDHT_PUBLIC friend std::istream& operator>> (std::istream& s, InfoHash& h); + const char* to_c_str() const; + std::string toString() const; template <typename Packer> diff --git a/src/infohash.cpp b/src/infohash.cpp index 5070abe43fb14e761d21ff6e49d4bcf50a0292d0..7530ca1d4edd305e5eb88727327a90859edbf670 100644 --- a/src/infohash.cpp +++ b/src/infohash.cpp @@ -71,20 +71,40 @@ InfoHash::getRandom() return h; } +struct HexMap : public std::array<std::array<char, 2>, 256> { + HexMap() { + for (size_t i=0; i<size(); i++) { + auto& e = (*this)[i]; + e[0] = hex_digits[(i >> 4) & 0x0F]; + e[1] = hex_digits[i & 0x0F]; + } + } +private: + static constexpr const char* hex_digits = "0123456789abcdef"; +}; + +const char* +InfoHash::to_c_str() const +{ + static const HexMap map; + thread_local std::array<char, HASH_LEN*2+1> buf; + for (size_t i=0; i<HASH_LEN; i++) { + auto b = buf.data()+i*2; + const auto& m = map[(*this)[i]]; + *((uint16_t*)b) = *((uint16_t*)&m); + } + return buf.data(); +} + std::string InfoHash::toString() const { - std::stringstream ss; - ss << *this; - return ss.str(); + return std::string(to_c_str(), HASH_LEN*2); } std::ostream& operator<< (std::ostream& s, const InfoHash& h) { - s << std::hex; - for (unsigned i=0; i<HASH_LEN; i++) - s << std::setfill('0') << std::setw(2) << (unsigned)h[i]; - s << std::dec; + s.write(h.to_c_str(), HASH_LEN*2); return s; }