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   ***/
34  
35  public final class ToNetASCIIInputStream extends FilterInputStream
36  {
37      private static final int __NOTHING_SPECIAL = 0;
38      private static final int __LAST_WAS_CR = 1;
39      private static final int __LAST_WAS_NL = 2;
40      private int __status;
41  
42      /***
43       * Creates a ToNetASCIIInputStream instance that wraps an existing
44       * InputStream.
45       * <p>
46       * @param input  The InputStream to wrap.
47       ***/
48      public ToNetASCIIInputStream(InputStream input)
49      {
50          super(input);
51          __status = __NOTHING_SPECIAL;
52      }
53  
54  
55      /***
56       * Reads and returns the next byte in the stream.  If the end of the
57       * message has been reached, returns -1.
58       * <p>
59       * @return The next character in the stream. Returns -1 if the end of the
60       *          stream has been reached.
61       * @exception IOException If an error occurs while reading the underlying
62       *            stream.
63       ***/
64      @Override
65      public int read() throws IOException
66      {
67          int ch;
68  
69          if (__status == __LAST_WAS_NL)
70          {
71              __status = __NOTHING_SPECIAL;
72              return '\n';
73          }
74  
75          ch = in.read();
76  
77          switch (ch)
78          {
79          case '\r':
80              __status = __LAST_WAS_CR;
81              return '\r';
82          case '\n':
83              if (__status != __LAST_WAS_CR)
84              {
85                  __status = __LAST_WAS_NL;
86                  return '\r';
87              }
88              //$FALL-THROUGH$
89          default:
90              __status = __NOTHING_SPECIAL;
91              return ch;
92          }
93          // statement not reached
94          //return ch;
95      }
96  
97  
98      /***
99       * Reads the next number of bytes from the stream into an array and
100      * returns the number of bytes read.  Returns -1 if the end of the
101      * stream has been reached.
102      * <p>
103      * @param buffer  The byte array in which to store the data.
104      * @return The number of bytes read. Returns -1 if the
105      *          end of the message has been reached.
106      * @exception IOException If an error occurs in reading the underlying
107      *            stream.
108      ***/
109     @Override
110     public int read(byte buffer[]) throws IOException
111     {
112         return read(buffer, 0, buffer.length);
113     }
114 
115 
116     /***
117      * Reads the next number of bytes from the stream into an array and returns
118      * the number of bytes read.  Returns -1 if the end of the
119      * message has been reached.  The characters are stored in the array
120      * starting from the given offset and up to the length specified.
121      * <p>
122      * @param buffer The byte array in which to store the data.
123      * @param offset  The offset into the array at which to start storing data.
124      * @param length   The number of bytes to read.
125      * @return The number of bytes read. Returns -1 if the
126      *          end of the stream has been reached.
127      * @exception IOException If an error occurs while reading the underlying
128      *            stream.
129      ***/
130     @Override
131     public int read(byte buffer[], int offset, int length) throws IOException
132     {
133         int ch, off;
134 
135         if (length < 1) {
136             return 0;
137         }
138 
139         ch = available();
140 
141         if (length > ch) {
142             length = ch;
143         }
144 
145         // If nothing is available, block to read only one character
146         if (length < 1) {
147             length = 1;
148         }
149 
150         if ((ch = read()) == -1) {
151             return -1;
152         }
153 
154         off = offset;
155 
156         do
157         {
158             buffer[offset++] = (byte)ch;
159         }
160         while (--length > 0 && (ch = read()) != -1);
161 
162         return (offset - off);
163     }
164 
165     /*** Returns false.  Mark is not supported. ***/
166     @Override
167     public boolean markSupported()
168     {
169         return false;
170     }
171 
172     @Override
173     public int available() throws IOException
174     {
175         int result;
176 
177         result = in.available();
178 
179         if (__status == __LAST_WAS_NL) {
180             return (result + 1);
181         }
182 
183         return result;
184     }
185 }