Changeset 753

Show
Ignore:
Timestamp:
01/11/06 17:32:22 (3 years ago)
Author:
kris
Message:

Overhaul of the tokenizers -- now use iterators instead.
See text.LineIterator? for examples.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/mango/http/client/HttpClient.d

    r752 r753  
    4747 
    4848private import  mango.io.Uri, 
    49                 mango.io.Token, 
    5049                mango.io.Buffer, 
     50                mango.io.Exception, 
    5151                mango.io.SocketConduit, 
    52                 mango.io.Exception, 
    53                 mango.io.Tokenizer, 
    5452                mango.io.DisplayWriter; 
     53 
     54private import  mango.text.LineIterator; 
    5555 
    5656private import  mango.http.utils.TokenTriplet; 
     
    438438 
    439439                    // Token for initial parsing of input header lines 
    440                     CompositeToken line = new CompositeToken (Tokenizers.line, input); 
     440                    auto line = new LineIterator (input); 
    441441 
    442442                    // skip any blank lines 
    443                     while (line.next() && line.getLength() == 0)  
     443                    while (line.next && line.get.length is 0)  
    444444                          {} 
    445445 
     
    452452 
    453453                    // read response line 
    454                     responseLine.parse (line.toString); 
     454                    responseLine.parse (line.get); 
    455455 
    456456                    // parse headers 
  • trunk/mango/http/server/HttpCookies.d

    r625 r753  
    4040module mango.http.server.HttpCookies; 
    4141 
    42 private import  mango.text.Text; 
    43  
    44 private import  mango.io.Token, 
    45                 mango.io.Buffer, 
    46                 mango.io.Tokenizer; 
     42private import  mango.io.Buffer; 
     43 
     44private import  mango.text.Text, 
     45                mango.text.Iterator; 
    4746 
    4847private import  mango.io.model.IWriter, 
     
    348347{ 
    349348        private bool                    parsed; 
    350         private Cookie                  cookie; 
    351         private IBuffer                 buffer; 
    352349        private CookieStack             stack; 
     350        private CookieParser            parser; 
    353351        private HttpHeaders             headers; 
    354352 
    355         private static CookieParser     parser; 
    356  
    357         /********************************************************************** 
    358  
    359                 Setup the parser for server-side cookies 
    360  
    361         **********************************************************************/ 
    362  
    363         static this () 
    364         { 
    365                 parser = new CookieParser (); 
    366         } 
    367  
    368353        /********************************************************************** 
    369354 
     
    375360        { 
    376361                this.headers = headers; 
    377  
    378                 // setup an empty buffer for later use 
    379                 buffer = new Buffer; 
    380362 
    381363                // create a stack for parsed cookies 
    382364                stack = new CookieStack (10); 
     365 
     366                // create a parser 
     367                parser = new CookieParser (stack); 
    383368        } 
    384369 
     
    391376        void write (IWriter writer) 
    392377        { 
    393                 foreach (Cookie cookie; parse()
     378                foreach (Cookie cookie; parse
    394379                         writer.put (cookie).cr(); 
    395380        } 
     
    422407                   foreach (HeaderElement header; headers) 
    423408                            if (header.name.value == HttpHeader.Cookie.value) 
    424                                { 
    425                                buffer.setValidContent (header.value); 
    426                                parser.next (buffer, stack); 
    427                                } 
     409                                parser.parse (header.value); 
    428410                   } 
    429411                return stack; 
     
    456438        { 
    457439                this.headers = headers; 
    458                 writer = new HttpWriter (headers.getOutputBuffer()); 
     440                writer = new HttpWriter (headers.getOutputBuffer); 
    459441        } 
    460442 
     
    486468*******************************************************************************/ 
    487469 
    488 class CookieParser : Scanner 
     470class CookieParser : IteratorT!(char) 
    489471{ 
    490472        private enum State {Begin, LValue, Equals, RValue, Token, SQuote, DQuote}; 
    491473 
     474        private CookieStack stack; 
     475 
     476        /*********************************************************************** 
     477 
     478        ***********************************************************************/ 
     479 
     480        this (CookieStack stack) 
     481        { 
     482                super (); 
     483                this.stack = stack; 
     484        } 
     485 
     486        /*********************************************************************** 
     487 
     488                Callback for iterator.next(). We scan for name-value 
     489                pairs, populating Cookie instances along the way. 
     490 
     491        ***********************************************************************/ 
     492 
     493        protected uint scan (void[] data) 
     494        {       
     495                char    c; 
     496                int     mark, 
     497                        vrsn; 
     498                char[]  name, 
     499                        token; 
     500                Cookie  cookie; 
     501 
     502                State   state = State.Begin; 
     503                char[]  content = cast(char[]) data; 
     504 
     505                /*************************************************************** 
     506 
     507                        Found a value; set that also 
     508 
     509                ***************************************************************/ 
     510 
     511                void setValue (int i) 
     512                {    
     513                        token = content [mark..i]; 
     514                        //Print ("::name '%.*s'\n", name); 
     515                        //Print ("::value '%.*s'\n", token); 
     516 
     517                        if (name[0] != '$') 
     518                           { 
     519                           cookie = stack.push(); 
     520                           cookie.setName (name); 
     521                           cookie.setValue (token); 
     522                           cookie.setVersion (vrsn); 
     523                           } 
     524                        else 
     525                           switch (toLower (name)) 
     526                                  { 
     527                                  case "$path": 
     528                                        if (cookie) 
     529                                            cookie.setPath (token);  
     530                                        break; 
     531 
     532                                  case "$domain": 
     533                                        if (cookie) 
     534                                            cookie.setDomain (token);  
     535                                        break; 
     536 
     537                                  case "$version": 
     538                                        vrsn = cast(int) Integer.parse (token);  
     539                                        break; 
     540 
     541                                  default: 
     542                                       break; 
     543                                  } 
     544                        state = State.Begin; 
     545                } 
     546 
     547                /*************************************************************** 
     548 
     549                        Scan content looking for cookie fields 
     550 
     551                ***************************************************************/ 
     552 
     553                for (int i; i < content.length; ++i) 
     554                    { 
     555                    c = content [i]; 
     556                    switch (state) 
     557                           { 
     558                           // look for an lValue 
     559                           case State.Begin: 
     560                                mark = i; 
     561                                if (isalpha (c) || c is '$') 
     562                                    state = State.LValue; 
     563                                continue; 
     564 
     565                           // scan until we have all lValue chars 
     566                           case State.LValue: 
     567                                if (! isalnum (c)) 
     568                                   { 
     569                                   state = State.Equals; 
     570                                   name = content [mark..i]; 
     571                                   --i; 
     572                                   } 
     573                                continue; 
     574 
     575                           // should now have either a '=', ';', or ',' 
     576                           case State.Equals: 
     577                                if (c is '=') 
     578                                    state = State.RValue; 
     579                                else 
     580                                   if (c is ',' || c is ';') 
     581                                       // get next NVPair 
     582                                       state = State.Begin; 
     583                                continue; 
     584 
     585                           // look for a quoted token, or a plain one 
     586                           case State.RValue: 
     587                                mark = i; 
     588                                if (c is '\'') 
     589                                    state = State.SQuote; 
     590                                else 
     591                                   if (c is '"') 
     592                                       state = State.DQuote; 
     593                                   else 
     594                                      if (isalpha (c)) 
     595                                          state = State.Token; 
     596                                continue; 
     597 
     598                           // scan for all plain token chars 
     599                           case State.Token: 
     600                                if (! isalnum (c)) 
     601                                   { 
     602                                   setValue (i); 
     603                                   --i; 
     604                                   } 
     605                                continue; 
     606 
     607                           // scan until the next ' 
     608                           case State.SQuote: 
     609                                if (c is '\'') 
     610                                    ++mark, setValue (i); 
     611                                continue; 
     612 
     613                           // scan until the next " 
     614                           case State.DQuote: 
     615                                if (c is '"') 
     616                                    ++mark, setValue (i); 
     617                                continue; 
     618 
     619                           default: 
     620                                continue; 
     621                           } 
     622                    } 
     623 
     624                // we ran out of content; patch partial cookie values  
     625                if (state is State.Token) 
     626                    setValue (content.length); 
     627 
     628                // go home 
     629                return IConduit.Eof; 
     630        } 
     631                                 
    492632        /*********************************************************************** 
    493633         
     
    508648        ***********************************************************************/ 
    509649 
    510         bool next (IBuffer buffer, CookieStack stack) 
    511         { 
    512                 /*************************************************************** 
    513  
    514                         callback from Scanner.next(). We scan for name-value 
    515                         pairs, populating Cookie instances along the way. 
    516  
    517                 ***************************************************************/ 
    518  
    519                 uint scan (char[] content) 
    520                 {       
    521                         char    c; 
    522                         int     mark, 
    523                                 vrsn; 
    524                         char[]  name, 
    525                                 token; 
    526                         Cookie  cookie; 
    527                         State   state = State.Begin; 
    528                          
    529                         /******************************************************* 
    530  
    531                                 Found a value; set that also 
    532  
    533                         *******************************************************/ 
    534  
    535                         void setValue (int i) 
    536                         {    
    537                                 token = content [mark..i]; 
    538                                 //printf ("::name '%.*s'\n", name); 
    539                                 //printf ("::value '%.*s'\n", token); 
    540  
    541                                 if (name[0] != '$') 
    542                                    { 
    543                                    cookie = stack.push(); 
    544                                    cookie.setName (name); 
    545                                    cookie.setValue (token); 
    546                                    cookie.setVersion (vrsn); 
    547                                    } 
    548                                 else 
    549                                    switch (toLower (name)) 
    550                                           { 
    551                                           case "$path": 
    552                                                 if (cookie) 
    553                                                     cookie.setPath (token);  
    554                                                 break; 
    555  
    556                                           case "$domain": 
    557                                                 if (cookie) 
    558                                                     cookie.setDomain (token);  
    559                                                 break; 
    560  
    561                                           case "$version": 
    562                                                 vrsn = cast(int) Integer.parse (token);  
    563                                                 break; 
    564  
    565                                           default: 
    566                                                break; 
    567                                           } 
    568                                 state = State.Begin; 
    569                         } 
    570  
    571                         /******************************************************* 
    572  
    573                                 Scan content looking for cookie fields 
    574  
    575                         *******************************************************/ 
    576  
    577                         for (int i; i < content.length; ++i) 
    578                             { 
    579                             c = content [i]; 
    580                             switch (state) 
    581                                    { 
    582                                    // look for an lValue 
    583                                    case State.Begin: 
    584                                         mark = i; 
    585                                         if (isalpha (c) || c == '$') 
    586                                             state = State.LValue; 
    587                                         continue; 
    588  
    589                                    // scan until we have all lValue chars 
    590                                    case State.LValue: 
    591                                         if (! isalnum (c)) 
    592                                            { 
    593                                            state = State.Equals; 
    594                                            name = content [mark..i]; 
    595                                            --i; 
    596                                            } 
    597                                         continue; 
    598  
    599                                    // should now have either a '=', ';', or ',' 
    600                                    case State.Equals: 
    601                                         if (c == '=') 
    602                                             state = State.RValue; 
    603                                         else 
    604                                            if (c == ',' || c == ';') 
    605                                                // get next NVPair 
    606                                                state = State.Begin; 
    607                                         continue; 
    608  
    609                                    // look for a quoted token, or a plain one 
    610                                    case State.RValue: 
    611                                         mark = i; 
    612                                         if (c == '\'') 
    613                                             state = State.SQuote; 
    614                                         else 
    615                                            if (c == '"') 
    616                                                state = State.DQuote; 
    617                                            else 
    618                                               if (isalpha (c)) 
    619                                                   state = State.Token; 
    620                                         continue; 
    621  
    622                                    // scan for all plain token chars 
    623                                    case State.Token: 
    624                                         if (! isalnum (c)) 
    625                                            { 
    626                                            setValue (i); 
    627                                            --i; 
    628                                            } 
    629                                         continue; 
    630  
    631                                    // scan until the next ' 
    632                                    case State.SQuote: 
    633                                         if (c == '\'') 
    634                                             ++mark, setValue (i); 
    635                                         continue; 
    636  
    637                                    // scan until the next " 
    638                                    case State.DQuote: 
    639                                         if (c == '"') 
    640                                             ++mark, setValue (i); 
    641                                         continue; 
    642  
    643                                    default: 
    644                                         continue; 
    645                                    } 
    646                             } 
    647  
    648                         // we ran out of content; patch partial cookie values  
    649                         if (state == State.Token) 
    650                             setValue (content.length); 
    651                          
    652                         // go home 
    653                         return IConduit.Eof; 
    654                 } 
    655  
    656                 return super.next (buffer, &scan); 
    657         } 
    658  
     650        bool parse (char[] header) 
     651        { 
     652                super.set (header); 
     653                return next (); 
     654        } 
    659655 
    660656        /********************************************************************** 
  • trunk/mango/http/server/HttpHeaders.d

    r609 r753  
    3939module mango.http.server.HttpHeaders; 
    4040 
    41 private import  mango.io.Token, 
    42                 mango.io.Tokenizer; 
     41private import  mango.text.LineIterator; 
    4342 
    4443private import  mango.io.model.IBuffer, 
     
    153152class HttpHeaders : HttpTokens 
    154153{ 
    155         private static BoundToken line; 
    156  
    157154        // tell compiler to used super.parse() also 
    158155        alias HttpTokens.parse parse; 
    159156 
    160         /********************************************************************** 
    161                  
    162                 Setup a line tokenizer for later use 
    163            
    164         **********************************************************************/ 
    165  
    166         static this () 
    167         { 
    168                 // have to make our own LineTokenizer since we can't  
    169                 // depend upon the static Tokenizer.line to be 'live' 
    170                 // before we're invoked here. 
    171                 line = new BoundToken (new LineTokenizer()); 
    172         } 
     157        private LineIterator line; 
    173158 
    174159        /********************************************************************** 
     
    184169                // part of the name whilst iterating 
    185170                super (':', true); 
     171 
     172                // construct a line tokenizer for later usage 
     173                line = new LineIterator; 
    186174        } 
    187175 
     
    218206        { 
    219207                setParsed (true); 
    220                 while (line.next(input) && line.getLength()) 
    221                        stack.push(line); 
     208                line.set (input); 
     209 
     210                while (line.next && line.get.length) 
     211                       stack.push (line.get); 
    222212        } 
    223213 
  • trunk/mango/http/server/HttpParams.d

    r609 r753  
    3939module mango.http.server.HttpParams; 
    4040 
    41 private import  mango.io.Token, 
    42                 mango.io.Tokenizer; 
     41private import  mango.io.model.IBuffer; 
    4342 
    44 private import  mango.io.model.IBuffer; 
     43private import  mango.text.SimpleIterator; 
    4544 
    4645private import  mango.http.server.HttpTokens; 
     
    6160class HttpParams : HttpTokens 
    6261{ 
    63         private static BoundToken amp; 
    64  
    6562        // tell compiler to used super.parse() also 
    6663        alias HttpTokens.parse parse; 
    6764 
    68         /********************************************************************** 
    69                  
    70                 Setup a token for extracting each query construct 
    71  
    72         **********************************************************************/ 
    73  
    74         static this () 
    75         { 
    76                 amp = new BoundToken (new SimpleTokenizer('&')); 
    77         } 
     65        private SimpleIterator amp; 
    7866 
    7967        /********************************************************************** 
     
    8775        { 
    8876                super ('='); 
     77 
     78                // construct a line tokenizer for later usage 
     79                amp = new SimpleIterator ("&"); 
    8980        } 
    9081 
     
    121112        { 
    122113                setParsed (true); 
    123                 while (amp.next(input) || amp.getLength()) 
    124                        stack.push (amp); 
     114                amp.set (input); 
     115 
     116                while (amp.next || amp.get.length) 
     117                       stack.push (amp.get); 
    125118        } 
    126119} 
  • trunk/mango/http/server/HttpRequest.d

    r726 r753  
    3939module mango.http.server.HttpRequest; 
    4040 
    41 private import  mango.text.Text; 
     41private import  mango.text.Text, 
     42                mango.text.LineIterator; 
    4243 
    4344private import  mango.convert.Atoi; 
    4445 
    4546private import  mango.io.Uri, 
    46                 mango.io.Token, 
    4747                mango.io.Buffer, 
    4848                mango.io.Reader, 
    4949                mango.io.Socket, 
    50                 mango.io.Exception, 
    51                 mango.io.Tokenizer; 
     50                mango.io.Exception; 
    5251 
    5352private import  mango.io.model.IBuffer, 
     
    8281        // these are per-thread instances also 
    8382        private MutableUri              uri; 
    84         private CompositeToken          line; 
     83        private LineIterator            line; 
    8584        private HttpReader              reader; 
    8685        private HttpQueryParams         params; 
    8786        private HttpCookies             cookies; 
    8887        private StartLine               startLine; 
    89                  
     88 
    9089        static private InvalidStateException InvalidState; 
    9190 
     
    112111        this (IProviderBridge bridge) 
    113112        { 
    114                 IBuffer buffer; 
    115  
    116113                super (bridge, null); 
    117                 buffer = super.getBuffer(); 
    118114                 
    119115                // workspace for parsing the request URI 
    120                 uri = new MutableUri();  
     116                uri = new MutableUri;  
    121117 
    122118                // HTTP request start-line (e.g. "GET / HTTP/1.1")       
    123                 startLine = new StartLine()
     119                startLine = new StartLine
    124120 
    125121                // input parameters, parsed from the query string 
    126                 params = new HttpQueryParams ()
     122                params = new HttpQueryParams
    127123 
    128124                // Convenience reader. Typically used for POST requests 
    129                 reader = new HttpReader (buffer); 
     125                reader = new HttpReader (super.getBuffer); 
     126         
     127                // construct a line tokenizer 
     128                line = new LineIterator; 
    130129 
    131130                // Cookie parser. This is a wrapper around the Headers 
    132                 cookies = new HttpCookies (getHeader()); 
    133  
    134                 // Token for initial parsing of input header lines 
    135                 line = new CompositeToken (Tokenizers.line, buffer); 
     131                cookies = new HttpCookies (getHeader); 
    136132        } 
    137133 
     
    177173                if (! uried) 
    178174                   { 
    179                    uri.parse (startLine.getPath()); 
     175                   uri.parse (startLine.getPath); 
    180176                   if (uri.getScheme() is null) 
    181                        uri.setScheme (getServerScheme()); 
     177                       uri.setScheme (getServerScheme); 
    182178                   uried = true; 
    183179                   } 
     
    251247        { 
    252248                // parse Query or Post parameters 
    253                 if (! params.isParsed ()
     249                if (! params.isParsed
    254250                   { 
    255                    char[] query = getRequestUri().getQuery(); 
     251                   char[] query = getRequestUri.getQuery(); 
    256252 
    257253                   // do we have a query string? 
     
    321317        { 
    322318                IBuffer input = super.getBuffer(); 
     319                line.set (input); 
    323320 
    324321                // skip any blank lines 
    325                 while (line.next() && line.getLength() == 0)  
     322                while (line.next && line.get.length is 0)  
    326323                      {} 
    327324 
     
    331328                     
    332329                // load HTTP request 
    333                 startLine.parse (line.toString()); 
     330                startLine.parse (line.get); 
    334331 
    335332                // populate headers 
  • trunk/mango/http/server/HttpTokens.d

    r692 r753  
    4141private import  mango.text.Text; 
    4242 
    43 private import  mango.io.Token, 
    44                 mango.io.Buffer, 
    45                 mango.io.Tokenizer; 
     43private import  mango.io.Buffer; 
    4644 
    4745private import  mango.convert.Integer, 
  • trunk/mango/http/utils/TokenStack.d

    r609 r753  
    3939module mango.http.utils.TokenStack; 
    4040 
    41 private import  mango.io.Token, 
    42                 mango.io.Exception; 
     41private import  mango.io.Exception; 
    4342 
    4443/****************************************************************************** 
     
    5857        extern (C) int strncasecmp (char *, char*, uint); 
    5958        } 
     59 
     60 
     61/****************************************************************************** 
     62 
     63        Internal representation of a token 
     64 
     65******************************************************************************/ 
     66 
     67class Token 
     68{ 
     69        private char[] value; 
     70 
     71        Token set (char[] value) 
     72        { 
     73                this.value = value; 
     74                return this; 
     75        } 
     76 
     77        char[] toString () 
     78        { 
     79                return value; 
     80        } 
     81} 
    6082 
    6183/****************************************************************************** 
     
    163185 
    164186        final int size () 
    165         { 
     187        {        
    166188                return depth; 
    167189        } 
     
    176198        final Token push (char[] content) 
    177199        { 
    178               return push().set (content);   
     200                return push().set (content);   
    179201        } 
    180202 
     
    188210        final Token push (Token token) 
    189211        { 
    190               return push (token.toString());   
     212                return push (token.toString());   
    191213        } 
    192214 
  • trunk/mango/io/Buffer.d

    r745 r753  
    236236        this (IConduit conduit) 
    237237        { 
    238                 this (conduit.bufferSize()); 
     238                this (conduit.bufferSize); 
    239239                setConduit (conduit); 
     240                this.style = conduit.isTextual ? Text : Binary; 
    240241        } 
    241242 
     
    344345                return this;             
    345346        } 
    346 /+ 
    347         /*********************************************************************** 
    348  
    349                 Overridable method to grow the buffer to the specified size  
    350                 when it becomes full. Default is to not grow at all. 
    351  
    352         ***********************************************************************/ 
    353  
    354         protected bool grow (uint size) 
    355         { 
    356                 return false; 
    357         } 
    358 +/ 
     347 
    359348        /*********************************************************************** 
    360349         
     
    442431                       } 
    443432                    else 
    444                        // try to grow buffer ... 
    445 //                       if (! grow (size)) 
    446                              error (overflow); 
     433                       error (overflow); 
    447434 
    448435                copy (src, size); 
     
    491478        /*********************************************************************** 
    492479         
     480                Support for tokenizing iterators.  
     481                 
     482<