Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

TokenStack.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file TokenStack.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032         
00033         @version        Initial version, April 2004      
00034         @author         Kris, John Reimer
00035 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.http.utils.TokenStack;
00040 
00041 private import  mango.io.Token,
00042                 mango.io.Exception;
00043 
00044 /******************************************************************************
00045 
00046         Unix doesn't appear to have a memicmp() ... JJR notes that the
00047         strncasecmp() is available instead.
00048 
00049 ******************************************************************************/
00050 
00051 version (Win32)
00052         {
00053         extern (C) int memicmp (char *, char *, uint);
00054         }
00055 
00056 version (Posix) 
00057         {
00058         extern (C) int strncasecmp (char *, char*, uint);
00059         }
00060 
00061 /******************************************************************************
00062 
00063         A stack of Tokens, used for capturing http headers. The tokens
00064         themselves are typically mapped onto the content of a Buffer, 
00065         or some other external content, so there's minimal allocation 
00066         involved (typically zero).
00067 
00068 ******************************************************************************/
00069 
00070 class TokenStack
00071 {
00072         private int     depth;
00073         private Token[] tokens;
00074 
00075         private static const int MaxTokenStackSize = 256;
00076 
00077         /**********************************************************************
00078 
00079                 Construct a TokenStack with the specified initial size. 
00080                 The stack will later be resized as necessary.
00081 
00082         **********************************************************************/
00083 
00084         this (int size = 10)
00085         {
00086                 tokens = new Token[0];
00087                 resize (tokens, size);
00088         }
00089 
00090         /**********************************************************************
00091 
00092                 Clone this stack of tokens
00093 
00094         **********************************************************************/
00095 
00096         TokenStack clone ()
00097         {
00098                 // setup a new tokenstack of the same depth
00099                 TokenStack clone = new TokenStack(depth);
00100                 
00101                 clone.depth = depth;
00102 
00103                 // duplicate the content of each original token
00104                 for (int i=0; i < depth; ++i)
00105                      clone.tokens[i].set (tokens[i].toString().dup);
00106 
00107                 return clone;
00108         }
00109 
00110         /**********************************************************************
00111 
00112                 Iterate over all tokens in stack
00113 
00114         **********************************************************************/
00115 
00116         int opApply (int delegate(inout Token) dg)
00117         {
00118                 int result = 0;
00119 
00120                 for (int i=0; i < depth; ++i)
00121                      if ((result = dg (tokens[i])) != 0)
00122                           break;
00123                 return result;
00124         }
00125 
00126         /**********************************************************************
00127 
00128                 Pop the stack all the way back to zero
00129 
00130         **********************************************************************/
00131 
00132         final void reset ()
00133         {
00134                 depth = 0;
00135         }
00136 
00137         /**********************************************************************
00138 
00139                 Scan the tokens looking for the first one with a matching
00140                 name. Returns the matching Token, or null if there is no
00141                 such match.
00142 
00143         **********************************************************************/
00144 
00145         final Token findToken (char[] match)
00146         {
00147                 Token tok;
00148 
00149                 for (int i=0; i < depth; ++i)
00150                     {
00151                     tok = tokens[i];
00152                     if (isMatch (tok, match))
00153                         return tok;
00154                     }
00155                 return null;
00156         }
00157 
00158         /**********************************************************************
00159 
00160                 Return the current stack depth
00161 
00162         **********************************************************************/
00163 
00164         final int size ()
00165         {
00166                 return depth;
00167         }
00168 
00169         /**********************************************************************
00170 
00171                 Push a new token onto the stack, and set it content to 
00172                 that provided. Returns the new Token.
00173 
00174         **********************************************************************/
00175 
00176         final Token push (char[] content)
00177         {
00178               return push().set (content);  
00179         }
00180 
00181         /**********************************************************************
00182 
00183                 Push a new token onto the stack, and set it content to 
00184                 be that of the specified token. Returns the new Token.
00185 
00186         **********************************************************************/
00187 
00188         final Token push (Token token)
00189         {
00190               return push (token.toString());  
00191         }
00192 
00193         /**********************************************************************
00194 
00195                 Push a new token onto the stack, and return it.
00196 
00197         **********************************************************************/
00198 
00199         final Token push ()
00200         {
00201                 if (depth == tokens.length)
00202                     resize (tokens, depth * 2);
00203                 return tokens[depth++];
00204         }
00205 
00206         /**********************************************************************
00207 
00208                 Pop the stack by one.
00209 
00210         **********************************************************************/
00211 
00212         final void pop ()
00213         {
00214                 if (depth)
00215                     --depth;
00216                 else
00217                    throw new IOException ("illegal attempt to pop Token stack");
00218         }
00219 
00220         /**********************************************************************
00221 
00222                 See if the given token matches the specified text. The 
00223                 two must match the minimal extent exactly.
00224 
00225         **********************************************************************/
00226 
00227         final static bool isMatch (Token token, char[] match)
00228         {
00229                 char[] target = token.toString();
00230 
00231                 int length = target.length;
00232                 if (length > match.length)
00233                     length = match.length;
00234 
00235                 version (Win32)
00236                          return memicmp (target, match, length) == 0;
00237                 version (Posix)
00238                          return strncasecmp (cast(char *)target, cast(char *)match, length) == 0;
00239         }
00240         
00241         /**********************************************************************
00242 
00243                 Resize this stack by extending the array.
00244 
00245         **********************************************************************/
00246 
00247         final static void resize (inout Token[] tokens, int size)
00248         {
00249                 int i = tokens.length;
00250 
00251                 // this should *never* realistically happen 
00252                 if (size > MaxTokenStackSize)
00253                     throw new IOException ("Token stack exceeds maximum depth");
00254 
00255                 for (tokens.length=size; i < tokens.length; ++i)
00256                      tokens[i] = new Token();
00257         }
00258 }

Generated on Tue Jan 25 21:18:23 2005 for Mango by doxygen 1.3.6