mongrel_esi 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. data/Rakefile +15 -8
  2. data/bin/mongrel_esi +0 -0
  3. data/ext/esi/common.rl +32 -27
  4. data/ext/esi/esi_parser.c +11 -4
  5. data/ext/esi/parser.c +4536 -901
  6. data/ext/esi/parser.h +7 -0
  7. data/ext/esi/parser.rl +171 -53
  8. data/ext/esi/run-test.rb +0 -0
  9. data/ext/esi/test/common.rl +32 -27
  10. data/ext/esi/test/parser.c +322 -1342
  11. data/ext/esi/test/parser.h +7 -0
  12. data/ext/esi/test/parser.rl +171 -53
  13. data/ext/esi/test/test.c +13 -4
  14. data/ext/esi/test1.rb +35 -3
  15. data/lib/esi/cache.rb +2 -1
  16. data/lib/esi/config.rb +37 -0
  17. data/lib/esi/dispatcher.rb +3 -5
  18. data/lib/esi/invalidator.rb +3 -0
  19. data/lib/esi/logger.rb +0 -7
  20. data/lib/esi/parser.rb +70 -0
  21. data/lib/esi/processor.rb +88 -0
  22. data/lib/esi/proxy.rb +104 -0
  23. data/lib/esi/response.rb +106 -0
  24. data/lib/esi/router.rb +3 -0
  25. data/lib/esi/tag/attempt.rb +3 -0
  26. data/lib/esi/tag/base.rb +3 -1
  27. data/lib/esi/tag/except.rb +2 -0
  28. data/lib/esi/tag/include.rb +131 -132
  29. data/lib/esi/tag/invalidate.rb +2 -0
  30. data/lib/esi/tag/try.rb +3 -0
  31. data/test/integration/basic_test.rb +0 -1
  32. data/test/integration/docs/esi_max_age_varies.html +10 -0
  33. data/test/integration/handler_test.rb +31 -5
  34. data/test/integration/help.rb +13 -1
  35. data/test/load_test.rb +133 -0
  36. data/test/unit/include_request_test.rb +1 -1
  37. data/test/unit/parser_test.rb +41 -5
  38. data/test/unit/response_test.rb +184 -0
  39. metadata +50 -224
  40. data/doc/rdoc/classes/ESI/Cache.html +0 -178
  41. data/doc/rdoc/classes/ESI/Cache.src/M000060.html +0 -17
  42. data/doc/rdoc/classes/ESI/Cache.src/M000061.html +0 -20
  43. data/doc/rdoc/classes/ESI/Config/CacheConfig.html +0 -212
  44. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000055.html +0 -19
  45. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000056.html +0 -19
  46. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000057.html +0 -18
  47. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000058.html +0 -18
  48. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000059.html +0 -18
  49. data/doc/rdoc/classes/ESI/Config/ConfigRouter.html +0 -187
  50. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000052.html +0 -19
  51. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000053.html +0 -21
  52. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000054.html +0 -21
  53. data/doc/rdoc/classes/ESI/Config.html +0 -291
  54. data/doc/rdoc/classes/ESI/Config.src/M000043.html +0 -18
  55. data/doc/rdoc/classes/ESI/Config.src/M000044.html +0 -18
  56. data/doc/rdoc/classes/ESI/Config.src/M000045.html +0 -35
  57. data/doc/rdoc/classes/ESI/Config.src/M000046.html +0 -38
  58. data/doc/rdoc/classes/ESI/Config.src/M000047.html +0 -23
  59. data/doc/rdoc/classes/ESI/Config.src/M000048.html +0 -18
  60. data/doc/rdoc/classes/ESI/Config.src/M000049.html +0 -20
  61. data/doc/rdoc/classes/ESI/Config.src/M000050.html +0 -18
  62. data/doc/rdoc/classes/ESI/Config.src/M000051.html +0 -24
  63. data/doc/rdoc/classes/ESI/Dispatcher.html +0 -172
  64. data/doc/rdoc/classes/ESI/Dispatcher.src/M000062.html +0 -23
  65. data/doc/rdoc/classes/ESI/Dispatcher.src/M000063.html +0 -20
  66. data/doc/rdoc/classes/ESI/Fragment.html +0 -218
  67. data/doc/rdoc/classes/ESI/Fragment.src/M000076.html +0 -21
  68. data/doc/rdoc/classes/ESI/Fragment.src/M000077.html +0 -18
  69. data/doc/rdoc/classes/ESI/Fragment.src/M000078.html +0 -18
  70. data/doc/rdoc/classes/ESI/Handler.html +0 -236
  71. data/doc/rdoc/classes/ESI/Handler.src/M000079.html +0 -19
  72. data/doc/rdoc/classes/ESI/Handler.src/M000080.html +0 -161
  73. data/doc/rdoc/classes/ESI/Handler.src/M000081.html +0 -24
  74. data/doc/rdoc/classes/ESI/Handler.src/M000082.html +0 -18
  75. data/doc/rdoc/classes/ESI/Handler.src/M000083.html +0 -26
  76. data/doc/rdoc/classes/ESI/Handler.src/M000084.html +0 -30
  77. data/doc/rdoc/classes/ESI/Invalidator.html +0 -131
  78. data/doc/rdoc/classes/ESI/Invalidator.src/M000004.html +0 -41
  79. data/doc/rdoc/classes/ESI/Log.html +0 -251
  80. data/doc/rdoc/classes/ESI/Log.src/M000005.html +0 -18
  81. data/doc/rdoc/classes/ESI/Log.src/M000006.html +0 -18
  82. data/doc/rdoc/classes/ESI/Log.src/M000007.html +0 -18
  83. data/doc/rdoc/classes/ESI/Log.src/M000008.html +0 -18
  84. data/doc/rdoc/classes/ESI/Log.src/M000009.html +0 -18
  85. data/doc/rdoc/classes/ESI/Log.src/M000010.html +0 -18
  86. data/doc/rdoc/classes/ESI/Log.src/M000011.html +0 -18
  87. data/doc/rdoc/classes/ESI/Log.src/M000012.html +0 -18
  88. data/doc/rdoc/classes/ESI/Log.src/M000013.html +0 -18
  89. data/doc/rdoc/classes/ESI/MemcachedCache.html +0 -314
  90. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000034.html +0 -24
  91. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000035.html +0 -22
  92. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000036.html +0 -19
  93. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000037.html +0 -23
  94. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000038.html +0 -18
  95. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000039.html +0 -19
  96. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000040.html +0 -18
  97. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000041.html +0 -18
  98. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000042.html +0 -17
  99. data/doc/rdoc/classes/ESI/Router.html +0 -229
  100. data/doc/rdoc/classes/ESI/Router.src/M000073.html +0 -36
  101. data/doc/rdoc/classes/ESI/Router.src/M000074.html +0 -25
  102. data/doc/rdoc/classes/ESI/Router.src/M000075.html +0 -24
  103. data/doc/rdoc/classes/ESI/RubyCache.html +0 -278
  104. data/doc/rdoc/classes/ESI/RubyCache.src/M000064.html +0 -20
  105. data/doc/rdoc/classes/ESI/RubyCache.src/M000065.html +0 -22
  106. data/doc/rdoc/classes/ESI/RubyCache.src/M000066.html +0 -21
  107. data/doc/rdoc/classes/ESI/RubyCache.src/M000067.html +0 -22
  108. data/doc/rdoc/classes/ESI/RubyCache.src/M000068.html +0 -18
  109. data/doc/rdoc/classes/ESI/RubyCache.src/M000069.html +0 -22
  110. data/doc/rdoc/classes/ESI/RubyCache.src/M000070.html +0 -18
  111. data/doc/rdoc/classes/ESI/RubyCache.src/M000071.html +0 -18
  112. data/doc/rdoc/classes/ESI/RubyCache.src/M000072.html +0 -18
  113. data/doc/rdoc/classes/ESI/Tag/Attempt.html +0 -113
  114. data/doc/rdoc/classes/ESI/Tag/Base.html +0 -267
  115. data/doc/rdoc/classes/ESI/Tag/Base.src/M000028.html +0 -26
  116. data/doc/rdoc/classes/ESI/Tag/Base.src/M000029.html +0 -23
  117. data/doc/rdoc/classes/ESI/Tag/Base.src/M000030.html +0 -22
  118. data/doc/rdoc/classes/ESI/Tag/Base.src/M000031.html +0 -18
  119. data/doc/rdoc/classes/ESI/Tag/Base.src/M000032.html +0 -22
  120. data/doc/rdoc/classes/ESI/Tag/Base.src/M000033.html +0 -23
  121. data/doc/rdoc/classes/ESI/Tag/Except.html +0 -184
  122. data/doc/rdoc/classes/ESI/Tag/Except.src/M000020.html +0 -21
  123. data/doc/rdoc/classes/ESI/Tag/Except.src/M000021.html +0 -20
  124. data/doc/rdoc/classes/ESI/Tag/Except.src/M000022.html +0 -18
  125. data/doc/rdoc/classes/ESI/Tag/Include.html +0 -189
  126. data/doc/rdoc/classes/ESI/Tag/Include.src/M000017.html +0 -20
  127. data/doc/rdoc/classes/ESI/Tag/Include.src/M000018.html +0 -18
  128. data/doc/rdoc/classes/ESI/Tag/Include.src/M000019.html +0 -125
  129. data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.html +0 -155
  130. data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.src/M000016.html +0 -19
  131. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.html +0 -199
  132. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000014.html +0 -18
  133. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000015.html +0 -42
  134. data/doc/rdoc/classes/ESI/Tag/Invalidate.html +0 -171
  135. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000025.html +0 -19
  136. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000026.html +0 -51
  137. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000027.html +0 -19
  138. data/doc/rdoc/classes/ESI/Tag/Try.html +0 -161
  139. data/doc/rdoc/classes/ESI/Tag/Try.src/M000023.html +0 -40
  140. data/doc/rdoc/classes/ESI/Tag/Try.src/M000024.html +0 -18
  141. data/doc/rdoc/classes/ESI/Tag.html +0 -137
  142. data/doc/rdoc/classes/ESI.html +0 -169
  143. data/doc/rdoc/classes/MultiDirHandler.html +0 -198
  144. data/doc/rdoc/classes/MultiDirHandler.src/M000001.html +0 -20
  145. data/doc/rdoc/classes/MultiDirHandler.src/M000002.html +0 -28
  146. data/doc/rdoc/classes/MultiDirHandler.src/M000003.html +0 -22
  147. data/doc/rdoc/classes/Net/An/HTTP.html +0 -137
  148. data/doc/rdoc/classes/Net/An/HTTP.src/M000087.html +0 -17
  149. data/doc/rdoc/classes/Net/An/IORequest.html +0 -139
  150. data/doc/rdoc/classes/Net/An/IORequest.src/M000088.html +0 -17
  151. data/doc/rdoc/classes/Net/An/IOResponse.html +0 -139
  152. data/doc/rdoc/classes/Net/An/IOResponse.src/M000085.html +0 -17
  153. data/doc/rdoc/classes/Net/An/IOSocket.html +0 -137
  154. data/doc/rdoc/classes/Net/An/IOSocket.src/M000086.html +0 -17
  155. data/doc/rdoc/classes/Net/An.html +0 -114
  156. data/doc/rdoc/classes/Net.html +0 -119
  157. data/doc/rdoc/created.rid +0 -1
  158. data/doc/rdoc/files/COPYING.html +0 -168
  159. data/doc/rdoc/files/LICENSE.html +0 -605
  160. data/doc/rdoc/files/README.html +0 -361
  161. data/doc/rdoc/files/lib/esi/cache_rb.html +0 -113
  162. data/doc/rdoc/files/lib/esi/config_rb.html +0 -108
  163. data/doc/rdoc/files/lib/esi/dispatcher_rb.html +0 -109
  164. data/doc/rdoc/files/lib/esi/handler_rb.html +0 -121
  165. data/doc/rdoc/files/lib/esi/invalidator_rb.html +0 -117
  166. data/doc/rdoc/files/lib/esi/logger_rb.html +0 -108
  167. data/doc/rdoc/files/lib/esi/router_rb.html +0 -101
  168. data/doc/rdoc/files/lib/esi/tag/attempt_rb.html +0 -101
  169. data/doc/rdoc/files/lib/esi/tag/base_rb.html +0 -108
  170. data/doc/rdoc/files/lib/esi/tag/except_rb.html +0 -101
  171. data/doc/rdoc/files/lib/esi/tag/include_rb.html +0 -109
  172. data/doc/rdoc/files/lib/esi/tag/invalidate_rb.html +0 -109
  173. data/doc/rdoc/files/lib/esi/tag/try_rb.html +0 -108
  174. data/doc/rdoc/files/lib/multi_dirhandler_rb.html +0 -109
  175. data/doc/rdoc/files/lib/net/ahttp_rb.html +0 -109
  176. data/doc/rdoc/fr_class_index.html +0 -55
  177. data/doc/rdoc/fr_file_index.html +0 -44
  178. data/doc/rdoc/fr_method_index.html +0 -114
  179. data/doc/rdoc/index.html +0 -24
  180. data/doc/rdoc/rdoc-style.css +0 -208
  181. data/ext/esi/parser.rb +0 -49
  182. data/ext/esi/ruby_esi.rl +0 -135
  183. data/lib/esi/handler.rb +0 -221
  184. data/lib/net/ahttp.rb +0 -36
@@ -6,6 +6,8 @@
6
6
  #define ESI_PARSER_H
7
7
  #include <sys/types.h>
8
8
 
9
+ /* how much output to hold in memory before sending out */
10
+ #define ESI_OUTPUT_BUFFER_SIZE 1024
9
11
 
10
12
  char *esi_strndup( const char *str, size_t len );
11
13
 
@@ -75,6 +77,11 @@ typedef struct _ESIParser {
75
77
 
76
78
  ESIAttribute *attributes, *last;
77
79
 
80
+ /* this memory will be pass to the output_cb when either it's full
81
+ * or eof is encountered */
82
+ char output_buffer[ESI_OUTPUT_BUFFER_SIZE+1];
83
+ size_t output_buffer_size;
84
+
78
85
  start_tag_cb start_tag_handler;
79
86
  end_tag_cb end_tag_handler;
80
87
  output_cb output_handler;
@@ -1,9 +1,22 @@
1
+ /**
2
+ * Copyright (c) 2008 Todd A. Fisher
3
+ * see LICENSE
4
+ */
1
5
  #include <stdio.h>
2
6
  #include <stdlib.h>
3
7
  #include <string.h>
4
8
  #include <ctype.h>
5
9
  #include "parser.h"
6
10
 
11
+ #ifdef DEBUG
12
+ static void debug_string( const char *msg, const char *str, size_t len )
13
+ {
14
+ char *pstr = esi_strndup( str, len );
15
+ printf( "%s :'%s'\n", msg, pstr );
16
+ free( pstr );
17
+ }
18
+ #endif
19
+
7
20
  /* define default callbacks */
8
21
  static void
9
22
  esi_parser_default_start_cb( const void *data,
@@ -26,58 +39,102 @@ esi_parser_default_output_cp(const void *data,
26
39
  void *user_data)
27
40
  {
28
41
  }
29
- #ifdef DEBUG
30
- static void debug_string( const char *msg, const char *str, size_t len )
42
+
43
+ /*
44
+ * flush output buffer
45
+ */
46
+ static void esi_parser_flush_output( ESIParser *parser )
31
47
  {
32
- char *pstr = esi_strndup( str, len );
33
- printf( "%s :'%s'\n", msg, pstr );
34
- free( pstr );
48
+ if( parser->output_buffer_size > 0 ) {
49
+ //debug_string( "esi_parser_flush_output:", parser->output_buffer, parser->output_buffer_size );
50
+ parser->output_handler( (void*)parser->output_buffer, parser->output_buffer_size, parser->user_data );
51
+ parser->output_buffer_size = 0;
52
+ }
35
53
  }
36
- #endif
37
-
54
+ /* send the character to the output handler marking it
55
+ * as ready for consumption, e.g. not an esi tag
56
+ */
38
57
  static void esi_parser_echo_char( ESIParser *parser, char ch )
39
58
  {
40
- parser->output_handler( (void*)&ch, 1, parser->user_data );
59
+ parser->output_buffer[parser->output_buffer_size++] = ch;
60
+ if( parser->output_buffer_size == ESI_OUTPUT_BUFFER_SIZE ) {
61
+ // flush the buffer to the consumer
62
+ esi_parser_flush_output( parser );
63
+ }
41
64
  }
42
-
65
+ /* send any buffered characters to the output handler.
66
+ * This happens when we enter a case such as <em> where the
67
+ * first two characters < and e match the <esi: expression
68
+ */
43
69
  static void esi_parser_echo_buffer( ESIParser *parser )
44
70
  {
45
- // debug_string( "echobuffer", parser->echobuffer, parser->echobuffer_index+1 );
46
- parser->output_handler( parser->echobuffer, parser->echobuffer_index+1, parser->user_data );
71
+ size_t i = 0, len = parser->echobuffer_index + 1;;
72
+ //debug_string( "echobuffer", parser->echobuffer, parser->echobuffer_index+1 );
73
+ //parser->output_handler( parser->echobuffer, parser->echobuffer_index+1, parser->user_data );
74
+ for( ; i < len; ++i ) {
75
+ esi_parser_echo_char( parser, parser->echobuffer[i] );
76
+ }
47
77
  }
48
-
78
+ /*
79
+ * clear the buffer, no buffered characters should be emitted .
80
+ * e.g. we matched an esi tag completely and all buffered characters can be tossed out
81
+ */
49
82
  static void esi_parser_echobuffer_clear( ESIParser *parser )
50
83
  {
51
84
  parser->echobuffer_index = -1;
52
85
  }
53
86
 
87
+ /*
88
+ * add a character to the echobuffer.
89
+ * this happens when we can't determine if the character is allowed to be sent to the client device
90
+ * e.g. matching <e it's not yet determined if these characters are safe to send or not
91
+ */
54
92
  static void esi_parser_concat_to_echobuffer( ESIParser *parser, char ch )
55
93
  {
56
94
  parser->echobuffer_index++;
57
95
 
58
96
  if( parser->echobuffer_allocated <= parser->echobuffer_index ){
59
- // double the echobuffer size
97
+ /* double the echobuffer size
98
+ * we're getting some crazy input if this case ever happens
99
+ */
60
100
  parser->echobuffer_allocated *= 2;
61
101
  parser->echobuffer = (char*)realloc( parser->echobuffer, parser->echobuffer_allocated );
62
102
  }
63
103
  parser->echobuffer[parser->echobuffer_index] = ch;
64
104
  // debug_string( "echo buffer", parser->echobuffer, parser->echobuffer_index+1 );
65
105
  }
66
-
106
+ /*
107
+ * the mark boundary is not always going to be exactly on the attribute or tag name boundary
108
+ * this trims characters from the left to right, advancing *ptr and reducing *len
109
+ */
67
110
  static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
68
111
  {
69
112
  // remove any spaces or = at the before the value
70
- while( isspace( **ptr ) ||
113
+ while( (isspace( **ptr ) ||
71
114
  **ptr == '=' ||
72
115
  **ptr == '"' ||
73
116
  **ptr == '<' ||
74
- **ptr == '\'' &&
75
- *len > 0 &&
76
- (*ptr != bounds) ){
117
+ **ptr == '\'' ) && (*len > 0) && (*ptr != bounds) ){
77
118
  (*ptr)++;
78
119
  (*len)--;
79
120
  }
80
121
  }
122
+ /*
123
+ * similar to ltrim_pointer, this walks from bounds to *ptr, reducing *len
124
+ */
125
+ static void rtrim_pointer( const char **ptr, const char *bounds, size_t *len )
126
+ {
127
+ bounds = (*ptr+(*len-1));
128
+ // remove any spaces or = at the before the value
129
+ while( (isspace( *bounds ) ||
130
+ *bounds == '=' ||
131
+ *bounds == '"' ||
132
+ *bounds == '>' ||
133
+ *bounds == '\'') && (*len > 0) && (*ptr != bounds) ){
134
+ bounds--;
135
+ (*len)--;
136
+ }
137
+ }
81
138
 
82
139
  %%{
83
140
  machine esi;
@@ -94,53 +151,84 @@ static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
94
151
  action see_start_tag {
95
152
  parser->tag_text = parser->mark+1;
96
153
  parser->tag_text_length = p - (parser->mark+1);
97
- // debug_string( "have esi start", parser->tag_text, parser->tag_text_length );
98
154
  parser->mark = p;
99
- //debug_string( "see_start_tag", p, 1 );
100
155
  }
101
156
 
157
+ # detected an inline tag end, sends the start tag and end tag callback
102
158
  action see_end_tag {
103
- //debug_string( "see_end_tag: before parsed esi tag", parser->tag_text, parser->tag_text_length );
159
+ /* trim the tag text */
104
160
  ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
105
- //debug_string( "see_end_tag: after parsed esi tag", parser->tag_text, parser->tag_text_length );
161
+ rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
162
+
163
+ /* send the start tag and end tag message */
164
+ esi_parser_flush_output( parser );
106
165
  parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->attributes, parser->user_data );
107
- //debug_string( "see_end_tag: after start parsed esi tag", parser->tag_text, parser->tag_text_length );
166
+ esi_parser_flush_output( parser );
108
167
  parser->end_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->user_data );
109
- //debug_string( "see_end_tag: after end parsed esi tag", parser->tag_text, parser->tag_text_length );
168
+ esi_parser_flush_output( parser );
169
+
170
+ /* mark the position */
110
171
  parser->tag_text = NULL;
111
172
  parser->tag_text_length = 0;
112
173
  parser->mark = p;
113
- //debug_string( "see_end_tag", p, 1 );
174
+
175
+ /* clear out the echo buffer */
176
+ esi_parser_echobuffer_clear( parser );
114
177
  }
115
-
178
+
179
+ # block tag start, with attributes
116
180
  action see_block_start_with_attributes {
117
- // debug_string( "parsed esi tag", parser->tag_text, parser->tag_text_length );
181
+ /* trim tag text */
118
182
  ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
183
+ rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
184
+
185
+ /* send the start and end tag message */
186
+ esi_parser_flush_output( parser );
119
187
  parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->attributes, parser->user_data );
188
+ esi_parser_flush_output( parser );
189
+
120
190
  parser->tag_text = NULL;
121
191
  parser->tag_text_length = 0;
192
+ parser->mark = p;
193
+
194
+ /* clear out the echo buffer */
195
+ esi_parser_echobuffer_clear( parser );
122
196
  }
123
-
197
+
198
+ # see an attribute key, /foo\s*=/
124
199
  action see_attribute_key {
200
+ /* save the attribute key start */
125
201
  parser->attr_key = parser->mark;
202
+ /* compute the length of the key */
126
203
  parser->attr_key_length = p - parser->mark;
204
+ /* save the position following the key */
127
205
  parser->mark = p;
206
+
207
+ /* trim the attribute key */
128
208
  ltrim_pointer( &(parser->attr_key), p, &(parser->attr_key_length) );
129
- // debug_string( "\tattribute key", parser->attr_key, parser->attr_key_length );
130
- //debug_string( "see_attribute_key", p, 1 );
209
+ rtrim_pointer( &(parser->attr_key), p, &(parser->attr_key_length) );
131
210
  }
132
211
 
212
+ # see an attribute value, aprox ~= /['"].*['"]/
133
213
  action see_attribute_value {
134
214
  ESIAttribute *attr;
215
+
216
+ /* save the attribute value start */
135
217
  parser->attr_value = parser->mark;
218
+ /* compute the length of the value */
136
219
  parser->attr_value_length = p - parser->mark;
220
+ /* svae the position following the value */
137
221
  parser->mark = p;
138
-
222
+
223
+ /* trim the attribute value */
139
224
  ltrim_pointer( &(parser->attr_value), p, &(parser->attr_value_length) );
225
+ rtrim_pointer( &(parser->attr_value), p, &(parser->attr_value_length) );
140
226
 
141
- // allocate a new attribute
227
+ /* using the attr_key and attr_value, allocate a new attribute object */
142
228
  attr = esi_attribute_new( parser->attr_key, parser->attr_key_length,
143
229
  parser->attr_value, parser->attr_value_length );
230
+
231
+ /* add the new attribute to the list of attributes */
144
232
  if( parser->attributes ){
145
233
  parser->last->next = attr;
146
234
  parser->last = attr;
@@ -148,49 +236,67 @@ static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
148
236
  else{
149
237
  parser->last = parser->attributes = attr;
150
238
  }
151
- // debug_string( "\tattribute value", parser->attr_value, parser->attr_value_length );
152
- //debug_string( "see_attribute_value", p, 1 );
153
239
  }
154
240
 
241
+ # simple block start tag detected, e.g. <esi:try> no attributes
155
242
  action block_start_tag {
243
+
156
244
  parser->tag_text = parser->mark;
157
245
  parser->tag_text_length = p - parser->mark;
246
+
158
247
  parser->mark = p;
248
+
159
249
  ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
250
+ rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
251
+
252
+ esi_parser_flush_output( parser );
160
253
  parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, NULL, parser->user_data );
161
- //debug_string( "block_start_tag", p, 1 );
254
+ esi_parser_flush_output( parser );
255
+
256
+ esi_parser_echobuffer_clear( parser );
162
257
  }
163
258
 
259
+ # block end tag detected, e.g. </esi:try>
164
260
  action block_end_tag {
261
+ /* offset by 2 to account for the </ characters */
165
262
  parser->tag_text = parser->mark+2;
166
263
  parser->tag_text_length = p - (parser->mark+2);
167
- //printf( "mark: [%s], p: [%s], length: %d\n", parser->mark, p, parser->tag_text_length );
264
+
168
265
  parser->mark = p;
169
- //debug_string( "block_end_tag: before parsed esi tag", parser->tag_text, parser->tag_text_length );
266
+
170
267
  ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
171
- //debug_string( "block_end_tag: after parsed esi tag", parser->tag_text, parser->tag_text_length );
268
+ rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
269
+
270
+ esi_parser_flush_output( parser );
172
271
  parser->end_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->user_data );
272
+ esi_parser_flush_output( parser );
273
+
274
+ esi_parser_echobuffer_clear( parser );
173
275
  }
174
276
 
277
+ # process each character in the input stream for output
175
278
  action echo {
279
+ //printf( "[%c:%d],", *p, cs );
176
280
  switch( cs ){
177
- case 0:
178
- if( parser->prev_state != 12 && parser->prev_state != 7 ){
179
- if( parser->echobuffer && (parser->prev_state != (esi_en_main +1)) && parser->prev_state != 60 ){
180
- // stream echobuffer
281
+ case 0: /* non matching state */
282
+ if( parser->prev_state != 12 && parser->prev_state != 7 ){ /* states following a possible end state for a tag */
283
+ if( parser->echobuffer && parser->echobuffer_index != -1 ){
284
+ /* send the echo buffer */
181
285
  esi_parser_echo_buffer( parser );
182
286
  }
183
- // printf( "[%d: %c]", cs, *p );
184
- // stream the current character
287
+ /* send the current character */
185
288
  esi_parser_echo_char( parser, *p );
186
289
  }
187
- // clear the echobuffer
290
+ /* clear the echo buffer */
188
291
  esi_parser_echobuffer_clear( parser );
189
292
  break;
190
293
  default:
191
- // append characters to echobuffer
294
+ /* append to the echo buffer */
192
295
  esi_parser_concat_to_echobuffer( parser, *p );
193
296
  }
297
+ /* save the previous state, necessary for end case detection such as /> and </esi:try> the trailing > character
298
+ is state 12 and 7
299
+ */
194
300
  parser->prev_state = cs;
195
301
  }
196
302
 
@@ -199,6 +305,7 @@ static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
199
305
 
200
306
  %%write data;
201
307
 
308
+ /* dup the string up to len */
202
309
  char *esi_strndup( const char *str, size_t len )
203
310
  {
204
311
  char *s = (char*)malloc(sizeof(char)*(len+1));
@@ -260,7 +367,7 @@ ESIParser *esi_parser_new()
260
367
  parser->overflow_data = NULL;
261
368
 
262
369
  /* allocate 1024 bytes for the echobuffer */
263
- parser->echobuffer_allocated = 1024;
370
+ parser->echobuffer_allocated = ESI_OUTPUT_BUFFER_SIZE; /* NOTE: change this value, to reduce memory consumtion or allocations */
264
371
  parser->echobuffer_index = -1;
265
372
  parser->echobuffer = (char*)malloc(sizeof(char)*parser->echobuffer_allocated);
266
373
 
@@ -271,6 +378,9 @@ ESIParser *esi_parser_new()
271
378
  parser->end_tag_handler = esi_parser_default_end_cb;
272
379
  parser->output_handler = esi_parser_default_output_cp;
273
380
 
381
+ parser->output_buffer_size = 0;
382
+ memset( parser->output_buffer, 0, ESI_OUTPUT_BUFFER_SIZE );
383
+
274
384
  return parser;
275
385
  }
276
386
  void esi_parser_free( ESIParser *parser )
@@ -304,14 +414,22 @@ static int compute_offset( const char *mark, const char *data )
304
414
  return -1;
305
415
  }
306
416
 
417
+ /* accept an arbitrary length string buffer
418
+ * when this methods exits it determines if an end state was reached
419
+ * if no end state was reached it saves the full input into an internal buffer
420
+ * when invoked next, it reuses that internable buffer copying all pointers into the
421
+ * newly allocated buffer. if it exits in a terminal state, e.g. 0 then it will dump these buffers
422
+ */
307
423
  int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
308
424
  {
309
425
  int cs = parser->cs;
310
426
  const char *p = data;
427
+ const char *eof = NULL; // ragel 6.x compat
311
428
  const char *pe = data + length;
312
429
 
313
430
  if( length == 0 ){ return cs; }
314
431
 
432
+ /* there's an existing overflow buffer data append the new data to the existing data */
315
433
  if( parser->overflow_data && parser->overflow_data_size > 0 ){
316
434
 
317
435
  // recompute mark, tag_text, attr_key, and attr_value since they all exist within overflow_data
@@ -320,13 +438,11 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
320
438
  int attr_key_offset = compute_offset( parser->attr_key, parser->overflow_data );
321
439
  int attr_value_offset = compute_offset( parser->attr_value, parser->overflow_data );
322
440
 
323
- // debug_string("grow overflow buffer", parser->overflow_data, parser->overflow_data_size );
324
-
325
441
  parser->overflow_data = (char*)realloc( parser->overflow_data, sizeof(char)*(parser->overflow_data_size+length) );
326
442
  memcpy( parser->overflow_data+parser->overflow_data_size, data, length );
327
443
 
328
444
  p = parser->overflow_data + parser->overflow_data_size;
329
-
445
+
330
446
  // in our new memory space mark will now be
331
447
  parser->mark = ( mark_offset >= 0 ) ? parser->overflow_data + mark_offset : NULL;
332
448
  parser->tag_text = ( tag_text_offset >= 0 ) ? parser->overflow_data + tag_text_offset : NULL;
@@ -335,9 +451,9 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
335
451
 
336
452
  data = parser->overflow_data;
337
453
  parser->overflow_data_size = length = length + parser->overflow_data_size;
454
+ // printf( "grow overflow data: %ld\n", parser->overflow_data_size );
338
455
  pe = data + length;
339
456
 
340
- // debug_string( "overflow", parser->overflow_data, parser->overflow_data_size );
341
457
  }
342
458
 
343
459
  if( !parser->mark ){
@@ -345,7 +461,6 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
345
461
  }
346
462
 
347
463
  // printf( "cs: %d, ", cs );
348
- // debug_string( "data", data, length );
349
464
 
350
465
  %% write exec;
351
466
 
@@ -353,6 +468,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
353
468
 
354
469
  if( cs != esi_start && cs != 0 ){
355
470
 
471
+ /* reached the end and we're not at a termination point save the buffer as overflow */
356
472
  if( !parser->overflow_data ){
357
473
  // recompute mark, tag_text, attr_key, and attr_value since they all exist within overflow_data
358
474
  int mark_offset = compute_offset( parser->mark, data );
@@ -364,6 +480,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
364
480
  parser->overflow_data = (char*)malloc( sizeof( char ) * length );
365
481
  memcpy( parser->overflow_data, data, length );
366
482
  parser->overflow_data_size = length;
483
+ // printf( "allocate overflow data: %ld\n", parser->overflow_data_size );
367
484
 
368
485
  // in our new memory space mark will now be
369
486
  parser->mark = ( mark_offset >= 0 ) ? parser->overflow_data + mark_offset : NULL;
@@ -374,6 +491,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
374
491
  }
375
492
 
376
493
  }else if( parser->overflow_data ){
494
+ /* dump the overflow buffer execution ended at a final state */
377
495
  free( parser->overflow_data );
378
496
  parser->overflow_data = NULL;
379
497
  parser->overflow_data_size = 0;
@@ -383,7 +501,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
383
501
  }
384
502
  int esi_parser_finish( ESIParser *parser )
385
503
  {
386
- %% write eof;
504
+ esi_parser_flush_output( parser );
387
505
  return 0;
388
506
  }
389
507