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