From 66639ee119b9c274c004417e206af493801153b3 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 23 Jan 2021 03:52:23 -0800 Subject: [PATCH] ircd::png: Elaborate callback surface; add logger to prevent libpng writes to stderr. --- include/ircd/png.h | 2 + ircd/png.cc | 153 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 118 insertions(+), 37 deletions(-) diff --git a/include/ircd/png.h b/include/ircd/png.h index 4541e89b5..5b37d6d82 100644 --- a/include/ircd/png.h +++ b/include/ircd/png.h @@ -14,6 +14,8 @@ /// Portable Network Graphics; wrappers a la carte namespace ircd::png { + IRCD_EXCEPTION(ircd::error, error) + bool is_animated(const const_buffer &); extern const info::versions version_api, version_abi; diff --git a/ircd/png.cc b/ircd/png.cc index 2fe2fc288..a04da1172 100644 --- a/ircd/png.cc +++ b/ircd/png.cc @@ -10,6 +10,23 @@ #include (ptr), sz - }; - - // Get source buffer from our callback user data. - const_buffer &src - { - *reinterpret_cast(png_get_io_ptr(handle)) - }; - - // Copy from our buffer to libpng buffer. - const size_t copied - { - copy(dst, src) - }; - - // Advance our source pointer for the amount copied. - const size_t consumed - { - consume(src, copied) - }; - - assert(copied == consumed); - }); + const_buffer src {buf}; + png_set_read_fn(handle, &src, &handle_read); // Invokes the read callback a few times to traverse the buffer. png_read_info(handle, info); // If there's a non-zero result there's acTL for animation. - uint32_t frames(0), plays(0); - if(png_get_acTL(handle, info, &frames, &plays) != 0) - return true; - - return false; + uint32_t num_frames {0}, num_plays {0}; + return png_get_acTL(handle, info, &num_frames, &num_plays) != 0; } #else { @@ -107,3 +106,83 @@ ircd::png::is_animated(const const_buffer &buf) return false; } #endif + +void +ircd::png::handle_read(png_structp handle, + uint8_t *const ptr, + size_t size) +noexcept +{ + // Destination where libpng wants data + const mutable_buffer dst + { + reinterpret_cast(ptr), size + }; + + // Get source buffer from our callback user data. + const_buffer &src + { + *reinterpret_cast(png_get_io_ptr(handle)) + }; + + // Copy from our buffer to libpng buffer. + const size_t copied + { + copy(dst, src) + }; + + // Advance our source pointer for the amount copied. + const size_t consumed + { + consume(src, copied) + }; + + assert(copied == consumed); +} + +void * +ircd::png::handle_alloc(png_structp handle, + size_t size) +noexcept +{ + return std::malloc(size); +} + +void +ircd::png::handle_free(png_structp handle, + void *const ptr) +noexcept +{ + std::free(ptr); +} + +void +ircd::png::handle_warn(png_structp handle, + const char *const msg) +noexcept +{ + log::dwarning + { + log, "handle(%p) :%s", + static_cast(handle), + msg, + }; +} + +void +ircd::png::handle_error(png_structp handle, + const char *const msg) +noexcept(false) +{ + log::error + { + log, "handle(%p) :%s", + static_cast(handle), + msg, + }; + + throw error + { + "%s", msg + }; +}