fast_xs 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ = 0.2
2
+ === 6th December, 2007
3
+ * First real release
4
+ * added fast_xs_html and fast_xs_cgi methods
5
+
6
+ = 0.1
7
+ === 3rd October, 2007
8
+ * initial implementation, not officially released
data/COPYING ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2007 Eric Wong <normalperson@yhbt.net>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,18 @@
1
+ = fast_xs, a fast C extension for cleaning XML
2
+
3
+ == Overview
4
+
5
+ The original fast_xs method is based on the xchar code by Sam Ruby:
6
+
7
+ http://intertwingly.net/stories/2005/09/28/xchar.rb
8
+ http://intertwingly.net/blog/2005/09/28/XML-Cleansing
9
+
10
+ _why also packages a slightly modified version in the latest version
11
+ of Hpricot (not-yet-released) that also escapes '"' to "&quot;" (which
12
+ is optional).
13
+
14
+ This is an exact translation (to the best of my knowledge :) of Sam's
15
+ original implementation, so it does not escape "&quot;". The version
16
+ of XML::Builder packaged with Rails also uses Sam's version, and
17
+ XML::Builder as packaged in Rails 2.0 will be automatically use
18
+ fast_xs if available.
data/Rakefile ADDED
@@ -0,0 +1,119 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/testtask'
6
+ require 'hoe'
7
+ require 'fileutils'
8
+ include FileUtils
9
+
10
+ name = "fast_xs"
11
+ rev = `git describe 2>/dev/null`.chomp rescue nil
12
+ version = ENV['VERSION'] || "0.2" + (rev && rev.length > 0 ? "-#{rev}" : "")
13
+ pkg = "#{name}-#{version}"
14
+ bin = "*.{so,o}"
15
+ archlib = "lib/#{::Config::CONFIG['arch']}"
16
+ CLEAN.include ["ext/fast_xs/#{bin}", "lib/**/#{bin}",
17
+ 'ext/fast_xs/Makefile', '**/.*.sw?', '*.gem', '.config']
18
+ rdoc_opts = ['--quiet', '--title', 'fast_xs notes', '--main', 'README',
19
+ '--inline-source']
20
+ pkg_files = %w(CHANGELOG COPYING README Rakefile) +
21
+ Dir.glob("{test,lib}/**/*.rb") +
22
+ Dir.glob("ext/**/*.{c,rb}")
23
+
24
+
25
+ spec = Gem::Specification.new do |s|
26
+ s.name = name
27
+ s.version = version
28
+ s.platform = Gem::Platform::RUBY
29
+ s.has_rdoc = true
30
+ s.rdoc_options += rdoc_opts
31
+ s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"]
32
+ s.summary = "escape faster!"
33
+ s.description = s.summary
34
+ s.author = "Eric Wong"
35
+ s.email = 'normalperson@yhbt.net'
36
+ s.homepage = 'http://bogonips.org/fast_xs/'
37
+ s.files = pkg_files
38
+ s.require_paths = [archlib, "lib"]
39
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
40
+ end
41
+
42
+ hoe = Hoe.new(name, version) do |p|
43
+ p.author = spec.author
44
+ p.description = spec.description
45
+ p.email = spec.email
46
+ p.summary = spec.summary
47
+ p.url = spec.homepage
48
+ p.rubyforge_name = 'fast-xs'
49
+ end
50
+
51
+ desc "Does a full compile, test run"
52
+ task :default => [:compile, :test]
53
+
54
+ desc "Run all the tests"
55
+ Rake::TestTask.new do |t|
56
+ t.libs << "test" << archlib
57
+ t.test_files = FileList['test/test_*.rb']
58
+ t.verbose = true
59
+ end
60
+
61
+ Rake::RDocTask.new do |rdoc|
62
+ rdoc.rdoc_dir = 'doc/rdoc'
63
+ rdoc.options += rdoc_opts
64
+ rdoc.main = "README"
65
+ rdoc.rdoc_files.add ['README', 'CHANGELOG', 'COPYING' ]
66
+ end
67
+
68
+ Rake::GemPackageTask.new(spec) do |p|
69
+ p.need_tar = true
70
+ p.gem_spec = spec
71
+ end
72
+
73
+ ['fast_xs'].each do |extension|
74
+ ext = "ext/#{extension}"
75
+ ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
76
+ ext_files = FileList[
77
+ "#{ext}/*.c",
78
+ "#{ext}/*.h",
79
+ "#{ext}/*.rl",
80
+ "#{ext}/extconf.rb",
81
+ "#{ext}/Makefile",
82
+ "lib"
83
+ ]
84
+
85
+ desc "Builds just the #{extension} extension"
86
+ task extension.to_sym => ["#{ext}/Makefile", ext_so ]
87
+
88
+ file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
89
+ Dir.chdir(ext) do ruby "extconf.rb" end
90
+ end
91
+
92
+ file ext_so => ext_files do
93
+ Dir.chdir(ext) do sh('make') end
94
+ mkdir_p archlib
95
+ chmod 0644, ext_so
96
+ cp ext_so, archlib
97
+ end
98
+ end
99
+
100
+ task "lib" do
101
+ directory "lib"
102
+ end
103
+
104
+ desc "Compiles the Ruby extension"
105
+ task :compile => [:fast_xs] do
106
+ if Dir.glob(File.join(archlib,"fast_xs.*")).empty?
107
+ STDERR.puts 'Gem failed to build'
108
+ exit(1)
109
+ end
110
+ end
111
+
112
+ task :install do
113
+ sh %{rake package}
114
+ sh %{sudo gem install pkg/#{name}-#{version}}
115
+ end
116
+
117
+ task :uninstall => [:clean] do
118
+ sh %{sudo gem uninstall #{name}}
119
+ end
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ have_header('assert.h') or exit
3
+ dir_config('fast_xs')
4
+ create_makefile('fast_xs')
@@ -0,0 +1,279 @@
1
+ #define VERSION "0.1"
2
+
3
+ #include <ruby.h>
4
+ #include <assert.h>
5
+
6
+ static ID unpack_id;
7
+ static VALUE U_fmt, C_fmt;
8
+
9
+ /* give GCC hints for better branch prediction
10
+ * (we layout branches so that ASCII characters are handled faster) */
11
+ #if defined(__GNUC__) && (__GNUC__ >= 3)
12
+ # define likely(x) __builtin_expect (!!(x), 1)
13
+ # define unlikely(x) __builtin_expect (!!(x), 0)
14
+ #else
15
+ # define unlikely(x) (x)
16
+ # define likely(x) (x)
17
+ #endif
18
+
19
+ /* pass-through certain characters for CP-1252 */
20
+ #define p(x) (x-128)
21
+
22
+ static const int cp_1252[] = {
23
+ 8364, /* 128 => 8364, euro sign */
24
+ p(129), /* 129 => 129, pass-through */
25
+ 8218, /* 130 => 8218, single low-9 quotation mark */
26
+ 402, /* 131 => 402, latin small letter f with hook */
27
+ 8222, /* 132 => 8222, double low-9 quotation mark */
28
+ 8230, /* 133 => 8230, horizontal ellipsis */
29
+ 8224, /* 134 => 8224, dagger */
30
+ 8225, /* 135 => 8225, double dagger */
31
+ 710, /* 136 => 710, modifier letter circumflex accent */
32
+ 8240, /* 137 => 8240, per mille sign */
33
+ 352, /* 138 => 352, latin capital letter s with caron */
34
+ 8249, /* 139 => 8249, single left-pointing angle quotation mark */
35
+ 338, /* 140 => 338, latin capital ligature oe */
36
+ p(141), /* 141 => 141, pass-through */
37
+ 381, /* 142 => 381, latin capital letter z with caron */
38
+ p(143), /* 143 => 143, pass-through */
39
+ p(144), /* 144 => 144, pass-through */
40
+ 8216, /* 145 => 8216, left single quotation mark */
41
+ 8217, /* 146 => 8217, right single quotation mark */
42
+ 8220, /* 147 => 8220, left double quotation mark */
43
+ 8221, /* 148 => 8221, right double quotation mark */
44
+ 8226, /* 149 => 8226, bullet */
45
+ 8211, /* 150 => 8211, en dash */
46
+ 8212, /* 151 => 8212, em dash */
47
+ 732, /* 152 => 732, small tilde */
48
+ 8482, /* 153 => 8482, trade mark sign */
49
+ 353, /* 154 => 353, latin small letter s with caron */
50
+ 8250, /* 155 => 8250, single right-pointing angle quotation mark */
51
+ 339, /* 156 => 339, latin small ligature oe */
52
+ p(157), /* 157 => 157, pass-through */
53
+ 382, /* 158 => 382, latin small letter z with caron */
54
+ 376 /* 159 => 376} latin capital letter y with diaeresis */
55
+ };
56
+
57
+ #define VALID_VALUE(n) \
58
+ (n >= 0x20 && n <= 0xD7FF) || \
59
+ (n >= 0xE000 && n <= 0xFFFD) || \
60
+ (n >= 0x10000 && n <= 0x10FFFF)
61
+
62
+ #define CP_1252_ESCAPE(n) do { \
63
+ if (n >= 128 && n <= 159) \
64
+ n = cp_1252[n - 128]; \
65
+ } while(0)
66
+
67
+ static inline size_t bytes_for(int n)
68
+ {
69
+ if (n < 1000)
70
+ return sizeof("&#999;") - 1;
71
+ if (n < 10000)
72
+ return sizeof("&#9999;") - 1;
73
+ if (n < 100000)
74
+ return sizeof("&#99999;") - 1;
75
+ if (n < 1000000)
76
+ return sizeof("&#999999;") - 1;
77
+ /* if (n < 10000000), we won't have cases above 0x10FFFF */
78
+ return sizeof("&#9999999;") - 1;
79
+ }
80
+
81
+ static size_t escape(char *buf, int n)
82
+ {
83
+
84
+ #define return_const_len(x) do { \
85
+ memcpy(buf, x, sizeof(x) - 1); \
86
+ return (sizeof(x) - 1); \
87
+ } while (0)
88
+
89
+ /* handle ASCII first */
90
+ if (likely(n < 128)) {
91
+ if (likely(n >= 0x20 || n == '\t' || n == '\n' || n == '\r')) {
92
+ if (unlikely(n == '&'))
93
+ return_const_len("&amp;");
94
+ if (unlikely(n == '<'))
95
+ return_const_len("&lt;");
96
+ if (unlikely(n == '>'))
97
+ return_const_len("&gt;");
98
+ buf[0] = (char)n;
99
+ return 1;
100
+ }
101
+
102
+ buf[0] = '*';
103
+ return 1;
104
+ }
105
+
106
+ #undef return_const_len
107
+
108
+ CP_1252_ESCAPE(n);
109
+
110
+ if (VALID_VALUE(n)) {
111
+ /* return snprintf(buf, sizeof("&#1114111;"), "&#%i;", n); */
112
+ extern const char ruby_digitmap[];
113
+ size_t rv = sizeof("&#;") - 1;
114
+ buf += bytes_for(n);
115
+ *--buf = ';';
116
+ do {
117
+ *--buf = ruby_digitmap[(int)(n % 10)];
118
+ ++rv;
119
+ } while (n /= 10);
120
+ *--buf = '#';
121
+ *--buf = '&';
122
+ return rv;
123
+ }
124
+ buf[0] = '*';
125
+ return 1;
126
+ }
127
+
128
+ static long escaped_len(int n)
129
+ {
130
+ if (likely(n < 128)) {
131
+ if (unlikely(n == '&'))
132
+ return (sizeof("&amp;") - 1);
133
+ if (unlikely(n == '>' || n == '<'))
134
+ return (sizeof("&gt;") - 1);
135
+ return 1;
136
+ }
137
+
138
+ CP_1252_ESCAPE(n);
139
+
140
+ return VALID_VALUE(n) ? bytes_for(n) : 1;
141
+ }
142
+
143
+ static VALUE unpack_utf8(VALUE self)
144
+ {
145
+ return rb_funcall(self, unpack_id, 1, U_fmt);
146
+ }
147
+
148
+ static VALUE unpack_uchar(VALUE self)
149
+ {
150
+ return rb_funcall(self, unpack_id, 1, C_fmt);
151
+ }
152
+
153
+ static VALUE fast_xs(VALUE self)
154
+ {
155
+ long i;
156
+ struct RArray *array;
157
+ char *s, *c;
158
+ size_t s_len = 0;
159
+ VALUE *tmp;
160
+
161
+ array = RARRAY(rb_rescue(unpack_utf8, self, unpack_uchar, self));
162
+
163
+ for (tmp = array->ptr, i = array->len; --i >= 0; tmp++)
164
+ s_len += escaped_len(NUM2INT(*tmp));
165
+
166
+ c = s = alloca(s_len);
167
+
168
+ for (tmp = array->ptr, i = array->len; --i >= 0; tmp++)
169
+ c += escape(c, NUM2INT(*tmp));
170
+
171
+ return rb_str_new(s, s_len);
172
+ }
173
+
174
+ /*
175
+ * This is coding agnostic, and works on each byte, so some multibyte
176
+ * character sets may not be fully supported (but UTF-8 should be).
177
+ * This is meant to be 100% compatible with the
178
+ * ERB::Util::escape_html and CGI::escapeHTML methods
179
+ */
180
+ static VALUE fast_xs_html(VALUE self)
181
+ {
182
+ struct RString *string = RSTRING(self);
183
+ long i;
184
+ char *s;
185
+ size_t new_len = 0;
186
+ char *new_str;
187
+
188
+ for (s = string->ptr, i = string->len; --i >= 0; ++s) {
189
+ if (unlikely(*s == '&'))
190
+ new_len += (sizeof("&amp;") - 1);
191
+ else if (unlikely(*s == '<' || *s == '>'))
192
+ new_len += (sizeof("&gt;") - 1);
193
+ else if (unlikely(*s == '"'))
194
+ new_len += (sizeof("&quot;") - 1);
195
+ else
196
+ new_len += 1;
197
+ }
198
+
199
+ new_str = alloca(new_len);
200
+
201
+ #define append_const(buf, x) do { \
202
+ buf = memcpy(buf, x, sizeof(x) - 1) + sizeof(x) - 1; \
203
+ } while (0)
204
+
205
+ for (s = string->ptr, i = string->len; --i >= 0; ++s) {
206
+ if (unlikely(*s == '&'))
207
+ append_const(new_str, "&amp;");
208
+ else if (unlikely(*s == '<'))
209
+ append_const(new_str, "&lt;");
210
+ else if (unlikely(*s == '>'))
211
+ append_const(new_str, "&gt;");
212
+ else if (unlikely(*s == '"'))
213
+ append_const(new_str, "&quot;");
214
+ else
215
+ *new_str++ = *s;
216
+ }
217
+
218
+ #undef append_const
219
+
220
+ return rb_str_new(new_str - new_len, new_len);
221
+ }
222
+
223
+ #define CGI_URI_OK(x) \
224
+ ((x >= 'a' && x <= 'z') || \
225
+ (x >= 'A' && x <= 'Z') || \
226
+ (x >= '0' && x <= '9') || \
227
+ (x == '.' || x == '-' || x == '_'))
228
+
229
+ /*
230
+ * Compatible with CGI::escape(), this iterates through each byte, so
231
+ * multibyte character sets may not supported (but UTF-8 should be).
232
+ */
233
+ static VALUE fast_xs_cgi(VALUE self)
234
+ {
235
+ struct RString *string = RSTRING(self);
236
+ long i;
237
+ char *s;
238
+ size_t new_len = 0;
239
+ char *new_str;
240
+
241
+ for (s = string->ptr, i = string->len; --i >= 0; ++s) {
242
+ if (likely(CGI_URI_OK(*s) || *s == ' '))
243
+ ++new_len;
244
+ else /* we'll only get <= "%FF" here */
245
+ new_len += 3;
246
+ }
247
+
248
+ new_str = alloca(new_len);
249
+
250
+ for (s = string->ptr, i = string->len; --i >= 0; ++s) {
251
+ if (likely(CGI_URI_OK(*s)))
252
+ *new_str++ = *s;
253
+ else if (*s == ' ')
254
+ *new_str++ = '+';
255
+ else {
256
+ static const char cgi_digitmap[] = "0123456789ABCDEF";
257
+ new_str[2] = cgi_digitmap[(*s % 16)];
258
+ new_str[1] = cgi_digitmap[((*s/16) % 16)];
259
+ new_str[0] = '%';
260
+ new_str += 3;
261
+ }
262
+ }
263
+ return rb_str_new(new_str - new_len, new_len);
264
+ }
265
+
266
+ void Init_fast_xs(void)
267
+ {
268
+ assert(cp_1252[159 - 128] == 376); /* just in case I skipped a line */
269
+
270
+ unpack_id = rb_intern("unpack");
271
+ U_fmt = rb_str_new("U*", 2);
272
+ C_fmt = rb_str_new("C*", 2);
273
+ rb_global_variable(&U_fmt);
274
+ rb_global_variable(&C_fmt);
275
+
276
+ rb_define_method(rb_cString, "fast_xs", fast_xs, 0);
277
+ rb_define_method(rb_cString, "fast_xs_html", fast_xs_html, 0);
278
+ rb_define_method(rb_cString, "fast_xs_cgi", fast_xs_cgi, 0);
279
+ }
@@ -0,0 +1,32 @@
1
+ require 'fast_xs'
2
+
3
+ if defined?(CGI)
4
+
5
+ class CGI
6
+
7
+ def CGI::escapeHTML(value)
8
+ value.to_s.fast_xs_html
9
+ end
10
+
11
+ def CGI::escape(value)
12
+ value.to_s.fast_xs_cgi
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ if defined?(ERB::Util)
20
+
21
+ module ERB::Util
22
+
23
+ def html_escape(value)
24
+ value.to_s.fast_xs_html
25
+ end
26
+ alias h html_escape
27
+ module_function :h
28
+ module_function :html_escape
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require 'cgi'
3
+ load 'fast_xs_monkey_patcher.rb'
4
+
5
+ class TestCgiClassOverrides < Test::Unit::TestCase
6
+
7
+ def test_escape_html_predefined
8
+ assert_equal '&amp;', CGI::escapeHTML('&')
9
+ assert_equal '&quot;', CGI::escapeHTML('"')
10
+ assert_equal '&lt;', CGI::escapeHTML('<')
11
+ assert_equal '&gt;', CGI::escapeHTML('>')
12
+ end
13
+
14
+ def test_escape_html_normal
15
+ assert_equal 'hello world', CGI::escapeHTML('hello world')
16
+ assert_equal '', CGI::escapeHTML('')
17
+ end
18
+
19
+ def test_escape_html_ignore
20
+ assert_equal "\x00", CGI::escapeHTML("\x00")
21
+ assert_equal "\x0C", CGI::escapeHTML("\x0C")
22
+ assert_equal "\xEF\xBF\xBF", CGI::escapeHTML("\xEF\xBF\xBF")
23
+ end
24
+
25
+ def test_escape_cgi
26
+ assert_equal 'hello%3Dworld', CGI::escape('hello=world')
27
+ assert_equal '+', CGI::escape(' ')
28
+ assert_equal '%2B', CGI::escape('+')
29
+ assert_equal '%2C', CGI::escape(',')
30
+ assert_equal 'hello-world', CGI::escape('hello-world')
31
+ assert_equal 'H3LL0+W0RLD', CGI::escape('H3LL0 W0RLD')
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,29 @@
1
+ require 'erb'
2
+ require 'test/unit'
3
+ load 'fast_xs_monkey_patcher.rb'
4
+
5
+ class TestErbUtilModuleOverrides < Test::Unit::TestCase
6
+
7
+ include ERB::Util
8
+
9
+ def test_escape_html_predefined
10
+ assert_equal '&amp;', html_escape('&')
11
+ assert_equal '&quot;', html_escape('"')
12
+ assert_equal '&lt;', html_escape('<')
13
+ assert_equal '&gt;', html_escape('>')
14
+ end
15
+
16
+ def test_escape_html_normal
17
+ assert_equal 'hello world', html_escape('hello world')
18
+ assert_equal '', html_escape('')
19
+ end
20
+
21
+ def test_escape_html_ignore
22
+ assert_equal "\x00", html_escape("\x00")
23
+ assert_equal "\x0C", html_escape("\x0C")
24
+ assert_equal "\xEF\xBF\xBF", html_escape("\xEF\xBF\xBF")
25
+ end
26
+
27
+ end
28
+
29
+
@@ -0,0 +1,39 @@
1
+ require 'fast_xs'
2
+ require 'test/unit'
3
+
4
+ # Based on Sam's original xchar.rb tests:
5
+
6
+ class TestXmlEscaping < Test::Unit::TestCase
7
+
8
+ def test_ascii
9
+ assert_equal 'abc', 'abc'.fast_xs
10
+ end
11
+
12
+ def test_predefined
13
+ assert_equal '&amp;', '&'.fast_xs # ampersand
14
+ assert_equal '&lt;', '<'.fast_xs # left angle bracket
15
+ assert_equal '&gt;', '>'.fast_xs # right angle bracket
16
+ end
17
+
18
+ def test_invalid
19
+ assert_equal '*', "\x00".fast_xs # null
20
+ assert_equal '*', "\x0C".fast_xs # form feed
21
+ assert_equal '*', "\xEF\xBF\xBF".fast_xs # U+FFFF
22
+ end
23
+
24
+ def test_iso_8859_1
25
+ assert_equal '&#231;', "\xE7".fast_xs # small c cedilla
26
+ assert_equal '&#169;', "\xA9".fast_xs # copyright symbol
27
+ end
28
+
29
+ def test_win_1252
30
+ assert_equal '&#8217;', "\x92".fast_xs # smart quote
31
+ assert_equal '&#8364;', "\x80".fast_xs # euro
32
+ end
33
+
34
+ def test_utf8
35
+ assert_equal '&#8217;', "\xE2\x80\x99".fast_xs # right single quote
36
+ assert_equal '&#169;', "\xC2\xA9".fast_xs # copy
37
+ end
38
+
39
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4.7
3
+ specification_version: 2
4
+ name: fast_xs
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.2"
7
+ date: 2007-12-07 00:00:00 -08:00
8
+ summary: escape faster!
9
+ require_paths:
10
+ - lib/i486-linux
11
+ - lib
12
+ email: normalperson@yhbt.net
13
+ homepage: http://bogonips.org/fast_xs/
14
+ rubyforge_project:
15
+ description: escape faster!
16
+ autorequire:
17
+ default_executable:
18
+ bindir: bin
19
+ has_rdoc: true
20
+ required_ruby_version: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ required_rubygems_version: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: "0"
31
+ version:
32
+ platform: ruby
33
+ signing_key:
34
+ cert_chain: []
35
+
36
+ post_install_message:
37
+ authors:
38
+ - Eric Wong
39
+ files:
40
+ - CHANGELOG
41
+ - COPYING
42
+ - README
43
+ - Rakefile
44
+ - test/test_cgi_class_overrides.rb
45
+ - test/test_xml_escaping.rb
46
+ - test/test_erb_util_module_overrides.rb
47
+ - lib/fast_xs_monkey_patcher.rb
48
+ - ext/fast_xs/fast_xs.c
49
+ - ext/fast_xs/extconf.rb
50
+ test_files: []
51
+
52
+ rdoc_options:
53
+ - --quiet
54
+ - --title
55
+ - fast_xs notes
56
+ - --main
57
+ - README
58
+ - --inline-source
59
+ extra_rdoc_files:
60
+ - README
61
+ - CHANGELOG
62
+ - COPYING
63
+ executables: []
64
+
65
+ extensions:
66
+ - ext/fast_xs/extconf.rb
67
+ requirements: []
68
+
69
+ dependencies: []
70
+