comparison tango/tango/net/http/HttpStack.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Initial release: April 2004
8
9 author: Kris, John Reimer
10
11 *******************************************************************************/
12
13 module tango.net.http.HttpStack;
14
15 private import tango.core.Exception;
16
17 /******************************************************************************
18
19 Unix doesn't appear to have a memicmp() ... JJR notes that the
20 strncasecmp() is available instead.
21
22 ******************************************************************************/
23
24 version (Win32)
25 {
26 extern (C) int memicmp (char *, char *, uint);
27 }
28
29 version (Posix)
30 {
31 extern (C) int strncasecmp (char *, char*, uint);
32 }
33
34 extern (C) void* memmove (void* dst, void* src, int n);
35
36
37 /******************************************************************************
38
39 Internal representation of a token
40
41 ******************************************************************************/
42
43 class Token
44 {
45 private char[] value;
46
47 Token set (char[] value)
48 {
49 this.value = value;
50 return this;
51 }
52
53 char[] toString ()
54 {
55 return value;
56 }
57 }
58
59 /******************************************************************************
60
61 A stack of Tokens, used for capturing http headers. The tokens
62 themselves are typically mapped onto the content of a Buffer,
63 or some other external content, so there's minimal allocation
64 involved (typically zero).
65
66 ******************************************************************************/
67
68 class HttpStack
69 {
70 private int depth;
71 private Token[] tokens;
72
73 private static const int MaxHttpStackSize = 256;
74
75 /**********************************************************************
76
77 Construct a HttpStack with the specified initial size.
78 The stack will later be resized as necessary.
79
80 **********************************************************************/
81
82 this (int size = 10)
83 {
84 tokens = new Token[0];
85 resize (tokens, size);
86 }
87
88 /**********************************************************************
89
90 Clone this stack of tokens
91
92 **********************************************************************/
93
94 HttpStack clone ()
95 {
96 // setup a new HttpStack of the same depth
97 HttpStack clone = new HttpStack(depth);
98
99 clone.depth = depth;
100
101 // duplicate the content of each original token
102 for (int i=0; i < depth; ++i)
103 clone.tokens[i].set (tokens[i].toString().dup);
104
105 return clone;
106 }
107
108 /**********************************************************************
109
110 Iterate over all tokens in stack
111
112 **********************************************************************/
113
114 int opApply (int delegate(inout Token) dg)
115 {
116 int result = 0;
117
118 for (int i=0; i < depth; ++i)
119 if ((result = dg (tokens[i])) != 0)
120 break;
121 return result;
122 }
123
124 /**********************************************************************
125
126 Pop the stack all the way back to zero
127
128 **********************************************************************/
129
130 final void reset ()
131 {
132 depth = 0;
133 }
134
135 /**********************************************************************
136
137 Scan the tokens looking for the first one with a matching
138 name. Returns the matching Token, or null if there is no
139 such match.
140
141 **********************************************************************/
142
143 final Token findToken (char[] match)
144 {
145 Token tok;
146
147 for (int i=0; i < depth; ++i)
148 {
149 tok = tokens[i];
150 if (isMatch (tok, match))
151 return tok;
152 }
153 return null;
154 }
155
156 /**********************************************************************
157
158 Scan the tokens looking for the first one with a matching
159 name, and remove it. Returns true if a match was found, or
160 false if not.
161
162 **********************************************************************/
163
164 final bool removeToken (char[] match)
165 {
166 for (int i=0; i < depth; ++i)
167 if (isMatch (tokens[i], match))
168 {
169 tokens[i].value = null;
170 return true;
171 }
172 return false;
173 }
174
175 /**********************************************************************
176
177 Return the current stack depth
178
179 **********************************************************************/
180
181 final int size ()
182 {
183 return depth;
184 }
185
186 /**********************************************************************
187
188 Push a new token onto the stack, and set it content to
189 that provided. Returns the new Token.
190
191 **********************************************************************/
192
193 final Token push (char[] content)
194 {
195 return push().set (content);
196 }
197
198 /**********************************************************************
199
200 Push a new token onto the stack, and set it content to
201 be that of the specified token. Returns the new Token.
202
203 **********************************************************************/
204
205 final Token push (inout Token token)
206 {
207 return push (token.toString());
208 }
209
210 /**********************************************************************
211
212 Push a new token onto the stack, and return it.
213
214 **********************************************************************/
215
216 final Token push ()
217 {
218 if (depth == tokens.length)
219 resize (tokens, depth * 2);
220 return tokens[depth++];
221 }
222
223 /**********************************************************************
224
225 Pop the stack by one.
226
227 **********************************************************************/
228
229 final void pop ()
230 {
231 if (depth)
232 --depth;
233 else
234 throw new IOException ("illegal attempt to pop Token stack");
235 }
236
237 /**********************************************************************
238
239 See if the given token matches the specified text. The
240 two must match the minimal extent exactly.
241
242 **********************************************************************/
243
244 final static bool isMatch (inout Token token, char[] match)
245 {
246 char[] target = token.toString();
247
248 int length = target.length;
249 if (length > match.length)
250 length = match.length;
251
252 if (length is 0)
253 return false;
254
255 version (Win32)
256 return memicmp (target.ptr, match.ptr, length) is 0;
257 version (Posix)
258 return strncasecmp (target.ptr, match.ptr, length) is 0;
259 }
260
261 /**********************************************************************
262
263 Resize this stack by extending the array.
264
265 **********************************************************************/
266
267 final static void resize (inout Token[] tokens, int size)
268 {
269 int i = tokens.length;
270
271 // this should *never* realistically happen
272 if (size > MaxHttpStackSize)
273 throw new IOException ("Token stack exceeds maximum depth");
274
275 for (tokens.length=size; i < tokens.length; ++i)
276 tokens[i] = new Token();
277 }
278 }