• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef IMAGE_IO_BASE_BYTE_DATA_H_  // NOLINT
2 #define IMAGE_IO_BASE_BYTE_DATA_H_  // NOLINT
3 
4 #include <cctype>
5 #include <string>
6 
7 #include "image_io/base/types.h"
8 
9 namespace photos_editing_formats {
10 namespace image_io {
11 
12 /// A string representation of byte data destined to be added to a ByteBuffer,
13 /// and thence defining a portion of a DataSegment.
14 class ByteData {
15  public:
16   /// The type of data represented in the string value.
17   enum Type {
18     /// The string value contains hex digits.
19     kHex,
20 
21     /// The string value contains ascii text. When adding the string to
22     /// a ByteBuffer, do not add the terminating null character.
23     kAscii,
24 
25     /// The string value contains ascii text. When adding the string to
26     /// a ByteBuffer, add the terminating null character as well.
27     kAscii0
28   };
29 
30   /// @param type The type of byte data
31   /// @param value The string value of the byte data.
ByteData(Type type,const std::string & value)32   ByteData(Type type, const std::string& value) : type_(type), value_(value) {}
33 
34   /// @return The type of byte data.
GetType()35   Type GetType() const { return type_; }
36 
37   /// @return The string value of the byte data.
GetValue()38   const std::string& GetValue() const { return value_; }
39 
40   /// @return Whether the byte data string value has a valid length and is made
41   ///     up of a valid set of characters.
IsValid()42   bool IsValid() const { return IsValidLength() && HasValidCharacters(); }
43 
44   /// @return Whether the byte data string value has a valid length. The kAscii
45   ///     and kAscii0 type values have no restrictions, but the kHex type values
46   ///     must have an even number of characters (zero length is ok).
IsValidLength()47   bool IsValidLength() const {
48     return type_ != kHex || ((value_.length() % 2) == 0u);
49   }
50 
51   /// @return Whether the byte data string value is made up of valid characters.
52   ///     The kAscii and kAscii0 type values have no restrictions, but the kHex
53   ///     type values can only have these characters: [0-9][a-f][A-F]
HasValidCharacters()54   bool HasValidCharacters() const {
55     if (type_ != kHex) {
56       return true;
57     }
58     for (const auto& chr : value_) {
59       if (!isxdigit(chr)) {
60         return false;
61       }
62     }
63     return true;
64   }
65 
66   /// @return The number of bytes this data requires when converted to Bytes,
67   ///     or 0 if the byte data is invalid.
GetByteCount()68   size_t GetByteCount() const {
69     if (!IsValid()) {
70       return 0;
71     } else if (type_ == kHex) {
72       return value_.length() / 2;
73     } else if (type_ == kAscii) {
74       return value_.length();
75     } else {
76       return value_.length() + 1;
77     }
78   }
79 
80   /// @param hex_digit The hex character to convert to its decimal equivalent.
81   /// @return The decimal equivalent of the hex_digit, or -1 if the character is
82   ///     not a valid hex digit.
Hex2Decimal(char hex_digit)83   static int Hex2Decimal(char hex_digit) {
84     if (hex_digit >= '0' && hex_digit <= '9') {
85       return static_cast<int>(hex_digit - '0');
86     } else if (hex_digit >= 'a' && hex_digit <= 'f') {
87       return static_cast<int>(hex_digit - 'a' + 10);
88     } else if (hex_digit >= 'A' && hex_digit <= 'F') {
89       return static_cast<int>(hex_digit - 'A' + 10);
90     } else {
91       return -1;
92     }
93   }
94 
95   /// @param hi_char The hi-order nibble of the byte.
96   /// @param hi_char The lo-order nibble of the byte.
97   /// @param value The pointer to the Byte to receive the value.
98   /// @return Whether the conversion was successful.
Hex2Byte(char hi_char,char lo_char,Byte * value)99   static bool Hex2Byte(char hi_char, char lo_char, Byte* value) {
100     int hi = Hex2Decimal(hi_char);
101     int lo = Hex2Decimal(lo_char);
102     if (hi < 0 || lo < 0 || value == nullptr) {
103       return false;
104     }
105     *value = ((hi << 4) | lo);
106     return true;
107   }
108 
109   /// @param value The byte value to convert to a two digit hex string.
110   /// @return The hex string equivalent of the value.
Byte2Hex(Byte value)111   static std::string Byte2Hex(Byte value) {
112     const char kHexChars[] = "0123456789ABCDEF";
113     std::string str(2, ' ');
114     str[0] = kHexChars[(value >> 4) & 0xF];
115     str[1] = kHexChars[value & 0xF];
116     return str;
117   }
118 
119   /// @param value The size_t value to convert to an eight digit hex string.
120   /// @return The big endian hex string equivalent of the value.
Size2BigEndianHex(size_t value)121   static std::string Size2BigEndianHex(size_t value) {
122     std::string hex_string = Byte2Hex((value >> 24) & 0xFF);
123     hex_string += Byte2Hex((value >> 16) & 0xFF);
124     hex_string += Byte2Hex((value >> 8) & 0xFF);
125     hex_string += Byte2Hex(value & 0xFF);
126     return hex_string;
127   }
128 
129  private:
130   Type type_;
131   std::string value_;
132 };
133 
134 }  // namespace image_io
135 }  // namespace photos_editing_formats
136 
137 #endif // IMAGE_IO_BASE_BYTE_DATA_H_  // NOLINT
138