From b6b6c9b15c34471fd3938bdb9715754f09f10e00 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 13 Apr 2023 05:49:05 +1000 Subject: Allow loading PNG/JPEG/MS DIB bitmaps from Lua, and cleanup. Use VirtualAlloc rather than VirtualProtect on Windows to change page protection, as the latter can cause severe performance issues with some antivirus software. Added noexcept to lots of hash- and bitmap-related things, and added a little more error checking. Yes, I realise it will abort if an allocation fails while printing a log message, but if you get to that point, you're probably screwed already. --- docs/source/techspecs/luareference.rst | 4 + hash/msx1_cart.xml | 4 +- src/emu/rendutil.cpp | 231 +++++++++++++++++---------------- src/emu/rendutil.h | 10 +- src/frontend/mame/luaengine_render.cpp | 36 ++++- src/lib/util/hash.cpp | 25 ++-- src/lib/util/hash.h | 21 +-- src/lib/util/hashing.cpp | 98 +++++++------- src/lib/util/hashing.h | 124 +++++++++--------- src/lib/util/md5.cpp | 3 +- src/lib/util/msdib.cpp | 22 ++-- src/lib/util/msdib.h | 6 +- src/lib/util/png.cpp | 170 ++++++++++++------------ src/lib/util/png.h | 24 ++-- src/osd/modules/lib/osdlib_win32.cpp | 4 +- 15 files changed, 421 insertions(+), 361 deletions(-) diff --git a/docs/source/techspecs/luareference.rst b/docs/source/techspecs/luareference.rst index 967fc889729..18af28b5c2a 100644 --- a/docs/source/techspecs/luareference.rst +++ b/docs/source/techspecs/luareference.rst @@ -3209,6 +3209,10 @@ emu.bitmap_argb32(source, [x0, y0, x1, y1]) The source bitmap must be owned by the Lua script and must use the ARGB format. Raises an error if coordinates are specified representing a rectangle not fully contained within the source bitmap’s clipping rectangle. +emu.bitmap_argb32.load(data) + Creates an ARGB format bitmap from data in PNG, JPEG (JFIF/EXIF) or + Microsoft DIB (BMP) format. Raises an error if the data invalid or not a + supported format. Methods ^^^^^^^ diff --git a/hash/msx1_cart.xml b/hash/msx1_cart.xml index d267d165125..0f36d12acc8 100644 --- a/hash/msx1_cart.xml +++ b/hash/msx1_cart.xml @@ -13091,10 +13091,10 @@ kept for now until finding out what those bytes affect... - Yogoetamjeong (Korea) + Yogoetamjeong Chimagun Chimachima (Korea) 19?? Topia - + diff --git a/src/emu/rendutil.cpp b/src/emu/rendutil.cpp index cffef8263d7..db7220351b8 100644 --- a/src/emu/rendutil.cpp +++ b/src/emu/rendutil.cpp @@ -26,18 +26,18 @@ namespace { struct jpeg_corefile_source : public jpeg_source_mgr { - static void source(j_decompress_ptr cinfo, util::random_read &file); + static void source(j_decompress_ptr cinfo, util::random_read &file) noexcept; private: static constexpr unsigned INPUT_BUF_SIZE = 4096; - static void do_init(j_decompress_ptr cinfo) + static void do_init(j_decompress_ptr cinfo) noexcept { jpeg_corefile_source &src = *static_cast(cinfo->src); src.start_of_file = true; } - static boolean do_fill(j_decompress_ptr cinfo) + static boolean do_fill(j_decompress_ptr cinfo) noexcept { jpeg_corefile_source &src = *static_cast(cinfo->src); @@ -61,7 +61,7 @@ private: return TRUE; } - static void do_skip(j_decompress_ptr cinfo, long num_bytes) + static void do_skip(j_decompress_ptr cinfo, long num_bytes) noexcept { jpeg_corefile_source &src = *static_cast(cinfo->src); @@ -70,14 +70,14 @@ private: while (long(src.bytes_in_buffer) < num_bytes) { num_bytes -= long(src.bytes_in_buffer); - (void)(*src.fill_input_buffer)(cinfo); + std::ignore = (*src.fill_input_buffer)(cinfo); } src.next_input_byte += size_t(num_bytes); src.bytes_in_buffer -= size_t(num_bytes); } } - static void do_term(j_decompress_ptr cinfo) + static void do_term(j_decompress_ptr cinfo) noexcept { } @@ -86,7 +86,7 @@ private: bool start_of_file; }; -void jpeg_corefile_source::source(j_decompress_ptr cinfo, util::random_read &file) +void jpeg_corefile_source::source(j_decompress_ptr cinfo, util::random_read &file) noexcept { jpeg_corefile_source *src; if (!cinfo->src) @@ -121,7 +121,7 @@ void jpeg_corefile_source::source(j_decompress_ptr cinfo, util::random_read &fil struct jpeg_setjmp_error_mgr : public jpeg_error_mgr { - jpeg_setjmp_error_mgr() + jpeg_setjmp_error_mgr() noexcept { jpeg_std_error(this); error_exit = [] (j_common_ptr cinfo) { std::longjmp(static_cast(cinfo->err)->m_jump_buffer, 1); }; @@ -138,9 +138,9 @@ struct jpeg_setjmp_error_mgr : public jpeg_error_mgr ***************************************************************************/ /* utilities */ -static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy); -static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy); -static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png); +static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept; +static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept; +static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png) noexcept; @@ -153,15 +153,15 @@ static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info quality resampling of a texture -------------------------------------------------*/ -void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force) +void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force) noexcept { if (dest.width() == 0 || dest.height() == 0) return; - /* adjust the source base */ + // adjust the source base const u32 *sbase = &source.pix(0); - /* determine the steppings */ + // determine the steppings u32 swidth = source.width(); u32 sheight = source.height(); u32 dwidth = dest.width(); @@ -169,7 +169,7 @@ void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, u32 dx = (swidth << 12) / dwidth; u32 dy = (sheight << 12) / dheight; - /* if the source is higher res than the target, use full averaging */ + // if the source is higher res than the target, use full averaging if (dx > 0x1000 || dy > 0x1000 || force) resample_argb_bitmap_average(&dest.pix(0), dest.rowpixels(), dwidth, dheight, sbase, source.rowpixels(), swidth, sheight, color, dx, dy); else @@ -183,62 +183,58 @@ void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, all contributing pixels -------------------------------------------------*/ -static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) +static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept { - u64 sumscale = u64(dx) * u64(dy); - u32 r, g, b, a; - u32 x, y; - - /* precompute premultiplied R/G/B/A factors */ - r = color.r * color.a * 256.0f; - g = color.g * color.a * 256.0f; - b = color.b * color.a * 256.0f; - a = color.a * 256.0f; - - /* loop over the target vertically */ - for (y = 0; y < dheight; y++) + u64 const sumscale = u64(dx) * u64(dy); + + // precompute premultiplied R/G/B/A factors + u32 const r = color.r * color.a * 256.0f; + u32 const g = color.g * color.a * 256.0f; + u32 const b = color.b * color.a * 256.0f; + u32 const a = color.a * 256.0f; + + // loop over the target vertically + for (u32 y = 0; y < dheight; y++) { - u32 starty = y * dy; + u32 const starty = y * dy; - /* loop over the target horizontally */ - for (x = 0; x < dwidth; x++) + // loop over the target horizontally + for (u32 x = 0; x < dwidth; x++) { u64 sumr = 0, sumg = 0, sumb = 0, suma = 0; - u32 startx = x * dx; - u32 xchunk, ychunk; - u32 curx, cury; + u32 const startx = x * dx; u32 yremaining = dy; + u32 ychunk; - /* accumulate all source pixels that contribute to this pixel */ - for (cury = starty; yremaining; cury += ychunk) + // accumulate all source pixels that contribute to this pixel + for (u32 cury = starty; yremaining; cury += ychunk) { u32 xremaining = dx; + u32 xchunk; - /* determine the Y contribution, clamping to the amount remaining */ + // determine the Y contribution, clamping to the amount remaining ychunk = 0x1000 - (cury & 0xfff); if (ychunk > yremaining) ychunk = yremaining; yremaining -= ychunk; - /* loop over all source pixels in the X direction */ - for (curx = startx; xremaining; curx += xchunk) + // loop over all source pixels in the X direction + for (u32 curx = startx; xremaining; curx += xchunk) { - u32 factor; - - /* determine the X contribution, clamping to the amount remaining */ + // determine the X contribution, clamping to the amount remaining xchunk = 0x1000 - (curx & 0xfff); if (xchunk > xremaining) xchunk = xremaining; xremaining -= xchunk; - /* total contribution = x * y */ - factor = xchunk * ychunk; + // total contribution = x * y + u32 const factor = xchunk * ychunk; - /* fetch the source pixel */ - rgb_t pix = source[(cury >> 12) * srowpixels + (curx >> 12)]; + // fetch the source pixel + rgb_t const pix = source[(cury >> 12) * srowpixels + (curx >> 12)]; - /* accumulate the RGBA values */ + // accumulate the RGBA values sumr += factor * pix.r(); sumg += factor * pix.g(); sumb += factor * pix.b(); @@ -246,23 +242,23 @@ static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, } } - /* apply scaling */ + // apply scaling suma = (suma / sumscale) * a / 256; sumr = (sumr / sumscale) * r / 256; sumg = (sumg / sumscale) * g / 256; sumb = (sumb / sumscale) * b / 256; - /* if we're translucent, add in the destination pixel contribution */ + // if we're translucent, add in the destination pixel contribution if (a < 256) { - rgb_t dpix = dest[y * drowpixels + x]; + rgb_t const dpix = dest[y * drowpixels + x]; suma += dpix.a() * (256 - a); sumr += dpix.r() * (256 - a); sumg += dpix.g() * (256 - a); sumb += dpix.b() * (256 - a); } - /* store the target pixel, dividing the RGBA values by the overall scale factor */ + // store the target pixel, dividing the RGBA values by the overall scale factor dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); } } @@ -274,44 +270,37 @@ static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, sampling via a bilinear filter -------------------------------------------------*/ -static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) +static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept { - u32 maxx = swidth << 12, maxy = sheight << 12; - u32 r, g, b, a; - u32 x, y; - - /* precompute premultiplied R/G/B/A factors */ - r = color.r * color.a * 256.0f; - g = color.g * color.a * 256.0f; - b = color.b * color.a * 256.0f; - a = color.a * 256.0f; - - /* loop over the target vertically */ - for (y = 0; y < dheight; y++) + u32 const maxx = swidth << 12, maxy = sheight << 12; + + // precompute premultiplied R/G/B/A factors + u32 const r = color.r * color.a * 256.0f; + u32 const g = color.g * color.a * 256.0f; + u32 const b = color.b * color.a * 256.0f; + u32 const a = color.a * 256.0f; + + // loop over the target vertically + for (u32 y = 0; y < dheight; y++) { - u32 starty = y * dy; + u32 const starty = y * dy; - /* loop over the target horizontally */ - for (x = 0; x < dwidth; x++) + // loop over the target horizontally + for (u32 x = 0; x < dwidth; x++) { - u32 startx = x * dx; - rgb_t pix0, pix1, pix2, pix3; - u32 sumr, sumg, sumb, suma; - u32 nextx, nexty; - u32 curx, cury; - u32 factor; + u32 const startx = x * dx; - /* adjust start to the center; note that this math will tend to produce */ - /* negative results on the first pixel, which is why we clamp below */ - curx = startx + dx / 2 - 0x800; - cury = starty + dy / 2 - 0x800; + // adjust start to the center; note that this math will tend to produce + // negative results on the first pixel, which is why we clamp below + u32 curx = startx + dx / 2 - 0x800; + u32 cury = starty + dy / 2 - 0x800; - /* compute the neighboring pixel */ - nextx = curx + 0x1000; - nexty = cury + 0x1000; + // compute the neighboring pixel + u32 const nextx = curx + 0x1000; + u32 const nexty = cury + 0x1000; - /* fetch the four relevant pixels */ - pix0 = pix1 = pix2 = pix3 = 0; + // fetch the four relevant pixels + rgb_t pix0 = 0, pix1 = 0, pix2 = 0, pix3 = 0; if (s32(cury) >= 0 && cury < maxy && s32(curx) >= 0 && curx < maxx) pix0 = source[(cury >> 12) * srowpixels + (curx >> 12)]; if (s32(cury) >= 0 && cury < maxy && s32(nextx) >= 0 && nextx < maxx) @@ -321,55 +310,58 @@ static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, if (s32(nexty) >= 0 && nexty < maxy && s32(nextx) >= 0 && nextx < maxx) pix3 = source[(nexty >> 12) * srowpixels + (nextx >> 12)]; - /* compute the x/y scaling factors */ + // compute the x/y scaling factors curx &= 0xfff; cury &= 0xfff; - /* contributions from pixel 0 (top,left) */ + u32 factor; + u32 sumr, sumg, sumb, suma; + + // contributions from pixel 0 (top,left) factor = (0x1000 - curx) * (0x1000 - cury); sumr = factor * pix0.r(); sumg = factor * pix0.g(); sumb = factor * pix0.b(); suma = factor * pix0.a(); - /* contributions from pixel 1 (top,right) */ + // contributions from pixel 1 (top,right) factor = curx * (0x1000 - cury); sumr += factor * pix1.r(); sumg += factor * pix1.g(); sumb += factor * pix1.b(); suma += factor * pix1.a(); - /* contributions from pixel 2 (bottom,left) */ + // contributions from pixel 2 (bottom,left) factor = (0x1000 - curx) * cury; sumr += factor * pix2.r(); sumg += factor * pix2.g(); sumb += factor * pix2.b(); suma += factor * pix2.a(); - /* contributions from pixel 3 (bottom,right) */ + // contributions from pixel 3 (bottom,right) factor = curx * cury; sumr += factor * pix3.r(); sumg += factor * pix3.g(); sumb += factor * pix3.b(); suma += factor * pix3.a(); - /* apply scaling */ + // apply scaling suma = (suma >> 24) * a / 256; sumr = (sumr >> 24) * r / 256; sumg = (sumg >> 24) * g / 256; sumb = (sumb >> 24) * b / 256; - /* if we're translucent, add in the destination pixel contribution */ + // if we're translucent, add in the destination pixel contribution if (a < 256) { - rgb_t dpix = dest[y * drowpixels + x]; + rgb_t const dpix = dest[y * drowpixels + x]; suma += dpix.a() * (256 - a); sumr += dpix.r() * (256 - a); sumg += dpix.g() * (256 - a); sumb += dpix.b() * (256 - a); } - /* store the target pixel, dividing the RGBA values by the overall scale factor */ + // store the target pixel, dividing the RGBA values by the overall scale factor dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); } } @@ -653,7 +645,7 @@ std::pair render_line_to_quad(const render_bounds into a bitmap -------------------------------------------------*/ -void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) +void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) noexcept { // deallocate previous bitmap bitmap.reset(); @@ -673,7 +665,7 @@ void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) bitmap -------------------------------------------------*/ -void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) +void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) noexcept { // deallocate previous bitmap bitmap.reset(); @@ -711,30 +703,39 @@ void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) // allocates a buffer to receive the information and copy them into the bitmap row_stride = cinfo.output_width * cinfo.output_components; buffer = reinterpret_cast(std::malloc(sizeof(JSAMPROW))); - buffer[0] = reinterpret_cast(std::malloc(sizeof(JSAMPLE) * row_stride)); + if (buffer) + buffer[0] = reinterpret_cast(std::malloc(sizeof(JSAMPLE) * row_stride)); - while (cinfo.output_scanline < cinfo.output_height) + if (bitmap.valid() && buffer && buffer[0]) { - j = cinfo.output_scanline; - jpeg_read_scanlines(&cinfo, buffer, 1); - - if (s == 1) + while (cinfo.output_scanline < cinfo.output_height) { - for (i = 0; i < w; ++i) - bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i], buffer[0][i], buffer[0][i]); + j = cinfo.output_scanline; + jpeg_read_scanlines(&cinfo, buffer, 1); + if (s == 1) + { + for (i = 0; i < w; ++i) + bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i], buffer[0][i], buffer[0][i]); + + } + else if (s == 3) + { + for (i = 0; i < w; ++i) + bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]); + } + else + { + osd_printf_error("Cannot read JPEG data from file.\n"); + bitmap.reset(); + break; + } } - else if (s == 3) - { - for (i = 0; i < w; ++i) - bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]); - } - else - { - osd_printf_error("Cannot read JPEG data from file.\n"); - bitmap.reset(); - break; - } + } + else + { + osd_printf_error("Error allocating memory for JPEG image.\n"); + bitmap.reset(); } // finish decompression and free the memory @@ -755,7 +756,7 @@ cleanup: bitmap -------------------------------------------------*/ -bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing) +bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing) noexcept { // deallocate if we're not overlaying alpha if (!load_as_alpha_to_existing) @@ -810,7 +811,7 @@ bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_a to the alpha channel of a bitmap -------------------------------------------------*/ -static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png) +static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png) noexcept { // FIXME: this function is basically copy/pasted from the PNG code in util, and should be unified with it u8 accumalpha = 0xff; @@ -921,7 +922,7 @@ static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info render_detect_image - detect image format -------------------------------------------------*/ -ru_imgformat render_detect_image(util::random_read &file) +ru_imgformat render_detect_image(util::random_read &file) noexcept { // PNG: check for valid header { diff --git a/src/emu/rendutil.h b/src/emu/rendutil.h index de29ed64d2a..71e5bdc95c3 100644 --- a/src/emu/rendutil.h +++ b/src/emu/rendutil.h @@ -42,14 +42,14 @@ enum ru_imgformat /* ----- render utilities ----- */ -void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force = false); +void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force = false) noexcept; bool render_clip_line(render_bounds &bounds, const render_bounds &clip); bool render_clip_quad(render_bounds &bounds, const render_bounds &clip, render_quad_texuv *texcoords); std::pair render_line_to_quad(const render_bounds &bounds, float width, float length_extension); -void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file); -void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file); -bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing = false); -ru_imgformat render_detect_image(util::random_read &file); +void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) noexcept; +void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) noexcept; +bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing = false) noexcept; +ru_imgformat render_detect_image(util::random_read &file) noexcept; diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp index 903db9acaa1..e4286a2493f 100644 --- a/src/frontend/mame/luaengine_render.cpp +++ b/src/frontend/mame/luaengine_render.cpp @@ -16,6 +16,9 @@ #include "render.h" #include "rendlay.h" +#include "rendutil.h" + +#include "ioprocs.h" #include #include @@ -733,7 +736,38 @@ void lua_engine::initialize_render(sol::table &emu) bitmap_helper::make_type(emu, "bitmap_yuy16"); bitmap_helper::make_type(emu, "bitmap_rgb32"); - bitmap_helper::make_type(emu, "bitmap_argb32"); + + // ARGB32 bitmaps get extra functionality + auto bitmap_argb32_type = bitmap_helper::make_type(emu, "bitmap_argb32"); + bitmap_argb32_type.set_function("load", + [] (sol::this_state s, std::string_view data) + { + auto stream(util::ram_read(data.data(), data.size())); + if (!stream) + luaL_error(s, "Error allocating stream wrapper"); + auto b = std::make_shared >(s, 0, 0, 0, 0); + switch (render_detect_image(*stream)) + { + case RENDUTIL_IMGFORMAT_PNG: + render_load_png(*b, *stream); + if (!b->valid()) + luaL_error(s, "Invalid or unsupported PNG data"); + break; + case RENDUTIL_IMGFORMAT_JPEG: + render_load_jpeg(*b, *stream); + if (!b->valid()) + luaL_error(s, "Invalid or unsupported PNG data"); + break; + case RENDUTIL_IMGFORMAT_MSDIB: + render_load_msdib(*b, *stream); + if (!b->valid()) + luaL_error(s, "Invalid or unsupported Microsoft DIB data"); + break; + default: + luaL_error(s, "Unsupported bitmap data format"); + } + return b; + }); auto render_texture_type = emu.new_usertype("render_texture", sol::no_constructor); render_texture_type.set_function("free", &render_texture_helper::free); diff --git a/src/lib/util/hash.cpp b/src/lib/util/hash.cpp index 8cdf41ba0e9..9100ff6abde 100644 --- a/src/lib/util/hash.cpp +++ b/src/lib/util/hash.cpp @@ -38,7 +38,7 @@ class hash_collection::hash_creator { public: // constructor - hash_creator(bool doing_crc32, bool doing_sha1) + hash_creator(bool doing_crc32, bool doing_sha1) noexcept { if (doing_crc32) m_crc32_creator.emplace(); @@ -47,7 +47,7 @@ public: } // add the given buffer to the hash - void append(void const *buffer, std::size_t length) + void append(void const *buffer, std::size_t length) noexcept { // append to each active hash if (m_crc32_creator) @@ -57,7 +57,7 @@ public: } // stop hashing - void finish(hash_collection &hashes) + void finish(hash_collection &hashes) noexcept { // finish up the CRC32 if (m_crc32_creator) @@ -112,15 +112,16 @@ hash_collection &hash_collection::operator=(const hash_collection &src) // operator== - test for equality //------------------------------------------------- -bool hash_collection::operator==(const hash_collection &rhs) const +bool hash_collection::operator==(const hash_collection &rhs) const noexcept { + bool matches = false; + // match CRCs - int matches = 0; if (m_has_crc32 && rhs.m_has_crc32) { if (m_crc32 != rhs.m_crc32) return false; - matches++; + matches = true; } // match SHA1s @@ -128,11 +129,11 @@ bool hash_collection::operator==(const hash_collection &rhs) const { if (m_sha1 != rhs.m_sha1) return false; - matches++; + matches = true; } - // if all shared hashes match, return true - return (matches > 0); + // if at least one type is shared and matches, return true + return matches; } @@ -157,7 +158,7 @@ std::string hash_collection::hash_types() const // set of hashes and flags //------------------------------------------------- -void hash_collection::reset() +void hash_collection::reset() noexcept { m_flags.clear(); m_has_crc32 = m_has_sha1 = false; @@ -169,7 +170,7 @@ void hash_collection::reset() // from a string //------------------------------------------------- -bool hash_collection::add_from_string(char type, std::string_view string) +bool hash_collection::add_from_string(char type, std::string_view string) noexcept { // handle CRCs if (type == HASH_CRC) @@ -187,7 +188,7 @@ bool hash_collection::add_from_string(char type, std::string_view string) // remove - remove a hash of the given type //------------------------------------------------- -bool hash_collection::remove(char type) +bool hash_collection::remove(char type) noexcept { bool result = false; diff --git a/src/lib/util/hash.h b/src/lib/util/hash.h index 5fa4f787097..bd111224e6f 100644 --- a/src/lib/util/hash.h +++ b/src/lib/util/hash.h @@ -34,6 +34,7 @@ namespace util { + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -68,25 +69,25 @@ public: // operators hash_collection &operator=(const hash_collection &src); - bool operator==(const hash_collection &rhs) const; - bool operator!=(const hash_collection &rhs) const { return !(*this == rhs); } + bool operator==(const hash_collection &rhs) const noexcept; + bool operator!=(const hash_collection &rhs) const noexcept { return !(*this == rhs); } // getters - bool flag(char flag) const { return (m_flags.find_first_of(flag) != std::string::npos); } + bool flag(char flag) const noexcept { return (m_flags.find_first_of(flag) != std::string::npos); } std::string hash_types() const; // hash manipulators - void reset(); - bool add_from_string(char type, std::string_view string); - bool remove(char type); + void reset() noexcept; + bool add_from_string(char type, std::string_view string) noexcept; + bool remove(char type) noexcept; // CRC-specific helpers - bool crc(uint32_t &result) const { result = m_crc32; return m_has_crc32; } - void add_crc(uint32_t crc) { m_crc32 = crc; m_has_crc32 = true; } + bool crc(uint32_t &result) const noexcept { result = m_crc32; return m_has_crc32; } + void add_crc(uint32_t crc) noexcept { m_crc32 = crc; m_has_crc32 = true; } // SHA1-specific helpers - bool sha1(sha1_t &result) const { result = m_sha1; return m_has_sha1; } - void add_sha1(sha1_t sha1) { m_has_sha1 = true; m_sha1 = sha1; } + bool sha1(sha1_t &result) const noexcept { result = m_sha1; return m_has_sha1; } + void add_sha1(sha1_t sha1) noexcept { m_has_sha1 = true; m_sha1 = sha1; } // string conversion std::string internal_string() const; diff --git a/src/lib/util/hashing.cpp b/src/lib/util/hashing.cpp index 62447c7b6c0..3410389fdc8 100644 --- a/src/lib/util/hashing.cpp +++ b/src/lib/util/hashing.cpp @@ -9,12 +9,14 @@ ***************************************************************************/ #include "hashing.h" + #include "strformat.h" #include "eminline.h" #include +#include #include #include @@ -42,7 +44,7 @@ constexpr int char_to_hex(char c) } -inline uint32_t sha1_b(uint32_t *data, unsigned i) +inline uint32_t sha1_b(uint32_t *data, unsigned i) noexcept { uint32_t r = data[(i + 13) & 15U]; r ^= data[(i + 8) & 15U]; @@ -53,37 +55,37 @@ inline uint32_t sha1_b(uint32_t *data, unsigned i) return r; } -inline void sha1_r0(const uint32_t *data, std::array &d, unsigned i) +inline void sha1_r0(const uint32_t *data, std::array &d, unsigned i) noexcept { d[i % 5] = d[i % 5] + ((d[(i + 3) % 5] & (d[(i + 2) % 5] ^ d[(i + 1) % 5])) ^ d[(i + 1) % 5]) + data[i] + 0x5a827999U + rotl_32(d[(i + 4) % 5], 5); d[(i + 3) % 5] = rotl_32(d[(i + 3) % 5], 30); } -inline void sha1_r1(uint32_t *data, std::array &d, unsigned i) +inline void sha1_r1(uint32_t *data, std::array &d, unsigned i) noexcept { d[i % 5] = d[i % 5] + ((d[(i + 3) % 5] & (d[(i + 2) % 5] ^ d[(i + 1) % 5])) ^ d[(i + 1) % 5])+ sha1_b(data, i) + 0x5a827999U + rotl_32(d[(i + 4) % 5], 5); d[(i + 3) % 5] = rotl_32(d[(i + 3) % 5], 30); } -inline void sha1_r2(uint32_t *data, std::array &d, unsigned i) +inline void sha1_r2(uint32_t *data, std::array &d, unsigned i) noexcept { d[i % 5] = d[i % 5] + (d[(i + 3) % 5] ^ d[(i + 2) % 5] ^ d[(i + 1) % 5]) + sha1_b(data, i) + 0x6ed9eba1U + rotl_32(d[(i + 4) % 5], 5); d[(i + 3) % 5] = rotl_32(d[(i + 3) % 5], 30); } -inline void sha1_r3(uint32_t *data, std::array &d, unsigned i) +inline void sha1_r3(uint32_t *data, std::array &d, unsigned i) noexcept { d[i % 5] = d[i % 5] + (((d[(i + 3) % 5] | d[(i + 2) % 5]) & d[(i + 1) % 5]) | (d[(i + 3) % 5] & d[(i + 2) % 5])) + sha1_b(data, i) + 0x8f1bbcdcU + rotl_32(d[(i + 4) % 5], 5); d[(i + 3) % 5] = rotl_32(d[(i + 3) % 5], 30); } -inline void sha1_r4(uint32_t *data, std::array &d, unsigned i) +inline void sha1_r4(uint32_t *data, std::array &d, unsigned i) noexcept { d[i % 5] = d[i % 5] + (d[(i + 3) % 5] ^ d[(i + 2) % 5] ^ d[(i + 1) % 5]) + sha1_b(data, i) + 0xca62c1d6U + rotl_32(d[(i + 4) % 5], 5); d[(i + 3) % 5] = rotl_32(d[(i + 3) % 5], 30); } -inline void sha1_process(std::array &st, uint32_t *data) +inline void sha1_process(std::array &st, uint32_t *data) noexcept { std::array d = st; unsigned i = 0U; @@ -125,18 +127,18 @@ const sum16_t sum16_t::null = { 0 }; // from_string - convert from a string //------------------------------------------------- -bool sha1_t::from_string(std::string_view string) +bool sha1_t::from_string(std::string_view string) noexcept { // must be at least long enough to hold everything - memset(m_raw, 0, sizeof(m_raw)); + std::fill(std::begin(m_raw), std::end(m_raw), 0); if (string.length() < 2 * sizeof(m_raw)) return false; // iterate through our raw buffer - for (auto & elem : m_raw) + for (auto &elem : m_raw) { - int upper = char_to_hex(string[0]); - int lower = char_to_hex(string[1]); + int const upper = char_to_hex(string[0]); + int const lower = char_to_hex(string[1]); if (upper == -1 || lower == -1) return false; elem = (upper << 4) | lower; @@ -152,12 +154,16 @@ bool sha1_t::from_string(std::string_view string) std::string sha1_t::as_string() const { - std::ostringstream buffer; - buffer.fill('0'); - buffer << std::hex; - for (auto & elem : m_raw) - buffer << std::setw(2) << unsigned(elem); - return buffer.str(); + std::string result(2 * std::size(m_raw), ' '); + auto it = result.begin(); + for (auto const &elem : m_raw) + { + auto const upper = elem >> 4; + auto const lower = elem & 0x0f; + *it++ = ((10 > upper) ? '0' : ('a' - 10)) + upper; + *it++ = ((10 > lower) ? '0' : ('a' - 10)) + lower; + } + return result; } @@ -165,7 +171,7 @@ std::string sha1_t::as_string() const // reset - prepare to digest a block of data //------------------------------------------------- -void sha1_creator::reset() +void sha1_creator::reset() noexcept { m_cnt = 0U; m_st[0] = 0xc3d2e1f0U; @@ -180,7 +186,7 @@ void sha1_creator::reset() // append - digest a block of data //------------------------------------------------- -void sha1_creator::append(const void *data, uint32_t length) +void sha1_creator::append(const void *data, uint32_t length) noexcept { #ifdef LSB_FIRST constexpr unsigned swizzle = 3U; @@ -215,7 +221,7 @@ void sha1_creator::append(const void *data, uint32_t length) // finish - compute final hash //------------------------------------------------- -sha1_t sha1_creator::finish() +sha1_t sha1_creator::finish() noexcept { const unsigned padlen = 64U - (63U & ((unsigned(m_cnt) >> 3) + 8U)); uint8_t padbuf[64]; @@ -243,18 +249,18 @@ sha1_t sha1_creator::finish() // from_string - convert from a string //------------------------------------------------- -bool md5_t::from_string(std::string_view string) +bool md5_t::from_string(std::string_view string) noexcept { // must be at least long enough to hold everything - memset(m_raw, 0, sizeof(m_raw)); + std::fill(std::begin(m_raw), std::end(m_raw), 0); if (string.length() < 2 * sizeof(m_raw)) return false; // iterate through our raw buffer - for (auto & elem : m_raw) + for (auto &elem : m_raw) { - int upper = char_to_hex(string[0]); - int lower = char_to_hex(string[1]); + int const upper = char_to_hex(string[0]); + int const lower = char_to_hex(string[1]); if (upper == -1 || lower == -1) return false; elem = (upper << 4) | lower; @@ -270,12 +276,16 @@ bool md5_t::from_string(std::string_view string) std::string md5_t::as_string() const { - std::ostringstream buffer; - buffer.fill('0'); - buffer << std::hex; - for (auto & elem : m_raw) - buffer << std::setw(2) << unsigned(elem); - return buffer.str(); + std::string result(2 * std::size(m_raw), ' '); + auto it = result.begin(); + for (auto const &elem : m_raw) + { + auto const upper = elem >> 4; + auto const lower = elem & 0x0f; + *it++ = ((10 > upper) ? '0' : ('a' - 10)) + upper; + *it++ = ((10 > lower) ? '0' : ('a' - 10)) + lower; + } + return result; } @@ -288,18 +298,18 @@ std::string md5_t::as_string() const // from_string - convert from a string //------------------------------------------------- -bool crc32_t::from_string(std::string_view string) +bool crc32_t::from_string(std::string_view string) noexcept { // must be at least long enough to hold everything m_raw = 0; - if (string.length() < 2 * sizeof(m_raw)) + if (string.length() < (2 * sizeof(m_raw))) return false; // iterate through our raw buffer m_raw = 0; for (int bytenum = 0; bytenum < sizeof(m_raw) * 2; bytenum++) { - int nibble = char_to_hex(string[0]); + int const nibble = char_to_hex(string[0]); if (nibble == -1) return false; m_raw = (m_raw << 4) | nibble; @@ -324,7 +334,7 @@ std::string crc32_t::as_string() const // the currently-accumulated value //------------------------------------------------- -void crc32_creator::append(const void *data, uint32_t length) +void crc32_creator::append(const void *data, uint32_t length) noexcept { m_accum.m_raw = crc32(m_accum, reinterpret_cast(data), length); } @@ -339,18 +349,18 @@ void crc32_creator::append(const void *data, uint32_t length) // from_string - convert from a string //------------------------------------------------- -bool crc16_t::from_string(std::string_view string) +bool crc16_t::from_string(std::string_view string) noexcept { // must be at least long enough to hold everything m_raw = 0; - if (string.length() < 2 * sizeof(m_raw)) + if (string.length() < (2 * sizeof(m_raw))) return false; // iterate through our raw buffer m_raw = 0; for (int bytenum = 0; bytenum < sizeof(m_raw) * 2; bytenum++) { - int nibble = char_to_hex(string[0]); + int const nibble = char_to_hex(string[0]); if (nibble == -1) return false; m_raw = (m_raw << 4) | nibble; @@ -385,7 +395,7 @@ std::string crc16_t::as_string() const * @param length The length. */ -void crc16_creator::append(const void *data, uint32_t length) +void crc16_creator::append(const void *data, uint32_t length) noexcept { static const uint16_t s_table[256] = { @@ -442,18 +452,18 @@ void crc16_creator::append(const void *data, uint32_t length) // from_string - convert from a string //------------------------------------------------- -bool sum16_t::from_string(std::string_view string) +bool sum16_t::from_string(std::string_view string) noexcept { // must be at least long enough to hold everything m_raw = 0; - if (string.length() < 2 * sizeof(m_raw)) + if (string.length() < (2 * sizeof(m_raw))) return false; // iterate through our raw buffer m_raw = 0; for (int bytenum = 0; bytenum < sizeof(m_raw) * 2; bytenum++) { - int nibble = char_to_hex(string[0]); + int const nibble = char_to_hex(string[0]); if (nibble == -1) return false; m_raw = (m_raw << 4) | nibble; @@ -488,7 +498,7 @@ std::string sum16_t::as_string() const * @param length The length. */ -void sum16_creator::append(const void *data, uint32_t length) +void sum16_creator::append(const void *data, uint32_t length) noexcept { const auto *src = reinterpret_cast(data); diff --git a/src/lib/util/hashing.h b/src/lib/util/hashing.h index 6cd73ac1846..c57d403de1b 100644 --- a/src/lib/util/hashing.h +++ b/src/lib/util/hashing.h @@ -34,10 +34,10 @@ namespace util { // final digest struct sha1_t { - bool operator==(const sha1_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; } - bool operator!=(const sha1_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; } - operator uint8_t *() { return m_raw; } - bool from_string(std::string_view string); + bool operator==(const sha1_t &rhs) const noexcept { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; } + bool operator!=(const sha1_t &rhs) const noexcept { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; } + operator uint8_t *() noexcept { return m_raw; } + bool from_string(std::string_view string) noexcept; std::string as_string() const; uint8_t m_raw[20]; static const sha1_t null; @@ -48,19 +48,19 @@ class sha1_creator { public: // construction/destruction - sha1_creator() { reset(); } + sha1_creator() noexcept { reset(); } // reset - void reset(); + void reset() noexcept; // append data - void append(const void *data, uint32_t length); + void append(const void *data, uint32_t length) noexcept; // finalize and compute the final digest - sha1_t finish(); + sha1_t finish() noexcept; // static wrapper to just get the digest from a block - static sha1_t simple(const void *data, uint32_t length) + static sha1_t simple(const void *data, uint32_t length) noexcept { sha1_creator creator; creator.append(data, length); @@ -80,10 +80,10 @@ protected: // final digest struct md5_t { - bool operator==(const md5_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; } - bool operator!=(const md5_t &rhs) const { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; } - operator uint8_t *() { return m_raw; } - bool from_string(std::string_view string); + bool operator==(const md5_t &rhs) const noexcept { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) == 0; } + bool operator!=(const md5_t &rhs) const noexcept { return memcmp(m_raw, rhs.m_raw, sizeof(m_raw)) != 0; } + operator uint8_t *() noexcept { return m_raw; } + bool from_string(std::string_view string) noexcept; std::string as_string() const; uint8_t m_raw[16]; static const md5_t null; @@ -94,16 +94,16 @@ class md5_creator { public: // construction/destruction - md5_creator() { reset(); } + md5_creator() noexcept { reset(); } // reset - void reset() { MD5Init(&m_context); } + void reset() noexcept { MD5Init(&m_context); } // append data - void append(const void *data, uint32_t length) { MD5Update(&m_context, reinterpret_cast(data), length); } + void append(const void *data, uint32_t length) noexcept { MD5Update(&m_context, reinterpret_cast(data), length); } // finalize and compute the final digest - md5_t finish() + md5_t finish() noexcept { md5_t result; MD5Final(result.m_raw, &m_context); @@ -111,7 +111,7 @@ public: } // static wrapper to just get the digest from a block - static md5_t simple(const void *data, uint32_t length) + static md5_t simple(const void *data, uint32_t length) noexcept { md5_creator creator; creator.append(data, length); @@ -130,19 +130,19 @@ protected: // final digest struct crc32_t { - crc32_t() { } - constexpr crc32_t(const crc32_t &rhs) = default; - constexpr crc32_t(const uint32_t crc) : m_raw(crc) { } + crc32_t() noexcept { } + constexpr crc32_t(const crc32_t &rhs) noexcept = default; + constexpr crc32_t(const uint32_t crc) noexcept : m_raw(crc) { } - constexpr bool operator==(const crc32_t &rhs) const { return m_raw == rhs.m_raw; } - constexpr bool operator!=(const crc32_t &rhs) const { return m_raw != rhs.m_raw; } + constexpr bool operator==(const crc32_t &rhs) const noexcept { return m_raw == rhs.m_raw; } + constexpr bool operator!=(const crc32_t &rhs) const noexcept { return m_raw != rhs.m_raw; } - crc32_t &operator=(const crc32_t &rhs) = default; - crc32_t &operator=(const uint32_t crc) { m_raw = crc; return *this; } + crc32_t &operator=(const crc32_t &rhs) noexcept = default; + crc32_t &operator=(const uint32_t crc) noexcept { m_raw = crc; return *this; } - constexpr operator uint32_t() const { return m_raw; } + constexpr operator uint32_t() const noexcept { return m_raw; } - bool from_string(std::string_view string); + bool from_string(std::string_view string) noexcept; std::string as_string() const; uint32_t m_raw; @@ -155,19 +155,19 @@ class crc32_creator { public: // construction/destruction - crc32_creator() { reset(); } + crc32_creator() noexcept { reset(); } // reset - void reset() { m_accum.m_raw = 0; } + void reset() noexcept { m_accum.m_raw = 0; } // append data - void append(const void *data, uint32_t length); + void append(const void *data, uint32_t length) noexcept; // finalize and compute the final digest - crc32_t finish() { return m_accum; } + crc32_t finish() noexcept { return m_accum; } // static wrapper to just get the digest from a block - static crc32_t simple(const void *data, uint32_t length) + static crc32_t simple(const void *data, uint32_t length) noexcept { crc32_creator creator; creator.append(data, length); @@ -186,19 +186,19 @@ protected: // final digest struct crc16_t { - crc16_t() { } - constexpr crc16_t(const crc16_t &rhs) = default; - constexpr crc16_t(const uint16_t crc) : m_raw(crc) { } + crc16_t() noexcept { } + constexpr crc16_t(const crc16_t &rhs) noexcept = default; + constexpr crc16_t(const uint16_t crc) noexcept : m_raw(crc) { } - constexpr bool operator==(const crc16_t &rhs) const { return m_raw == rhs.m_raw; } - constexpr bool operator!=(const crc16_t &rhs) const { return m_raw != rhs.m_raw; } + constexpr bool operator==(const crc16_t &rhs) const noexcept { return m_raw == rhs.m_raw; } + constexpr bool operator!=(const crc16_t &rhs) const noexcept { return m_raw != rhs.m_raw; } - crc16_t &operator=(const crc16_t &rhs) = default; - crc16_t &operator=(const uint16_t crc) { m_raw = crc; return *this; } + crc16_t &operator=(const crc16_t &rhs) noexcept = default; + crc16_t &operator=(const uint16_t crc) noexcept { m_raw = crc; return *this; } - constexpr operator uint16_t() const { return m_raw; } + constexpr operator uint16_t() const noexcept { return m_raw; } - bool from_string(std::string_view string); + bool from_string(std::string_view string) noexcept; std::string as_string() const; uint16_t m_raw; @@ -211,19 +211,19 @@ class crc16_creator { public: // construction/destruction - crc16_creator() { reset(); } + crc16_creator() noexcept { reset(); } // reset - void reset() { m_accum.m_raw = 0xffff; } + void reset() noexcept { m_accum.m_raw = 0xffff; } // append data - void append(const void *data, uint32_t length); + void append(const void *data, uint32_t length) noexcept; // finalize and compute the final digest - crc16_t finish() { return m_accum; } + crc16_t finish() noexcept { return m_accum; } // static wrapper to just get the digest from a block - static crc16_t simple(const void *data, uint32_t length) + static crc16_t simple(const void *data, uint32_t length) noexcept { crc16_creator creator; creator.append(data, length); @@ -242,19 +242,19 @@ protected: // final digest struct sum16_t { - sum16_t() { } - constexpr sum16_t(const sum16_t &rhs) = default; - constexpr sum16_t(const uint16_t sum) : m_raw(sum) { } + sum16_t() noexcept { } + constexpr sum16_t(const sum16_t &rhs) noexcept = default; + constexpr sum16_t(const uint16_t sum) noexcept : m_raw(sum) { } - constexpr bool operator==(const sum16_t &rhs) const { return m_raw == rhs.m_raw; } - constexpr bool operator!=(const sum16_t &rhs) const { return m_raw != rhs.m_raw; } + constexpr bool operator==(const sum16_t &rhs) const noexcept { return m_raw == rhs.m_raw; } + constexpr bool operator!=(const sum16_t &rhs) const noexcept { return m_raw != rhs.m_raw; } - sum16_t &operator=(const sum16_t &rhs) = default; - sum16_t &operator=(const uint16_t sum) { m_raw = sum; return *this; } + sum16_t &operator=(const sum16_t &rhs) noexcept = default; + sum16_t &operator=(const uint16_t sum) noexcept { m_raw = sum; return *this; } - constexpr operator uint16_t() const { return m_raw; } + constexpr operator uint16_t() const noexcept { return m_raw; } - bool from_string(std::string_view string); + bool from_string(std::string_view string) noexcept; std::string as_string() const; uint16_t m_raw; @@ -267,19 +267,19 @@ class sum16_creator { public: // construction/destruction - sum16_creator() { reset(); } + sum16_creator() noexcept { reset(); } // reset - void reset() { m_accum.m_raw = 0; } + void reset() noexcept { m_accum.m_raw = 0; } // append data - void append(const void *data, uint32_t length); + void append(const void *data, uint32_t length) noexcept; // finalize and compute the final digest - sum16_t finish() { return m_accum; } + sum16_t finish() noexcept { return m_accum; } // static wrapper to just get the digest from a block - static sum16_t simple(const void *data, uint32_t length) + static sum16_t simple(const void *data, uint32_t length) noexcept { sum16_creator creator; creator.append(data, length); @@ -299,14 +299,14 @@ template <> struct hash<::util::crc32_t> { typedef ::util::crc32_t argument_type; typedef std::size_t result_type; - result_type operator()(argument_type const & s) const { return std::hash()(s); } + result_type operator()(argument_type const &s) const noexcept { return std::hash()(s); } }; template <> struct hash<::util::crc16_t> { typedef ::util::crc16_t argument_type; typedef std::size_t result_type; - result_type operator()(argument_type const & s) const { return std::hash()(s); } + result_type operator()(argument_type const &s) const noexcept { return std::hash()(s); } }; } // namespace std diff --git a/src/lib/util/md5.cpp b/src/lib/util/md5.cpp index 3e26d0c5b07..ca36792220e 100644 --- a/src/lib/util/md5.cpp +++ b/src/lib/util/md5.cpp @@ -22,9 +22,10 @@ * Still in the public domain. */ +#include "md5.h" + #include /* for memcpy() */ -#include "md5.h" #ifndef LSB_FIRST void diff --git a/src/lib/util/msdib.cpp b/src/lib/util/msdib.cpp index 6ce0e0fd990..7b537fdae61 100644 --- a/src/lib/util/msdib.cpp +++ b/src/lib/util/msdib.cpp @@ -93,7 +93,7 @@ union bitmap_headers }; -bool dib_parse_mask(std::uint32_t mask, unsigned &shift, unsigned &bits) +bool dib_parse_mask(std::uint32_t mask, unsigned &shift, unsigned &bits) noexcept { shift = count_leading_zeros_32(mask); mask <<= shift; @@ -104,7 +104,7 @@ bool dib_parse_mask(std::uint32_t mask, unsigned &shift, unsigned &bits) } -void dib_truncate_channel(unsigned &shift, unsigned &bits) +void dib_truncate_channel(unsigned &shift, unsigned &bits) noexcept { if (8U < bits) { @@ -115,7 +115,7 @@ void dib_truncate_channel(unsigned &shift, unsigned &bits) } -std::uint8_t dib_splat_sample(std::uint8_t val, unsigned bits) +std::uint8_t dib_splat_sample(std::uint8_t val, unsigned bits) noexcept { assert(8U >= bits); for (val <<= (8U - bits); bits && (8U > bits); bits <<= 1) @@ -124,7 +124,7 @@ std::uint8_t dib_splat_sample(std::uint8_t val, unsigned bits) } -msdib_error dib_read_file_header(read_stream &fp, std::uint32_t &filelen) +msdib_error dib_read_file_header(read_stream &fp, std::uint32_t &filelen) noexcept { std::size_t actual; @@ -172,7 +172,7 @@ msdib_error dib_read_bitmap_header( std::size_t &palette_entries, std::size_t &palette_size, std::size_t &row_bytes, - std::uint32_t length) + std::uint32_t length) noexcept { std::size_t actual; @@ -397,7 +397,7 @@ msdib_error dib_read_bitmap_header( -msdib_error msdib_verify_header(random_read &fp) +msdib_error msdib_verify_header(random_read &fp) noexcept { msdib_error err; @@ -438,7 +438,7 @@ msdib_error msdib_verify_header(random_read &fp) } -msdib_error msdib_read_bitmap(random_read &fp, bitmap_argb32 &bitmap) +msdib_error msdib_read_bitmap(random_read &fp, bitmap_argb32 &bitmap) noexcept { std::uint32_t file_length; msdib_error const headerr(dib_read_file_header(fp, file_length)); @@ -449,7 +449,7 @@ msdib_error msdib_read_bitmap(random_read &fp, bitmap_argb32 &bitmap) } -msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::uint32_t length, std::uint32_t dirheight) +msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::uint32_t length, std::uint32_t dirheight) noexcept { // read the bitmap header std::size_t actual; @@ -570,11 +570,15 @@ msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std:: dib_truncate_channel(alpha_shift, alpha_bits); } - // allocate the bitmap and process row data + // allocate a row buffer as well as the destination bitmap std::unique_ptr row_data(new (std::nothrow) std::uint8_t [row_bytes]); if (!row_data) return msdib_error::OUT_OF_MEMORY; bitmap.allocate(header.info.width, header.info.height); + if (!bitmap.valid()) + return msdib_error::OUT_OF_MEMORY; + + // process row data int const y_inc(top_down ? 1 : -1); for (std::int32_t i = 0, y = top_down ? 0 : (header.info.height - 1); header.info.height > i; ++i, y += y_inc) { diff --git a/src/lib/util/msdib.h b/src/lib/util/msdib.h index 8d8a9078c5b..fb6697c2eb6 100644 --- a/src/lib/util/msdib.h +++ b/src/lib/util/msdib.h @@ -36,9 +36,9 @@ enum class msdib_error UNSUPPORTED_FORMAT }; -msdib_error msdib_verify_header(random_read &fp); -msdib_error msdib_read_bitmap(random_read &fp, bitmap_argb32 &bitmap); -msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::uint32_t length, std::uint32_t dirheight = 0U); +msdib_error msdib_verify_header(random_read &fp) noexcept; +msdib_error msdib_read_bitmap(random_read &fp, bitmap_argb32 &bitmap) noexcept; +msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::uint32_t length, std::uint32_t dirheight = 0U) noexcept; } // namespace util diff --git a/src/lib/util/png.cpp b/src/lib/util/png.cpp index e2fc9aecfe7..8e077f92114 100644 --- a/src/lib/util/png.cpp +++ b/src/lib/util/png.cpp @@ -37,7 +37,7 @@ namespace util { pnginfo structure -------------------------------------------------*/ -void png_info::free_data() +void png_info::free_data() noexcept { textlist.clear(); palette.reset(); @@ -94,15 +94,15 @@ constexpr std::uint8_t PNG_PF_Paeth = 4; INLINE FUNCTIONS ***************************************************************************/ -inline int compute_rowbytes(const png_info &pnginfo) { return (pnginfo.width * samples[pnginfo.color_type] * pnginfo.bit_depth + 7) / 8; } +inline int compute_rowbytes(const png_info &pnginfo) noexcept { return (pnginfo.width * samples[pnginfo.color_type] * pnginfo.bit_depth + 7) / 8; } -inline uint8_t fetch_8bit(uint8_t const *v) { return *v; } -inline uint16_t fetch_16bit(uint8_t const *v) { return big_endianize_int16(*reinterpret_cast(v)); } -inline uint32_t fetch_32bit(uint8_t const *v) { return big_endianize_int32(*reinterpret_cast(v)); } +inline uint8_t fetch_8bit(uint8_t const *v) noexcept { return *v; } +inline uint16_t fetch_16bit(uint8_t const *v) noexcept { return big_endianize_int16(*reinterpret_cast(v)); } +inline uint32_t fetch_32bit(uint8_t const *v) noexcept { return big_endianize_int32(*reinterpret_cast(v)); } -inline void put_8bit(uint8_t *v, uint8_t data) { *v = data; } -inline void put_16bit(uint8_t *v, uint16_t data) { *reinterpret_cast(v) = big_endianize_int16(data); } -inline void put_32bit(uint8_t *v, uint32_t data) { *reinterpret_cast(v) = big_endianize_int32(data); } +inline void put_8bit(uint8_t *v, uint8_t data) noexcept { *v = data; } +inline void put_16bit(uint8_t *v, uint16_t data) noexcept { *reinterpret_cast(v) = big_endianize_int16(data); } +inline void put_32bit(uint8_t *v, uint32_t data) noexcept { *reinterpret_cast(v) = big_endianize_int32(data); } /*************************************************************************** @@ -149,13 +149,13 @@ private: struct image_data_chunk { - image_data_chunk(std::uint32_t l, std::unique_ptr &&d) : length(l), data(std::move(d)) { } + image_data_chunk(std::uint32_t l, std::unique_ptr &&d) noexcept : length(l), data(std::move(d)) { } std::uint32_t length; std::unique_ptr data; }; - std::error_condition process(std::list const &idata) + std::error_condition process(std::list const &idata) noexcept { // do some basic checks for unsupported images if (!pnginfo.bit_depth || (std::size(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type]) @@ -206,7 +206,7 @@ private: return error; } - std::error_condition decompress(std::list const &idata, std::uint32_t expected) + std::error_condition decompress(std::list const &idata, std::uint32_t expected) noexcept { // only deflate is permitted if (0 != pnginfo.compression_method) @@ -254,7 +254,7 @@ private: return png_error::DECOMPRESS_ERROR; // TODO: refactor this function for more fine-grained error reporting? } - std::error_condition unfilter_row(std::uint8_t type, uint8_t const *src, uint8_t *dst, uint8_t const *dstprev, int bpp, std::uint32_t rowbytes) + std::error_condition unfilter_row(std::uint8_t type, uint8_t const *src, uint8_t *dst, uint8_t const *dstprev, int bpp, std::uint32_t rowbytes) noexcept { if (0 != pnginfo.filter_method) return png_error::UNKNOWN_FILTER; @@ -320,7 +320,7 @@ private: } } - std::error_condition process_chunk(std::list &idata, std::unique_ptr &&data, uint32_t type, uint32_t length) + std::error_condition process_chunk(std::list &idata, std::unique_ptr &&data, uint32_t type, uint32_t length) noexcept { switch (type) { @@ -406,12 +406,12 @@ private: return std::error_condition(); } - unsigned get_pass_count() const + unsigned get_pass_count() const noexcept { return (1 == pnginfo.interlace_method) ? 7 : 1; } - std::pair get_pass_dimensions(unsigned pass) const + std::pair get_pass_dimensions(unsigned pass) const noexcept { if (0 == pnginfo.interlace_method) return std::make_pair(pnginfo.width, pnginfo.height); @@ -419,39 +419,39 @@ private: return std::make_pair((pnginfo.width + ADAM7_X_BIAS[pass]) >> ADAM7_X_SHIFT[pass], (pnginfo.height + ADAM7_Y_BIAS[pass]) >> ADAM7_Y_SHIFT[pass]); } - std::uint32_t get_pass_bytes(unsigned pass) const + std::uint32_t get_pass_bytes(unsigned pass) const noexcept { return get_pass_bytes(pass, pnginfo.bit_depth); } - std::uint32_t get_pass_bytes(unsigned pass, uint8_t bit_depth) const + std::uint32_t get_pass_bytes(unsigned pass, uint8_t bit_depth) const noexcept { std::pair const dimensions(get_pass_dimensions(pass)); return (get_row_bytes(dimensions.first, bit_depth) + 1) * dimensions.second; } - std::uint32_t get_row_bytes(std::uint32_t width) const + std::uint32_t get_row_bytes(std::uint32_t width) const noexcept { return get_row_bytes(width, pnginfo.bit_depth); } - std::uint32_t get_row_bytes(std::uint32_t width, uint8_t bit_depth) const + std::uint32_t get_row_bytes(std::uint32_t width, uint8_t bit_depth) const noexcept { return ((width * samples[pnginfo.color_type] * bit_depth) + 7) >> 3; } - std::uint32_t get_bytes_per_pixel() const + std::uint32_t get_bytes_per_pixel() const noexcept { return ((samples[pnginfo.color_type] * pnginfo.bit_depth) + 7) >> 3; } - static std::error_condition read_chunk(read_stream &fp, std::unique_ptr &data, std::uint32_t &type, std::uint32_t &length) + static std::error_condition read_chunk(read_stream &fp, std::unique_ptr &data, std::uint32_t &type, std::uint32_t &length) noexcept { std::error_condition err; std::size_t actual; std::uint8_t tempbuff[4]; - /* fetch the length of this chunk */ + // fetch the length of this chunk err = fp.read(tempbuff, 4, actual); if (err) return err; @@ -459,7 +459,7 @@ private: return png_error::FILE_TRUNCATED; length = fetch_32bit(tempbuff); - /* fetch the type of this chunk */ + // fetch the type of this chunk err = fp.read(tempbuff, 4, actual); if (err) return err; @@ -467,22 +467,22 @@ private: return png_error::FILE_TRUNCATED; type = fetch_32bit(tempbuff); - /* stop when we hit an IEND chunk */ + // stop when we hit an IEND chunk if (type == PNG_CN_IEND) return std::error_condition(); - /* start the CRC with the chunk type (but not the length) */ + // start the CRC with the chunk type (but not the length) std::uint32_t crc = crc32(0, tempbuff, 4); - /* read the chunk itself into an allocated memory buffer */ + // read the chunk itself into an allocated memory buffer if (length) { - /* allocate memory for this chunk */ + // allocate memory for this chunk data.reset(new (std::nothrow) std::uint8_t [length]); if (!data) return std::errc::not_enough_memory; - /* read the data from the file */ + // read the data from the file err = fp.read(data.get(), length, actual); if (err) { @@ -495,11 +495,11 @@ private: return png_error::FILE_TRUNCATED; } - /* update the CRC */ + // update the CRC crc = crc32(crc, data.get(), length); } - /* read the CRC */ + // read the CRC err = fp.read(tempbuff, 4, actual); if (err) { @@ -513,7 +513,7 @@ private: } std::uint32_t const chunk_crc = fetch_32bit(tempbuff); - /* validate the CRC */ + // validate the CRC if (crc != chunk_crc) { data.reset(); @@ -526,11 +526,11 @@ private: png_info & pnginfo; public: - png_private(png_info &info) : pnginfo(info) + png_private(png_info &info) noexcept : pnginfo(info) { } - std::error_condition copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) const + std::error_condition copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) const noexcept { // do some basic checks for unsupported images if ((8 > pnginfo.bit_depth) || (pnginfo.bit_depth % 8)) @@ -542,8 +542,12 @@ public: if ((3 == pnginfo.color_type) && (8 != pnginfo.bit_depth)) return png_error::UNSUPPORTED_FORMAT; // indexed colour must be exactly 8bpp - // everything looks sane, allocate the bitmap and deinterlace into it + // try to allocate the bitmap bitmap.allocate(pnginfo.width, pnginfo.height); + if (!bitmap.valid()) + return std::errc::not_enough_memory; + + // everything looks sane, deinterlace into the bitmap std::uint8_t accumalpha(0xff); uint32_t const bps(pnginfo.bit_depth >> 3); uint32_t const bpp(bps * samples[pnginfo.color_type]); @@ -659,7 +663,7 @@ public: return std::error_condition(); } - std::error_condition expand_buffer_8bit() + std::error_condition expand_buffer_8bit() noexcept { // nothing to do if we're at 8 or greater already if (pnginfo.bit_depth >= 8) @@ -743,7 +747,7 @@ public: return std::error_condition(); } - std::error_condition read_file(read_stream &fp) + std::error_condition read_file(read_stream &fp) noexcept { // initialize the data structures std::error_condition error; @@ -780,7 +784,7 @@ public: return error; } - static std::error_condition verify_header(read_stream &fp) + static std::error_condition verify_header(read_stream &fp) noexcept { std::uint8_t signature[sizeof(PNG_SIGNATURE)]; @@ -817,7 +821,7 @@ constexpr unsigned png_private::ADAM7_Y_OFFS[7]; core stream -------------------------------------------------*/ -std::error_condition png_info::verify_header(read_stream &fp) +std::error_condition png_info::verify_header(read_stream &fp) noexcept { return png_private::verify_header(fp); } @@ -827,7 +831,7 @@ std::error_condition png_info::verify_header(read_stream &fp) read_file - read a PNG from a core stream -------------------------------------------------*/ -std::error_condition png_info::read_file(read_stream &fp) +std::error_condition png_info::read_file(read_stream &fp) noexcept { return png_private(*this).read_file(fp); } @@ -838,7 +842,7 @@ std::error_condition png_info::read_file(read_stream &fp) bitmap -------------------------------------------------*/ -std::error_condition png_read_bitmap(read_stream &fp, bitmap_argb32 &bitmap) +std::error_condition png_read_bitmap(read_stream &fp, bitmap_argb32 &bitmap) noexcept { std::error_condition result; png_info pnginfo; @@ -868,7 +872,7 @@ std::error_condition png_read_bitmap(read_stream &fp, bitmap_argb32 &bitmap) bitmap -------------------------------------------------*/ -std::error_condition png_info::copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) +std::error_condition png_info::copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) noexcept { return png_private(*this).copy_to_bitmap(bitmap, hasalpha); } @@ -879,7 +883,7 @@ std::error_condition png_info::copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasal sub 8-bit to 8-bit -------------------------------------------------*/ -std::error_condition png_info::expand_buffer_8bit() +std::error_condition png_info::expand_buffer_8bit() noexcept { return png_private(*this).expand_buffer_8bit(); } @@ -894,7 +898,7 @@ std::error_condition png_info::expand_buffer_8bit() add_text - add a text entry to the png_info -------------------------------------------------*/ -std::error_condition png_info::add_text(std::string_view keyword, std::string_view text) +std::error_condition png_info::add_text(std::string_view keyword, std::string_view text) noexcept { // apply rules to keyword char32_t prev(0); @@ -934,26 +938,26 @@ std::error_condition png_info::add_text(std::string_view keyword, std::string_vi the given file -------------------------------------------------*/ -static std::error_condition write_chunk(write_stream &fp, const uint8_t *data, uint32_t type, uint32_t length) +static std::error_condition write_chunk(write_stream &fp, const uint8_t *data, uint32_t type, uint32_t length) noexcept { std::error_condition err; std::size_t written; std::uint8_t tempbuff[8]; std::uint32_t crc; - /* stuff the length/type into the buffer */ + // stuff the length/type into the buffer put_32bit(tempbuff + 0, length); put_32bit(tempbuff + 4, type); crc = crc32(0, tempbuff + 4, 4); - /* write that data */ + // write that data err = fp.write(tempbuff, 8, written); if (err) return err; else if (8 != written) return std::errc::io_error; - /* append the actual data */ + // append the actual data if (length > 0) { err = fp.write(data, length, written); @@ -964,7 +968,7 @@ static std::error_condition write_chunk(write_stream &fp, const uint8_t *data, u crc = crc32(crc, data, length); } - /* write the CRC */ + // write the CRC put_32bit(tempbuff, crc); err = fp.write(tempbuff, 4, written); if (err) @@ -981,7 +985,7 @@ static std::error_condition write_chunk(write_stream &fp, const uint8_t *data, u chunk to the given file by deflating it -------------------------------------------------*/ -static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data, uint32_t type, uint32_t length) +static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data, uint32_t type, uint32_t length) noexcept { std::error_condition err; std::uint64_t lengthpos; @@ -996,19 +1000,19 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data std::uint32_t crc; int zerr; - /* stuff the length/type into the buffer */ + // stuff the length/type into the buffer put_32bit(tempbuff + 0, length); put_32bit(tempbuff + 4, type); crc = crc32(0, tempbuff + 4, 4); - /* write that data */ + // write that data err = fp.write(tempbuff, 8, written); if (err) return err; else if (8 != written) return std::errc::io_error; - /* initialize the stream */ + // initialize the stream memset(&stream, 0, sizeof(stream)); stream.next_in = data; stream.avail_in = length; @@ -1020,7 +1024,7 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data else if (Z_OK != zerr) return png_error::COMPRESS_ERROR; - /* now loop until we run out of data */ + // now loop until we run out of data for ( ; ; ) { /* compress this chunk */ @@ -1028,7 +1032,7 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data stream.avail_out = sizeof(tempbuff); zerr = deflate(&stream, Z_FINISH); - /* if there's data to write, do it */ + // if there's data to write, do it if (stream.avail_out < sizeof(tempbuff)) { int bytes = sizeof(tempbuff) - stream.avail_out; @@ -1047,11 +1051,11 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data zlength += bytes; } - /* stop at the end of the stream */ + // stop at the end of the stream if (zerr == Z_STREAM_END) break; - /* other errors are fatal */ + // other errors are fatal if (zerr != Z_OK) { deflateEnd(&stream); @@ -1064,7 +1068,7 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data } } - /* clean up deflater(maus) */ + // clean up deflater zerr = deflateEnd(&stream); if (Z_ERRNO == zerr) return std::error_condition(errno, std::generic_category()); @@ -1073,7 +1077,7 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data else if (Z_OK != zerr) return png_error::COMPRESS_ERROR; - /* write the CRC */ + // write the CRC put_32bit(tempbuff, crc); err = fp.write(tempbuff, 4, written); if (err) @@ -1081,7 +1085,7 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data else if (4 != written) return std::errc::io_error; - /* seek back and update the length */ + // seek back and update the length err = fp.seek(lengthpos, SEEK_SET); if (err) return err; @@ -1092,7 +1096,7 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data else if (4 != written) return std::errc::io_error; - /* return to the end */ + // return to the end return fp.seek(lengthpos + 8 + zlength + 4, SEEK_SET); } @@ -1102,9 +1106,9 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data bitmap to a palettized image -------------------------------------------------*/ -static std::error_condition convert_bitmap_to_image_palette(png_info &pnginfo, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) +static std::error_condition convert_bitmap_to_image_palette(png_info &pnginfo, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) noexcept { - /* set the common info */ + // set the common info pnginfo.width = bitmap.width(); pnginfo.height = bitmap.height(); pnginfo.bit_depth = 8; @@ -1112,12 +1116,12 @@ static std::error_condition convert_bitmap_to_image_palette(png_info &pnginfo, b pnginfo.num_palette = 256; int const rowbytes = pnginfo.width; - /* allocate memory for the palette */ + // allocate memory for the palette pnginfo.palette.reset(new (std::nothrow) std::uint8_t [3 * 256]); if (!pnginfo.palette) return std::errc::not_enough_memory; - /* build the palette */ + // build the palette std::fill_n(pnginfo.palette.get(), 3 * 256, 0); for (int x = 0; x < palette_length; x++) { @@ -1127,7 +1131,7 @@ static std::error_condition convert_bitmap_to_image_palette(png_info &pnginfo, b pnginfo.palette[3 * x + 2] = color.b(); } - /* allocate memory for the image */ + // allocate memory for the image pnginfo.image.reset(new (std::nothrow) std::uint8_t [pnginfo.height * (rowbytes + 1)]); if (!pnginfo.image) { @@ -1135,13 +1139,13 @@ static std::error_condition convert_bitmap_to_image_palette(png_info &pnginfo, b return std::errc::not_enough_memory; } - /* copy in the pixels, specifying a nullptr filter */ + // copy in the pixels, specifying a nullptr filter for (int y = 0; y < pnginfo.height; y++) { uint16_t const *src = reinterpret_cast(bitmap.raw_pixptr(y)); uint8_t *dst = &pnginfo.image[y * (rowbytes + 1)]; - /* store the filter byte, then copy the data */ + // store the filter byte, then copy the data *dst++ = 0; for (int x = 0; x < pnginfo.width; x++) *dst++ = *src++; @@ -1156,33 +1160,33 @@ static std::error_condition convert_bitmap_to_image_palette(png_info &pnginfo, b bitmap to an RGB image -------------------------------------------------*/ -static std::error_condition convert_bitmap_to_image_rgb(png_info &pnginfo, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) +static std::error_condition convert_bitmap_to_image_rgb(png_info &pnginfo, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) noexcept { bool const alpha = (bitmap.format() == BITMAP_FORMAT_ARGB32); - /* set the common info */ + // set the common info pnginfo.width = bitmap.width(); pnginfo.height = bitmap.height(); pnginfo.bit_depth = 8; pnginfo.color_type = alpha ? 6 : 2; int const rowbytes = pnginfo.width * (alpha ? 4 : 3); - /* allocate memory for the image */ + // allocate memory for the image pnginfo.image.reset(new (std::nothrow) std::uint8_t [pnginfo.height * (rowbytes + 1)]); if (!pnginfo.image) return std::errc::not_enough_memory; - /* copy in the pixels, specifying a nullptr filter */ + // copy in the pixels, specifying a nullptr filter for (int y = 0; y < pnginfo.height; y++) { uint8_t *dst = &pnginfo.image[y * (rowbytes + 1)]; - /* store the filter byte, then copy the data */ + // store the filter byte, then copy the data *dst++ = 0; if (bitmap.format() == BITMAP_FORMAT_IND16) { - /* 16bpp palettized format */ + // 16bpp palettized format uint16_t const *src16 = reinterpret_cast(bitmap.raw_pixptr(y)); for (int x = 0; x < pnginfo.width; x++) { @@ -1194,7 +1198,7 @@ static std::error_condition convert_bitmap_to_image_rgb(png_info &pnginfo, bitma } else if (bitmap.format() == BITMAP_FORMAT_RGB32) { - /* 32-bit RGB direct */ + // 32-bit RGB direct uint32_t const *src32 = reinterpret_cast(bitmap.raw_pixptr(y)); for (int x = 0; x < pnginfo.width; x++) { @@ -1206,7 +1210,7 @@ static std::error_condition convert_bitmap_to_image_rgb(png_info &pnginfo, bitma } else if (bitmap.format() == BITMAP_FORMAT_ARGB32) { - /* 32-bit ARGB direct */ + // 32-bit ARGB direct uint32_t const *src32 = reinterpret_cast(bitmap.raw_pixptr(y)); for (int x = 0; x < pnginfo.width; x++) { @@ -1219,7 +1223,7 @@ static std::error_condition convert_bitmap_to_image_rgb(png_info &pnginfo, bitma } else { - /* unsupported format */ + // unsupported format return png_error::UNSUPPORTED_FORMAT; } } @@ -1233,7 +1237,7 @@ static std::error_condition convert_bitmap_to_image_rgb(png_info &pnginfo, bitma chunks to the given file -------------------------------------------------*/ -static std::error_condition write_png_stream(random_write &fp, png_info &pnginfo, const bitmap_t &bitmap, int palette_length, const rgb_t *palette) +static std::error_condition write_png_stream(random_write &fp, png_info &pnginfo, const bitmap_t &bitmap, int palette_length, const rgb_t *palette) noexcept { uint8_t tempbuff[16]; std::error_condition error; @@ -1290,7 +1294,7 @@ static std::error_condition write_png_stream(random_write &fp, png_info &pnginfo src.remove_prefix(len); } - // NUL separator between keword and text + // NUL separator between keyword and text *dst++ = 0; // convert text to ISO-8859-1 @@ -1314,7 +1318,7 @@ static std::error_condition write_png_stream(random_write &fp, png_info &pnginfo } -std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) +std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) noexcept { // use a dummy pnginfo if none passed to us png_info pnginfo; @@ -1329,7 +1333,7 @@ std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t else if (sizeof(PNG_SIGNATURE) != written) return std::errc::io_error; - /* write the rest of the PNG data */ + // write the rest of the PNG data return write_png_stream(fp, *info, bitmap, palette_length, palette); } @@ -1341,7 +1345,7 @@ std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t ********************************************************************************/ -std::error_condition mng_capture_start(random_write &fp, bitmap_t const &bitmap, unsigned rate) +std::error_condition mng_capture_start(random_write &fp, bitmap_t const &bitmap, unsigned rate) noexcept { std::size_t written; std::error_condition err = fp.write(MNG_Signature, 8, written); @@ -1360,13 +1364,13 @@ std::error_condition mng_capture_start(random_write &fp, bitmap_t const &bitmap, } -std::error_condition mng_capture_frame(random_write &fp, png_info &info, bitmap_t const &bitmap, int palette_length, rgb_t const *palette) +std::error_condition mng_capture_frame(random_write &fp, png_info &info, bitmap_t const &bitmap, int palette_length, rgb_t const *palette) noexcept { return write_png_stream(fp, info, bitmap, palette_length, palette); } -std::error_condition mng_capture_stop(random_write &fp) +std::error_condition mng_capture_stop(random_write &fp) noexcept { return write_chunk(fp, nullptr, MNG_CN_MEND, 0); } diff --git a/src/lib/util/png.h b/src/lib/util/png.h index d802c1a5a82..2f9b7ac29cb 100644 --- a/src/lib/util/png.h +++ b/src/lib/util/png.h @@ -60,16 +60,16 @@ public: ~png_info() { free_data(); } - std::error_condition read_file(read_stream &fp); - std::error_condition copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha); - std::error_condition expand_buffer_8bit(); + std::error_condition read_file(read_stream &fp) noexcept; + std::error_condition copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) noexcept; + std::error_condition expand_buffer_8bit() noexcept; - std::error_condition add_text(std::string_view keyword, std::string_view text); + std::error_condition add_text(std::string_view keyword, std::string_view text) noexcept; - void free_data(); - void reset() { free_data(); operator=(png_info()); } + void free_data() noexcept; + void reset() noexcept { free_data(); operator=(png_info()); } - static std::error_condition verify_header(read_stream &fp); + static std::error_condition verify_header(read_stream &fp) noexcept; std::unique_ptr image; std::uint32_t width, height; @@ -102,13 +102,13 @@ private: FUNCTION PROTOTYPES ***************************************************************************/ -std::error_condition png_read_bitmap(read_stream &fp, bitmap_argb32 &bitmap); +std::error_condition png_read_bitmap(read_stream &fp, bitmap_argb32 &bitmap) noexcept; -std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette); +std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) noexcept; -std::error_condition mng_capture_start(random_write &fp, bitmap_t const &bitmap, unsigned rate); -std::error_condition mng_capture_frame(random_write &fp, png_info &info, bitmap_t const &bitmap, int palette_length, rgb_t const *palette); -std::error_condition mng_capture_stop(random_write &fp); +std::error_condition mng_capture_start(random_write &fp, bitmap_t const &bitmap, unsigned rate) noexcept; +std::error_condition mng_capture_frame(random_write &fp, png_info &info, bitmap_t const &bitmap, int palette_length, rgb_t const *palette) noexcept; +std::error_condition mng_capture_stop(random_write &fp) noexcept; } // namespace util diff --git a/src/osd/modules/lib/osdlib_win32.cpp b/src/osd/modules/lib/osdlib_win32.cpp index 067fbd1224f..23e75bf9dc2 100644 --- a/src/osd/modules/lib/osdlib_win32.cpp +++ b/src/osd/modules/lib/osdlib_win32.cpp @@ -356,12 +356,12 @@ void virtual_memory_allocation::do_free(void *start, std::size_t size) bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access) { - DWORD p, o; + DWORD p; if (access & EXECUTE) p = (access & WRITE) ? PAGE_EXECUTE_READWRITE : (access & READ) ? PAGE_EXECUTE_READ : PAGE_EXECUTE; else p = (access & WRITE) ? PAGE_READWRITE : (access & READ) ? PAGE_READONLY : PAGE_NOACCESS; - return VirtualProtect(start, size, p, &o) != 0; + return VirtualAlloc(start, size, MEM_COMMIT, p) != nullptr; } -- cgit v1.2.3