blob: 7bfc97e9659bd4f56cbeab2ab96c058760b1f01a [file] [log] [blame]
#ifndef IMAGE_IO_BASE_BYTE_DATA_H_ // NOLINT
#define IMAGE_IO_BASE_BYTE_DATA_H_ // NOLINT
#include <cctype>
#include <string>
#include "image_io/base/types.h"
namespace photos_editing_formats {
namespace image_io {
/// A string representation of byte data destined to be added to a ByteBuffer,
/// and thence defining a portion of a DataSegment.
class ByteData {
public:
/// The type of data represented in the string value.
enum Type {
/// The string value contains hex digits.
kHex,
/// The string value contains ascii text. When adding the string to
/// a ByteBuffer, do not add the terminating null character.
kAscii,
/// The string value contains ascii text. When adding the string to
/// a ByteBuffer, add the terminating null character as well.
kAscii0
};
/// @param type The type of byte data
/// @param value The string value of the byte data.
ByteData(Type type, const std::string& value) : type_(type), value_(value) {}
/// @return The type of byte data.
Type GetType() const { return type_; }
/// @return The string value of the byte data.
const std::string& GetValue() const { return value_; }
/// @return Whether the byte data string value has a valid length and is made
/// up of a valid set of characters.
bool IsValid() const { return IsValidLength() && HasValidCharacters(); }
/// @return Whether the byte data string value has a valid length. The kAscii
/// and kAscii0 type values have no restrictions, but the kHex type values
/// must have an even number of characters (zero length is ok).
bool IsValidLength() const {
return type_ != kHex || ((value_.length() % 2) == 0u);
}
/// @return Whether the byte data string value is made up of valid characters.
/// The kAscii and kAscii0 type values have no restrictions, but the kHex
/// type values can only have these characters: [0-9][a-f][A-F]
bool HasValidCharacters() const {
if (type_ != kHex) {
return true;
}
for (const auto& chr : value_) {
if (!isxdigit(chr)) {
return false;
}
}
return true;
}
/// @return The number of bytes this data requires when converted to Bytes,
/// or 0 if the byte data is invalid.
size_t GetByteCount() const {
if (!IsValid()) {
return 0;
} else if (type_ == kHex) {
return value_.length() / 2;
} else if (type_ == kAscii) {
return value_.length();
} else {
return value_.length() + 1;
}
}
/// @param hex_digit The hex character to convert to its decimal equivalent.
/// @return The decimal equivalent of the hex_digit, or -1 if the character is
/// not a valid hex digit.
static int Hex2Decimal(char hex_digit) {
if (hex_digit >= '0' && hex_digit <= '9') {
return static_cast<int>(hex_digit - '0');
} else if (hex_digit >= 'a' && hex_digit <= 'f') {
return static_cast<int>(hex_digit - 'a' + 10);
} else if (hex_digit >= 'A' && hex_digit <= 'F') {
return static_cast<int>(hex_digit - 'A' + 10);
} else {
return -1;
}
}
/// @param hi_char The hi-order nibble of the byte.
/// @param hi_char The lo-order nibble of the byte.
/// @param value The pointer to the Byte to receive the value.
/// @return Whether the conversion was successful.
static bool Hex2Byte(char hi_char, char lo_char, Byte* value) {
int hi = Hex2Decimal(hi_char);
int lo = Hex2Decimal(lo_char);
if (hi < 0 || lo < 0 || value == nullptr) {
return false;
}
*value = ((hi << 4) | lo);
return true;
}
/// @param value The byte value to convert to a two digit hex string.
/// @return The hex string equivalent of the value.
static std::string Byte2Hex(Byte value) {
const char kHexChars[] = "0123456789ABCDEF";
std::string str(2, ' ');
str[0] = kHexChars[(value >> 4) & 0xF];
str[1] = kHexChars[value & 0xF];
return str;
}
/// @param value The size_t value to convert to an eight digit hex string.
/// @return The big endian hex string equivalent of the value.
static std::string Size2BigEndianHex(size_t value) {
std::string hex_string = Byte2Hex((value >> 24) & 0xFF);
hex_string += Byte2Hex((value >> 16) & 0xFF);
hex_string += Byte2Hex((value >> 8) & 0xFF);
hex_string += Byte2Hex(value & 0xFF);
return hex_string;
}
private:
Type type_;
std::string value_;
};
} // namespace image_io
} // namespace photos_editing_formats
#endif // IMAGE_IO_BASE_BYTE_DATA_H_ // NOLINT