mongrel_esi 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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