1 #ifndef IMAGE_IO_BASE_DATA_SEGMENT_H_ // NOLINT 2 #define IMAGE_IO_BASE_DATA_SEGMENT_H_ // NOLINT 3 4 #include <cstring> 5 #include <memory> 6 7 #include "image_io/base/data_range.h" 8 #include "image_io/base/types.h" 9 10 namespace photos_editing_formats { 11 namespace image_io { 12 13 class DataRange; 14 15 /// A DataSegment represents a portion of a larger "array" of byte data. Each 16 /// data segment knows (via its DataRange member) its location in the larger 17 /// array. The byte data of each data segment is accessed by its location 18 /// in that larger array. Instances of DataSegment are typically created or 19 /// managed by instances of DataSource which offers them up to client code. 20 /// A shared_ptr is used to control the lifetime of DataSegments. For more 21 /// information on this, see the comments in DataSource. 22 class DataSegment { 23 public: 24 /// A creation parameter for indicating whether or not, upon destruction, the 25 /// DataSegment's buffer should be deallocated. 26 enum BufferDispositionPolicy { 27 /// Policy to deallocate the buffer upon destruction. 28 kDelete, 29 30 /// Policy to leave the buffer upon destruction. 31 kDontDelete 32 }; 33 34 /// Creates a new DataSegment with the given DataRange and byte buffer. 35 /// @param data_range The DataRange of the byte data in the buffer. 36 /// @param buffer The byte data of the data segment. 37 /// @param buffer_policy The buffer ownership policy (Delete or DontDelete). 38 /// @return A shared pointer to the data segment. 39 static std::shared_ptr<DataSegment> Create( 40 const DataRange& data_range, const Byte* buffer, 41 BufferDispositionPolicy buffer_policy); 42 43 /// Creates a new DataSegment with the given DataRange and byte buffer. 44 /// The DataSegment takes ownership of the buffer and will delete the buffer 45 /// when the DataSegment itself is destroyed. 46 /// @param data_range The DataRange of the byte data in the buffer. 47 /// @param buffer The byte data of the data segment; The DataSegment takes 48 /// ownership of the buffer and will delete it when it is deleted. 49 /// @return A shared pointer to the data segment. Create(const DataRange & data_range,const Byte * buffer)50 static std::shared_ptr<DataSegment> Create(const DataRange& data_range, 51 const Byte* buffer) { 52 return Create(data_range, buffer, BufferDispositionPolicy::kDelete); 53 } 54 55 /// @return The DataRange of the data in the segment. GetDataRange()56 const DataRange& GetDataRange() const { return data_range_; } 57 58 /// @return The begin location of the segment's data range. GetBegin()59 size_t GetBegin() const { return data_range_.GetBegin(); } 60 61 /// @return The end location of the segment's data range. GetEnd()62 size_t GetEnd() const { return data_range_.GetEnd(); } 63 64 /// @return The length of the segment's data range. GetLength()65 size_t GetLength() const { return data_range_.GetLength(); } 66 67 /// @return Whether the segment's range is valid. Contains(size_t location)68 bool Contains(size_t location) const { 69 return data_range_.Contains(location); 70 } 71 72 /// Gets the validated byte value of the segment at the given location. 73 /// @param location The location in the segment to get the byte value of. 74 /// @return The validated byte at the given location or 0/false if the 75 /// segment's range does does not contain the location. GetValidatedByte(size_t location)76 ValidatedByte GetValidatedByte(size_t location) const { 77 return Contains(location) ? ValidatedByte(buffer_[location - GetBegin()]) 78 : InvalidByte(); 79 } 80 81 /// Returns a pointer to the type at the give location in the dta segment. 82 /// @param location The location of the byte to get the buffer pointer of. 83 /// @return The pointer to the byte in the segment's buffer, or the nullptr 84 /// if the segment does not contain the location. GetBuffer(size_t location)85 const Byte* GetBuffer(size_t location) const { 86 return Contains(location) ? &buffer_[location - GetBegin()] : nullptr; 87 } 88 89 /// Finds the location of the string in the data segment. Although a data 90 /// segment has an array of Bytes (an unsigned quantity), very often the 91 /// data they contain are strings - a sequence of bytes, none of which have 92 /// the sign bit set. As an aid in expressing the alorithms for finding such 93 /// strings, this function allows client code to express the searched-for 94 /// string as a zero-terminated array of chars. 95 /// @param start_location The location at which to start looking. 96 /// @param str The string to find in the segment. The strlen function is 97 /// used to find the length of the string to search for. 98 /// @return The location of the start of the string, or the segment's end 99 /// location value. Find(size_t start_location,const char * str)100 size_t Find(size_t start_location, const char* str) const { 101 return Find(start_location, str, std::strlen(str)); 102 } 103 104 /// Finds the location of the string in the data segment. Although a data 105 /// segment has an array of Bytes (an unsigned quantity), very often the 106 /// data they contain are strings - a sequence of bytes, none of which have 107 /// the sign bit set. As an aid in expressing the alorithms for finding such 108 /// strings, this function allows client code to express the searched-for 109 /// string as an array of chars and a length. 110 /// @param start_location The location at which to start looking. 111 /// @param str The string to find in the segment. 112 /// @param str_length The length of the string to find. 113 /// @return The location of the start of the string, or the segment's end 114 /// location value. 115 size_t Find(size_t location, const char* str, size_t str_length) const; 116 117 /// Finds the location of the given byte value in the data segment. 118 /// @param start_location The location at which to start looking. 119 /// @param value The byte value to search for. 120 /// @return The location of the value, or the segment's end location value. 121 size_t Find(size_t start_location, Byte value) const; 122 123 /// Sometimes the data of concern spans two data segments. For instance, a 124 /// JPEG data segment marker may start at the end of one data segment and 125 /// extend into the following segment. This helper function makes it easier to 126 /// write code to treat two data segments as one entity for the purpose of 127 /// getting the byte value at the given location. 128 /// @param location The location in the segment to get the byte value of. 129 /// @param segment1 The first data segment to use (maybe nullptr). 130 /// @param segment2 The second data segment to use (may be nullptr). 131 /// @return The validated byte at the given location, or InvalidByte() if 132 /// neither segment contains the location. 133 static ValidatedByte GetValidatedByte(size_t location, 134 const DataSegment* segment1, 135 const DataSegment* segment2); 136 137 /// Sometimes the data of concern spans two data segments. For instance, a 138 /// JPEG data segment marker may start at the end of one data segment and 139 /// extend into the following segment. This helper function makes it easier to 140 /// write code to treat two data segments as one entity for the purpose of 141 /// finding a byte value. 142 /// @param start_location The location at which to start looking. 143 /// @param value The byte value to search for. 144 /// @param segment1 The first data segment to use. 145 /// @param segment2 The second data segment to use. 146 /// @return The location of the value if it's found and the two segments are 147 /// contiguous (i.e., if segment1->GetEnd() == segment2->GetBegin()), 148 /// else the max(segment1->GetEnd(), segment2->GetEnd()). 149 static size_t Find(size_t start_location, Byte value, 150 const DataSegment* segment1, const DataSegment* segment2); 151 152 private: DataSegment(const DataRange & data_range,const Byte * buffer,BufferDispositionPolicy buffer_policy)153 DataSegment(const DataRange& data_range, const Byte* buffer, 154 BufferDispositionPolicy buffer_policy) 155 : data_range_(data_range), 156 buffer_(buffer), 157 buffer_policy_(buffer_policy) {} 158 ~DataSegment()159 ~DataSegment() { 160 // If kDelete is not set (default) the buffer memory will remain allocated. 161 if (buffer_policy_ == BufferDispositionPolicy::kDelete) { 162 delete[] buffer_; 163 } 164 } 165 166 /// The default_delete needs to be a friend so that the shared pointer can 167 /// call the private destructor. 168 friend struct std::default_delete<DataSegment>; 169 170 private: 171 /// The data range of the data segment. 172 DataRange data_range_; 173 174 /// The buffer that contains the segment data. 175 const Byte* buffer_; 176 177 /// The policy that dictates whether or not the buffer will be deallocated. 178 BufferDispositionPolicy buffer_policy_; 179 }; 180 181 } // namespace image_io 182 } // namespace photos_editing_formats 183 184 #endif // IMAGE_IO_BASE_DATA_SEGMENT_H_ // NOLINT 185