diff --git a/include/faker-cxx/Helper.h b/include/faker-cxx/Helper.h index eae16f413..4e761ac32 100644 --- a/include/faker-cxx/Helper.h +++ b/include/faker-cxx/Helper.h @@ -1,7 +1,9 @@ #pragma once +#include #include #include +#include #include #include @@ -67,6 +69,32 @@ class Helper return data[index]; } + /** + * @brief Get a random element from a std::set. + * + * @tparam T an element type of the std::set. + * + * @param std::set of elements. + * + * @return T a random element from the std::set. + * + * @code + * std::set chars{'a', 'b', 'c', 'd', 'e'}; + * Helper::setElement(chars) // 'd' + * @endcode + */ + template + static T setElement(const std::set& data) + { + if (data.empty()) + { + throw std::invalid_argument{"Data is empty."}; + } + T item; + std::sample(data.begin(), data.end(), &item, 1, pseudoRandomGenerator); + return item; + } + template struct WeightedElement { diff --git a/src/modules/helper/HelperTest.cpp b/src/modules/helper/HelperTest.cpp index b58053a1c..864200358 100644 --- a/src/modules/helper/HelperTest.cpp +++ b/src/modules/helper/HelperTest.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "gtest/gtest.h" @@ -18,6 +19,24 @@ class HelperTest : public Test namespace { +TEST_F(HelperTest, SetElement) +{ + std::set chars{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'l', 'm'}; + std::vector randomChars; + for (int i = 0; i < 30; ++i) + { + randomChars.push_back(Helper::setElement(chars)); + } + for (auto character : randomChars) + { + ASSERT_TRUE(chars.find(character) != chars.end()); + } +} +TEST_F(HelperTest, SetElementEmptyData) +{ + std::set chars{}; + ASSERT_THROW(Helper::setElement(chars), std::invalid_argument); +} TEST_F(HelperTest, ReplaceSymbolWithNumber) { std::string input = "123#456!"; diff --git a/src/modules/string/String.cpp b/src/modules/string/String.cpp index d80fff49f..4a118e009 100644 --- a/src/modules/string/String.cpp +++ b/src/modules/string/String.cpp @@ -186,8 +186,7 @@ std::string String::binary(GuaranteeMap&& guarantee, unsigned int length) while (true) { // pick random char from targetCharacters - std::mt19937 gen(std::random_device{}()); - std::sample(targetCharacters.begin(), targetCharacters.end(), &generatedChar, 1, gen); + generatedChar = Helper::setElement(targetCharacters); auto it = guarantee.find(generatedChar); // if no constraint on generated char, break out of loop