diff options
Diffstat (limited to 'includes/image_io/base/data_segment.h')
-rw-r--r-- | includes/image_io/base/data_segment.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/includes/image_io/base/data_segment.h b/includes/image_io/base/data_segment.h new file mode 100644 index 0000000..ec6d584 --- /dev/null +++ b/includes/image_io/base/data_segment.h @@ -0,0 +1,183 @@ +#ifndef IMAGE_IO_BASE_DATA_SEGMENT_H_ // NOLINT +#define IMAGE_IO_BASE_DATA_SEGMENT_H_ // NOLINT + +#include <memory> + +#include "image_io/base/data_range.h" +#include "image_io/base/types.h" + +namespace photos_editing_formats { +namespace image_io { + +class DataRange; + +/// A DataSegment represents a portion of a larger "array" of byte data. Each +/// data segment knows (via its DataRange member) its location in the larger +/// array. The byte data of each data segment is accessed by its location +/// in that larger array. Instances of DataSegment are typically created or +/// managed by instances of DataSource which offers them up to client code. +/// A shared_ptr is used to control the lifetime of DataSegments. For more +/// information on this, see the comments in DataSource. +class DataSegment { + public: + /// A creation parameter for indicating whether or not, upon destruction, the + /// DataSegment's buffer should be deallocated. + enum BufferDispositionPolicy { + /// Policy to deallocate the buffer upon destruction. + kDelete, + + /// Policy to leave the buffer upon destruction. + kDontDelete + }; + + /// Creates a new DataSegment with the given DataRange and byte buffer. + /// @param data_range The DataRange of the byte data in the buffer. + /// @param buffer The byte data of the data segment. + /// @param buffer_policy The buffer ownership policy (Delete or DontDelete). + /// @return A shared pointer to the data segment. + static std::shared_ptr<DataSegment> Create( + const DataRange& data_range, const Byte* buffer, + BufferDispositionPolicy buffer_policy); + + /// Creates a new DataSegment with the given DataRange and byte buffer. + /// The DataSegment takes ownership of the buffer and will delete the buffer + /// when the DataSegment itself is destroyed. + /// @param data_range The DataRange of the byte data in the buffer. + /// @param buffer The byte data of the data segment; The DataSegment takes + /// ownership of the buffer and will delete it when it is deleted. + /// @return A shared pointer to the data segment. + static std::shared_ptr<DataSegment> Create(const DataRange& data_range, + const Byte* buffer) { + return Create(data_range, buffer, BufferDispositionPolicy::kDelete); + } + + /// @return The DataRange of the data in the segment. + const DataRange& GetDataRange() const { return data_range_; } + + /// @return The begin location of the segment's data range. + size_t GetBegin() const { return data_range_.GetBegin(); } + + /// @return The end location of the segment's data range. + size_t GetEnd() const { return data_range_.GetEnd(); } + + /// @return The length of the segment's data range. + size_t GetLength() const { return data_range_.GetLength(); } + + /// @return Whether the segment's range is valid. + bool Contains(size_t location) const { + return data_range_.Contains(location); + } + + /// Gets the validated byte value of the segment at the given location. + /// @param location The location in the segment to get the byte value of. + /// @return The validated byte at the given location or 0/false if the + /// segment's range does does not contain the location. + ValidatedByte GetValidatedByte(size_t location) const { + return Contains(location) ? ValidatedByte(buffer_[location - GetBegin()]) + : InvalidByte(); + } + + /// Returns a pointer to the type at the give location in the dta segment. + /// @param location The location of the byte to get the buffer pointer of. + /// @return The pointer to the byte in the segment's buffer, or the nullptr + /// if the segment does not contain the location. + const Byte* GetBuffer(size_t location) const { + return Contains(location) ? &buffer_[location - GetBegin()] : nullptr; + } + + /// Finds the location of the string in the data segment. Although a data + /// segment has an array of Bytes (an unsigned quantity), very often the + /// data they contain are strings - a sequence of bytes, none of which have + /// the sign bit set. As an aid in expressing the alorithms for finding such + /// strings, this function allows client code to express the searched-for + /// string as a zero-terminated array of chars. + /// @param start_location The location at which to start looking. + /// @param str The string to find in the segment. The strlen function is + /// used to find the length of the string to search for. + /// @return The location of the start of the string, or the segment's end + /// location value. + size_t Find(size_t start_location, const char* str) const { + return Find(start_location, str, strlen(str)); + } + + /// Finds the location of the string in the data segment. Although a data + /// segment has an array of Bytes (an unsigned quantity), very often the + /// data they contain are strings - a sequence of bytes, none of which have + /// the sign bit set. As an aid in expressing the alorithms for finding such + /// strings, this function allows client code to express the searched-for + /// string as an array of chars and a length. + /// @param start_location The location at which to start looking. + /// @param str The string to find in the segment. + /// @param str_length The length of the string to find. + /// @return The location of the start of the string, or the segment's end + /// location value. + size_t Find(size_t location, const char* str, size_t str_length) const; + + /// Finds the location of the given byte value in the data segment. + /// @param start_location The location at which to start looking. + /// @param value The byte value to search for. + /// @return The location of the value, or the segment's end location value. + size_t Find(size_t start_location, Byte value) const; + + /// Sometimes the data of concern spans two data segments. For instance, a + /// JPEG data segment marker may start at the end of one data segment and + /// extend into the following segment. This helper function makes it easier to + /// write code to treat two data segments as one entity for the purpose of + /// getting the byte value at the given location. + /// @param location The location in the segment to get the byte value of. + /// @param segment1 The first data segment to use (maybe nullptr). + /// @param segment2 The second data segment to use (may be nullptr). + /// @return The validated byte at the given location, or InvalidByte() if + /// neither segment contains the location. + static ValidatedByte GetValidatedByte(size_t location, + const DataSegment* segment1, + const DataSegment* segment2); + + /// Sometimes the data of concern spans two data segments. For instance, a + /// JPEG data segment marker may start at the end of one data segment and + /// extend into the following segment. This helper function makes it easier to + /// write code to treat two data segments as one entity for the purpose of + /// finding a byte value. + /// @param start_location The location at which to start looking. + /// @param value The byte value to search for. + /// @param segment1 The first data segment to use. + /// @param segment2 The second data segment to use. + /// @return The location of the value if it's found and the two segments are + /// contiguous (i.e., if segment1->GetEnd() == segment2->GetBegin()), + /// else the max(segment1->GetEnd(), segment2->GetEnd()). + static size_t Find(size_t start_location, Byte value, + const DataSegment* segment1, const DataSegment* segment2); + + private: + DataSegment(const DataRange& data_range, const Byte* buffer, + BufferDispositionPolicy buffer_policy) + : data_range_(data_range), + buffer_(buffer), + buffer_policy_(buffer_policy) {} + + ~DataSegment() { + // If kDelete is not set (default) the buffer memory will remain allocated. + if (buffer_policy_ == BufferDispositionPolicy::kDelete) { + delete[] buffer_; + } + } + + /// The default_delete needs to be a friend so that the shared pointer can + /// call the private destructor. + friend struct std::default_delete<DataSegment>; + + private: + /// The data range of the data segment. + DataRange data_range_; + + /// The buffer that contains the segment data. + const Byte* buffer_; + + /// The policy that dictates whether or not the buffer will be deallocated. + BufferDispositionPolicy buffer_policy_; +}; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_BASE_DATA_SEGMENT_H_ // NOLINT |