From 9c13257da22208fc00acec95c6489aa3c33769fb Mon Sep 17 00:00:00 2001 From: jules Date: Sun, 6 Sep 2015 15:42:34 +0100 Subject: [PATCH] Added flag JUCE_EXCEPTIONS_DISABLED to detect compiling with exceptions turned off, and removed internal exception use from a few places in the codebase. --- modules/juce_core/memory/juce_HeapBlock.h | 6 +- .../juce_core/system/juce_CompilerSupport.h | 18 ++ .../juce_core/unit_tests/juce_UnitTest.cpp | 4 + .../image_formats/juce_JPEGLoader.cpp | 102 ++++++------ .../image_formats/juce_PNGLoader.cpp | 156 +++++++++--------- .../images/juce_ImageFileFormat.cpp | 10 +- 6 files changed, 161 insertions(+), 135 deletions(-) diff --git a/modules/juce_core/memory/juce_HeapBlock.h b/modules/juce_core/memory/juce_HeapBlock.h index 5672d372ab..bf0ff83b81 100644 --- a/modules/juce_core/memory/juce_HeapBlock.h +++ b/modules/juce_core/memory/juce_HeapBlock.h @@ -29,7 +29,7 @@ #ifndef JUCE_HEAPBLOCK_H_INCLUDED #define JUCE_HEAPBLOCK_H_INCLUDED -#ifndef DOXYGEN +#if ! (defined (DOXYGEN) || JUCE_EXCEPTIONS_DISABLED) namespace HeapBlockHelper { template @@ -295,7 +295,11 @@ private: void throwOnAllocationFailure() const { + #if JUCE_EXCEPTIONS_DISABLED + jassert (data != nullptr); // without exceptions, you'll need to find a better way to handle this failure case. + #else HeapBlockHelper::ThrowOnFail::check (data); + #endif } #if ! (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD)) diff --git a/modules/juce_core/system/juce_CompilerSupport.h b/modules/juce_core/system/juce_CompilerSupport.h index b25b1f255c..103cd51326 100644 --- a/modules/juce_core/system/juce_CompilerSupport.h +++ b/modules/juce_core/system/juce_CompilerSupport.h @@ -54,6 +54,12 @@ #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && ! defined (JUCE_COMPILER_SUPPORTS_LAMBDAS) #define JUCE_COMPILER_SUPPORTS_LAMBDAS 1 #endif + + #ifndef JUCE_EXCEPTIONS_DISABLED + #if ! __EXCEPTIONS + #define JUCE_EXCEPTIONS_DISABLED 1 + #endif + #endif #endif //============================================================================== @@ -95,6 +101,12 @@ #define JUCE_COMPILER_SUPPORTS_ARC 1 #endif + #ifndef JUCE_EXCEPTIONS_DISABLED + #if ! __has_feature (cxx_exceptions) + #define JUCE_EXCEPTIONS_DISABLED 1 + #endif + #endif + #endif //============================================================================== @@ -119,6 +131,12 @@ #if _MSC_VER >= 1900 #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1 #endif + + #ifndef JUCE_EXCEPTIONS_DISABLED + #if ! _CPPUNWIND + #define JUCE_EXCEPTIONS_DISABLED 1 + #endif + #endif #endif //============================================================================== diff --git a/modules/juce_core/unit_tests/juce_UnitTest.cpp b/modules/juce_core/unit_tests/juce_UnitTest.cpp index 249374b075..597314d685 100644 --- a/modules/juce_core/unit_tests/juce_UnitTest.cpp +++ b/modules/juce_core/unit_tests/juce_UnitTest.cpp @@ -143,6 +143,9 @@ void UnitTestRunner::runTests (const Array& tests, int64 randomSeed) if (shouldAbortTests()) break; + #if JUCE_EXCEPTIONS_DISABLED + tests.getUnchecked(i)->performTest (this); + #else try { tests.getUnchecked(i)->performTest (this); @@ -151,6 +154,7 @@ void UnitTestRunner::runTests (const Array& tests, int64 randomSeed) { addFail ("An unhandled exception was thrown!"); } + #endif } endTest(); diff --git a/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp b/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp index 1f98a97fcd..a5a09a590a 100644 --- a/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp +++ b/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp @@ -139,9 +139,7 @@ namespace JPEGHelpers using jpeglibNamespace::boolean; #endif - struct JPEGDecodingFailure {}; - - static void fatalErrorHandler (j_common_ptr) { throw JPEGDecodingFailure(); } + static void fatalErrorHandler (j_common_ptr p) { *((bool*) (p->client_data)) = true; } static void silentErrorCallback1 (j_common_ptr) {} static void silentErrorCallback2 (j_common_ptr, int) {} static void silentErrorCallback3 (j_common_ptr, char*) {} @@ -264,6 +262,9 @@ Image JPEGImageFormat::decodeImage (InputStream& in) jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small) ((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr)); + bool hasFailed = false; + jpegDecompStruct.client_data = &hasFailed; + jpegDecompStruct.src->init_source = dummyCallback1; jpegDecompStruct.src->fill_input_buffer = jpegFill; jpegDecompStruct.src->skip_input_data = jpegSkip; @@ -273,67 +274,72 @@ Image JPEGImageFormat::decodeImage (InputStream& in) jpegDecompStruct.src->next_input_byte = static_cast (mb.getData()); jpegDecompStruct.src->bytes_in_buffer = mb.getDataSize(); - try - { - jpeg_read_header (&jpegDecompStruct, TRUE); + jpeg_read_header (&jpegDecompStruct, TRUE); + if (! hasFailed) + { jpeg_calc_output_dimensions (&jpegDecompStruct); - const int width = (int) jpegDecompStruct.output_width; - const int height = (int) jpegDecompStruct.output_height; - - jpegDecompStruct.out_color_space = JCS_RGB; - - JSAMPARRAY buffer - = (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct, - JPOOL_IMAGE, - (JDIMENSION) width * 3, 1); - - if (jpeg_start_decompress (&jpegDecompStruct)) + if (! hasFailed) { - image = Image (Image::RGB, width, height, false); - image.getProperties()->set ("originalImageHadAlpha", false); - const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) + const int width = (int) jpegDecompStruct.output_width; + const int height = (int) jpegDecompStruct.output_height; - const Image::BitmapData destData (image, Image::BitmapData::writeOnly); + jpegDecompStruct.out_color_space = JCS_RGB; - for (int y = 0; y < height; ++y) + JSAMPARRAY buffer + = (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct, + JPOOL_IMAGE, + (JDIMENSION) width * 3, 1); + + if (jpeg_start_decompress (&jpegDecompStruct) && ! hasFailed) { - jpeg_read_scanlines (&jpegDecompStruct, buffer, 1); + image = Image (Image::RGB, width, height, false); + image.getProperties()->set ("originalImageHadAlpha", false); + const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) - const uint8* src = *buffer; - uint8* dest = destData.getLinePointer (y); + const Image::BitmapData destData (image, Image::BitmapData::writeOnly); - if (hasAlphaChan) + for (int y = 0; y < height; ++y) { - for (int i = width; --i >= 0;) + jpeg_read_scanlines (&jpegDecompStruct, buffer, 1); + + if (hasFailed) + break; + + const uint8* src = *buffer; + uint8* dest = destData.getLinePointer (y); + + if (hasAlphaChan) { - ((PixelARGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); - ((PixelARGB*) dest)->premultiply(); - dest += destData.pixelStride; - src += 3; - } - } - else - { - for (int i = width; --i >= 0;) - { - ((PixelRGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); - dest += destData.pixelStride; - src += 3; + for (int i = width; --i >= 0;) + { + ((PixelARGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); + ((PixelARGB*) dest)->premultiply(); + dest += destData.pixelStride; + src += 3; + } + } + else + { + for (int i = width; --i >= 0;) + { + ((PixelRGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); + dest += destData.pixelStride; + src += 3; + } } } + + if (! hasFailed) + jpeg_finish_decompress (&jpegDecompStruct); + + in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); } - - jpeg_finish_decompress (&jpegDecompStruct); - - in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); } - - jpeg_destroy_decompress (&jpegDecompStruct); } - catch (...) - {} + + jpeg_destroy_decompress (&jpegDecompStruct); } return image; diff --git a/modules/juce_graphics/image_formats/juce_PNGLoader.cpp b/modules/juce_graphics/image_formats/juce_PNGLoader.cpp index fa3b8875cb..8ce62199b5 100644 --- a/modules/juce_graphics/image_formats/juce_PNGLoader.cpp +++ b/modules/juce_graphics/image_formats/juce_PNGLoader.cpp @@ -313,9 +313,9 @@ namespace PNGHelpers struct PNGErrorStruct {}; - static void JUCE_CDECL errorCallback (png_structp, png_const_charp) + static void JUCE_CDECL errorCallback (png_structp p, png_const_charp) { - throw PNGErrorStruct(); + longjmp (*(jmp_buf*) p->error_ptr, 1); } static void JUCE_CDECL warningCallback (png_structp, png_const_charp) {} @@ -354,106 +354,102 @@ Image PNGImageFormat::decodeImage (InputStream& in) if (png_structp pngReadStruct = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0)) { - try + if (png_infop pngInfoStruct = png_create_info_struct (pngReadStruct)) { - png_infop pngInfoStruct = png_create_info_struct (pngReadStruct); + jmp_buf errorJumpBuf; + png_set_error_fn (pngReadStruct, &errorJumpBuf, PNGHelpers::errorCallback, PNGHelpers::warningCallback); - if (pngInfoStruct == nullptr) + if (setjmp (errorJumpBuf) == 0) { - png_destroy_read_struct (&pngReadStruct, 0, 0); - return Image::null; - } + // read the header.. + png_set_read_fn (pngReadStruct, &in, PNGHelpers::readCallback); - png_set_error_fn (pngReadStruct, 0, PNGHelpers::errorCallback, PNGHelpers::warningCallback); + png_uint_32 width = 0, height = 0; + int bitDepth = 0, colorType = 0, interlaceType; - // read the header.. - png_set_read_fn (pngReadStruct, &in, PNGHelpers::readCallback); + png_read_info (pngReadStruct, pngInfoStruct); - png_uint_32 width = 0, height = 0; - int bitDepth = 0, colorType = 0, interlaceType; + png_get_IHDR (pngReadStruct, pngInfoStruct, + &width, &height, + &bitDepth, &colorType, + &interlaceType, 0, 0); - png_read_info (pngReadStruct, pngInfoStruct); + if (bitDepth == 16) + png_set_strip_16 (pngReadStruct); - png_get_IHDR (pngReadStruct, pngInfoStruct, - &width, &height, - &bitDepth, &colorType, - &interlaceType, 0, 0); + if (colorType == PNG_COLOR_TYPE_PALETTE) + png_set_expand (pngReadStruct); - if (bitDepth == 16) - png_set_strip_16 (pngReadStruct); + if (bitDepth < 8) + png_set_expand (pngReadStruct); - if (colorType == PNG_COLOR_TYPE_PALETTE) - png_set_expand (pngReadStruct); + if (png_get_valid (pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) + png_set_expand (pngReadStruct); - if (bitDepth < 8) - png_set_expand (pngReadStruct); + if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb (pngReadStruct); - if (png_get_valid (pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) - png_set_expand (pngReadStruct); + png_set_add_alpha (pngReadStruct, 0xff, PNG_FILLER_AFTER); - if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb (pngReadStruct); + bool hasAlphaChan = (colorType & PNG_COLOR_MASK_ALPHA) != 0 + || pngInfoStruct->num_trans > 0; - png_set_add_alpha (pngReadStruct, 0xff, PNG_FILLER_AFTER); + // Load the image into a temp buffer in the pnglib format.. + const size_t lineStride = width * 4; + HeapBlock tempBuffer (height * lineStride); - bool hasAlphaChan = (colorType & PNG_COLOR_MASK_ALPHA) != 0 - || pngInfoStruct->num_trans > 0; + HeapBlock rows (height); + for (size_t y = 0; y < height; ++y) + rows[y] = (png_bytep) (tempBuffer + lineStride * y); - // Load the image into a temp buffer in the pnglib format.. - const size_t lineStride = width * 4; - HeapBlock tempBuffer (height * lineStride); - - HeapBlock rows (height); - for (size_t y = 0; y < height; ++y) - rows[y] = (png_bytep) (tempBuffer + lineStride * y); - - try - { png_read_image (pngReadStruct, rows); png_read_end (pngReadStruct, pngInfoStruct); + png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, 0); + + // now convert the data to a juce image format.. + image = Image (hasAlphaChan ? Image::ARGB : Image::RGB, + (int) width, (int) height, hasAlphaChan); + + image.getProperties()->set ("originalImageHadAlpha", image.hasAlphaChannel()); + hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) + + const Image::BitmapData destData (image, Image::BitmapData::writeOnly); + + for (int y = 0; y < (int) height; ++y) + { + const uint8* src = rows[y]; + uint8* dest = destData.getLinePointer (y); + + if (hasAlphaChan) + { + for (int i = (int) width; --i >= 0;) + { + ((PixelARGB*) dest)->setARGB (src[3], src[0], src[1], src[2]); + ((PixelARGB*) dest)->premultiply(); + dest += destData.pixelStride; + src += 4; + } + } + else + { + for (int i = (int) width; --i >= 0;) + { + ((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]); + dest += destData.pixelStride; + src += 4; + } + } + } } - catch (PNGHelpers::PNGErrorStruct&) - {} - - png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, 0); - - // now convert the data to a juce image format.. - image = Image (hasAlphaChan ? Image::ARGB : Image::RGB, - (int) width, (int) height, hasAlphaChan); - - image.getProperties()->set ("originalImageHadAlpha", image.hasAlphaChannel()); - hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) - - const Image::BitmapData destData (image, Image::BitmapData::writeOnly); - - for (int y = 0; y < (int) height; ++y) + else { - const uint8* src = rows[y]; - uint8* dest = destData.getLinePointer (y); - - if (hasAlphaChan) - { - for (int i = (int) width; --i >= 0;) - { - ((PixelARGB*) dest)->setARGB (src[3], src[0], src[1], src[2]); - ((PixelARGB*) dest)->premultiply(); - dest += destData.pixelStride; - src += 4; - } - } - else - { - for (int i = (int) width; --i >= 0;) - { - ((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]); - dest += destData.pixelStride; - src += 4; - } - } + png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, 0); } } - catch (PNGHelpers::PNGErrorStruct&) - {} + else + { + png_destroy_read_struct (&pngReadStruct, 0, 0); + } } return image; diff --git a/modules/juce_graphics/images/juce_ImageFileFormat.cpp b/modules/juce_graphics/images/juce_ImageFileFormat.cpp index 3ce2dc6347..30b47d0c79 100644 --- a/modules/juce_graphics/images/juce_ImageFileFormat.cpp +++ b/modules/juce_graphics/images/juce_ImageFileFormat.cpp @@ -74,12 +74,10 @@ ImageFileFormat* ImageFileFormat::findImageFormatForFileExtension (const File& f //============================================================================== Image ImageFileFormat::loadFrom (InputStream& input) { - ImageFileFormat* const format = findImageFormatForStream (input); - - if (format != nullptr) + if (ImageFileFormat* format = findImageFormatForStream (input)) return format->decodeImage (input); - return Image::null; + return Image(); } Image ImageFileFormat::loadFrom (const File& file) @@ -92,7 +90,7 @@ Image ImageFileFormat::loadFrom (const File& file) return loadFrom (b); } - return Image::null; + return Image(); } Image ImageFileFormat::loadFrom (const void* rawData, const size_t numBytes) @@ -103,5 +101,5 @@ Image ImageFileFormat::loadFrom (const void* rawData, const size_t numBytes) return loadFrom (stream); } - return Image::null; + return Image(); }