View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.io;
19  
20  import java.io.FilterInputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  
24  /***
25   * This class wraps an input stream, replacing all singly occurring
26   * <LF> (linefeed) characters with <CR><LF> (carriage return
27   * followed by linefeed), which is the NETASCII standard for representing
28   * a newline.
29   * You would use this class to implement ASCII file transfers requiring
30   * conversion to NETASCII.
31   * <p>
32   * <p>
33   * @author Daniel F. Savarese
34   ***/
35  
36  public final class ToNetASCIIInputStream extends FilterInputStream
37  {
38      private static final int __NOTHING_SPECIAL = 0;
39      private static final int __LAST_WAS_CR = 1;
40      private static final int __LAST_WAS_NL = 2;
41      private int __status;
42  
43      /***
44       * Creates a ToNetASCIIInputStream instance that wraps an existing
45       * InputStream.
46       * <p>
47       * @param input  The InputStream to .
48       ***/
49      public ToNetASCIIInputStream(InputStream input)
50      {
51          super(input);
52          __status = __NOTHING_SPECIAL;
53      }
54  
55  
56      /***
57       * Reads and returns the next byte in the stream.  If the end of the
58       * message has been reached, returns -1.
59       * <p>
60       * @return The next character in the stream. Returns -1 if the end of the
61       *          stream has been reached.
62       * @exception IOException If an error occurs while reading the underlying
63       *            stream.
64       ***/
65      @Override
66      public int read() throws IOException
67      {
68          int ch;
69  
70          if (__status == __LAST_WAS_NL)
71          {
72              __status = __NOTHING_SPECIAL;
73              return '\n';
74          }
75  
76          ch = in.read();
77  
78          switch (ch)
79          {
80          case '\r':
81              __status = __LAST_WAS_CR;
82              return '\r';
83          case '\n':
84              if (__status != __LAST_WAS_CR)
85              {
86                  __status = __LAST_WAS_NL;
87                  return '\r';
88              }
89              // else fall through
90          default:
91              __status = __NOTHING_SPECIAL;
92              return ch;
93          }
94          // statement not reached
95          //return ch;
96      }
97  
98  
99      /***
100      * Reads the next number of bytes from the stream into an array and
101      * returns the number of bytes read.  Returns -1 if the end of the
102      * stream has been reached.
103      * <p>
104      * @param buffer  The byte array in which to store the data.
105      * @return The number of bytes read. Returns -1 if the
106      *          end of the message has been reached.
107      * @exception IOException If an error occurs in reading the underlying
108      *            stream.
109      ***/
110     @Override
111     public int read(byte buffer[]) throws IOException
112     {
113         return read(buffer, 0, buffer.length);
114     }
115 
116 
117     /***
118      * Reads the next number of bytes from the stream into an array and returns
119      * the number of bytes read.  Returns -1 if the end of the
120      * message has been reached.  The characters are stored in the array
121      * starting from the given offset and up to the length specified.
122      * <p>
123      * @param buffer The byte array in which to store the data.
124      * @param offset  The offset into the array at which to start storing data.
125      * @param length   The number of bytes to read.
126      * @return The number of bytes read. Returns -1 if the
127      *          end of the stream has been reached.
128      * @exception IOException If an error occurs while reading the underlying
129      *            stream.
130      ***/
131     @Override
132     public int read(byte buffer[], int offset, int length) throws IOException
133     {
134         int ch, off;
135 
136         if (length < 1)
137             return 0;
138 
139         ch = available();
140 
141         if (length > ch)
142             length = ch;
143 
144         // If nothing is available, block to read only one character
145         if (length < 1)
146             length = 1;
147 
148         if ((ch = read()) == -1)
149             return -1;
150 
151         off = offset;
152 
153         do
154         {
155             buffer[offset++] = (byte)ch;
156         }
157         while (--length > 0 && (ch = read()) != -1);
158 
159         return (offset - off);
160     }
161 
162     /*** Returns false.  Mark is not supported. ***/
163     @Override
164     public boolean markSupported()
165     {
166         return false;
167     }
168 
169     @Override
170     public int available() throws IOException
171     {
172         int result;
173 
174         result = in.available();
175 
176         if (__status == __LAST_WAS_NL)
177             return (result + 1);
178 
179         return result;
180     }
181 }