diff options
Diffstat (limited to 'includes/image_io')
21 files changed, 388 insertions, 105 deletions
diff --git a/includes/image_io/base/istream_data_source.h b/includes/image_io/base/istream_data_source.h index 4564e14..9b87542 100644 --- a/includes/image_io/base/istream_data_source.h +++ b/includes/image_io/base/istream_data_source.h @@ -1,46 +1,28 @@ #ifndef IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT #define IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT -#include <iostream> #include <memory> #include <utility> -#include "image_io/base/data_source.h" +#include "image_io/base/istream_ref_data_source.h" namespace photos_editing_formats { namespace image_io { -/// A DataSource that obtains data from an istream. -class IStreamDataSource : public DataSource { +/// A DataSource that obtains data from an istream that it owns. +class IStreamDataSource : public IStreamRefDataSource { public: /// Constructs an IStreamDataSource using the given istream. /// @param istram_ptr The istream from which to read. explicit IStreamDataSource(std::unique_ptr<std::istream> istream_ptr) - : istream_(std::move(istream_ptr)) {} - - void Reset() override; - std::shared_ptr<DataSegment> GetDataSegment(size_t begin, - size_t min_size) override; - TransferDataResult TransferData(const DataRange& data_range, size_t best_size, - DataDestination* data_destination) override; - - private: - /// The worker function to create a DataSegment and fill it with the given - /// number of bytes read from the istream, starting at the given location. - /// @param begin The location in the istream at which to start reading. - /// @param count The number of bytes to read. - /// @return A DataSegment pointer, or nullptr if the read failed. - std::shared_ptr<DataSegment> Read(size_t begin, size_t count); + : IStreamRefDataSource(*istream_ptr), istream_(std::move(istream_ptr)) {} private: - /// The istream from which to read. + /// The istream that is owned by this data source. std::unique_ptr<std::istream> istream_; - - /// The current data segment that was read in the GetDataSegment() function. - std::shared_ptr<DataSegment> current_data_segment_; }; } // namespace image_io } // namespace photos_editing_formats -#endif // IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT +#endif // IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT diff --git a/includes/image_io/base/istream_ref_data_source.h b/includes/image_io/base/istream_ref_data_source.h new file mode 100644 index 0000000..2460bb1 --- /dev/null +++ b/includes/image_io/base/istream_ref_data_source.h @@ -0,0 +1,46 @@ +#ifndef IMAGE_IO_BASE_ISTREAM_REF_DATA_SOURCE_H_ // NOLINT +#define IMAGE_IO_BASE_ISTREAM_REF_DATA_SOURCE_H_ // NOLINT + +#include <iostream> + +#include "image_io/base/data_source.h" + +namespace photos_editing_formats { +namespace image_io { + +/// A DataSource that obtains data from an istream held as a reference. +class IStreamRefDataSource : public DataSource { + public: + /// Constructs an IStreamDataSource using the given istream. + /// @param istream_ref The istream from which to read. + explicit IStreamRefDataSource(std::istream& istream_ref) + : istream_ref_(istream_ref) {} + IStreamRefDataSource(const IStreamRefDataSource&) = delete; + IStreamRefDataSource& operator=(const IStreamRefDataSource&) = delete; + + void Reset() override; + std::shared_ptr<DataSegment> GetDataSegment(size_t begin, + size_t min_size) override; + TransferDataResult TransferData(const DataRange& data_range, size_t best_size, + DataDestination* data_destination) override; + + private: + /// The worker function to create a DataSegment and fill it with the given + /// number of bytes read from the istream, starting at the given location. + /// @param begin The location in the istream at which to start reading. + /// @param count The number of bytes to read. + /// @return A DataSegment pointer, or nullptr if the read failed. + std::shared_ptr<DataSegment> Read(size_t begin, size_t count); + + private: + /// The istream from which to read. + std::istream& istream_ref_; + + /// The current data segment that was read in the GetDataSegment() function. + std::shared_ptr<DataSegment> current_data_segment_; +}; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_BASE_ISTREAM_REF_DATA_SOURCE_H_ // NOLINT diff --git a/includes/image_io/base/message.h b/includes/image_io/base/message.h index 8c225d8..fef2fd6 100644 --- a/includes/image_io/base/message.h +++ b/includes/image_io/base/message.h @@ -15,6 +15,9 @@ class Message { /// A Status message. kStatus, + /// A Warning message. + kWarning, + /// An error from the stdlib was detected. The std::errno variable can be /// used to programmatically decide what to do, or use the std::strerror /// function to get a string description of the error. @@ -66,6 +69,17 @@ class Message { /// @return The text of the message. const std::string& GetText() const { return text_; } + /// @return Whether the message is an error message. + bool IsError() const { + return type_ != Message::kStatus && type_ != Message::kWarning; + } + + /// @return Whether the message is a warning message. + bool IsWarning() const { return type_ == Message::kWarning; } + + /// @return Whether the message is a status message. + bool IsStatus() const { return type_ == Message::kStatus; } + private: /// The type of message. Type type_; diff --git a/includes/image_io/base/message_handler.h b/includes/image_io/base/message_handler.h index dc33679..b60a593 100644 --- a/includes/image_io/base/message_handler.h +++ b/includes/image_io/base/message_handler.h @@ -5,6 +5,7 @@ #include <vector> #include "image_io/base/message.h" +#include "image_io/base/message_stats.h" #include "image_io/base/message_store.h" #include "image_io/base/message_writer.h" @@ -15,20 +16,9 @@ namespace image_io { /// to report status and error conditions. class MessageHandler { public: - /// Initializes the MessageHandler for client use. Multithread applications - /// might find this function useful to call in their initialization section, - /// to guarentee that threads will not create race conditions when calling the - /// Get function for the first time. - static void Init(std::unique_ptr<MessageWriter> message_writer, - std::unique_ptr<MessageStore> message_store); - - /// This function is thread-safe as long as the Init() function is called in - /// non-multiple-threaded startup code; if the Init() fucnction was not called - /// there may be race conditions that causes the message handler returned from - /// Get() called in one thread to be different from that returned by the call - /// in a different thread. - /// @return The message handler used by the code in this library. - static MessageHandler* Get(); + /// The default constructor for MessageHandler creates a MessageWriter and + /// VectorMessageStore for handling writing and storing messages. + MessageHandler(); /// Sets the message writer to use when ReportMessage() is called. If client /// code does not call this function, the MessageHandler returned by the Get() @@ -55,14 +45,29 @@ class MessageHandler { /// should call this function again so that memory is not leaked when it is /// done using this library. void ClearMessages() { + message_stats_->Clear(); if (message_store_) { message_store_->ClearMessages(); } } /// @return Whether the message handler's store has error messages or not. - bool HasErrorMessages() const { - return message_store_ ? message_store_->HasErrorMessages() : false; + bool HasErrorMessages() const { return GetErrorMessageCount() > 0; } + + /// @return The number of error messages reported. + size_t GetErrorMessageCount() const { return message_stats_->error_count; } + + /// @return The number of warning messages reported. + size_t GetWarningMessageCount() const { + return message_stats_->warning_count; + } + + /// @return The number of status messages reported. + size_t GetStatusMessageCount() const { return message_stats_->status_count; } + + /// @return The message stats object as a shared pointer. + std::shared_ptr<MessageStats> GetMessageStats() const { + return message_stats_; } /// @return The vector of errors maintained by the message handler's store. @@ -85,15 +90,14 @@ class MessageHandler { void ReportMessage(const Message& message); private: - MessageHandler() = default; - ~MessageHandler(); - - private: /// The message writer used by ReportMessage, or null. std::unique_ptr<MessageWriter> message_writer_; /// The message store for saving messages for later, or null. std::unique_ptr<MessageStore> message_store_; + + /// The message stats for counting messages. + std::shared_ptr<MessageStats> message_stats_; }; } // namespace image_io diff --git a/includes/image_io/base/message_stats.h b/includes/image_io/base/message_stats.h new file mode 100644 index 0000000..6b338f0 --- /dev/null +++ b/includes/image_io/base/message_stats.h @@ -0,0 +1,21 @@ +#ifndef IMAGE_IO_BASE_MESSAGE_STATS_H_ // NOLINT +#define IMAGE_IO_BASE_MESSAGE_STATS_H_ // NOLINT + +#include "image_io/base/types.h" + +namespace photos_editing_formats { +namespace image_io { + +/// A structure for holding message stats. +struct MessageStats { + MessageStats() { Clear(); } + void Clear() { error_count = warning_count = status_count = 0; } + size_t error_count; + size_t warning_count; + size_t status_count; +}; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_BASE_MESSAGE_STATS_H_ // NOLINT diff --git a/includes/image_io/base/message_store.h b/includes/image_io/base/message_store.h index 1d492f1..8db0b9f 100644 --- a/includes/image_io/base/message_store.h +++ b/includes/image_io/base/message_store.h @@ -61,7 +61,7 @@ class ErrorFlagMessageStore : public MessageStore { ErrorFlagMessageStore() : has_error_(false) {} void ClearMessages() override { has_error_ = false; } void AddMessage(const Message& message) override { - if (message.GetType() != Message::kStatus) { + if (message.IsError()) { has_error_ = true; } } diff --git a/includes/image_io/base/ostream_data_destination.h b/includes/image_io/base/ostream_data_destination.h index 15a1155..d0cf04c 100644 --- a/includes/image_io/base/ostream_data_destination.h +++ b/includes/image_io/base/ostream_data_destination.h @@ -1,58 +1,31 @@ #ifndef IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT #define IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT -#include <iostream> #include <memory> -#include <string> #include <utility> -#include "image_io/base/data_destination.h" +#include "image_io/base/ostream_ref_data_destination.h" namespace photos_editing_formats { namespace image_io { /// A DataDestination that writes its output to an ostream. -class OStreamDataDestination : public DataDestination { +class OStreamDataDestination : public OStreamRefDataDestination { public: /// Constructs an OStreamDataDestination using the given ostream. /// @param ostream_ptr The ostream to which data is written. - explicit OStreamDataDestination(std::unique_ptr<std::ostream> ostream_ptr) - : ostream_(std::move(ostream_ptr)), - bytes_transferred_(0), - has_error_(false) {} - - /// @param name A name to associate with the ostream. Used for error messages. - void SetName(const std::string& name) { name_ = name; } - - /// @return The name associated with the ostream. - const std::string& GetName() const { return name_; } - - /// @return The number of bytes written to the ostream. - size_t GetBytesTransferred() const override { return bytes_transferred_; } - - /// @return True if errors were encountered while writing to the ostream. - bool HasError() const { return has_error_; } - - void StartTransfer() override; - TransferStatus Transfer(const DataRange& transfer_range, - const DataSegment& data_segment) override; - void FinishTransfer() override; + /// @param message_handler An option message handler for writing messages. + OStreamDataDestination(std::unique_ptr<std::ostream> ostream_ptr, + MessageHandler* message_handler) + : OStreamRefDataDestination(*ostream_ptr, message_handler), + ostream_(std::move(ostream_ptr)) {} private: - /// The ostream written to. + /// The ostream that is owned by this data destination. std::unique_ptr<std::ostream> ostream_; - - /// The number of bytes written so far. - size_t bytes_transferred_; - - /// A (file) name to associate with the ostream, used with error messages. - std::string name_; - - /// If true indicates an error has occurred writing to the ostream. - bool has_error_; }; } // namespace image_io } // namespace photos_editing_formats -#endif // IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT +#endif // IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT diff --git a/includes/image_io/base/ostream_ref_data_destination.h b/includes/image_io/base/ostream_ref_data_destination.h new file mode 100644 index 0000000..266e2be --- /dev/null +++ b/includes/image_io/base/ostream_ref_data_destination.h @@ -0,0 +1,66 @@ +#ifndef IMAGE_IO_BASE_OSTREAM_REF_DATA_DESTINATION_H_ // NOLINT +#define IMAGE_IO_BASE_OSTREAM_REF_DATA_DESTINATION_H_ // NOLINT + +#include <iostream> +#include <string> + +#include "image_io/base/data_destination.h" +#include "image_io/base/message_handler.h" + +namespace photos_editing_formats { +namespace image_io { + +/// A DataDestination that writes its output to an ostream held as a reference. +class OStreamRefDataDestination : public DataDestination { + public: + /// Constructs an OStreamDataDestination using the given ostream. + /// @param ostream_ref The ostream to which data is written. + /// @param message_handler An option message handler for writing messages. + OStreamRefDataDestination(std::ostream& ostream_ref, + MessageHandler* message_handler) + : ostream_ref_(ostream_ref), + message_handler_(message_handler), + bytes_transferred_(0), + has_error_(false) {} + OStreamRefDataDestination(const OStreamRefDataDestination&) = delete; + OStreamRefDataDestination& operator=(const OStreamRefDataDestination&) = + delete; + + /// @param name A name to associate with the ostream. Used for error messages. + void SetName(const std::string& name) { name_ = name; } + + /// @return The name associated with the ostream. + const std::string& GetName() const { return name_; } + + /// @return The number of bytes written to the ostream. + size_t GetBytesTransferred() const override { return bytes_transferred_; } + + /// @return True if errors were encountered while writing to the ostream. + bool HasError() const { return has_error_; } + + void StartTransfer() override; + TransferStatus Transfer(const DataRange& transfer_range, + const DataSegment& data_segment) override; + void FinishTransfer() override; + + private: + /// The ostream written to. + std::ostream& ostream_ref_; + + /// An optional message handler to write messages to. + MessageHandler* message_handler_; + + /// The number of bytes written so far. + size_t bytes_transferred_; + + /// A (file) name to associate with the ostream, used with error messages. + std::string name_; + + /// If true indicates an error has occurred writing to the ostream. + bool has_error_; +}; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_BASE_OSTREAM_REF_DATA_DESTINATION_H_ // NOLINT diff --git a/includes/image_io/base/types.h b/includes/image_io/base/types.h index aaa88b3..ed49350 100644 --- a/includes/image_io/base/types.h +++ b/includes/image_io/base/types.h @@ -7,8 +7,14 @@ namespace photos_editing_formats { namespace image_io { -/// Byte is the noumenon unit of data. +/// The various integer and byte types used in this package. using Byte = std::uint8_t; +using Int32 = std::int32_t; +using Int64 = std::int64_t; +using UInt8 = std::uint8_t; +using UInt16 = std::uint16_t; +using UInt32 = std::uint32_t; +using UInt64 = std::uint64_t; /// A Byte value and a validity flag. struct ValidatedByte { diff --git a/includes/image_io/base/validated_number.h b/includes/image_io/base/validated_number.h new file mode 100644 index 0000000..ead5ab3 --- /dev/null +++ b/includes/image_io/base/validated_number.h @@ -0,0 +1,38 @@ +#ifndef IMAGE_IO_BASE_VALIDATED_NUMBER_H_ // NOLINT +#define IMAGE_IO_BASE_VALIDATED_NUMBER_H_ // NOLINT + +#include <sstream> +#include <string> + +namespace photos_editing_formats { +namespace image_io { + +template <class T> +struct ValidatedNumber { + ValidatedNumber() : ValidatedNumber(T(), false) {} + ValidatedNumber(const T& value_, bool is_valid_) + : value(value_), is_valid(is_valid_) {} + using value_type = T; + T value; + bool is_valid; +}; + +template <class T> +ValidatedNumber<T> GetValidatedNumber(const std::string& str) { + std::stringstream ss(str); + ValidatedNumber<T> result; + ss >> result.value; + if (!ss.fail()) { + std::string extra; + ss >> extra; + if (extra.empty()) { + result.is_valid = true; + } + } + return result; +} + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_BASE_VALIDATED_NUMBER_H_ // NOLINT diff --git a/includes/image_io/extras/base64_decoder_data_destination.h b/includes/image_io/extras/base64_decoder_data_destination.h index cde1dbc..107ea4b 100644 --- a/includes/image_io/extras/base64_decoder_data_destination.h +++ b/includes/image_io/extras/base64_decoder_data_destination.h @@ -5,6 +5,7 @@ #include <vector> #include "image_io/base/data_destination.h" +#include "image_io/base/message_handler.h" namespace photos_editing_formats { namespace image_io { @@ -16,8 +17,11 @@ class Base64DecoderDataDestination : public DataDestination { public: /// @param next_destination The next DataDestination in the chain which will /// be sent the decoded bytes received by the Transfer() function. - explicit Base64DecoderDataDestination(DataDestination* next_destination) + /// @param message_handler An optional message handler to write messages to. + Base64DecoderDataDestination(DataDestination* next_destination, + MessageHandler* message_handler) : next_destination_(next_destination), + message_handler_(message_handler), next_decoded_location_(0), has_error_(false) {} @@ -39,6 +43,9 @@ class Base64DecoderDataDestination : public DataDestination { /// The destination that the decoded data is sent to. DataDestination* next_destination_; + /// An optional message handler to write messages to. + MessageHandler* message_handler_; + /// If the transfer_range parameter of the Transfer function does not have a /// length that is a multiple of 4, then the leftover bytes are placed in this /// vector and are prepended to the data in the next call to Transfer. diff --git a/includes/image_io/gcontainer/gcontainer.h b/includes/image_io/gcontainer/gcontainer.h index c0bd66f..118956c 100644 --- a/includes/image_io/gcontainer/gcontainer.h +++ b/includes/image_io/gcontainer/gcontainer.h @@ -1,6 +1,7 @@ #ifndef IMAGE_IO_GCONTAINER_GCONTAINER_H_ // NOLINT #define IMAGE_IO_GCONTAINER_GCONTAINER_H_ // NOLINT +#include <iostream> #include <string> #include <vector> @@ -29,6 +30,11 @@ bool ParseFileAfterImage(const std::string& input_file_name, size_t file_start_offset, size_t file_length, std::string* out_file_contents); +// Used by AOSP. +bool ParseFileAfterImageFromStream(size_t start_offset, size_t length, + std::istream& input_jpeg_stream, + std::string* out_contents); + } // namespace gcontainer } // namespace image_io } // namespace photos_editing_formats diff --git a/includes/image_io/jpeg/jpeg_apple_depth_builder.h b/includes/image_io/jpeg/jpeg_apple_depth_builder.h index 7f5c595..4c0f192 100644 --- a/includes/image_io/jpeg/jpeg_apple_depth_builder.h +++ b/includes/image_io/jpeg/jpeg_apple_depth_builder.h @@ -6,6 +6,7 @@ #include "image_io/base/data_destination.h" #include "image_io/base/data_range.h" #include "image_io/base/data_source.h" +#include "image_io/base/message_handler.h" namespace photos_editing_formats { namespace image_io { @@ -14,8 +15,9 @@ namespace image_io { /// and original depth image. class JpegAppleDepthBuilder { public: - JpegAppleDepthBuilder() - : primary_image_data_source_(nullptr), + explicit JpegAppleDepthBuilder(MessageHandler* message_handler) + : message_handler_(message_handler), + primary_image_data_source_(nullptr), depth_image_data_source_(nullptr), data_destination_(nullptr) {} @@ -69,6 +71,9 @@ class JpegAppleDepthBuilder { /// @param data_range The data range in the data source to transfer. bool TransferData(DataSource *data_source, const DataRange& data_range); + /// An optional message handler to write messages to. + MessageHandler* message_handler_; + /// The data source containing the primary image. DataSource* primary_image_data_source_; diff --git a/includes/image_io/jpeg/jpeg_image_extractor.h b/includes/image_io/jpeg/jpeg_image_extractor.h index 91237e5..966f609 100644 --- a/includes/image_io/jpeg/jpeg_image_extractor.h +++ b/includes/image_io/jpeg/jpeg_image_extractor.h @@ -3,6 +3,7 @@ #include "image_io/base/data_destination.h" #include "image_io/base/data_source.h" +#include "image_io/base/message_handler.h" #include "image_io/jpeg/jpeg_info.h" namespace photos_editing_formats { @@ -15,8 +16,12 @@ class JpegImageExtractor { public: /// @param jpeg_info The JpegInfo instance containing depth/image data. /// @param data_source The DataSource from which to transfer depth/image data. - JpegImageExtractor(const JpegInfo& jpeg_info, DataSource* data_source) - : jpeg_info_(jpeg_info), data_source_(data_source) {} + /// @param message_handler An optional message handler to write messages to. + JpegImageExtractor(const JpegInfo& jpeg_info, DataSource* data_source, + MessageHandler* message_handler) + : jpeg_info_(jpeg_info), + data_source_(data_source), + message_handler_(message_handler) {} /// This function extracts the Apple depth image from the DataSource and sends /// the bytes to the DataDestination. @@ -65,6 +70,9 @@ class JpegImageExtractor { /// The data source from which the images are extracted. DataSource* data_source_; + + /// An optional message handler to write messages to. + MessageHandler* message_handler_; }; } // namespace image_io diff --git a/includes/image_io/jpeg/jpeg_info_builder.h b/includes/image_io/jpeg/jpeg_info_builder.h index ee4d611..a9f1928 100644 --- a/includes/image_io/jpeg/jpeg_info_builder.h +++ b/includes/image_io/jpeg/jpeg_info_builder.h @@ -34,6 +34,12 @@ class JpegInfoBuilder : public JpegSegmentProcessor { /// @param type The type of segment info to capture the value of. void SetCaptureSegmentBytes(const std::string& segment_info_type); + /// @return True if the segment is a primary Xmp segment. + bool IsPrimaryXmpSegment(const JpegSegment& segment) const; + + /// @return True if the segment is an extended Xmp segment. + bool IsExtendedXmpSegment(const JpegSegment& segment) const; + void Start(JpegScanner* scanner) override; void Process(JpegScanner* scanner, const JpegSegment& segment) override; void Finish(JpegScanner* scanner) override; @@ -45,12 +51,6 @@ class JpegInfoBuilder : public JpegSegmentProcessor { /// @return True if the data members indicate Apple matte is present. bool HasAppleMatte() const; - /// @return True if the segment is a primary Xmp segment. - bool IsPrimaryXmpSegment(const JpegSegment& segment) const; - - /// @return True if the segment is an extended Xmp segment. - bool IsExtendedXmpSegment(const JpegSegment& segment) const; - /// @return True if the segment is an Mpf segment. bool IsMpfSegment(const JpegSegment& segment) const; diff --git a/includes/image_io/jpeg/jpeg_scanner.h b/includes/image_io/jpeg/jpeg_scanner.h index 0ab0488..932d3db 100644 --- a/includes/image_io/jpeg/jpeg_scanner.h +++ b/includes/image_io/jpeg/jpeg_scanner.h @@ -5,6 +5,7 @@ #include "image_io/base/data_segment.h" #include "image_io/base/data_source.h" +#include "image_io/base/message_handler.h" #include "image_io/jpeg/jpeg_marker.h" #include "image_io/jpeg/jpeg_segment_processor.h" @@ -16,8 +17,9 @@ namespace image_io { /// examination. class JpegScanner { public: - JpegScanner() - : data_source_(nullptr), + explicit JpegScanner(MessageHandler* message_handler) + : message_handler_(message_handler), + data_source_(nullptr), segment_processor_(nullptr), current_location_(0), done_(false), @@ -70,6 +72,9 @@ class JpegScanner { void GetNextSegment(); private: + /// An optional message handler to write messages to. + MessageHandler* message_handler_; + /// The DataSource from which DataSegments are obtained. DataSource* data_source_; diff --git a/includes/image_io/jpeg/jpeg_xmp_data_extractor.h b/includes/image_io/jpeg/jpeg_xmp_data_extractor.h index 30d62a1..29b16b6 100644 --- a/includes/image_io/jpeg/jpeg_xmp_data_extractor.h +++ b/includes/image_io/jpeg/jpeg_xmp_data_extractor.h @@ -2,6 +2,7 @@ #define IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_H_ // NOLINT #include "image_io/base/data_destination.h" +#include "image_io/base/message_handler.h" #include "image_io/jpeg/jpeg_info.h" namespace photos_editing_formats { @@ -17,10 +18,13 @@ class JpegXmpDataExtractor : public DataDestination { /// @param data_destination The destination to which the extracted xmp data /// is to be sent. JpegXmpDataExtractor(JpegXmpInfo::Type xmp_info_type, size_t segment_count, - DataDestination* data_destination) + DataDestination* data_destination, + MessageHandler* message_handler) : xmp_info_type_(xmp_info_type), last_segment_index_(segment_count - 1), data_destination_(data_destination), + message_handler_(message_handler), + segment_index_(0), has_error_(false) {} /// Set the current segment index to the given value. @@ -52,6 +56,9 @@ class JpegXmpDataExtractor : public DataDestination { /// The DataDestination that the extracted xmp data is sent to. DataDestination* data_destination_; + /// An optional message handler to write messages to. + MessageHandler* message_handler_; + /// The xmp data is spread over one or more segments in the DataSource. This /// index tracks which one is being transferred. size_t segment_index_; diff --git a/includes/image_io/utils/file_utils.h b/includes/image_io/utils/file_utils.h index d1a469d..3a8d2c6 100644 --- a/includes/image_io/utils/file_utils.h +++ b/includes/image_io/utils/file_utils.h @@ -6,34 +6,35 @@ #include <string> #include "image_io/base/data_segment.h" +#include "image_io/base/message_handler.h" namespace photos_editing_formats { namespace image_io { -/// A policy that controls whether an error is reported or not. -enum class ReportErrorPolicy { kDontReportError, kReportError }; - /// @param file_name The name of the file to get the size in bytes of. /// @param size A pointer to a variable to receive the size. /// @return Whether file size was obtained properly. bool GetFileSize(const std::string& file_name, size_t* size); /// @param file_name The name of the file to open for output. +/// @param message_handler Optional message handler to write messages to. /// @return An ostream pointer or nullptr if the open failed. -std::unique_ptr<std::ostream> OpenOutputFile( - const std::string& file_name, ReportErrorPolicy report_error_policy); +std::unique_ptr<std::ostream> OpenOutputFile(const std::string& file_name, + MessageHandler* message_handler); /// @param file_name The name of the file to open for input. +/// @param message_handler Optional message handler to write messages to. /// @return An istream pointer or nullptr if the open failed. -std::unique_ptr<std::istream> OpenInputFile( - const std::string& file_name, ReportErrorPolicy report_error_policy); +std::unique_ptr<std::istream> OpenInputFile(const std::string& file_name, + MessageHandler* message_handler); /// Opens the named file for input, gets its size, and reads the entire contents /// into a data segment that is returned to the caller. /// @param file_name The name of the file to open for input. +/// @param message_handler Optional message handler to write messages to. /// @return A DataSegment pointer or nullptr if the open and reading failed. -std::shared_ptr<DataSegment> ReadEntireFile( - const std::string& file_name, ReportErrorPolicy report_error_policy); +std::shared_ptr<DataSegment> ReadEntireFile(const std::string& file_name, + MessageHandler* message_handler); } // namespace image_io } // namespace photos_editing_formats diff --git a/includes/image_io/utils/message_stats_writer.h b/includes/image_io/utils/message_stats_writer.h new file mode 100644 index 0000000..24dd6b1 --- /dev/null +++ b/includes/image_io/utils/message_stats_writer.h @@ -0,0 +1,47 @@ +#ifndef IMAGE_IO_UTILS_MESSAGE_STATS_WRITER_H_ // NOLINT +#define IMAGE_IO_UTILS_MESSAGE_STATS_WRITER_H_ // NOLINT + +#include <memory> +#include <sstream> +#include <string> + +#include "image_io/base/message_stats.h" +#include "image_io/utils/string_outputter.h" + +namespace photos_editing_formats { +namespace image_io { + +/// A class to write the message stats for error and warning counts. The output +/// is written when the writer object is destroyed, making this a conveneient +/// class to use in functions that have multiple return points and for which +/// such output is desired at all return points. +class MessageStatsWriter { + public: + /// @param message_stats The message stats object holding the counts. + /// @param outputter The outputter function to write the stats to. + /// @param name The name of the tool or function that is "finished". + MessageStatsWriter(const std::shared_ptr<MessageStats>& message_stats, + const std::string& name, const StringOutputter& outputter) + : stats_(message_stats), outputter_(outputter), name_(name) {} + + /// Writes the finished message with the stats to the outputter function. + ~MessageStatsWriter() { + const string kError = stats_->error_count == 1 ? "error" : "errors"; + const string kWarning = stats_->warning_count == 1 ? "warning" : "warnings"; + std::stringstream ss; + ss << std::endl + << name_ << " finished, " << stats_->error_count << " " << kError << ", " + << stats_->warning_count << " " << kWarning << std::endl; + outputter_(ss.str()); + } + + private: + std::shared_ptr<MessageStats> stats_; + StringOutputter outputter_; + std::string name_; +}; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_UTILS_MESSAGE_STATS_WRITER_H_ // NOLINT diff --git a/includes/image_io/utils/string_outputter.h b/includes/image_io/utils/string_outputter.h new file mode 100644 index 0000000..b6ea013 --- /dev/null +++ b/includes/image_io/utils/string_outputter.h @@ -0,0 +1,19 @@ +#ifndef IMAGE_IO_UTILS_STRING_OUTPUTTER_H_ // NOLINT +#define IMAGE_IO_UTILS_STRING_OUTPUTTER_H_ // NOLINT + +#include <functional> +#include <string> + +namespace photos_editing_formats { +namespace image_io { + +/// A typedef for a function that accepts a string and writes it somewhere. +/// These types of functions are typically used in command line tools to write +/// the output of the tool to stdout or some other location. The function +/// should not write its own new line at the end of the str. +using StringOutputter = std::function<void(const std::string& str)>; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_UTILS_STRING_OUTPUTTER_H_ // NOLINT diff --git a/includes/image_io/utils/string_outputter_message_writer.h b/includes/image_io/utils/string_outputter_message_writer.h new file mode 100644 index 0000000..f34d975 --- /dev/null +++ b/includes/image_io/utils/string_outputter_message_writer.h @@ -0,0 +1,28 @@ +#ifndef IMAGE_IO_UTILS_STRING_OUTPUTTER_MESSAGE_WRITER_H_ // NOLINT +#define IMAGE_IO_UTILS_STRING_OUTPUTTER_MESSAGE_WRITER_H_ // NOLINT + +#include "image_io/base/message_writer.h" +#include "image_io/utils/string_outputter.h" + +namespace photos_editing_formats { +namespace image_io { + +/// A MessageWriter that writes the messages to the StringOutputter function. +class StringOutputterMessageWriter : public MessageWriter { + public: + /// @param outputter The outputter function to write messages to. + explicit StringOutputterMessageWriter(const StringOutputter& outputter) + : outputter_(outputter) {} + void WriteMessage(const Message& message) override { + outputter_(GetFormattedMessage(message)); + outputter_("\n"); + } + + private: + StringOutputter outputter_; +}; + +} // namespace image_io +} // namespace photos_editing_formats + +#endif // IMAGE_IO_UTILS_STRING_OUTPUTTER_MESSAGE_WRITER_H_ // NOLINT |