blob: 8b96d4bbbd3764a1f03a186a6471c566a61a915d [file] [log] [blame]
#ifndef IMAGE_IO_BASE_DATA_SOURCE_H_ // NOLINT
#define IMAGE_IO_BASE_DATA_SOURCE_H_ // NOLINT
#include <memory>
#include "image_io/base/data_destination.h"
#include "image_io/base/data_range.h"
#include "image_io/base/data_segment.h"
#include "image_io/base/types.h"
namespace photos_editing_formats {
namespace image_io {
/// DataSource is the abstract base class for implementations that can provide
/// data from a file or memory buffer or some other container. A data source
/// supports both a pull model for obtaining data, via the GetDataSegment()
/// function, and a push model via a collaborating DataDestination and the
/// TransferData() function.
///
/// Pushing with a DataSource can be a convenient alternative to using a
/// DataDestination directly when there is a large amount of data that is
/// located in a file, or some type of memory structure that be "wrapped" in
/// a DataSource. The push model provides the most efficient (i.e., least
/// copying of bytes) way to move data from one place to another. For usage of
/// this library on mobile devices with limited memory, this mode of operation
/// is the most attractive. Unfortunately, the push model typically assumes the
/// code knows what portion of bytes to push. The discovery of that portion is
/// most often easier to accomplish with a pull model.
///
/// The pull model, while needed for efficient implementation of objects that
/// scan the contents of a data source, does represent a challenge when managing
/// the lifetime of the DataSegment instances returned by the GetDataSegment()
/// function - depending on the implementation of the DataSource, the segment it
/// returns might represent the entire array of data, or it might represent just
/// a portion of it that was read from a file. In the first case, the DataSource
/// would probably want to keep ownership of the DataSegment, while in the other
/// case, the DataSource might very well want to pass ownership on to the caller
/// of GetDataSegment(). This problem is solved by allowing sharing of the
/// ownership of the DataSegment via a std::shared_ptr.
///
/// The push model implemented does not have these complications, so the
/// DataDestination class's Transfer() function takes a simple const reference
/// to a DataSegment, with the ownership firmly held by the DataSource.
class DataSource {
public:
/// The result of a TransferData() operation.
enum TransferDataResult {
/// An error occurred while calling DataDestination::Transfer(), or the
/// data destination was a nullptr.
kTransferDataError,
/// The DataDestination::Transfer() function was not called because the
/// DataRange was empty or the DataSource was not able to supply any data
/// in the range.
kTransferDataNone,
/// The data transfer was successful.
kTransferDataSuccess
};
virtual ~DataSource() = default;
/// Requests the data source to return a DataSegment with a range starting at
/// the given begin location and extending best_size bytes in length if
/// possible. (If not possible, a shorter range of data may be returned. A
/// larger range may also be returned, depending on the DataSource).
/// If a non-null data segment returned, its DataRange is guarenteed to have
/// at least some overlap with the requested range.
/// @param begin The begin location of the requested data segment.
/// @param min_size The min size of the requested data segment. The size of
/// the data segment returned may be larger depending on the data source.
/// @return The data segment, or a nullptr if the range of data did not exist
/// in the data source.
virtual std::shared_ptr<DataSegment> GetDataSegment(size_t begin,
size_t min_size) = 0;
/// Some data sources may need to be reset if they are accessed via repeated
/// calls to GetDataSegment() all the way to the end of the array of bytes.
/// (For example a file-based DataSource might have eof bits that need to be
/// cleared before re-reading data). This function does that kind of thing.
virtual void Reset() = 0;
/// Requests the data source to transfer data in the given range to the given
/// DataDestination. Callers must call the data destination's StartTransfer()
/// function before calling this function, and call its FinishTransfer()
/// after this call. This function will call the data destination's Transfer()
/// function zero or more times.
/// @param data_range The range of data to transfer from this data source to
/// the destination.
/// @param best_size The "best" size of the requested data segment to be sent
/// to the data destination. The size of the data segment that is sent to
/// the data destination may be larger than this value, depending on the
/// data source, or it may be smaller if the requested data range extends
/// past the end of the data source's range.
/// @param data_destination The receiver of the data.
virtual TransferDataResult TransferData(
const DataRange& data_range, size_t best_size,
DataDestination* data_destination) = 0;
};
} // namespace image_io
} // namespace photos_editing_formats
#endif // IMAGE_IO_BASE_DATA_SOURCE_H_ // NOLINT