View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util;
20  
21  import java.io.BufferedInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  
25  /**
26   * ReadLineInputStream
27   *
28   * Read from an input stream, accepting CR/LF, LF or just CR.
29   */
30  public class ReadLineInputStream extends BufferedInputStream
31  {
32      boolean _seenCRLF;
33      boolean _skipLF;
34      
35      public ReadLineInputStream(InputStream in)
36      {
37          super(in);
38      }
39  
40      public ReadLineInputStream(InputStream in, int size)
41      {
42          super(in,size);
43      }
44      
45      public String readLine() throws IOException
46      {
47          mark(buf.length);
48                  
49          while (true)
50          {
51              int b=super.read();
52              
53              if (markpos < 0)
54                  throw new IOException("Buffer size exceeded: no line terminator");
55              
56              if (b==-1)
57              {
58                  int m=markpos;
59                  markpos=-1;
60                  if (pos>m)
61                      return new String(buf,m,pos-m,StringUtil.__UTF8_CHARSET);
62  
63                  return null;
64              }
65              
66              if (b=='\r')
67              {
68                  int p=pos;
69                  
70                  // if we have seen CRLF before, hungrily consume LF
71                  if (_seenCRLF && pos<count)
72                  {
73                      if (buf[pos]=='\n')
74                          pos+=1;
75                  }
76                  else
77                      _skipLF=true;
78                  int m=markpos;
79                  markpos=-1;
80                  return new String(buf,m,p-m-1,StringUtil.__UTF8_CHARSET);
81              }
82              
83              if (b=='\n')
84              {
85                  if (_skipLF)
86                  {
87                      _skipLF=false;
88                      _seenCRLF=true;
89                      markpos++;
90                      continue;
91                  }
92                  int m=markpos;
93                  markpos=-1;
94                  return new String(buf,m,pos-m-1,StringUtil.__UTF8_CHARSET);
95              }
96          }
97      }
98  
99      @Override
100     public synchronized int read() throws IOException
101     {
102         int b = super.read();
103         if (_skipLF)
104         {
105             _skipLF=false;
106             if (_seenCRLF && b=='\n')
107                 b=super.read();
108         }
109         return b;
110     }
111 
112     @Override
113     public synchronized int read(byte[] buf, int off, int len) throws IOException
114     {
115         if (_skipLF && len>0)
116         {
117             _skipLF=false;
118             if (_seenCRLF)
119             {
120                 int b = super.read();
121                 if (b==-1)
122                     return -1;
123                 
124                 if (b!='\n')
125                 {
126                     buf[off]=(byte)(0xff&b);
127                     return 1+super.read(buf,off+1,len-1);
128                 }
129             }
130         }
131         
132         return super.read(buf,off,len);
133     }
134     
135     
136 }