ext/RMagick/rmutil.c in rmagick-4.1.0.rc2 vs ext/RMagick/rmutil.c in rmagick-4.1.0

- old
+ new

@@ -11,10 +11,11 @@ ******************************************************************************/ #include "rmagick.h" #include <errno.h> +static VALUE rescue_not_str(VALUE, VALUE ATTRIBUTE_UNUSED) ATTRIBUTE_NORETURN; static void handle_exception(ExceptionInfo *, Image *, ErrorRetention); /** * ImageMagick safe version of malloc. @@ -76,11 +77,11 @@ * @param ptr pointer to the existing block of memory */ void magick_free(void *ptr) { - (void) RelinquishMagickMemory(ptr); + RelinquishMagickMemory(ptr); } /** * ImageMagick safe version of realloc. @@ -111,32 +112,10 @@ return v; } /** - * ImageMagick version of realloc. - * - * No Ruby usage (internal function) - * - * @param ptr pointer to the existing block of memory - * @param size the new size of memory to allocate - * @return pointer to a block of memory - */ -void * -magick_realloc(void *ptr, const size_t size) -{ - void *v; - v = ResizeMagickMemory(ptr, size); - if (!v) - { - rb_raise(rb_eNoMemError, "not enough memory to continue"); - } - return v; -} - - -/** * Make a copy of a string in malloc'd memory. * * No Ruby usage (internal function) * * Notes: @@ -147,11 +126,11 @@ * @param str the string to copy */ void magick_clone_string(char **new_str, const char *str) { - (void) CloneString(new_str, str); + CloneString(new_str, str); } /** * Compare s1 and s2 ignoring case. @@ -207,10 +186,32 @@ return (int)(*s1 - *s2); } /** + * Get string length. + * + * No Ruby usage (internal function) + * + * @param str the string + * @param strsz the maximum number of characters + * @return same as strnlen_s() + */ +size_t +rm_strnlen_s(const char *str, size_t strsz) +{ + size_t length = 0; + while(*str && length < strsz) + { + str++; + length++; + } + return length; +} + + +/** * Raise exception if array too short. * * No Ruby usage (internal function) * * @param ary the array @@ -241,11 +242,11 @@ rm_check_ary_type(VALUE ary) { VALUE checked = rb_check_array_type(ary); if (NIL_P(checked)) { - rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" was given. (must respond to :to_ary)", rb_obj_class(ary)); + rb_raise(rb_eTypeError, "wrong argument type %"RMIsVALUE" was given. (must respond to :to_ary)", rb_obj_class(ary)); } return checked; } @@ -293,43 +294,20 @@ /** * Overrides freeze in classes that can't be frozen. * * No Ruby usage (internal function) * - * @param obj the object of the class to override - * @return 0 - * @throw TypeError + * @raise [TypeError] */ VALUE rm_no_freeze(VALUE obj) { rb_raise(rb_eTypeError, "can't freeze %s", rb_class2name(CLASS_OF(obj))); - return (VALUE)0; } /** - * Return obj.to_s, or obj if obj is already a string. - * - * No Ruby usage (internal function) - * - * @param obj a Ruby object - * @return a String representation of obj - */ -VALUE -rm_to_s(VALUE obj) -{ - - if (TYPE(obj) != T_STRING) - { - return rb_funcall(obj, rm_ID_to_s, 0); - } - return obj; -} - - -/** * Supply our own version of the "obsolete" rb_str2cstr. * * No Ruby usage (internal function) * * @param str the Ruby string @@ -347,39 +325,23 @@ return RSTRING_PTR(str); } /** - * Try to convert the argument to a double, raise an exception if fail. - * - * No Ruby usage (internal function) - * - * @param arg the argument - * @return arg - */ -static VALUE -arg_is_number(VALUE arg) -{ - return DBL2NUM(NUM2DBL(arg)); -} - - -/** * Called when `rb_str_to_str' raises an exception. * * No Ruby usage (internal function) * * @param arg the argument * @return 0 * @throw TypeError */ static VALUE -rescue_not_str(VALUE arg) +rescue_not_str(VALUE arg, VALUE raised_exc ATTRIBUTE_UNUSED) { rb_raise(rb_eTypeError, "argument must be a number or a string in the form 'NN%%' (%s given)", rb_class2name(CLASS_OF(arg))); - return (VALUE)0; } /** * Return a double between 0.0 and max (the second argument), inclusive. If the @@ -394,21 +356,20 @@ */ double rm_percentage(VALUE arg, double max) { double pct; - long pct_long; - char *pct_str, *end; + char *end; int not_num; - // Try to convert the argument to a number. If failure, sets not_num to non-zero. - (void) rb_protect(arg_is_number, arg, &not_num); - - if (not_num) + if (!rm_check_num2dbl(arg)) { + char *pct_str; + long pct_long; + arg = rb_rescue(rb_str_to_str, arg, rescue_not_str, arg); - pct_str = StringValuePtr(arg); + pct_str = StringValueCStr(arg); errno = 0; pct_long = strtol(pct_str, &end, 10); if (errno == ERANGE) { rb_raise(rb_eRangeError, "`%s' out of range", pct_str); @@ -453,11 +414,11 @@ * @return 0 */ static VALUE check_num2dbl(VALUE obj) { - (void) rb_num2dbl(obj); + rb_num2dbl(obj); return INT2FIX(1); } /** @@ -467,11 +428,11 @@ * * @param ignored a Ruby object (unused) * @return 0 */ static VALUE -rescue_not_dbl(VALUE ignored ATTRIBUTE_UNUSED) +rescue_not_dbl(VALUE ignored ATTRIBUTE_UNUSED, VALUE raised_exc ATTRIBUTE_UNUSED) { return INT2FIX(0); } @@ -503,11 +464,11 @@ { long pct; char *pct_str, *end; str = rb_rescue(rb_str_to_str, str, rescue_not_str, str); - pct_str = StringValuePtr(str); + pct_str = StringValueCStr(str); errno = 0; pct = strtol(pct_str, &end, 10); if (errno == ERANGE) { @@ -539,21 +500,20 @@ */ double rm_fuzz_to_dbl(VALUE fuzz_arg) { double fuzz; - char *fuzz_str, *end; + char *end; int not_num; - // Try to convert the argument to a number. If failure, sets not_num to non-zero. - (void) rb_protect(arg_is_number, fuzz_arg, &not_num); - - if (not_num) + if (!rm_check_num2dbl(fuzz_arg)) { + char *fuzz_str; + // Convert to string, issue error message if failure. fuzz_arg = rb_rescue(rb_str_to_str, fuzz_arg, rescue_not_str, fuzz_arg); - fuzz_str = StringValuePtr(fuzz_arg); + fuzz_str = StringValueCStr(fuzz_arg); errno = 0; fuzz = strtod(fuzz_str, &end); if (errno == ERANGE) { rb_raise(rb_eRangeError, "`%s' out of range", fuzz_str); @@ -604,15 +564,13 @@ { VALUE v = obj; if (TYPE(obj) == T_FLOAT) { - v = rb_funcall(obj, rm_ID_to_i, 0); + v = rb_Integer(obj); } - RB_GC_GUARD(v); - return NUM2QUANTUM(v); } /** @@ -630,12 +588,12 @@ Image *new_image; ExceptionInfo *exception; exception = AcquireExceptionInfo(); new_image = AcquireImage(info, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); return new_image; #else return AcquireImage(info); #endif } @@ -681,13 +639,13 @@ #if defined(IMAGEMAGICK_7) pp.depth = MAGICKCORE_QUANTUM_DEPTH; pp.colorspace = image->colorspace; #endif - (void) QueryColorname(image, &pp, X11Compliance, name, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + QueryColorname(image, &pp, X11Compliance, name, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); return rb_str_new2(name); } @@ -724,11 +682,11 @@ #else image->matte = MagickFalse; #endif color_name = rm_pixelcolor_to_color_name(image, color); - (void) DestroyImage(image); + DestroyImage(image); return color_name; } /** @@ -763,17 +721,17 @@ ExceptionInfo *exception; exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) - (void) QueryColorCompliance(color, AllCompliance, pp, exception); + QueryColorCompliance(color, AllCompliance, pp, exception); #else - (void) QueryMagickColor(color, pp, exception); + QueryMagickColor(color, pp, exception); #endif // This exception is ignored because the color comes from places where we control // the value and it is very unlikely that an exception will be thrown. - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); } /** * Write a temporary copy of the image to the IM registry. * @@ -783,14 +741,15 @@ * - The `temp_name' argument must point to an char array of size * MaxTextExtent. * * @param image the image * @param temp_name the temporary name to use + * @param temp_name_l the length of temp_name * @return the "filename" of the registered image */ void -rm_write_temp_image(Image *image, char *temp_name) +rm_write_temp_image(Image *image, char *temp_name, size_t temp_name_l) { #define TMPNAM_CLASS_VAR "@@_tmpnam_" MagickBooleanType okay; @@ -813,15 +772,15 @@ rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id)); } id += 1; rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id)); - sprintf(temp_name, "mpri:%d", id); + snprintf(temp_name, temp_name_l, "mpri:%d", id); // Omit "mpri:" from filename to form the key okay = SetImageRegistry(ImageRegistryType, temp_name+5, image, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); DestroyExceptionInfo(exception); if (!okay) { rb_raise(rb_eRuntimeError, "SetImageRegistry failed."); } @@ -888,32 +847,25 @@ VALUE exc, mesg; mesg = rb_str_new2(msg); exc = rb_funcall(Class_ImageMagickError, rm_ID_new, 2, mesg, Qnil); - (void) rb_funcall(rb_cObject, rb_intern("raise"), 1, exc); + rb_funcall(rb_cObject, rb_intern("raise"), 1, exc); RB_GC_GUARD(exc); RB_GC_GUARD(mesg); } /** * Initialize a new ImageMagickError object - store the "loc" string in the - * \@magick_location instance variable. + * magick_location instance variable. * - * Ruby usage: - * - @verbatim ImageMagickError#initialize(msg) @endverbatim - * - @verbatim ImageMagickError#initialize(msg, loc) @endverbatim - * - * Notes: - * - Default loc is nil - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self + * @overload initialize(msg, loc = nil) + * @param msg [String] the exception message + * @param loc [String] the location stored in the magick_location instance variable + * @return [Magick::ImageMagickError] self */ VALUE ImageMagickError_initialize(int argc, VALUE *argv, VALUE self) { VALUE super_argv[1] = {(VALUE)0}; @@ -931,12 +883,12 @@ break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 2)", argc); } - (void) rb_call_super(super_argc, (const VALUE *)super_argv); - (void) rb_iv_set(self, "@"MAGICK_LOC, extra); + rb_call_super(super_argc, (const VALUE *)super_argv); + rb_iv_set(self, "@"MAGICK_LOC, extra); RB_GC_GUARD(extra); return self; } @@ -958,12 +910,12 @@ const char *result; ExceptionInfo *exception; exception = AcquireExceptionInfo(); result = GetImageProperty(img, property, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); return result; #else return GetImageProperty(img, property); #endif } @@ -986,12 +938,12 @@ ExceptionInfo *exception; MagickBooleanType okay; exception = AcquireExceptionInfo(); okay = SetImageProperty(image, property, value, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); return okay; #else return SetImageProperty(image, property, value); #endif } @@ -1006,20 +958,21 @@ * @param images a list of images * @param info the info */ void rm_set_user_artifact(Image *images, Info *info) { - Image *image; const char *value; value = GetImageOption(info, "user"); if (value) { + Image *image; + image = GetFirstImageInList(images); while (image) { - (void) SetImageArtifact(image, "user", value); + SetImageArtifact(image, "user", value); image = GetNextImageInList(image); } } } @@ -1047,11 +1000,11 @@ if (rb_block_given_p()) { optional_method_arguments = rb_const_get_from(Module_Magick, rb_intern("OptionalMethodArguments")); argv[0] = img; opt_args = rb_class_new_instance(1, argv, optional_method_arguments); - (void) rb_obj_instance_eval(0, NULL, opt_args); + rb_obj_instance_eval(0, NULL, opt_args); } RB_GC_GUARD(optional_method_arguments); RB_GC_GUARD(opt_args); @@ -1068,21 +1021,22 @@ * @param info the Info structure */ static void copy_options(Image *image, Info *info) { char property[MaxTextExtent]; - const char *value, *option; + const char *option; ResetImageOptionIterator(info); for (option = GetNextImageOption(info); option; option = GetNextImageOption(info)) { - value = GetImageOption(info,option); + const char *value; + + value = GetImageOption(info, option); if (value) { - strncpy(property, value, MaxTextExtent); - property[MaxTextExtent-1] = '\0'; - (void) SetImageArtifact(image, property, value); + strlcpy(property, value, sizeof(property)); + SetImageArtifact(image, property, value); } } } @@ -1104,17 +1058,17 @@ ExceptionInfo *exception; #endif // The option strings will be set only when their attribute values were // set in the optional argument block. - option = GetImageOption(info,"background"); + option = GetImageOption(info, "background"); if (option) { image->background_color = info->background_color; } - option = GetImageOption(info,"bordercolor"); + option = GetImageOption(info, "bordercolor"); if (option) { image->border_color = info->border_color; } @@ -1124,11 +1078,11 @@ exception = AcquireExceptionInfo(); SetImageColorspace(image, info->colorspace, exception); // We should not throw an exception in this method because we will // leak memory in the place where this method is called. And that is // why the exception is being ignored here. - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else SetImageColorspace(image, info->colorspace); #endif } @@ -1193,11 +1147,11 @@ if (info->interlace != NoInterlace) { image->interlace = info->interlace; } - option = GetImageOption(info,"mattecolor"); + option = GetImageOption(info, "mattecolor"); if (option) { image->matte_color = info->matte_color; } @@ -1206,11 +1160,11 @@ image->orientation = info->orientation; } if (info->page) { - (void)ParseAbsoluteGeometry(info->page, &image->page); + ParseAbsoluteGeometry(info->page, &image->page); } if (info->quality != 0UL) { image->quality = info->quality; @@ -1223,11 +1177,11 @@ } option = GetImageOption(info, "tile-offset"); if (option) { - (void)ParseAbsoluteGeometry(option, &image->tile_offset); + ParseAbsoluteGeometry(option, &image->tile_offset); } option = GetImageOption(info, "transparent"); if (option) { @@ -1306,50 +1260,50 @@ VALUE v; #if defined(IMAGEMAGICK_7) ExceptionInfo *exception; exception = AcquireExceptionInfo(); - (void) GetImageProperty(image, "exif:*", exception); - CHECK_EXCEPTION() + GetImageProperty(image, "exif:*", exception); + CHECK_EXCEPTION(); #else - (void) GetImageProperty(image, "exif:*"); + GetImageProperty(image, "exif:*"); #endif ResetImagePropertyIterator(image); property = GetNextImageProperty(image); // Measure the exif properties and values while (property) { // ignore properties that don't start with "exif:" - property_l = strlen(property); + property_l = rm_strnlen_s(property, MaxTextExtent); if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0) { if (len > 0) { len += 1; // there will be a \n between property=value entries } len += property_l - 5; #if defined(IMAGEMAGICK_7) value = GetImageProperty(image, property, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); #else value = GetImageProperty(image, property); #endif if (value) { // add 1 for the = between property and value - len += 1 + strlen(value); + len += 1 + rm_strnlen_s(value, MaxTextExtent); } } property = GetNextImageProperty(image); } if (len == 0) { #if defined(IMAGEMAGICK_7) - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif return Qnil; } str = xmalloc(len); @@ -1359,11 +1313,11 @@ ResetImagePropertyIterator(image); property = GetNextImageProperty(image); while (property) { - property_l = strlen(property); + property_l = rm_strnlen_s(property, MaxTextExtent); if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0) { if (len > 0) { str[len++] = '\n'; @@ -1380,21 +1334,21 @@ #else value = GetImageProperty(image, property); #endif if (value) { - value_l = strlen(value); + value_l = rm_strnlen_s(value, MaxTextExtent); str[len++] = '='; memcpy(str+len, value, value_l); len += value_l; } } property = GetNextImageProperty(image); } #if defined(IMAGEMAGICK_7) - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif v = rb_str_new(str, len); xfree(str); @@ -1425,49 +1379,49 @@ VALUE v; #if defined(IMAGEMAGICK_7) ExceptionInfo *exception; exception = AcquireExceptionInfo(); - (void) GetImageProperty(image, "exif:!", exception); - CHECK_EXCEPTION() + GetImageProperty(image, "exif:!", exception); + CHECK_EXCEPTION(); #else - (void) GetImageProperty(image, "exif:!"); + GetImageProperty(image, "exif:!"); #endif ResetImagePropertyIterator(image); property = GetNextImageProperty(image); // Measure the exif properties and values while (property) { // ignore properties that don't start with "#" - property_l = strlen(property); + property_l = rm_strnlen_s(property, MaxTextExtent); if (property_l > 1 && property[0] == '#') { if (len > 0) { len += 1; // there will be a \n between property=value entries } len += property_l; #if defined(IMAGEMAGICK_7) value = GetImageProperty(image, property, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); #else value = GetImageProperty(image, property); #endif if (value) { // add 1 for the = between property and value - len += 1 + strlen(value); + len += 1 + rm_strnlen_s(value, MaxTextExtent); } } property = GetNextImageProperty(image); } if (len == 0) { #if defined(IMAGEMAGICK_7) - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif return Qnil; } str = xmalloc(len); @@ -1477,11 +1431,11 @@ ResetImagePropertyIterator(image); property = GetNextImageProperty(image); while (property) { - property_l = strlen(property); + property_l = rm_strnlen_s(property, MaxTextExtent); if (property_l > 1 && property[0] == '#') { if (len > 0) { str[len++] = '\n'; @@ -1498,21 +1452,21 @@ #else value = GetImageProperty(image, property); #endif if (value) { - value_l = strlen(value); + value_l = rm_strnlen_s(value, MaxTextExtent); str[len++] = '='; memcpy(str+len, value, value_l); len += value_l; } } property = GetNextImageProperty(image); } #if defined(IMAGEMAGICK_7) - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif v = rb_str_new(str, len); xfree(str); @@ -1521,70 +1475,10 @@ return v; } /** - * Get the values from a Geometry object and return them in C variables. - * - * No Ruby usage (internal function) - * - * Notes: - * - No return value: modifies x, y, width, height, and flag - * - * @param geom the Geometry object - * @param x pointer to the x position of the start of the rectangle - * @param y pointer to the y position of the start of the rectangle - * @param width pointer to the width of the rectangle - * @param height pointer to the height of the rectangle - * @param flag pointer to the Geometry's flag - */ -void -rm_get_geometry( - VALUE geom, - long *x, - long *y, - unsigned long *width, - unsigned long *height, - int *flag) -{ - VALUE v; - - v = rb_funcall(geom, rm_ID_x, 0); - *x = NUM2LONG(v); - v = rb_funcall(geom, rm_ID_y, 0); - *y = NUM2LONG(v); - v = rb_funcall(geom, rm_ID_width, 0); - *width = NUM2ULONG(v); - v = rb_funcall(geom, rm_ID_height, 0); - *height = NUM2ULONG(v); - - // Getting the flag field is a bit more difficult since it's - // supposed to be an instance of the GeometryValue Enum class. We - // may not know the VALUE for the GeometryValue class, and we - // need to check that the flag field is an instance of that class. - if (flag) - { - MagickEnum *magick_enum; - - v = rb_funcall(geom, rm_ID_flag, 0); - if (!Class_GeometryValue) - { - Class_GeometryValue = rb_const_get(Module_Magick, rm_ID_GeometryValue); - } - if (CLASS_OF(v) != Class_GeometryValue) - { - rb_raise(rb_eTypeError, "wrong enumeration type - expected %s, got %s" - , rb_class2name(Class_GeometryValue),rb_class2name(CLASS_OF(v))); - } - Data_Get_Struct(v, MagickEnum, magick_enum); - *flag = magick_enum->val; - } - -} - - -/** * Clone an image, handle errors. * * No Ruby usage (internal function) * * Notes: @@ -1605,11 +1499,11 @@ if (!clone) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } rm_check_exception(exception, clone, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return clone; } @@ -1688,11 +1582,11 @@ { rb_bug("RMagick FATAL: split called with NULL argument."); } while (image) { - (void) RemoveFirstImageFromList(&image); + RemoveFirstImageFromList(&image); } } #if defined(IMAGEMAGICK_6) @@ -1741,11 +1635,11 @@ if (badboy) { rm_check_exception(exception, imglist, retention); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); } #endif #define ERROR_MSG_SIZE 1024 @@ -1761,11 +1655,11 @@ */ static void format_exception(const ExceptionType severity, const char *reason, const char *description, char *msg) { int len; - memset(msg, 0, sizeof(ERROR_MSG_SIZE)); + memset(msg, 0, ERROR_MSG_SIZE); len = snprintf(msg, ERROR_MSG_SIZE, "%s%s%s", GetLocaleExceptionMessage(severity, reason), description ? ": " : "", description ? GetLocaleExceptionMessage(severity, description) : ""); @@ -1890,22 +1784,22 @@ // of image objects should be retained but split. if (imglist) { if (retention == DestroyOnError) { - (void) DestroyImageList(imglist); + DestroyImageList(imglist); imglist = NULL; } else { rm_split(imglist); } } format_exception(exception->severity, exception->reason, exception->description, msg); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_magick_error(msg); } @@ -1945,11 +1839,11 @@ rm_warning_handler(exception->severity, exception->reason, exception->description); } if (retention == DestroyExceptionRetention) { - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); } return MagickFalse; } @@ -1969,10 +1863,10 @@ { char msg[ERROR_MSG_SIZE]; format_exception(exception->severity, exception->reason, exception->description, msg); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_magick_error(msg); }