ruby-changes:41657
From: nobu <ko1@a...>
Date: Thu, 4 Feb 2016 12:39:14 +0900 (JST)
Subject: [ruby-changes:41657] nobu:r53731 (trunk): cgi/escape: Optimize CGI.escape
nobu 2016-02-04 12:39:12 +0900 (Thu, 04 Feb 2016) New Revision: 53731 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53731 Log: cgi/escape: Optimize CGI.escape * cgi/escape/escape.c: Optimize CGI.escape performance by C ext for ASCII-compatible encodings. [Fix GH-1238] Modified files: trunk/ChangeLog trunk/ext/cgi/escape/escape.c Index: ChangeLog =================================================================== --- ChangeLog (revision 53730) +++ ChangeLog (revision 53731) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Feb 4 12:39:08 2016 joker1007 <kakyoin.hierophant@g...> + + * cgi/escape/escape.c: Optimize CGI.escape performance by C ext + for ASCII-compatible encodings. [Fix GH-1238] + Thu Feb 4 11:53:56 2016 Martin Duerst <duerst@i...> * common.mk: Introduce two variables (UNICODE_DATA_DIR and Index: ext/cgi/escape/escape.c =================================================================== --- ext/cgi/escape/escape.c (revision 53730) +++ ext/cgi/escape/escape.c (revision 53731) @@ -1,6 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/escape.c#L1 #include "ruby.h" #include "ruby/encoding.h" +RUBY_EXTERN const char ruby_hexdigits[]; +#define lower_hexdigits (ruby_hexdigits+0) +#define upper_hexdigits (ruby_hexdigits+16) + static VALUE rb_cCGI, rb_mUtil, rb_mEscape; static void @@ -73,6 +77,68 @@ optimized_escape_html(VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/escape.c#L77 } } +static int +url_unreserved_char(unsigned char c) +{ + switch (c) { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '-': case '.': case '_': + return 1; + default: + break; + } + return 0; +} + +static VALUE +optimized_escape(VALUE str) +{ + long i, len, modified = 0, beg = 0; + VALUE dest; + const char *cstr; + char buf[4] = {'%'}; + + len = RSTRING_LEN(str); + cstr = RSTRING_PTR(str); + + for (i = 0; i < len; i++) { + if (!url_unreserved_char(cstr[i])) { + if (!modified) { + modified = 1; + dest = rb_str_buf_new(len); + } + + rb_str_cat(dest, cstr + beg, i - beg); + beg = i + 1; + + if (cstr[i] == ' ') { + rb_str_cat_cstr(dest, "+"); + } + else { + unsigned char c = (unsigned char)cstr[i]; + buf[1] = upper_hexdigits[c >> 4]; + buf[2] = upper_hexdigits[c & 0xf]; + rb_str_cat(dest, buf, 3); + } + } + } + + if (modified) { + rb_str_cat(dest, cstr + beg, len - beg); + preserve_original_state(str, dest); + return dest; + } + else { + return rb_str_dup(str); + } +} + /* * call-seq: * CGI.escapeHTML(string) -> string @@ -93,6 +159,26 @@ cgiesc_escape_html(VALUE self, VALUE str https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/escape.c#L159 } } +/* + * call-seq: + * CGI.escape(string) -> string + * + * Returns URL-escaped string. + * + */ +static VALUE +cgiesc_escape(VALUE self, VALUE str) +{ + StringValue(str); + + if (rb_enc_str_asciicompat_p(str)) { + return optimized_escape(str); + } + else { + return rb_call_super(1, &str); + } +} + void Init_escape(void) { @@ -100,6 +186,7 @@ Init_escape(void) https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/escape.c#L186 rb_mEscape = rb_define_module_under(rb_cCGI, "Escape"); rb_mUtil = rb_define_module_under(rb_cCGI, "Util"); rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1); + rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1); rb_prepend_module(rb_mUtil, rb_mEscape); rb_extend_object(rb_cCGI, rb_mEscape); } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/