1 /* 2 RawSpeed - RAW file decoder. 3 4 Copyright (C) 2009-2014 Klaus Post 5 Copyright (C) 2017 Roman Lebedev 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with this library; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #pragma once 23 24 #include "rawspeedconfig.h" // for RAWSPEED_NOINLINE, RAWSPEED_UNLIKELY_FUN... 25 26 #include "common/Common.h" // for writeLog, DEBUG_PRIO_EXTRA 27 #include <array> // for array 28 #include <cstdarg> // for va_end, va_list, va_start 29 #include <cstdio> // for vsnprintf, size_t 30 #include <stdexcept> // for runtime_error 31 32 namespace rawspeed { 33 34 template <typename T> 35 [[noreturn]] void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE 36 __attribute__((noreturn, format(printf, 1, 2))) ThrowException(const char * fmt,...)37 ThrowException(const char* fmt, ...) { 38 static constexpr size_t bufSize = 8192; 39 #if defined(HAVE_CXX_THREAD_LOCAL) 40 static thread_local std::array<char, bufSize> buf; 41 #elif defined(HAVE_GCC_THREAD_LOCAL) 42 static __thread char buf[bufSize]; 43 #else 44 #pragma message \ 45 "Don't have thread-local-storage! Exception text may be garbled if used multithreaded" 46 static char buf[bufSize]; 47 #endif 48 49 va_list val; 50 va_start(val, fmt); 51 vsnprintf(buf.data(), sizeof(buf), fmt, val); 52 va_end(val); 53 writeLog(DEBUG_PRIO_EXTRA, "EXCEPTION: %s", buf.data()); 54 throw T(buf.data()); 55 } 56 57 class RawspeedException : public std::runtime_error { 58 private: 59 static void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE log(const char * msg)60 log(const char* msg) { 61 writeLog(DEBUG_PRIO_EXTRA, "EXCEPTION: %s", msg); 62 } 63 64 public: 65 explicit RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE RawspeedException(const char * msg)66 RawspeedException(const char* msg) 67 : std::runtime_error(msg) { 68 log(msg); 69 } 70 }; 71 72 #undef XSTR 73 #define XSTR(a) #a 74 75 #undef STR 76 #define STR(a) XSTR(a) 77 78 #ifndef DEBUG 79 #define ThrowExceptionHelper(CLASS, fmt, ...) \ 80 rawspeed::ThrowException<CLASS>("%s, line " STR(__LINE__) ": " fmt, \ 81 __PRETTY_FUNCTION__, ##__VA_ARGS__) 82 #else 83 #define ThrowExceptionHelper(CLASS, fmt, ...) \ 84 rawspeed::ThrowException<CLASS>(__FILE__ ":" STR(__LINE__) ": %s: " fmt, \ 85 __PRETTY_FUNCTION__, ##__VA_ARGS__) 86 #endif 87 88 #define ThrowRSE(...) \ 89 ThrowExceptionHelper(rawspeed::RawspeedException, __VA_ARGS__) 90 91 } // namespace rawspeed 92