diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a2308129..e9cad359f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,13 @@ All notable changes to this project will be documented in this file ### ⚠ BREAKING CHANGES * moved `hexadecimal` function from `string` to `number` module +* moved `binary` function from `string` to `number` module +* moved `octal` function from `string` to `number` module ### Features * added locale to `book` module +* added locale to `weather` module ## v3.0.0 (28.08.2024) diff --git a/README.md b/README.md index f5fb2ee84..28fed348e 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ int main() - 🌍 Location - countries, cities, zip codes, street addresses - 📚 Lorem - lorem words, sentences, paragraphs - 🏥 Medicine - conditions, medical tests, specialties -- 🎥 Movie - actors, actresses, genres, movie enUSTitles +- 🎥 Movie - actors, actresses, genres, movie titles - 🎶 Music - artists, song names, genres - 🔢 Number - random integers, floating point numbers - 🧑 Person - first, last names, job enUSTitles, hobby, genders, sex, nationality, language @@ -123,6 +123,7 @@ int main() ## Consuming the library with CMake ## With Git submodules and add_library + 1. Add faker to git submodules (execute in project root): ``` @@ -142,14 +143,15 @@ int main() target_link_libraries(main faker-cxx) ``` + ## With FetchContent ```cmake set(BUILD_TESTING OFF) FetchContent_Declare(faker -GIT_REPOSITORY https://github.com/cieslarmichal/faker-cxx.git -GIT_TAG main + GIT_REPOSITORY https://github.com/cieslarmichal/faker-cxx.git + GIT_TAG main ) FetchContent_MakeAvailable(faker) diff --git a/include/faker-cxx/number.h b/include/faker-cxx/number.h index a7187a570..a989b8527 100644 --- a/include/faker-cxx/number.h +++ b/include/faker-cxx/number.h @@ -241,4 +241,35 @@ FAKER_CXX_EXPORT std::string hexadecimal(std::optional min = std::nullopt, * @endcode */ FAKER_CXX_EXPORT std::string octal(unsigned length = 1); + +/** + * @brief Generates a binary string of a specified length + * + * @param length The number of digits to generate. Defaults to `1`. + * + * @returns Binary string. + * + * @throws std::invalid_argument, if length is negative + * + * @code + * faker::string::binary(8) // "0b01110101" + * @endcode + */ +FAKER_CXX_EXPORT std::string binary(int length = 1); + +/** + * @brief Generates a random binary string which has its decimal equivalent between min and max inclusive + * + * @param min the minimum possible decimal equivalent of the output + * @param max the maximum possible decimal equivalent of the output + * + * @returns Binary string. + * + * @throws std::invalid_argument, if min > max, std::invalid_argument if min or max are negative + * + * @code + * faker::string::binary(0, 1024) // "0b10110" + * @endcode + */ +FAKER_CXX_EXPORT std::string binary(int min, int max); } diff --git a/include/faker-cxx/string.h b/include/faker-cxx/string.h index d21cd76e1..27a57fc48 100644 --- a/include/faker-cxx/string.h +++ b/include/faker-cxx/string.h @@ -62,10 +62,6 @@ FAKER_CXX_EXPORT bool isValidGuarantee(GuaranteeMap& guarantee, std::set& */ FAKER_CXX_EXPORT std::string generateAtLeastString(const GuaranteeMap& guarantee); -// namespace { -// std::string generateStringWithGuarantee(GuaranteeMap& guarantee, std::set& targetCharacters, -// unsigned int length); -// } /** * @brief Generates an Universally Unique Identifier with version 4. * @@ -289,35 +285,4 @@ FAKER_CXX_EXPORT std::string numeric(unsigned length = 1, bool allowLeadingZeros * @endcode */ FAKER_CXX_EXPORT std::string numeric(GuaranteeMap&& guarantee, unsigned length = 1, bool allowLeadingZeros = true); - -/** - * @brief Generates a binary string of a specified length - * - * @param length The number of digits to generate. Defaults to `1`. - * - * @returns Binary string. - * - * @throws std::invalid_argument, if length is negative - * - * @code - * faker::string::binary(8) // "0b01110101" - * @endcode - */ -FAKER_CXX_EXPORT std::string binary(int length = 1); - -/** - * @brief Generates a random binary string which has its decimal equivalent between min and max inclusive - * - * @param min the minimum possible decimal equivalent of the output - * @param max the maximum possible decimal equivalent of the output - * - * @returns Binary string. - * - * @throws std::invalid_argument, if min > max, std::invalid_argument if min or max are negative - * - * @code - * faker::string::binary(0, 1024) // "0b10110" - * @endcode - */ -FAKER_CXX_EXPORT std::string binary(int min, int max); } diff --git a/src/modules/number.cpp b/src/modules/number.cpp index 343a140da..76a3c0ba3 100644 --- a/src/modules/number.cpp +++ b/src/modules/number.cpp @@ -67,4 +67,52 @@ std::string octal(unsigned int length) return "0o" + octalNumber; } + +std::string binary(int length) +{ + if (length < 0) + { + throw std::invalid_argument("The length of a binary number cannot be negative"); + } + + std::string binaryNumber; + + for (int i = 0; i < length; ++i) + { + binaryNumber += static_cast(number::integer(1)); + } + + return "0b" + binaryNumber; +} + +std::string binary(int min, int max) +{ + if (min > max) + { + throw std::invalid_argument("min cannot be greater than max"); + } + + if (min < 0 || max < 0) + { + throw std::invalid_argument("The output binary string cannot be negative"); + } + + int num = number::integer(min, max); + + if (num == 0) + { + return "0b0"; + } + + std::string output; + + while (num > 0) + { + int remainder = num % 2; + output = std::to_string(remainder) + output; + num /= 2; + } + + return "0b" + output; +} } diff --git a/src/modules/number_data.h b/src/modules/number_data.h index 1843baa8f..42acc8f0e 100644 --- a/src/modules/number_data.h +++ b/src/modules/number_data.h @@ -7,6 +7,4 @@ namespace faker::number { const std::string hexUpperCharacters{"0123456789ABCDEF"}; const std::string hexLowerCharacters{"0123456789abcdef"}; -const std::set hexUpperCharSet{'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; -const std::set hexLowerCharSet{'a', 'b', 'c', 'd', 'e', 'f', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; } diff --git a/src/modules/string.cpp b/src/modules/string.cpp index 739de7e4c..83fc0f2b4 100644 --- a/src/modules/string.cpp +++ b/src/modules/string.cpp @@ -290,65 +290,4 @@ std::string numeric(GuaranteeMap&& guarantee, const unsigned length, bool allowL return firstChar + generateStringWithGuarantee(guarantee, targetCharacters, length - 1); } } - -std::string binary(int length) -{ - if (length < 0) - { - throw std::invalid_argument("The length of a binary number cannot be negative"); - } - - std::string binaryNumber; - - for (int i = 0; i < length; ++i) - { - binaryNumber += static_cast(number::integer(1)); - } - - return "0b" + binaryNumber; -} - -std::string binary(int min, int max) -{ - if (min > max) - { - throw std::invalid_argument("min cannot be greater than max"); - } - - if (min < 0 || max < 0) - { - throw std::invalid_argument("The output binary string cannot be negative"); - } - - int num = number::integer(min, max); - - if (num == 0) - { - return "0b0"; - } - - std::string output; - - while (num > 0) - { - int remainder = num % 2; - output = std::to_string(remainder) + output; - num /= 2; - } - - return "0b" + output; -} - -std::string binary(GuaranteeMap&& guarantee, unsigned int length) -{ - std::set targetCharacters{'0', '1'}; - - if (!isValidGuarantee(guarantee, targetCharacters, length)) - { - throw std::invalid_argument{"Invalid guarantee."}; - } - - return "0b" + generateStringWithGuarantee(guarantee, targetCharacters, length); -} - } diff --git a/src/modules/string_data.h b/src/modules/string_data.h index 7c903f1bb..6f1d5b27f 100644 --- a/src/modules/string_data.h +++ b/src/modules/string_data.h @@ -13,8 +13,6 @@ const std::string mixedAlphaCharacters{upperCharacters + lowerCharacters}; const std::string lowerAlphanumericCharacters{lowerCharacters + numericCharacters}; const std::string upperAlphanumericCharacters{upperCharacters + numericCharacters}; const std::string mixedAlphanumericCharacters{upperCharacters + lowerCharacters + numericCharacters}; -const std::string hexUpperCharacters{"0123456789ABCDEF"}; -const std::string hexLowerCharacters{"0123456789abcdef"}; const std::string symbolCharacters{"~`!@#$%^&*()_-+={[}]|:;\"'<,>.?/"}; const std::set lowerCharSet{ diff --git a/tests/modules/color_test.cpp b/tests/modules/color_test.cpp index 3e4579591..a3880cb6f 100644 --- a/tests/modules/color_test.cpp +++ b/tests/modules/color_test.cpp @@ -9,7 +9,7 @@ #include "common/string_helper.h" #include "faker-cxx/color.h" #include "faker-cxx/types/hex.h" -#include "string_data.h" +#include "number_data.h" using namespace ::testing; using namespace faker; @@ -77,7 +77,7 @@ TEST_F(ColorTest, shouldGenerateHexColorWithoutAlpha) ASSERT_EQ(prefix, "#"); ASSERT_TRUE( std::ranges::any_of(hexNumber, [hexNumber](char hexNumberCharacter) - { return string::hexLowerCharacters.find(hexNumberCharacter) != std::string::npos; })); + { return number::hexLowerCharacters.find(hexNumberCharacter) != std::string::npos; })); } TEST_F(ColorTest, shouldGenerateHexColorWithAlpha) @@ -91,7 +91,7 @@ TEST_F(ColorTest, shouldGenerateHexColorWithAlpha) ASSERT_EQ(prefix, "0x"); ASSERT_TRUE( std::ranges::any_of(hexNumber, [hexNumber](char hexNumberCharacter) - { return string::hexUpperCharacters.find(hexNumberCharacter) != std::string::npos; })); + { return number::hexUpperCharacters.find(hexNumberCharacter) != std::string::npos; })); } TEST_F(ColorTest, shouldGenerateHslWithoutAlpha) diff --git a/tests/modules/database_test.cpp b/tests/modules/database_test.cpp index f24da835c..b487c8680 100644 --- a/tests/modules/database_test.cpp +++ b/tests/modules/database_test.cpp @@ -5,7 +5,7 @@ #include "database_data.h" #include "faker-cxx/database.h" -#include "string_data.h" +#include "number_data.h" using namespace ::testing; using namespace faker; @@ -55,5 +55,5 @@ TEST_F(DatabaseTest, shouldGenerateMongoDbObjectId) ASSERT_EQ(generatedMongoDbObjectId.size(), 24); ASSERT_TRUE( std::ranges::any_of(generatedMongoDbObjectId, [](char hexNumberCharacter) - { return string::hexLowerCharacters.find(hexNumberCharacter) != std::string::npos; })); + { return number::hexLowerCharacters.find(hexNumberCharacter) != std::string::npos; })); } diff --git a/tests/modules/finance_test.cpp b/tests/modules/finance_test.cpp index f23828d8c..fc6ec5292 100644 --- a/tests/modules/finance_test.cpp +++ b/tests/modules/finance_test.cpp @@ -13,6 +13,7 @@ #include "faker-cxx/types/precision.h" #include "finance_data.h" #include "gmock/gmock.h" +#include "number_data.h" #include "string_data.h" using namespace ::testing; @@ -353,7 +354,7 @@ TEST_F(FinanceTest, shouldGenerateEthereumAddress) ASSERT_EQ(prefix, "0x"); ASSERT_TRUE( std::ranges::any_of(hexNumber, [hexNumber](char hexNumberCharacter) - { return string::hexLowerCharacters.find(hexNumberCharacter) != std::string::npos; })); + { return number::hexLowerCharacters.find(hexNumberCharacter) != std::string::npos; })); } TEST_F(FinanceTest, shouldGenerateExpirationDate) diff --git a/tests/modules/internet_test.cpp b/tests/modules/internet_test.cpp index afa28f5d3..64ac72b3d 100644 --- a/tests/modules/internet_test.cpp +++ b/tests/modules/internet_test.cpp @@ -13,6 +13,7 @@ #include "faker-cxx/internet.h" #include "faker-cxx/number.h" #include "internet_data.h" +#include "number_data.h" #include "person_data.h" #include "string_data.h" #include "word_data.h" @@ -661,7 +662,7 @@ TEST_F(InternetTest, shouldGenerateIpv6) [](const std::string_view& generatedIpv6Part) { return std::ranges::all_of(generatedIpv6Part, [](char hexCharacter) - { return string::hexLowerCharacters.find(hexCharacter) != std::string::npos; }); + { return number::hexLowerCharacters.find(hexCharacter) != std::string::npos; }); })); } diff --git a/tests/modules/number_test.cpp b/tests/modules/number_test.cpp index 8fb52c328..c097b9bfa 100644 --- a/tests/modules/number_test.cpp +++ b/tests/modules/number_test.cpp @@ -192,3 +192,65 @@ TEST_F(NumberTest, shouldGenerateOctalWithPrefix) std::ranges::any_of(generatedOctal, [](char octalNumberCharacter) { return std::string("01234567").find(octalNumberCharacter) != std::string::npos; })); } + +TEST_F(NumberTest, shouldGenerateBinary) +{ + const auto binaryLength = 8; + + const auto generatedBinary = binary(binaryLength); + + const auto prefix = generatedBinary.substr(0, 2); + const auto binaryNumber = generatedBinary.substr(2); + + ASSERT_EQ(generatedBinary.size(), binaryLength + 2); + ASSERT_EQ(prefix, "0b"); + ASSERT_TRUE(std::ranges::any_of(generatedBinary, [](char binaryNumberCharacter) + { return std::string("01").find(binaryNumberCharacter) != std::string::npos; })); +} + +TEST_F(NumberTest, givenValidArguments_shouldGenerateBinaryNumberInRange) +{ + const std::string generatedBinary = binary(1234, 1236); + int n = 1; + int decimalEquivalent = 0; + + for (int i = static_cast(generatedBinary.size() - 1); i >= 0; i--) + { + if (generatedBinary[static_cast(i)] == '1') + { + decimalEquivalent += n; + } + + n *= 2; + } + + ASSERT_EQ(generatedBinary[0], '0'); + ASSERT_EQ(generatedBinary[1], 'b'); + + ASSERT_TRUE(decimalEquivalent >= 1234); + ASSERT_TRUE(decimalEquivalent <= 1236); +} + +TEST_F(NumberTest, shouldGenerateBinaryFor0) +{ + const auto generatedBinary = binary(0, 0); + + ASSERT_EQ(generatedBinary, "0b0"); +} + +TEST_F(NumberTest, shouldGenerateBinaryFor7) +{ + const auto generatedBinary = binary(7, 7); + + ASSERT_EQ(generatedBinary, "0b111"); +} + +TEST_F(NumberTest, givenNegativeArguments_shouldThrowInvalidArgument) +{ + ASSERT_THROW(binary(INT_MIN, -1), std::invalid_argument); +} + +TEST_F(NumberTest, givenMinBiggerThanMax_shouldThrowInvalidArgument) +{ + ASSERT_THROW(binary(10, 1), std::invalid_argument); +} diff --git a/tests/modules/string_test.cpp b/tests/modules/string_test.cpp index 406c6d6a1..89d5dcfd3 100644 --- a/tests/modules/string_test.cpp +++ b/tests/modules/string_test.cpp @@ -894,65 +894,3 @@ TEST_F(StringTest, invalidGuaranteeForNumeric4) GuaranteeMap guarantee = {{'0', {5}}}; ASSERT_THROW(numeric(std::move(guarantee), numericLength, false), std::invalid_argument); } - -TEST_F(StringTest, shouldGenerateBinary) -{ - const auto binaryLength = 8; - - const auto generatedBinary = binary(binaryLength); - - const auto prefix = generatedBinary.substr(0, 2); - const auto binaryNumber = generatedBinary.substr(2); - - ASSERT_EQ(generatedBinary.size(), binaryLength + 2); - ASSERT_EQ(prefix, "0b"); - ASSERT_TRUE(std::ranges::any_of(generatedBinary, [](char binaryNumberCharacter) - { return std::string("01").find(binaryNumberCharacter) != std::string::npos; })); -} - -TEST_F(StringTest, givenValidArguments_shouldGenerateBinaryNumberInRange) -{ - const std::string generatedBinary = binary(1234, 1236); - int n = 1; - int decimalEquivalent = 0; - - for (int i = static_cast(generatedBinary.size() - 1); i >= 0; i--) - { - if (generatedBinary[static_cast(i)] == '1') - { - decimalEquivalent += n; - } - - n *= 2; - } - - ASSERT_EQ(generatedBinary[0], '0'); - ASSERT_EQ(generatedBinary[1], 'b'); - - ASSERT_TRUE(decimalEquivalent >= 1234); - ASSERT_TRUE(decimalEquivalent <= 1236); -} - -TEST_F(StringTest, shouldGenerateBinaryFor0) -{ - const auto generatedBinary = binary(0, 0); - - ASSERT_EQ(generatedBinary, "0b0"); -} - -TEST_F(StringTest, shouldGenerateBinaryFor7) -{ - const auto generatedBinary = binary(7, 7); - - ASSERT_EQ(generatedBinary, "0b111"); -} - -TEST_F(StringTest, givenNegativeArguments_shouldThrowInvalidArgument) -{ - ASSERT_THROW(binary(INT_MIN, -1), std::invalid_argument); -} - -TEST_F(StringTest, givenMinBiggerThanMax_shouldThrowInvalidArgument) -{ - ASSERT_THROW(binary(10, 1), std::invalid_argument); -} diff --git a/tests/modules/system_test.cpp b/tests/modules/system_test.cpp index ea36249e5..0a058b3de 100644 --- a/tests/modules/system_test.cpp +++ b/tests/modules/system_test.cpp @@ -141,7 +141,7 @@ TEST_F(SystemTest, CommonFileNameWithEmptyExtensionTest) const auto actualFileName = commonFileName(); const auto actualExtension = actualFileName.substr(actualFileName.find_last_of('.') + 1); - + EXPECT_FALSE(actualExtension.empty()); }