Mercurial > projects > ldc
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 } |