Created
December 24, 2020 09:40
-
-
Save martinmoene/58aacbc965ab79a521a6a9df782357c2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ./format-base.h | |
* | |
* In the public domain | |
* | |
* Author: Martin Moene | |
*/ | |
#ifndef FORMAT_BASE_H_INCLUDED | |
#define FORMAT_BASE_H_INCLUDED | |
#include <algorithm> | |
#include <cmath> | |
#include <cstdint> | |
#include <cstdlib> | |
#include <string> | |
namespace format { | |
// predefined number of symbols between separators ('). | |
const int sep_none = 0; | |
const int sep_each2 = 2; | |
const int sep_each4 = 4; | |
const int sep_each8 = 8; | |
namespace detail { | |
// default number of symbols between separator, in to_string(), format(). | |
const int sep_each_def = sep_each8; | |
// maximum number of symbols in given base to present given number of bits. | |
inline int positions( int const base, int const bits ) | |
{ | |
return static_cast<int>( 0.5 + bits / ( std::log( 1.0 * base ) / std::log( 2.0 ) ) ); | |
} | |
// a left-stripped copy of given text; at default strips space and tab. | |
inline std::string stripped_left( std::string text, std::string const & set = " \t" ) | |
{ | |
return text.erase( 0, text.find_first_not_of( set ) ); | |
} | |
// a copy of given textual number of 'base' and width with separators at 'each' number of symbols, . | |
inline std::string separated( std::string text, int const base, int const bits, int const each = sep_each_def ) | |
{ | |
if ( each == sep_none ) | |
return text; | |
const auto sep_count = base==10 ? 0 : (std::max)( 0, (positions( base, bits ) - 1) / each ); | |
for ( int i = 0; i < sep_count; ++i ) | |
{ | |
text.insert( text.length() - i - (i + 1) * each, 1, '\'' ); | |
} | |
return text; | |
} | |
// a zero-padded or space-padded (base-10 only) copy of given textual number. | |
inline std::string padded( std::string const & text, int const base, int const bits ) | |
{ | |
const auto pad_count = (std::max)( 0, positions(base, bits) - int(text.length()) ); | |
return pad_count > 0 ? std::string( pad_count, base==10 ? ' ':'0' ) + text : text; | |
} | |
} // namespace detail | |
/** | |
* number of bits in given type. | |
*/ | |
template< typename T > | |
std::size_t bits() | |
{ | |
return 8 * sizeof(T); | |
} | |
/** | |
* a textual number with sperators (') removed. | |
*/ | |
inline std::string unseparated( std::string text ) | |
{ | |
text.erase( | |
std::remove( text.begin(), text.end(), '\'' ), | |
text.end() | |
); | |
return text; | |
} | |
/** | |
* unsigned value in given 'base', with given 'bits' width and a separator 'sep_each' [8] symbols. | |
*/ | |
inline std::string format( std::uint32_t const x, int const base, int const bits = 0, int const sep_each = detail::sep_each_def ) | |
{ | |
char buf[65]; | |
return detail::separated( detail::padded( ::_ultoa( x, buf, base ), base, bits ), base, bits, sep_each ); | |
} | |
/** | |
* unsigned value in base 2, at given 'width' and separator each 'sep_each' symbols. | |
*/ | |
inline std::string format2( std::uint32_t const value, int const bits, int const sep_each ) | |
{ | |
return "0b" + format( value, 2, bits, sep_each ); | |
} | |
/** | |
* unsigned value in base 16, at given 'width' and separator each 'sep_each' symbols. | |
*/ | |
inline std::string format16( std::uint32_t const value, int const bits, int const sep_each ) | |
{ | |
return "0x" + format( value, 16, bits, sep_each ); | |
} | |
/** | |
* unsigned value in base 10, width as given. | |
*/ | |
inline std::string format10( std::uint32_t const value, int const bits ) | |
{ | |
return format( value, 10, bits ); | |
} | |
/** | |
* report unsigned value in 'base' presentation; default left-aligned, separator each 8 symbols. | |
*/ | |
inline std::string to_string( std::uint32_t const value, int const base, int const bits = 0, int const sep_each = detail::sep_each_def ) | |
{ | |
return base==2 ? format2 ( value, bits, sep_each ) : | |
base==16 ? format16( value, bits, sep_each ) : format10( value, bits ); | |
} | |
/** | |
* report unsigned value in decimal presentation, like 1234; default left-aligned | |
*/ | |
template< typename T > | |
inline std::string to_string10( T const value, int const width = 0 ) | |
{ | |
const int base10 = 10; | |
return to_string( value, base10, width, sep_none ); | |
} | |
/** | |
* report unsigned value in hexadecimal presentation, like 0x1234'5678 | |
*/ | |
template< typename T > | |
inline std::string to_string16( T const value, int const sep_each = sep_each4 ) | |
{ | |
const int base16 = 16; | |
return to_string( value, base16, bits<T>(), sep_each ); | |
} | |
/** | |
* report unsigned value in binary presentation, like 0b10101010'10101010. | |
*/ | |
template< typename T > | |
inline std::string to_string2( T const value, int const sep_each = sep_each8 ) | |
{ | |
const int base2 = 2; | |
return to_string( value, base2, bits<T>(), sep_each ); | |
} | |
/** | |
* report pattern in decimal, hexadecimal and binary type-specific fixed width presentation, | |
* like: 43690 - 0x007b - 0b10101010'10101010; | |
* width of decimal presentation can be specified: 0 is left-aligned. | |
*/ | |
template< typename T > | |
std::string to_pattern_string( T const pattern, int const width10 = bits<T>() ) | |
{ | |
return to_string10( pattern, width10 ) + " - " + | |
to_string16( pattern ) + " - " + | |
to_string2 ( pattern ); | |
} | |
} // namespace format | |
#endif // FORMAT_BASE_H_INCLUDED |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Exercise format::to_pattern_string(value): | |
// Output: | |
// 117 - 0x75 - 0b01110101 | |
// 43981 - 0xabcd - 0b10101011'11001101 | |
// 306752461 - 0x1248'abcd - 0b00010010'01001000'10101011'11001101 | |
#include "format-base.h" | |
#include <iostream> | |
int main() | |
{ | |
std::cout << | |
format::to_pattern_string( static_cast<std::uint8_t>( 0x75) ) << '\n' << | |
format::to_pattern_string( static_cast<std::uint16_t>(0xabcd) ) << '\n' << | |
format::to_pattern_string( static_cast<std::uint32_t>(0x1248abcd) ) << '\n'; | |
} | |
// g++ -std=c++11 -o main.exe main.cpp && main.exe |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment