// This function is equivalent to rb_str_cat(), but unlike the real // rb_str_cat(), it doesn't leak memory in some versions of Ruby. // For more information, see: // https://bugs.ruby-lang.org/issues/11328 VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) { size_t oldlen = RSTRING_LEN(rb_str); rb_str_modify_expand(rb_str, len); char *p = RSTRING_PTR(rb_str); memcpy(p + oldlen, str, len); rb_str_set_len(rb_str, oldlen + len); }
/* Use somewhat faster version with access to string capacity on MRI */ char * pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr ) { long curr_len = curr_ptr - RSTRING_PTR(str); long curr_capa = rb_str_capacity( str ); if( curr_capa < curr_len + expand_len ){ rb_str_set_len( str, curr_len ); rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa ); curr_ptr = RSTRING_PTR(str) + curr_len; } if( end_ptr ) *end_ptr = RSTRING_PTR(str) + rb_str_capacity( str ); return curr_ptr; }
static VALUE append_wstr(VALUE dst, const wchar_t *ws, size_t len, UINT cp, UINT path_cp, rb_encoding *path_encoding) { long olen, nlen = (long)len; if (cp == path_cp) { nlen = WideCharToMultiByte(cp, 0, ws, len, NULL, 0, NULL, NULL); olen = RSTRING_LEN(dst); rb_str_modify_expand(dst, nlen); WideCharToMultiByte(cp, 0, ws, len, RSTRING_PTR(dst) + olen, nlen, NULL, NULL); rb_enc_associate(dst, path_encoding); rb_str_set_len(dst, olen + nlen); } else { const int replaceflags = ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE; char *utf8str = wstr_to_mbstr(CP_UTF8, ws, (int)len, &nlen); rb_econv_t *ec = rb_econv_open("UTF-8", rb_enc_name(path_encoding), replaceflags); dst = rb_econv_append(ec, utf8str, nlen, dst, replaceflags); rb_econv_close(ec); free(utf8str); } return dst; }
static void process_arguments_of_image_initialize(int const argc, VALUE* const argv, VALUE* buffer_ptr, rb_image_file_image_pixel_format_t* pixel_format_ptr, long* width_ptr, long* height_ptr, long* stride_ptr ) { VALUE params; VALUE buffer = Qnil; VALUE pixel_format = Qnil; VALUE width = Qnil; VALUE height = Qnil; VALUE stride = Qnil; rb_image_file_image_pixel_format_t pf; long wd, ht, st; long min_len; ID id_pixel_format, id_data, id_width, id_height, id_row_stride; CONST_ID(id_data, "data"); CONST_ID(id_pixel_format, "pixel_format"); CONST_ID(id_width, "width"); CONST_ID(id_height, "height"); CONST_ID(id_row_stride, "row_stride"); rb_scan_args(argc, argv, "01", ¶ms); if (TYPE(params) == T_HASH) { buffer = rb_hash_lookup(params, ID2SYM(id_data)); pixel_format = rb_hash_lookup(params, ID2SYM(id_pixel_format)); width = rb_hash_lookup(params, ID2SYM(id_width)); height = rb_hash_lookup(params, ID2SYM(id_height)); stride = rb_hash_lookup(params, ID2SYM(id_row_stride)); } if (!NIL_P(buffer)) { Check_Type(buffer, T_STRING); buffer = rb_str_dup(buffer); } if (NIL_P(pixel_format)) rb_raise(rb_eArgError, "missing image pixel format"); if (TYPE(pixel_format) == T_STRING) pixel_format = rb_str_intern(pixel_format); pf = check_pixel_format(pixel_format); if (NIL_P(width)) rb_raise(rb_eArgError, "missing image width"); wd = NUM2LONG(width); if (wd <= 0) rb_raise(rb_eArgError, "zero or negative image width"); if (NIL_P(height)) rb_raise(rb_eArgError, "missing image height"); ht = NUM2LONG(height); if (ht <= 0) rb_raise(rb_eArgError, "zero or negative image height"); if (NIL_P(stride)) { #ifdef HAVE_RB_CAIRO_H st = cairo_format_stride_for_width(pixel_format_to_cairo_format(pf), (int)wd) / pixel_format_size(pf); stride = INT2NUM(st); #else stride = width; #endif } st = NUM2LONG(stride); if (st <= 0) rb_raise(rb_eArgError, "zero or negative image row-stride"); else if (st < wd) { rb_warning("the given row-stride is less than the given image width."); st = wd; } min_len = minimum_buffer_size(pf, st, ht); if (NIL_P(buffer)) { buffer = rb_str_new(NULL, min_len); } else if (RSTRING_LEN(buffer) < min_len) { void rb_str_modify_expand(VALUE, long); rb_warning("the size of the given data is too short for the given size of image"); rb_str_modify_expand(buffer, min_len - RSTRING_LEN(buffer)); } *buffer_ptr = buffer; *pixel_format_ptr = pf; *width_ptr = wd; *height_ptr = ht; *stride_ptr = st; }