Browse Source

std_utils - Templatize bin2hex() / hex2bin()

FIX: The random generators, they were totally broken. (exhausting the entropy pool)
LIB-18
heck 4 years ago
parent
commit
b8a208d3a5
  1. 63
      src/std_utils.cc
  2. 8
      src/std_utils.hh
  3. 43
      src/std_utils.hxx
  4. 47
      test/test_rand.cc

63
src/std_utils.cc

@ -342,64 +342,39 @@ namespace pEp {
std::this_thread::sleep_for(timespan);
}
int fastrand(int max)
{
static int g_seed = static_cast<int>(
std::chrono::system_clock::now().time_since_epoch().count());
g_seed = (214013 * g_seed + 2531011);
return ((g_seed >> 16) & 0x7FFF) % max + 1;
}
unsigned char random_char(unsigned char min, unsigned char max)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<short> dis(static_cast<short>(min), static_cast<short>(max));
return static_cast<unsigned char>(dis(gen));
static unsigned seed1 = std::chrono::system_clock::now().time_since_epoch().count();
static std::mt19937 gen{ seed1 };
static std::uniform_int_distribution<unsigned char> dis(min, max);
return dis(gen);
}
std::string random_string(unsigned char min, unsigned char max, int len)
{
std::stringstream ret;
for (int i = 0; i < len; i++) {
ret << random_char(97, 122);
ret << random_char(min, max);
}
return ret.str();
}
std::string bin2hex(const std::vector<unsigned char> &bin)
std::string random_string_fast(unsigned char min, unsigned char max, int len)
{
std::string ret{};
std::stringstream ss{};
for (const auto &i : bin) {
ss << std::hex << std::setfill('0') << std::setw(2) << (int)i;
}
ret = ss.str();
return ret;
}
std::vector<unsigned char> hex2bin(const std::string &hex_str)
{
std::vector<unsigned char> ret{};
if ((hex_str.size() % 2) != 0) {
throw std::runtime_error("hex2bin: Invalid hex string: must be even length");
}
for (int i = 0; i < hex_str.size(); i += 2) {
std::ostringstream val_hex{};
val_hex << hex_str.at(i);
val_hex << hex_str.at(i + 1);
int val_int;
std::istringstream conv_ss{ val_hex.str() };
conv_ss >> std::hex >> val_int;
if (conv_ss.fail()) {
throw std::runtime_error("hex2bin: invalid hex string" + hex_str);
}
ret.push_back((unsigned char)val_int);
int range = std::max(max - min, 1);
std::stringstream ret;
for (int i = 0; i < len; i++) {
ret << (fastrand(range) + min);
}
return ret;
// alternative way
// std::string extract;
// for (std::string::const_iterator pos = hex_str.begin(); pos < hex_str.end(); pos += 2) {
// extract.assign(pos, pos + 2);
// ret.push_back(std::stoi(extract, nullptr, 16));
// }
// return ret;
return ret.str();
}
} // namespace Utils
} // namespace pEp

8
src/std_utils.hh

@ -93,12 +93,16 @@ namespace pEp {
void sleep_millis(int milis);
// Random
int fastrand(int max);
unsigned char random_char(unsigned char min, unsigned char max);
std::string random_string(unsigned char min, unsigned char max, int len);
std::string random_string_fast(unsigned char min, unsigned char max, int len);
// conversion
std::vector<unsigned char> hex2bin(const std::string &hex_str);
std::string bin2hex(const std::vector<unsigned char>& bin);
template<class T>
std::string bin2hex(const T &bin);
template<class T>
T hex2bin(const std::string &hex_str);
} // namespace Utils
} // namespace pEp

43
src/std_utils.hxx

@ -48,6 +48,49 @@ namespace pEp {
}
}
template<class T>
std::string bin2hex(const T &bin)
{
std::string ret{};
std::stringstream ss{};
for (const auto &i : bin) {
ss << std::hex << std::setfill('0') << std::setw(2) << (int)i;
}
ret = ss.str();
return ret;
}
template<class T>
T hex2bin(const std::string &hex_str)
{
T ret{};
if ((hex_str.size() % 2) != 0) {
throw std::runtime_error("hex2bin: Invalid hex string: must be even length");
}
for (int i = 0; i < hex_str.size(); i += 2) {
std::ostringstream val_hex{};
val_hex << hex_str.at(i);
val_hex << hex_str.at(i + 1);
int val_int;
std::istringstream conv_ss{ val_hex.str() };
conv_ss >> std::hex >> val_int;
if (conv_ss.fail()) {
throw std::runtime_error("hex2bin: invalid hex string" + hex_str);
}
ret.push_back(static_cast<typename T::value_type>(val_int));
}
return ret;
// alternative way
// std::string extract;
// for (std::string::const_iterator pos = hex_str.begin(); pos < hex_str.end(); pos += 2) {
// extract.assign(pos, pos + 2);
// ret.push_back(std::stoi(extract, nullptr, 16));
// }
// return ret;
}
} // namespace Utils
} // namespace pEp
#endif // LIBPEPADAPTER_STD_UTILS_HXX

47
test/test_rand.cc

@ -0,0 +1,47 @@
#include "../src/std_utils.hh"
#include "pEp/pEpLog.hh"
#include <pEp/pitytest11/PityTest.hh>
#include <iostream>
#include <chrono>
using namespace pEp;
int main()
{
pEp::Adapter::pEpLog::set_enabled(true);
pEpLog("Random functions benchmark");
int nr_mb = 10;
int nr_bytes = 1024 * 1024 * nr_mb;
pEpLog("generating " + std::to_string(nr_mb) + "MB's of random");
{
pEpLog("Utils::random_char()");
auto time_start = std::chrono::steady_clock::now();
for (int i = 0; i < nr_bytes; i++) {
Utils::random_char(0, 255);
}
auto time_end = std::chrono::steady_clock::now();
double duration_ms = (double)std::chrono::duration_cast<std::chrono::microseconds>(
time_end - time_start)
.count() /
1000;
pEpLog("Time [ms/mbyte]:" + std::to_string(duration_ms / double(nr_mb)));
}
std::cout << "" << std::endl;
{
pEpLog("Utils::Fastrand()");
auto time_start = std::chrono::steady_clock::now();
for (int i = 0; i < nr_bytes; i++) {
Utils::fastrand(255);
}
auto time_end = std::chrono::steady_clock::now();
double duration_ms = (double)std::chrono::duration_cast<std::chrono::microseconds>(
time_end - time_start)
.count() /
1000;
pEpLog("Time [ms/mbyte]:" + std::to_string(duration_ms / double(nr_mb)));
}
return 0;
}
Loading…
Cancel
Save