base16.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Base16 encoder/decoder
  2. //
  3. // Platform: ISO C++ 98/11
  4. // $Id$
  5. //
  6. // (c) __vic 2016
  7. #ifndef __VIC_BASE16_H
  8. #define __VIC_BASE16_H
  9. #include<__vic/defs.h>
  10. #include<__vic/bits.h>
  11. #include<__vic/ascii.h>
  12. #include<exception>
  13. namespace __vic {
  14. //////////////////////////////////////////////////////////////////////////////
  15. class base16
  16. {
  17. template<class ByteReader, class CharWriter, class Func>
  18. static void encode_(ByteReader & , CharWriter & , Func );
  19. struct to_hex_digit_lower
  20. {
  21. char operator()(int d) const { return ascii::toxdigit_lower(d); }
  22. };
  23. struct to_hex_digit_upper
  24. {
  25. char operator()(int d) const { return ascii::toxdigit_upper(d); }
  26. };
  27. public:
  28. struct bad_format : public std::exception
  29. {
  30. const char *what() const noexcept;
  31. };
  32. // Bytes -> Text
  33. template<class ByteReader, class CharWriter>
  34. static void encode_lower(ByteReader , CharWriter );
  35. template<class ByteReader, class CharWriter>
  36. static void encode_upper(ByteReader , CharWriter );
  37. // Text -> Bytes
  38. template<class CharReader, class ByteWriter>
  39. static void decode(CharReader , ByteWriter );
  40. };
  41. //////////////////////////////////////////////////////////////////////////////
  42. //----------------------------------------------------------------------------
  43. template<class ByteReader, class CharWriter, class Func>
  44. inline void base16::encode_(ByteReader &r, CharWriter &w, Func to_hex_digit)
  45. {
  46. unsigned char byte;
  47. while(r.read(byte))
  48. {
  49. w.write(to_hex_digit(hi_nibble(byte)));
  50. w.write(to_hex_digit(lo_nibble(byte)));
  51. }
  52. }
  53. //----------------------------------------------------------------------------
  54. template<class ByteReader, class CharWriter>
  55. void base16::encode_lower(ByteReader r, CharWriter w)
  56. {
  57. encode_(r, w, to_hex_digit_lower());
  58. }
  59. //----------------------------------------------------------------------------
  60. template<class ByteReader, class CharWriter>
  61. void base16::encode_upper(ByteReader r, CharWriter w)
  62. {
  63. encode_(r, w, to_hex_digit_upper());
  64. }
  65. //----------------------------------------------------------------------------
  66. template<class CharReader, class ByteWriter>
  67. void base16::decode(CharReader r, ByteWriter w)
  68. {
  69. bool first = true;
  70. int hi_part;
  71. char ch;
  72. while(r.read(ch))
  73. {
  74. int d = ascii::xdigit_to_number(ch);
  75. if(d < 0) throw bad_format();
  76. if(first) hi_part = d;
  77. else w.write(static_cast<unsigned char>((hi_part << 4) | d));
  78. first = !first;
  79. }
  80. if(!first) throw bad_format(); // the length is odd
  81. }
  82. //----------------------------------------------------------------------------
  83. } // namespace
  84. #endif // header guard