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 
00027                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00028 
00029         
00030         @version        Initial version, April 2004      
00031         @author         Kris, John Reimer
00032 
00033 
00034 *******************************************************************************/
00035 
00036 module mango.http.utils.TokenStack;
00037 
00038 private import  mango.io.Token,
00039                 mango.io.Exception;
00040 
00041 /******************************************************************************
00042 
00043         linux doesn't appear to have a memicmp() ... JJR notes that the
00044         strncasecmp() is available instead.
00045 
00046 ******************************************************************************/
00047 
00048 version (Win32)
00049         {
00050         extern (C) int memicmp (char *, char *, uint);
00051         }
00052 
00053 version (linux) 
00054         {
00055         extern (C) int strncasecmp (char *, char*, uint);
00056         }
00057 
00058 /******************************************************************************
00059 
00060         A stack of Tokens, used for capturing http headers. The tokens
00061         themselves are typically mapped onto the content of a Buffer, 
00062         or some other external content, so there's minimal allocation 
00063         involved (typically zero).
00064 
00065 ******************************************************************************/
00066 
00067 class TokenStack
00068 {
00069         private int     depth;
00070         private Token[] tokens;
00071 
00072         private static const int MaxTokenStackSize = 256;
00073 
00074         /**********************************************************************
00075 
00076                 Construct a TokenStack with the specified initial size. 
00077                 The stack will later be resized as necessary.
00078 
00079         **********************************************************************/
00080 
00081         this (int size = 10)
00082         {
00083                 tokens = new Token[0];
00084                 resize (tokens, size);
00085         }
00086 
00087         /**********************************************************************
00088 
00089                 Clone this stack of tokens
00090 
00091         **********************************************************************/
00092 
00093         TokenStack clone ()
00094         {
00095                 // setup a new tokenstack of the same depth
00096                 TokenStack clone = new TokenStack(depth);
00097                 
00098                 clone.depth = depth;
00099 
00100                 // duplicate the content of each original token
00101                 for (int i=0; i < depth; ++i)
00102                      clone.tokens[i].set (tokens[i].toString().dup);
00103 
00104                 return clone;
00105         }
00106 
00107         /**********************************************************************
00108 
00109                 Iterate over all tokens in stack
00110 
00111         **********************************************************************/
00112 
00113         int opApply (int delegate(inout Token) dg)
00114         {
00115                 int result = 0;
00116 
00117                 for (int i=0; i < depth; ++i)
00118                      if ((result = dg (tokens[i])) != 0)
00119                           break;
00120                 return result;
00121         }
00122 
00123         /**********************************************************************
00124 
00125                 Pop the stack all the way back to zero
00126 
00127         **********************************************************************/
00128 
00129         final void reset ()
00130         {
00131                 depth = 0;
00132         }
00133 
00134         /**********************************************************************
00135 
00136                 Scan the tokens looking for the first one with a matching
00137                 name. Returns the matching Token, or null if there is no
00138                 such match.
00139 
00140         **********************************************************************/
00141 
00142         final Token findToken (char[] match)
00143         {
00144                 Token tok;
00145 
00146                 for (int i=0; i < depth; ++i)
00147                     {
00148                     tok = tokens[i];
00149                     if (isMatch (tok, match))
00150                         return tok;
00151                     }
00152                 return null;
00153         }
00154 
00155         /**********************************************************************
00156 
00157                 Return the current stack depth
00158 
00159         **********************************************************************/
00160 
00161         final int size ()
00162         {
00163                 return depth;
00164         }
00165 
00166         /**********************************************************************
00167 
00168                 Push a new token onto the stack, and set it content to 
00169                 that provided. Returns the new Token.
00170 
00171         **********************************************************************/
00172 
00173         final Token push (char[] content)
00174         {
00175               return push().set (content);  
00176         }
00177 
00178         /**********************************************************************
00179 
00180                 Push a new token onto the stack, and set it content to 
00181                 be that of the specified token. Returns the new Token.
00182 
00183         **********************************************************************/
00184 
00185         final Token push (Token token)
00186         {
00187               return push (token.toString());  
00188         }
00189 
00190         /**********************************************************************
00191 
00192                 Push a new token onto the stack, and return it.
00193 
00194         **********************************************************************/
00195 
00196         final Token push ()
00197         {
00198                 if (depth == tokens.length)
00199                     resize (tokens, depth * 2);
00200                 return tokens[depth++];
00201         }
00202 
00203         /**********************************************************************
00204 
00205                 Pop the stack by one.
00206 
00207         **********************************************************************/
00208 
00209         final void pop ()
00210         {
00211                 if (depth)
00212                     --depth;
00213                 else
00214                    throw new IOException ("illegal attempt to pop Token stack");
00215         }
00216 
00217         /**********************************************************************
00218 
00219                 See if the given token matches the specified text. The 
00220                 two must match the minimal extent exactly.
00221 
00222         **********************************************************************/
00223 
00224         final static bool isMatch (Token token, char[] match)
00225         {
00226                 char[] target = token.toString();
00227 
00228                 int length = target.length;
00229                 if (length > match.length)
00230                     length = match.length;
00231 
00232                 version (Win32)
00233                          return memicmp (target, match, length) == 0;
00234                 version (linux)
00235                          return strncasecmp (cast(char *)target, cast(char *)match, length) == 0;
00236         }
00237         
00238         /**********************************************************************
00239 
00240                 Resize this stack by extending the array.
00241 
00242         **********************************************************************/
00243 
00244         final static void resize (inout Token[] tokens, int size)
00245         {
00246                 int i = tokens.length;
00247 
00248                 // this should *never* realistically happen 
00249                 if (size > MaxTokenStackSize)
00250                     throw new IOException ("Token stack exceeds maximum depth");
00251 
00252                 for (tokens.length=size; i < tokens.length; ++i)
00253                      tokens[i] = new Token();
00254         }
00255 }

Generated on Sun Nov 7 19:06:53 2004 for Mango by doxygen 1.3.6