erbal 0.0.3.rc1 → 1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/erbal/parser.c CHANGED
@@ -23,10 +23,11 @@ static int act, cs;
23
23
 
24
24
  inline void erbal_parser_tag_open_common(erbal_parser *parser, int shift) {
25
25
  if (parser->chars_seen != 0) {
26
- rb_str_concat(parser->src, parser->buffer_name);
27
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
26
+ if (!parser->in_buffer_shift) {
27
+ erbal_open_buffer_shift(parser);
28
+ }
29
+
28
30
  erbal_concat_chars_seen(parser, shift);
29
- rb_str_buf_cat(parser->src, "\");", 3);
30
31
  parser->chars_seen = 0;
31
32
  }
32
33
  }
@@ -51,11 +52,18 @@ inline void erbal_parser_non_tag(erbal_parser *parser) {
51
52
 
52
53
  inline void erbal_parser_tag_close_common(erbal_parser *parser, int tag_size) {
53
54
  if (parser->state == TAG_OPEN_FOR_OUTPUT) {
54
- rb_str_concat(parser->src, parser->buffer_name);
55
- rb_str_buf_cat(parser->src, ".concat((", 9);
55
+ if (!parser->in_buffer_shift) {
56
+ erbal_open_buffer_shift(parser);
57
+ }
58
+
59
+ rb_str_buf_cat(parser->src, "#{", 2);
56
60
  erbal_concat_chars_seen(parser, -tag_size);
57
- rb_str_buf_cat(parser->src, ").to_s);", 8);
61
+ rb_str_buf_cat(parser->src, "}", 1);
58
62
  } else if (parser->state == TAG_OPEN) {
63
+ if (parser->in_buffer_shift) {
64
+ erbal_close_buffer_shift(parser);
65
+ }
66
+
59
67
  erbal_concat_chars_seen(parser, -tag_size);
60
68
  rb_str_buf_cat(parser->src, ";", 1);
61
69
  }
@@ -76,31 +84,84 @@ inline void erbal_parser_tag_close(erbal_parser *parser) {
76
84
  erbal_parser_tag_close_common(parser, 1);
77
85
  }
78
86
 
79
- inline void erbal_concat_chars_seen(erbal_parser *parser, int rewind_chars) {
87
+ inline VALUE erbal_escape_special_chars(erbal_parser *parser, int shift) {
88
+ VALUE buf = rb_str_buf_new(0);
89
+ int i, n, slashes_seen = 0;
90
+ char *current_char;
91
+
92
+ for (i = 0; i < parser->chars_seen; i++) {
93
+ current_char = (((p + shift) - parser->chars_seen) + i);
94
+
95
+ if (*current_char == '#' || *current_char == '`') {
96
+ if (slashes_seen == 0) {
97
+ rb_str_buf_cat(buf, "\\", 1);
98
+ rb_str_buf_cat(buf, current_char, 1);
99
+ } else {
100
+ for (n = 0; n <= (1 * slashes_seen); n++) {
101
+ rb_str_buf_cat(buf, "\\", 1);
102
+ }
103
+ rb_str_buf_cat(buf, current_char, 1);
104
+ }
105
+
106
+ slashes_seen = 0;
107
+ } else if (*current_char == '\\') {
108
+ slashes_seen++;
109
+ rb_str_buf_cat(buf, current_char, 1);
110
+ } else {
111
+ rb_str_buf_cat(buf, current_char, 1);
112
+ }
113
+ }
114
+
115
+ return buf;
116
+ }
117
+
118
+ inline void erbal_concat_chars_seen(erbal_parser *parser, int shift) {
80
119
  if (parser->chars_seen != 0) {
81
- rb_str_buf_cat(parser->src, ((p + rewind_chars) - parser->chars_seen), parser->chars_seen);
120
+ if (parser->in_buffer_shift) {
121
+ rb_str_concat(parser->src, erbal_escape_special_chars(parser, shift));
122
+ } else {
123
+ rb_str_buf_cat(parser->src, ((p + shift) - parser->chars_seen), parser->chars_seen);
124
+ }
82
125
  }
83
126
 
84
127
  parser->chars_seen = 0;
85
128
  }
86
129
 
130
+ inline void erbal_open_buffer_shift(erbal_parser *parser) {
131
+ rb_str_concat(parser->src, parser->buffer_name);
132
+ rb_str_buf_cat(parser->src, " << %Q`", 7);
133
+ parser->in_buffer_shift = 1;
134
+ }
135
+
136
+ inline void erbal_close_buffer_shift(erbal_parser *parser) {
137
+ rb_str_buf_cat(parser->src, "`;", 2);
138
+ parser->in_buffer_shift = 0;
139
+ }
140
+
87
141
  inline void erbal_parser_finish(erbal_parser *parser) {
88
142
  if (parser->chars_seen != 0) {
89
- rb_str_concat(parser->src, parser->buffer_name);
90
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
143
+ if (!parser->in_buffer_shift) {
144
+ erbal_open_buffer_shift(parser);
145
+ }
146
+
91
147
  erbal_concat_chars_seen(parser, 0);
92
- rb_str_buf_cat(parser->src, "\");", 3);
93
148
  }
149
+
150
+ if (parser->in_buffer_shift) {
151
+ erbal_close_buffer_shift(parser);
152
+ }
153
+
94
154
  rb_str_concat(parser->src, parser->buffer_name);
95
155
  }
96
156
 
97
157
  void erbal_parser_init(erbal_parser *parser) {
98
- parser->state = 0;
99
158
  parser->chars_seen = 0;
159
+ parser->in_buffer_shift = 0;
160
+ parser->state = OUTSIDE_TAG;
100
161
  parser->src = rb_str_dup(parser->buffer_name);
101
- rb_str_buf_cat(parser->src, "=\"\";", 4);
162
+ rb_str_buf_cat(parser->src, " = '';", 6);
102
163
 
103
- #line 104 "parser.c"
164
+ #line 165 "parser.c"
104
165
  {
105
166
  cs = erbal_parser_start;
106
167
  ts = 0;
@@ -108,14 +169,14 @@ void erbal_parser_init(erbal_parser *parser) {
108
169
  act = 0;
109
170
  }
110
171
 
111
- #line 101 "parser.rl"
172
+ #line 162 "parser.rl"
112
173
  }
113
174
 
114
175
  void erbal_parser_exec(erbal_parser *parser) {
115
176
  p = RSTRING(parser->str)->ptr;
116
177
  pe = p + strlen(p);
117
178
 
118
- #line 119 "parser.c"
179
+ #line 180 "parser.c"
119
180
  {
120
181
  if ( p == pe )
121
182
  goto _test_eof;
@@ -161,7 +222,7 @@ st1:
161
222
  case 1:
162
223
  #line 1 "NONE"
163
224
  {ts = p;}
164
- #line 165 "parser.c"
225
+ #line 226 "parser.c"
165
226
  switch( (*p) ) {
166
227
  case 37: goto st2;
167
228
  case 45: goto tr4;
@@ -183,7 +244,7 @@ st3:
183
244
  if ( ++p == pe )
184
245
  goto _test_eof3;
185
246
  case 3:
186
- #line 187 "parser.c"
247
+ #line 248 "parser.c"
187
248
  if ( (*p) == 37 )
188
249
  goto st0;
189
250
  goto tr6;
@@ -232,6 +293,6 @@ case 5:
232
293
 
233
294
  }
234
295
 
235
- #line 107 "parser.rl"
296
+ #line 168 "parser.rl"
236
297
  erbal_parser_finish(parser);
237
298
  }
data/ext/erbal/parser.h CHANGED
@@ -4,7 +4,7 @@
4
4
  #include "ruby.h"
5
5
 
6
6
  typedef struct erbal_parser {
7
- unsigned int state, chars_seen, tag_seen;
7
+ unsigned int state, chars_seen, in_buffer_shift;
8
8
  VALUE str, src, buffer_name;
9
9
  } erbal_parser;
10
10
 
@@ -18,6 +18,9 @@ inline void erbal_parser_tag_close_common(erbal_parser*, int shift);
18
18
  inline void erbal_parser_finish(erbal_parser*);
19
19
  inline void erbal_concat_chars_seen(erbal_parser*, int shift);
20
20
  inline void erbal_parser_tag_open_common(erbal_parser*, int shift);
21
+ inline void erbal_open_buffer_shift(erbal_parser*);
22
+ inline void erbal_close_buffer_shift(erbal_parser*);
23
+ inline VALUE erbal_escape_special_chars(erbal_parser*, int shift);
21
24
 
22
25
  #define TAG_OPEN 1
23
26
  #define TAG_OPEN_FOR_COMMENT 2
data/ext/erbal/parser.rl CHANGED
@@ -21,10 +21,11 @@ static int act, cs;
21
21
 
22
22
  inline void erbal_parser_tag_open_common(erbal_parser *parser, int shift) {
23
23
  if (parser->chars_seen != 0) {
24
- rb_str_concat(parser->src, parser->buffer_name);
25
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
24
+ if (!parser->in_buffer_shift) {
25
+ erbal_open_buffer_shift(parser);
26
+ }
27
+
26
28
  erbal_concat_chars_seen(parser, shift);
27
- rb_str_buf_cat(parser->src, "\");", 3);
28
29
  parser->chars_seen = 0;
29
30
  }
30
31
  }
@@ -49,11 +50,18 @@ inline void erbal_parser_non_tag(erbal_parser *parser) {
49
50
 
50
51
  inline void erbal_parser_tag_close_common(erbal_parser *parser, int tag_size) {
51
52
  if (parser->state == TAG_OPEN_FOR_OUTPUT) {
52
- rb_str_concat(parser->src, parser->buffer_name);
53
- rb_str_buf_cat(parser->src, ".concat((", 9);
53
+ if (!parser->in_buffer_shift) {
54
+ erbal_open_buffer_shift(parser);
55
+ }
56
+
57
+ rb_str_buf_cat(parser->src, "#{", 2);
54
58
  erbal_concat_chars_seen(parser, -tag_size);
55
- rb_str_buf_cat(parser->src, ").to_s);", 8);
59
+ rb_str_buf_cat(parser->src, "}", 1);
56
60
  } else if (parser->state == TAG_OPEN) {
61
+ if (parser->in_buffer_shift) {
62
+ erbal_close_buffer_shift(parser);
63
+ }
64
+
57
65
  erbal_concat_chars_seen(parser, -tag_size);
58
66
  rb_str_buf_cat(parser->src, ";", 1);
59
67
  }
@@ -74,29 +82,82 @@ inline void erbal_parser_tag_close(erbal_parser *parser) {
74
82
  erbal_parser_tag_close_common(parser, 1);
75
83
  }
76
84
 
77
- inline void erbal_concat_chars_seen(erbal_parser *parser, int rewind_chars) {
85
+ inline VALUE erbal_escape_special_chars(erbal_parser *parser, int shift) {
86
+ VALUE buf = rb_str_buf_new(0);
87
+ int i, n, slashes_seen = 0;
88
+ char *current_char;
89
+
90
+ for (i = 0; i < parser->chars_seen; i++) {
91
+ current_char = (((p + shift) - parser->chars_seen) + i);
92
+
93
+ if (*current_char == '#' || *current_char == '`') {
94
+ if (slashes_seen == 0) {
95
+ rb_str_buf_cat(buf, "\\", 1);
96
+ rb_str_buf_cat(buf, current_char, 1);
97
+ } else {
98
+ for (n = 0; n <= (1 * slashes_seen); n++) {
99
+ rb_str_buf_cat(buf, "\\", 1);
100
+ }
101
+ rb_str_buf_cat(buf, current_char, 1);
102
+ }
103
+
104
+ slashes_seen = 0;
105
+ } else if (*current_char == '\\') {
106
+ slashes_seen++;
107
+ rb_str_buf_cat(buf, current_char, 1);
108
+ } else {
109
+ rb_str_buf_cat(buf, current_char, 1);
110
+ }
111
+ }
112
+
113
+ return buf;
114
+ }
115
+
116
+ inline void erbal_concat_chars_seen(erbal_parser *parser, int shift) {
78
117
  if (parser->chars_seen != 0) {
79
- rb_str_buf_cat(parser->src, ((p + rewind_chars) - parser->chars_seen), parser->chars_seen);
118
+ if (parser->in_buffer_shift) {
119
+ rb_str_concat(parser->src, erbal_escape_special_chars(parser, shift));
120
+ } else {
121
+ rb_str_buf_cat(parser->src, ((p + shift) - parser->chars_seen), parser->chars_seen);
122
+ }
80
123
  }
81
124
 
82
125
  parser->chars_seen = 0;
83
126
  }
84
127
 
128
+ inline void erbal_open_buffer_shift(erbal_parser *parser) {
129
+ rb_str_concat(parser->src, parser->buffer_name);
130
+ rb_str_buf_cat(parser->src, " << %Q`", 7);
131
+ parser->in_buffer_shift = 1;
132
+ }
133
+
134
+ inline void erbal_close_buffer_shift(erbal_parser *parser) {
135
+ rb_str_buf_cat(parser->src, "`;", 2);
136
+ parser->in_buffer_shift = 0;
137
+ }
138
+
85
139
  inline void erbal_parser_finish(erbal_parser *parser) {
86
140
  if (parser->chars_seen != 0) {
87
- rb_str_concat(parser->src, parser->buffer_name);
88
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
141
+ if (!parser->in_buffer_shift) {
142
+ erbal_open_buffer_shift(parser);
143
+ }
144
+
89
145
  erbal_concat_chars_seen(parser, 0);
90
- rb_str_buf_cat(parser->src, "\");", 3);
91
146
  }
147
+
148
+ if (parser->in_buffer_shift) {
149
+ erbal_close_buffer_shift(parser);
150
+ }
151
+
92
152
  rb_str_concat(parser->src, parser->buffer_name);
93
153
  }
94
154
 
95
155
  void erbal_parser_init(erbal_parser *parser) {
96
- parser->state = 0;
97
156
  parser->chars_seen = 0;
157
+ parser->in_buffer_shift = 0;
158
+ parser->state = OUTSIDE_TAG;
98
159
  parser->src = rb_str_dup(parser->buffer_name);
99
- rb_str_buf_cat(parser->src, "=\"\";", 4);
160
+ rb_str_buf_cat(parser->src, " = '';", 6);
100
161
  %% write init;
101
162
  }
102
163
 
data/spec/erbal_spec.rb CHANGED
@@ -1,47 +1,82 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Erbal do
4
- def parse(str)
4
+ def erbal_parse(str)
5
5
  Erbal.new(str, '@out').parse
6
6
  end
7
7
 
8
+ def erubis_parse(str)
9
+ require 'rubygems'
10
+ require 'erubis'
11
+ Erubis::FastEruby.new.convert(str)
12
+ end
13
+
14
+ def compare(str)
15
+ erbal_parse(str).should == erb_parse(str)
16
+ end
17
+
8
18
  it "should parse a blank string" do
9
- parse("").should == '@out="";@out'
19
+ erbal_parse("").should == "@out = '';@out"
10
20
  end
11
21
 
12
22
  it "should parse content without any tags" do
13
- parse("I love unicorns!").should == '@out="";@out.concat("I love unicorns!");@out'
23
+ erbal_parse("I love unicorns!").should == "@out = '';@out << %Q`I love unicorns!`;@out"
14
24
  end
15
25
 
16
26
  it "should parse the <% tag" do
17
- parse("<% 1 + 1 %>").should == '@out=""; 1 + 1 ;@out'
27
+ erbal_parse("<% 1 + 1 %>").should == "@out = ''; 1 + 1 ;@out"
18
28
  end
19
29
 
20
30
  it "should parse the <%= tag" do
21
- parse("<%= 1 + 1 %>").should == '@out="";@out.concat(( 1 + 1 ).to_s);@out'
31
+ erbal_parse("<%= 1 + 1 %>").should == "@out = '';@out << %Q`\#{ 1 + 1 }`;@out"
22
32
  end
23
33
 
24
34
  it "should parse the comment tag <%#" do
25
- parse("<%# I'm a comment %>").should == '@out="";@out'
35
+ erbal_parse("<%# I'm a comment %>").should == "@out = '';@out"
26
36
  end
27
37
 
28
38
  it "should swallow the following newline if the -%> tag is used" do
29
- parse("<%= 1 + 1 -%>\n").should == '@out="";@out.concat(( 1 + 1 ).to_s);@out'
39
+ erbal_parse("<%= 1 + 1 -%>\n\n").should == "@out = '';@out << %Q`\#{ 1 + 1 }\n`;@out"
30
40
  end
31
41
 
32
42
  it "should not swallow the following character if the -%> tag is used and the following character is not a newline" do
33
- parse("<%= 1 + 1 -%>Z").should == '@out="";@out.concat(( 1 + 1 ).to_s);@out.concat("Z");@out'
43
+ erbal_parse("<%= 1 + 1 -%>Z").should == "@out = '';@out << %Q`\#{ 1 + 1 }Z`;@out"
34
44
  end
35
45
 
36
46
  it "should concat text surrounding the tags when the opening tag is <%" do
37
- parse("1 + 1 is <% 1 + 1 %>. Easy!").should == '@out="";@out.concat("1 + 1 is "); 1 + 1 ;@out.concat(". Easy!");@out'
47
+ erbal_parse("1 + 1 is <% 1 + 1 %>. Easy!").should == "@out = '';@out << %Q`1 + 1 is `; 1 + 1 ;@out << %Q`. Easy!`;@out"
38
48
  end
39
49
 
40
50
  it "should concat text surrounding the tags when the opening tag is <%=" do
41
- parse("1 + 1 is <%= 1 + 1 %>. Easy!").should == '@out="";@out.concat("1 + 1 is ");@out.concat(( 1 + 1 ).to_s);@out.concat(". Easy!");@out'
51
+ erbal_parse("1 + 1 is <%= 1 + 1 %>. Easy!").should == "@out = '';@out << %Q`1 + 1 is \#{ 1 + 1 }. Easy!`;@out"
42
52
  end
43
53
 
44
- it "should escape double quotes used outside tags" do
45
- puts eval(parse("1 + \" 1 is <%= \"weeee\" %>. Easy!"))
54
+ it "should not open a new buffer shift when there is more than one consecutive <%= tag" do
55
+ erbal_parse("1 + 1 is <%= 1 + 1 %>, and 2 + 2 is <%= 2 + 2 %>. Easy!").should == "@out = '';@out << %Q`1 + 1 is \#{ 1 + 1 }, and 2 + 2 is \#{ 2 + 2 }. Easy!`;@out"
56
+ end
57
+
58
+ it "should escape a hash character that signifies the start of a string interpolation" do
59
+ erbal_parse("<%= 1 + 1 -%> wee \#{1 + 3}").should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\#{1 + 3}`;@out"
60
+ eval(erbal_parse("<%= 1 + 1 -%> wee \#{1 + 3}")).should == eval(erubis_parse("<%= 1 + 1 -%> wee \#{1 + 3}"))
61
+
62
+ erbal_parse("<%= 1 + 1 -%> wee \\\#{1 + 3}").should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\\\\\#{1 + 3}`;@out"
63
+ eval(erbal_parse("<%= 1 + 1 -%> wee \\\#{1 + 3}")).should == eval(erubis_parse("<%= 1 + 1 -%> wee \\\#{1 + 3}"))
64
+
65
+ erbal_parse("<%= 1 + 1 -%> wee \\\\\\\#{1 + 3}").should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\\\\\\\\\\\\\#{1 + 3}`;@out"
66
+ eval(erbal_parse("<%= 1 + 1 -%> wee \\\\\\\#{1 + 3}")).should == eval(erubis_parse("<%= 1 + 1 -%> wee \\\\\\\#{1 + 3}"))
67
+
68
+ erbal_parse('<%= 1 + 1 -%> wee #{1 + 3}').should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\#{1 + 3}`;@out"
69
+ eval(erbal_parse('<%= 1 + 1 -%> wee #{1 + 3}')).should == eval(erubis_parse('<%= 1 + 1 -%> wee #{1 + 3}'))
70
+ end
71
+
72
+ it "should escape a backtick character that signifies the end off a buffer shift" do
73
+ erbal_parse("weeee `").should == "@out = '';@out << %Q`weeee \\``;@out"
74
+ eval(erbal_parse("weeee `")).should == eval(erubis_parse("weeee `"));
75
+
76
+ erbal_parse("weeee \\`").should == "@out = '';@out << %Q`weeee \\\\\\``;@out"
77
+ eval(erbal_parse("weeee \\`")).should == eval(erubis_parse("weeee \\`"))
78
+
79
+ erbal_parse("weeee \\\\\\\`").should == "@out = '';@out << %Q`weeee \\\\\\\\\\\\\\``;@out"
80
+ eval(erbal_parse("weeee \\\\\\\`")).should == eval(erubis_parse("weeee \\\\\\\`"))
46
81
  end
47
82
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'erb'
2
+
1
3
  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
2
4
  `rake clean`
3
5
  `rake compile`
data/tasks/gem.rake CHANGED
@@ -2,7 +2,7 @@ require 'rake/gempackagetask'
2
2
  require 'yaml'
3
3
 
4
4
  WIN_SUFFIX = ENV['WIN_SUFFIX'] || 'i386-mswin32'
5
- ERBAL_VERSION = '0.0.3.rc1'
5
+ ERBAL_VERSION = '1.0.rc1'
6
6
 
7
7
  task :clean => :clobber_package
8
8
 
@@ -13,7 +13,7 @@ spec = Gem::Specification.new do |s|
13
13
  s.summary =
14
14
  s.description = "Very small, very fast Ragel/C based ERB parser"
15
15
  s.author = "Ian Leitch"
16
- s.email = 'ian.leitch@systino.net'
16
+ s.email = 'port001@gmail.com'
17
17
  s.homepage = 'http://github.com/ileitch/erbal'
18
18
  s.has_rdoc = false
19
19
 
@@ -35,8 +35,7 @@ Rake::GemPackageTask.new(spec) do |p|
35
35
  end
36
36
 
37
37
  namespace :gem do
38
- desc "Update the gemspec for GitHub's gem server"
39
- task :github do
38
+ task :gemspec do
40
39
  File.open("erbal.gemspec", 'w') { |f| f << YAML.dump(spec) }
41
40
  end
42
41
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erbal
3
3
  version: !ruby/object:Gem::Version
4
- hash: 977940546
4
+ hash: 977940502
5
5
  prerelease: true
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 0
9
- - 3
10
9
  - rc1
11
- version: 0.0.3.rc1
10
+ version: 1.0.rc1
12
11
  platform: ruby
13
12
  authors:
14
13
  - Ian Leitch
@@ -16,12 +15,12 @@ autorequire:
16
15
  bindir: bin
17
16
  cert_chain: []
18
17
 
19
- date: 2010-12-17 00:00:00 +11:00
18
+ date: 2010-12-29 00:00:00 +11:00
20
19
  default_executable:
21
20
  dependencies: []
22
21
 
23
22
  description: Very small, very fast Ragel/C based ERB parser
24
- email: ian.leitch@systino.net
23
+ email: port001@gmail.com
25
24
  executables: []
26
25
 
27
26
  extensions:
@@ -34,7 +33,6 @@ files:
34
33
  - README.rdoc
35
34
  - Rakefile
36
35
  - lib/erbal/rails.rb
37
- - lib/erbal.bundle
38
36
  - spec/erbal_spec.rb
39
37
  - spec/spec_helper.rb
40
38
  - tasks/ext.rake
data/lib/erbal.bundle DELETED
Binary file