* Added options flags to hexdumpmaster
| @@ -10,7 +10,6 @@ | |||||
| #define cppcore_define_enum_value_traits(enum, ...) \ | #define cppcore_define_enum_value_traits(enum, ...) \ | ||||
| namespace cppcore { \ | namespace cppcore { \ | ||||
| namespace __impl { \ | |||||
| template<> \ | template<> \ | ||||
| struct enum_value_traits<enum, void> \ | struct enum_value_traits<enum, void> \ | ||||
| { \ | { \ | ||||
| @@ -25,72 +24,67 @@ | |||||
| }); \ | }); \ | ||||
| return value; \ | return value; \ | ||||
| } \ | } \ | ||||
| }; } } | |||||
| }; } | |||||
| namespace cppcore | namespace cppcore | ||||
| { | { | ||||
| namespace __impl | |||||
| /** | |||||
| * @brief Traits class to strore enum to string pairs and the needed data types. | |||||
| * | |||||
| * @tparam T_enum Enum type. | |||||
| */ | |||||
| template<typename T_enum, typename = void> | |||||
| struct enum_value_traits | |||||
| { | { | ||||
| using enum_type = T_enum; | |||||
| using enum_value_pair_type = std::pair<enum_type, std::string>; | |||||
| using enum_value_vector_type = std::vector<enum_value_pair_type>; | |||||
| /** | /** | ||||
| * @brief Traits class to strore enum to string pairs and the needed data types. | |||||
| * | |||||
| * @tparam T_enum Enum type. | |||||
| * @brief Returns a vector with all enum to string value paris. | |||||
| */ | */ | ||||
| template<typename T_enum, typename = void> | |||||
| struct enum_value_traits | |||||
| { | |||||
| using enum_type = T_enum; | |||||
| using enum_value_pair_type = std::pair<enum_type, std::string>; | |||||
| using enum_value_vector_type = std::vector<enum_value_pair_type>; | |||||
| /** | |||||
| * @brief Returns a vector with all enum to string value paris. | |||||
| */ | |||||
| static decltype(auto) get_enum_values(); | |||||
| }; | |||||
| static decltype(auto) get_enum_values(); | |||||
| }; | |||||
| /** | |||||
| * @brief Traits class for enum conersions to store the needed types and data. | |||||
| * | |||||
| * @tparam T_enum Enum type. | |||||
| * @tparam T_traits Traits that stores a list with all enum to string values pairs. | |||||
| */ | |||||
| template< | |||||
| typename T_enum, | |||||
| typename T_traits = enum_value_traits<T_enum>> | |||||
| struct enum_conversion_traits | |||||
| { | |||||
| public: | |||||
| using enum_type = T_enum; | |||||
| using traits_type = T_traits; | |||||
| using enum_to_string_map_type = std::map<enum_type, std::string>; | |||||
| using string_to_enum_map_type = std::map<std::string, enum_type, op_less_invariant_string>; | |||||
| /** | /** | ||||
| * @brief Traits class for enum conersions to store the needed types and data. | |||||
| * | |||||
| * @tparam T_enum Enum type. | |||||
| * @tparam T_traits Traits that stores a list with all enum to string values pairs. | |||||
| * @brief Returns a map with enum to string values. | |||||
| */ | */ | ||||
| template< | |||||
| typename T_enum, | |||||
| typename T_traits = enum_value_traits<T_enum>> | |||||
| struct enum_conversion_traits | |||||
| { | |||||
| public: | |||||
| using enum_type = T_enum; | |||||
| using traits_type = enum_value_traits<enum_type>; | |||||
| using enum_to_string_map_type = std::map<enum_type, std::string>; | |||||
| using string_to_enum_map_type = std::map<std::string, enum_type, op_less_invariant_string>; | |||||
| /** | |||||
| * @brief Returns a map with enum to string values. | |||||
| */ | |||||
| static inline decltype(auto) get_enum_to_string_map(); | |||||
| /** | |||||
| * @brief Returns a map with string to enum values. | |||||
| */ | |||||
| static inline decltype(auto) get_string_to_enum_map(); | |||||
| private: | |||||
| /** | |||||
| * @brief Helper method to create the enum to string map. | |||||
| */ | |||||
| static inline decltype(auto) create_enum_to_string_map(); | |||||
| /** | |||||
| * @brief Helper method to create the string to enum map. | |||||
| */ | |||||
| static inline decltype(auto) create_string_to_enum_map(); | |||||
| }; | |||||
| } | |||||
| static inline decltype(auto) get_enum_to_string_map(); | |||||
| /** | |||||
| * @brief Returns a map with string to enum values. | |||||
| */ | |||||
| static inline decltype(auto) get_string_to_enum_map(); | |||||
| private: | |||||
| /** | |||||
| * @brief Helper method to create the enum to string map. | |||||
| */ | |||||
| static inline decltype(auto) create_enum_to_string_map(); | |||||
| /** | |||||
| * @brief Helper method to create the string to enum map. | |||||
| */ | |||||
| static inline decltype(auto) create_string_to_enum_map(); | |||||
| }; | |||||
| /** | /** | ||||
| * @brief Class to convert enum values to and from string. | * @brief Class to convert enum values to and from string. | ||||
| @@ -100,13 +94,28 @@ namespace cppcore | |||||
| */ | */ | ||||
| template< | template< | ||||
| typename T_enum, | typename T_enum, | ||||
| typename T_traits = __impl::enum_conversion_traits<T_enum>> | |||||
| typename T_traits = enum_conversion_traits<T_enum>> | |||||
| struct enum_conversion | struct enum_conversion | ||||
| { | { | ||||
| using enum_type = T_enum; | using enum_type = T_enum; | ||||
| using base_type = typename std::underlying_type<enum_type>::type; | using base_type = typename std::underlying_type<enum_type>::type; | ||||
| using traits_type = T_traits; | using traits_type = T_traits; | ||||
| /** | |||||
| * @brief Try to convert the given enum value to a string. | |||||
| * | |||||
| * @param[in] value Enum value to convert to string. | |||||
| * @param[out] str Enum value converted to string. | |||||
| * @param[in] add_numeric_value Append the numeric value to the converted enum value. | |||||
| * | |||||
| * @retval true If the conversion was successfull. | |||||
| * @retval false If the enum could not be converted. | |||||
| */ | |||||
| static inline bool try_to_string( | |||||
| enum_type value, | |||||
| std::string& str, | |||||
| bool add_numeric_value = false); | |||||
| /** | /** | ||||
| * @brief Convert the given enum value to a string. | * @brief Convert the given enum value to a string. | ||||
| * | * | ||||
| @@ -5,80 +5,82 @@ | |||||
| namespace cppcore | namespace cppcore | ||||
| { | { | ||||
| namespace __impl | |||||
| /* enum_value_traits */ | |||||
| template<typename T_enum, typename T_enable> | |||||
| decltype(auto) enum_value_traits<T_enum, T_enable>::get_enum_values() | |||||
| { | { | ||||
| static const auto value = enum_value_vector_type(); | |||||
| return value; | |||||
| } | |||||
| /* enum_value_traits */ | |||||
| /* enum_conversion_traits */ | |||||
| template<typename T_enum, typename T_enable> | |||||
| decltype(auto) enum_value_traits<T_enum, T_enable>::get_enum_values() | |||||
| { | |||||
| static const auto value = enum_value_vector_type(); | |||||
| return value; | |||||
| } | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::get_enum_to_string_map() | |||||
| { | |||||
| static const auto value = create_enum_to_string_map(); | |||||
| return value; | |||||
| } | |||||
| /* enum_conversion_traits */ | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::get_string_to_enum_map() | |||||
| { | |||||
| static const auto value = create_string_to_enum_map(); | |||||
| return value; | |||||
| } | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::get_enum_to_string_map() | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::create_enum_to_string_map() | |||||
| { | |||||
| auto& values = traits_type::get_enum_values(); | |||||
| enum_to_string_map_type ret; | |||||
| for (auto& p : values) | |||||
| { | { | ||||
| static const auto value = create_enum_to_string_map(); | |||||
| return value; | |||||
| ret.emplace(p.first, p.second); | |||||
| } | } | ||||
| return ret; | |||||
| } | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::get_string_to_enum_map() | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::create_string_to_enum_map() | |||||
| { | |||||
| auto& values = traits_type::get_enum_values(); | |||||
| string_to_enum_map_type ret; | |||||
| for (auto& p : values) | |||||
| { | { | ||||
| static const auto value = create_string_to_enum_map(); | |||||
| return value; | |||||
| ret.emplace(p.second, p.first); | |||||
| } | } | ||||
| return ret; | |||||
| } | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::create_enum_to_string_map() | |||||
| { | |||||
| auto& values = traits_type::get_enum_values(); | |||||
| enum_to_string_map_type ret; | |||||
| for (auto& p : values) | |||||
| { | |||||
| ret.emplace(p.first, p.second); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| /* enum_conversion */ | |||||
| template<typename T_enum, typename T_traits> | |||||
| decltype(auto) enum_conversion_traits<T_enum, T_traits> | |||||
| ::create_string_to_enum_map() | |||||
| { | |||||
| auto& values = traits_type::get_enum_values(); | |||||
| string_to_enum_map_type ret; | |||||
| for (auto& p : values) | |||||
| { | |||||
| ret.emplace(p.second, p.first); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| template<typename T_enum, typename T_traits> | |||||
| bool enum_conversion<T_enum, T_traits> | |||||
| ::try_to_string(enum_type value, std::string& str, bool add_numeric_value) | |||||
| { | |||||
| auto& map = traits_type::get_enum_to_string_map(); | |||||
| auto it = map.find(value); | |||||
| if (it == map.end()) | |||||
| return false; | |||||
| str = it->second; | |||||
| if (add_numeric_value) | |||||
| str += '(' + std::to_string(static_cast<base_type>(value)) + ')'; | |||||
| return true; | |||||
| } | } | ||||
| /* enum_conversion */ | |||||
| template<typename T_enum, typename T_traits> | template<typename T_enum, typename T_traits> | ||||
| std::string enum_conversion<T_enum, T_traits> | std::string enum_conversion<T_enum, T_traits> | ||||
| ::to_string(enum_type value, bool add_numeric_value) | ::to_string(enum_type value, bool add_numeric_value) | ||||
| { | { | ||||
| std::string ret; | std::string ret; | ||||
| auto& map = traits_type::get_enum_to_string_map(); | |||||
| auto it = map.find(value); | |||||
| if (it != map.end()) | |||||
| { | |||||
| ret = it->second; | |||||
| if (add_numeric_value) | |||||
| ret += '(' + std::to_string(static_cast<base_type>(value)) + ')'; | |||||
| } | |||||
| else | |||||
| if (!try_to_string(value, ret, add_numeric_value)) | |||||
| ret = std::to_string(static_cast<base_type>(value)); | ret = std::to_string(static_cast<base_type>(value)); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -2,9 +2,19 @@ | |||||
| #include <iostream> | #include <iostream> | ||||
| #include <cppcore/misc/flags.h> | |||||
| namespace cppcore | namespace cppcore | ||||
| { | { | ||||
| enum class hexdump_flag | |||||
| { | |||||
| unknown = 0, | |||||
| print_header, | |||||
| print_footer, | |||||
| }; | |||||
| using hexdump_flags = cppcore::shifted_flags<hexdump_flag>; | |||||
| /** | /** | ||||
| * @brief Helper class to print hexdumps. | * @brief Helper class to print hexdumps. | ||||
| */ | */ | ||||
| @@ -15,6 +25,7 @@ namespace cppcore | |||||
| size_t offset; //!< Offset to start numbering at (this will not affect the passed data pointer). | size_t offset; //!< Offset to start numbering at (this will not affect the passed data pointer). | ||||
| size_t split; //!< Add extra colum after specified number of bytes. | size_t split; //!< Add extra colum after specified number of bytes. | ||||
| size_t newline; //!< Add new line after specified number of bytes. | size_t newline; //!< Add new line after specified number of bytes. | ||||
| hexdump_flags flags; //!< Flags with additional options. | |||||
| /** | /** | ||||
| * Constructor. | * Constructor. | ||||
| @@ -24,13 +35,15 @@ namespace cppcore | |||||
| * @param[in] p_offset Offset to start numbering at (this will not affect the passed data pointer). | * @param[in] p_offset Offset to start numbering at (this will not affect the passed data pointer). | ||||
| * @param[in] p_split Add extra colum after specified number of bytes. | * @param[in] p_split Add extra colum after specified number of bytes. | ||||
| * @param[in] p_newline Add new line after specified number of bytes. | * @param[in] p_newline Add new line after specified number of bytes. | ||||
| * @param[in] p_flags Flags with additional options. | |||||
| */ | */ | ||||
| inline hexdump( | inline hexdump( | ||||
| const void * p_data, | |||||
| size_t p_len, | |||||
| size_t p_offset = 0, | |||||
| size_t p_split = 8, | |||||
| size_t p_newline = 16); | |||||
| const void * p_data, | |||||
| size_t p_len, | |||||
| size_t p_offset = 0, | |||||
| size_t p_split = 8, | |||||
| size_t p_newline = 16, | |||||
| const hexdump_flags& p_flags = hexdump_flags::empty()); | |||||
| /** | /** | ||||
| * @pbrief Print the hexdump to the passed stream. | * @pbrief Print the hexdump to the passed stream. | ||||
| @@ -10,16 +10,18 @@ namespace cppcore | |||||
| /* hexdump */ | /* hexdump */ | ||||
| hexdump::hexdump( | hexdump::hexdump( | ||||
| const void * p_data, | |||||
| size_t p_len, | |||||
| size_t p_offset, | |||||
| size_t p_split, | |||||
| size_t p_newline) | |||||
| const void * p_data, | |||||
| size_t p_len, | |||||
| size_t p_offset, | |||||
| size_t p_split, | |||||
| size_t p_newline, | |||||
| const hexdump_flags& p_flags) | |||||
| : data (p_data) | : data (p_data) | ||||
| , len (p_len) | , len (p_len) | ||||
| , offset (p_offset) | , offset (p_offset) | ||||
| , split (p_split) | , split (p_split) | ||||
| , newline (p_newline) | , newline (p_newline) | ||||
| , flags (p_flags) | |||||
| { } | { } | ||||
| void hexdump::print(std::ostream& os) const | void hexdump::print(std::ostream& os) const | ||||
| @@ -31,6 +33,18 @@ namespace cppcore | |||||
| size_t l = 0; | size_t l = 0; | ||||
| std::string s; | std::string s; | ||||
| if (flags.is_set(hexdump_flag::print_header)) | |||||
| { | |||||
| os << " "; | |||||
| for (size_t x = 0; x < newline; ++x) | |||||
| { | |||||
| if (x % split == 0) | |||||
| os.put(' '); | |||||
| os << " " << hex << setw(2) << setfill('0') << x; | |||||
| } | |||||
| os << std::endl; | |||||
| } | |||||
| while (i < len) | while (i < len) | ||||
| { | { | ||||
| if (i % newline == 0) | if (i % newline == 0) | ||||
| @@ -69,6 +83,12 @@ namespace cppcore | |||||
| os << std::string(3 * rest + fill, ' ') | os << std::string(3 * rest + fill, ' ') | ||||
| << " " << s << std::string(rest + fill, ' ') << "|"; | << " " << s << std::string(rest + fill, ' ') << "|"; | ||||
| } | } | ||||
| if (flags.is_set(hexdump_flag::print_footer)) | |||||
| { | |||||
| os << std::endl | |||||
| << hex << setw(8) << setfill('0') << (offset + len); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -18,6 +18,26 @@ cppcore_define_enum_value_traits( | |||||
| { TestEnum::Test3, "Test3" } | { TestEnum::Test3, "Test3" } | ||||
| ); | ); | ||||
| struct custom_enum_value_traits | |||||
| { | |||||
| using enum_type = TestEnum; | |||||
| using enum_value_pair_type = std::pair<enum_type, std::string>; | |||||
| using enum_value_vector_type = std::vector<enum_value_pair_type>; | |||||
| static const enum_value_vector_type& get_enum_values() | |||||
| { | |||||
| static const enum_value_vector_type value({ | |||||
| { TestEnum::Test0, "Fuuu0" }, | |||||
| { TestEnum::Test1, "Fuuu1" }, | |||||
| { TestEnum::Test2, "Fuuu2" }, | |||||
| { TestEnum::Test3, "Fuuu3" } | |||||
| }); | |||||
| return value; | |||||
| } | |||||
| }; | |||||
| using custom_enum_conversion_traits = cppcore::enum_conversion_traits<TestEnum, custom_enum_value_traits>; | |||||
| using custom_enum_conversion = cppcore::enum_conversion <TestEnum, custom_enum_conversion_traits>; | |||||
| using namespace ::cppcore; | using namespace ::cppcore; | ||||
| using namespace ::testing; | using namespace ::testing; | ||||
| @@ -56,3 +76,11 @@ TEST(enum_tests, to_enum) | |||||
| EXPECT_TRUE (enum_conversion<TestEnum>::try_to_enum("2", e, true)); | EXPECT_TRUE (enum_conversion<TestEnum>::try_to_enum("2", e, true)); | ||||
| EXPECT_EQ (TestEnum::Test2, e); | EXPECT_EQ (TestEnum::Test2, e); | ||||
| } | } | ||||
| TEST(enum_tests, custom_traits) | |||||
| { | |||||
| EXPECT_EQ("Fuuu0", custom_enum_conversion::to_string(TestEnum::Test0)); | |||||
| EXPECT_EQ("Fuuu1", custom_enum_conversion::to_string(TestEnum::Test1)); | |||||
| EXPECT_EQ("Fuuu2", custom_enum_conversion::to_string(TestEnum::Test2)); | |||||
| EXPECT_EQ("Fuuu3", custom_enum_conversion::to_string(TestEnum::Test3)); | |||||
| } | |||||