• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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