1 /** 2 * Classes that wrap the Imagemagick exception handling. 3 * 4 * Copyright: Mike Wey 2011 5 * License: zlib (See accompanying LICENSE file) 6 * Authors: Mike Wey 7 */ 8 9 module dmagick.Exception; 10 11 import std.conv; 12 13 import dmagick.c.client; 14 import dmagick.c.exception; 15 16 /** 17 * A base class for all exceptions thrown bij DMagick. 18 * The following Exceptions are derived from this class: 19 * 20 * ResourceLimitException, TypeException, OptionException, 21 * DelegateException, MissingDelegateException, CorruptImageException, 22 * FileOpenException, BlobException, StreamException, CacheException, 23 * CoderException, FilterException, ModuleException, DrawException, 24 * ImageException, WandException, RandomException, XServerException, 25 * MonitorException, RegistryException, ConfigureException, PolicyException 26 */ 27 class DMagickException : Exception 28 { 29 this(string reason, string description = null, string file = __FILE__, size_t line = __LINE__) 30 { 31 string message = to!(string)(GetClientName()); 32 33 if ( reason.length > 0 ) 34 message ~= ": " ~ reason; 35 if ( description.length > 0 ) 36 message ~= " (" ~ description ~ ")"; 37 38 super(message, file, line); 39 } 40 41 private enum string[] severities = [ "Blob", "Cache", "Coder", 42 "Configure", "CorruptImage", "Delegate", "Draw", "FileOpen", 43 "Filter", "Image", "MissingDelegate", "Module", "Monitor", 44 "Option", "Policy", "Random", "Registry", "ResourceLimit", 45 "Stream", "Type", "Wand", "XServer" ]; 46 47 /** 48 * Throws an Exception or error matching the ExceptionInfo. 49 */ 50 static void throwException(ExceptionInfo* exception, string file = __FILE__, size_t line = __LINE__) 51 { 52 if ( exception.severity == ExceptionType.UndefinedException ) 53 return; 54 55 string reason = to!(string)(exception.reason); 56 string description = to!(string)(exception.description); 57 58 scope(exit) exception = DestroyExceptionInfo(exception); 59 60 mixin( 61 { 62 string exceptions = 63 "switch ( exception.severity ) 64 {"; 65 66 foreach ( severity; severities ) 67 { 68 //TODO: Warnings? 69 exceptions ~= 70 "case ExceptionType."~ severity ~"Error: 71 throw new "~ severity ~"Exception(reason, description, file, line); 72 case ExceptionType."~ severity ~"FatalError: 73 throw new "~ severity ~"Error(reason, description, file, line);"; 74 } 75 76 return exceptions ~= 77 " default: 78 return; 79 }"; 80 }()); 81 } 82 } 83 84 /** 85 * A base class for all errors thrown bij DMagick. 86 * The following Errors are derived from this class: 87 * 88 * ResourceLimitError, TypeError, OptionError, 89 * DelegateError, MissingDelegateError, CorruptImageError, 90 * FileOpenError, BlobError, StreamError, CacheError, 91 * CoderError, FilterError, ModuleError, DrawError, 92 * ImageError, WandError, RandomError, XServerError, 93 * MonitorError, RegistryError, ConfigureError, PolicyError 94 */ 95 class DMagickError : Error 96 { 97 this(string reason, string description = null, string file = __FILE__, size_t line = __LINE__) 98 { 99 string message = to!(string)(GetClientName()); 100 101 if ( reason.length > 0 ) 102 message ~= ": " ~ reason; 103 if ( description.length > 0 ) 104 message ~= " (" ~ description ~ ")"; 105 106 super(message, file, line); 107 } 108 } 109 110 /** 111 * Generate the exceptions and the throwException function; 112 */ 113 mixin( 114 { 115 string exceptions; 116 117 foreach ( severity; DMagickException.severities ) 118 { 119 exceptions ~= 120 "class " ~ severity ~ "Exception : DMagickException 121 { 122 this(string reason, string description = null, string file = __FILE__, size_t line = __LINE__) 123 { 124 super(reason, description, file, line); 125 } 126 }"; 127 128 exceptions ~= 129 "class " ~ severity ~ "Error : DMagickError 130 { 131 this(string reason, string description = null, string file = __FILE__, size_t line = __LINE__) 132 { 133 super(reason, description, file, line); 134 } 135 }"; 136 } 137 138 return exceptions; 139 }()); 140 141 /** 142 * This struct is used to wrap the ImageMagick exception handling. 143 * Needs dmd >= 2.053 144 * Usage: 145 * -------------------- 146 * CFunctionCall(param1, param2, DExceptionInfo()); 147 * -------------------- 148 */ 149 struct DMagickExceptionInfo 150 { 151 ExceptionInfo* exceptionInfo; 152 153 string file; 154 size_t line; 155 156 private bool isInitialized; 157 private size_t* refcount; 158 159 alias exceptionInfo this; 160 161 static DMagickExceptionInfo opCall(string file = __FILE__, size_t line = __LINE__) 162 { 163 DMagickExceptionInfo info; 164 165 info.exceptionInfo = AcquireExceptionInfo(); 166 info.refcount = new size_t; 167 168 *(info.refcount) = 1; 169 info.isInitialized = true; 170 171 info.file = file; 172 info.line = line; 173 174 return info; 175 } 176 177 this(this) 178 { 179 if ( isInitialized ) 180 (*refcount)++; 181 } 182 183 ~this() 184 { 185 if ( !isInitialized ) 186 return; 187 188 (*refcount)--; 189 190 if ( *refcount == 0 ) 191 { 192 DMagickException.throwException(exceptionInfo, file, line); 193 } 194 } 195 } 196 197 unittest 198 { 199 void testDMagickExcepionInfo(ExceptionInfo* info) 200 { 201 assert(info !is null); 202 } 203 204 testDMagickExcepionInfo(DMagickExceptionInfo()); 205 }