emul/src/main/java/java/io/DataInputStream.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 18 Nov 2012 19:01:38 +0100
branchjavap
changeset 185 d441042e6c11
parent 149 32653a09f0db
permissions -rw-r--r--
Reimplementing readDouble to not depend on too high longs
     1 /*
     2  * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.io;
    27 
    28 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    29 
    30 /**
    31  * A data input stream lets an application read primitive Java data
    32  * types from an underlying input stream in a machine-independent
    33  * way. An application uses a data output stream to write data that
    34  * can later be read by a data input stream.
    35  * <p>
    36  * DataInputStream is not necessarily safe for multithreaded access.
    37  * Thread safety is optional and is the responsibility of users of
    38  * methods in this class.
    39  *
    40  * @author  Arthur van Hoff
    41  * @see     java.io.DataOutputStream
    42  * @since   JDK1.0
    43  */
    44 public
    45 class DataInputStream extends FilterInputStream implements DataInput {
    46 
    47     /**
    48      * Creates a DataInputStream that uses the specified
    49      * underlying InputStream.
    50      *
    51      * @param  in   the specified input stream
    52      */
    53     public DataInputStream(InputStream in) {
    54         super(in);
    55     }
    56 
    57     /**
    58      * working arrays initialized on demand by readUTF
    59      */
    60     private byte bytearr[] = new byte[80];
    61     private char chararr[] = new char[80];
    62 
    63     /**
    64      * Reads some number of bytes from the contained input stream and
    65      * stores them into the buffer array <code>b</code>. The number of
    66      * bytes actually read is returned as an integer. This method blocks
    67      * until input data is available, end of file is detected, or an
    68      * exception is thrown.
    69      *
    70      * <p>If <code>b</code> is null, a <code>NullPointerException</code> is
    71      * thrown. If the length of <code>b</code> is zero, then no bytes are
    72      * read and <code>0</code> is returned; otherwise, there is an attempt
    73      * to read at least one byte. If no byte is available because the
    74      * stream is at end of file, the value <code>-1</code> is returned;
    75      * otherwise, at least one byte is read and stored into <code>b</code>.
    76      *
    77      * <p>The first byte read is stored into element <code>b[0]</code>, the
    78      * next one into <code>b[1]</code>, and so on. The number of bytes read
    79      * is, at most, equal to the length of <code>b</code>. Let <code>k</code>
    80      * be the number of bytes actually read; these bytes will be stored in
    81      * elements <code>b[0]</code> through <code>b[k-1]</code>, leaving
    82      * elements <code>b[k]</code> through <code>b[b.length-1]</code>
    83      * unaffected.
    84      *
    85      * <p>The <code>read(b)</code> method has the same effect as:
    86      * <blockquote><pre>
    87      * read(b, 0, b.length)
    88      * </pre></blockquote>
    89      *
    90      * @param      b   the buffer into which the data is read.
    91      * @return     the total number of bytes read into the buffer, or
    92      *             <code>-1</code> if there is no more data because the end
    93      *             of the stream has been reached.
    94      * @exception  IOException if the first byte cannot be read for any reason
    95      * other than end of file, the stream has been closed and the underlying
    96      * input stream does not support reading after close, or another I/O
    97      * error occurs.
    98      * @see        java.io.FilterInputStream#in
    99      * @see        java.io.InputStream#read(byte[], int, int)
   100      */
   101     public final int read(byte b[]) throws IOException {
   102         return in.read(b, 0, b.length);
   103     }
   104 
   105     /**
   106      * Reads up to <code>len</code> bytes of data from the contained
   107      * input stream into an array of bytes.  An attempt is made to read
   108      * as many as <code>len</code> bytes, but a smaller number may be read,
   109      * possibly zero. The number of bytes actually read is returned as an
   110      * integer.
   111      *
   112      * <p> This method blocks until input data is available, end of file is
   113      * detected, or an exception is thrown.
   114      *
   115      * <p> If <code>len</code> is zero, then no bytes are read and
   116      * <code>0</code> is returned; otherwise, there is an attempt to read at
   117      * least one byte. If no byte is available because the stream is at end of
   118      * file, the value <code>-1</code> is returned; otherwise, at least one
   119      * byte is read and stored into <code>b</code>.
   120      *
   121      * <p> The first byte read is stored into element <code>b[off]</code>, the
   122      * next one into <code>b[off+1]</code>, and so on. The number of bytes read
   123      * is, at most, equal to <code>len</code>. Let <i>k</i> be the number of
   124      * bytes actually read; these bytes will be stored in elements
   125      * <code>b[off]</code> through <code>b[off+</code><i>k</i><code>-1]</code>,
   126      * leaving elements <code>b[off+</code><i>k</i><code>]</code> through
   127      * <code>b[off+len-1]</code> unaffected.
   128      *
   129      * <p> In every case, elements <code>b[0]</code> through
   130      * <code>b[off]</code> and elements <code>b[off+len]</code> through
   131      * <code>b[b.length-1]</code> are unaffected.
   132      *
   133      * @param      b     the buffer into which the data is read.
   134      * @param off the start offset in the destination array <code>b</code>
   135      * @param      len   the maximum number of bytes read.
   136      * @return     the total number of bytes read into the buffer, or
   137      *             <code>-1</code> if there is no more data because the end
   138      *             of the stream has been reached.
   139      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
   140      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
   141      * <code>len</code> is negative, or <code>len</code> is greater than
   142      * <code>b.length - off</code>
   143      * @exception  IOException if the first byte cannot be read for any reason
   144      * other than end of file, the stream has been closed and the underlying
   145      * input stream does not support reading after close, or another I/O
   146      * error occurs.
   147      * @see        java.io.FilterInputStream#in
   148      * @see        java.io.InputStream#read(byte[], int, int)
   149      */
   150     public final int read(byte b[], int off, int len) throws IOException {
   151         return in.read(b, off, len);
   152     }
   153 
   154     /**
   155      * See the general contract of the <code>readFully</code>
   156      * method of <code>DataInput</code>.
   157      * <p>
   158      * Bytes
   159      * for this operation are read from the contained
   160      * input stream.
   161      *
   162      * @param      b   the buffer into which the data is read.
   163      * @exception  EOFException  if this input stream reaches the end before
   164      *             reading all the bytes.
   165      * @exception  IOException   the stream has been closed and the contained
   166      *             input stream does not support reading after close, or
   167      *             another I/O error occurs.
   168      * @see        java.io.FilterInputStream#in
   169      */
   170     public final void readFully(byte b[]) throws IOException {
   171         readFully(b, 0, b.length);
   172     }
   173 
   174     /**
   175      * See the general contract of the <code>readFully</code>
   176      * method of <code>DataInput</code>.
   177      * <p>
   178      * Bytes
   179      * for this operation are read from the contained
   180      * input stream.
   181      *
   182      * @param      b     the buffer into which the data is read.
   183      * @param      off   the start offset of the data.
   184      * @param      len   the number of bytes to read.
   185      * @exception  EOFException  if this input stream reaches the end before
   186      *               reading all the bytes.
   187      * @exception  IOException   the stream has been closed and the contained
   188      *             input stream does not support reading after close, or
   189      *             another I/O error occurs.
   190      * @see        java.io.FilterInputStream#in
   191      */
   192     public final void readFully(byte b[], int off, int len) throws IOException {
   193         if (len < 0)
   194             throw new IndexOutOfBoundsException();
   195         int n = 0;
   196         while (n < len) {
   197             int count = in.read(b, off + n, len - n);
   198             if (count < 0)
   199                 throw new EOFException();
   200             n += count;
   201         }
   202     }
   203 
   204     /**
   205      * See the general contract of the <code>skipBytes</code>
   206      * method of <code>DataInput</code>.
   207      * <p>
   208      * Bytes for this operation are read from the contained
   209      * input stream.
   210      *
   211      * @param      n   the number of bytes to be skipped.
   212      * @return     the actual number of bytes skipped.
   213      * @exception  IOException  if the contained input stream does not support
   214      *             seek, or the stream has been closed and
   215      *             the contained input stream does not support
   216      *             reading after close, or another I/O error occurs.
   217      */
   218     public final int skipBytes(int n) throws IOException {
   219         int total = 0;
   220         int cur = 0;
   221 
   222         while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {
   223             total += cur;
   224         }
   225 
   226         return total;
   227     }
   228 
   229     /**
   230      * See the general contract of the <code>readBoolean</code>
   231      * method of <code>DataInput</code>.
   232      * <p>
   233      * Bytes for this operation are read from the contained
   234      * input stream.
   235      *
   236      * @return     the <code>boolean</code> value read.
   237      * @exception  EOFException  if this input stream has reached the end.
   238      * @exception  IOException   the stream has been closed and the contained
   239      *             input stream does not support reading after close, or
   240      *             another I/O error occurs.
   241      * @see        java.io.FilterInputStream#in
   242      */
   243     public final boolean readBoolean() throws IOException {
   244         int ch = in.read();
   245         if (ch < 0)
   246             throw new EOFException();
   247         return (ch != 0);
   248     }
   249 
   250     /**
   251      * See the general contract of the <code>readByte</code>
   252      * method of <code>DataInput</code>.
   253      * <p>
   254      * Bytes
   255      * for this operation are read from the contained
   256      * input stream.
   257      *
   258      * @return     the next byte of this input stream as a signed 8-bit
   259      *             <code>byte</code>.
   260      * @exception  EOFException  if this input stream has reached the end.
   261      * @exception  IOException   the stream has been closed and the contained
   262      *             input stream does not support reading after close, or
   263      *             another I/O error occurs.
   264      * @see        java.io.FilterInputStream#in
   265      */
   266     public final byte readByte() throws IOException {
   267         int ch = in.read();
   268         if (ch < 0)
   269             throw new EOFException();
   270         return (byte)(ch);
   271     }
   272 
   273     /**
   274      * See the general contract of the <code>readUnsignedByte</code>
   275      * method of <code>DataInput</code>.
   276      * <p>
   277      * Bytes
   278      * for this operation are read from the contained
   279      * input stream.
   280      *
   281      * @return     the next byte of this input stream, interpreted as an
   282      *             unsigned 8-bit number.
   283      * @exception  EOFException  if this input stream has reached the end.
   284      * @exception  IOException   the stream has been closed and the contained
   285      *             input stream does not support reading after close, or
   286      *             another I/O error occurs.
   287      * @see         java.io.FilterInputStream#in
   288      */
   289     public final int readUnsignedByte() throws IOException {
   290         int ch = in.read();
   291         if (ch < 0)
   292             throw new EOFException();
   293         return ch;
   294     }
   295 
   296     /**
   297      * See the general contract of the <code>readShort</code>
   298      * method of <code>DataInput</code>.
   299      * <p>
   300      * Bytes
   301      * for this operation are read from the contained
   302      * input stream.
   303      *
   304      * @return     the next two bytes of this input stream, interpreted as a
   305      *             signed 16-bit number.
   306      * @exception  EOFException  if this input stream reaches the end before
   307      *               reading two bytes.
   308      * @exception  IOException   the stream has been closed and the contained
   309      *             input stream does not support reading after close, or
   310      *             another I/O error occurs.
   311      * @see        java.io.FilterInputStream#in
   312      */
   313     public final short readShort() throws IOException {
   314         int ch1 = in.read();
   315         int ch2 = in.read();
   316         if ((ch1 | ch2) < 0)
   317             throw new EOFException();
   318         return (short)((ch1 << 8) + (ch2 << 0));
   319     }
   320 
   321     /**
   322      * See the general contract of the <code>readUnsignedShort</code>
   323      * method of <code>DataInput</code>.
   324      * <p>
   325      * Bytes
   326      * for this operation are read from the contained
   327      * input stream.
   328      *
   329      * @return     the next two bytes of this input stream, interpreted as an
   330      *             unsigned 16-bit integer.
   331      * @exception  EOFException  if this input stream reaches the end before
   332      *             reading two bytes.
   333      * @exception  IOException   the stream has been closed and the contained
   334      *             input stream does not support reading after close, or
   335      *             another I/O error occurs.
   336      * @see        java.io.FilterInputStream#in
   337      */
   338     public final int readUnsignedShort() throws IOException {
   339         int ch1 = in.read();
   340         int ch2 = in.read();
   341         if ((ch1 | ch2) < 0)
   342             throw new EOFException();
   343         return (ch1 << 8) + (ch2 << 0);
   344     }
   345 
   346     /**
   347      * See the general contract of the <code>readChar</code>
   348      * method of <code>DataInput</code>.
   349      * <p>
   350      * Bytes
   351      * for this operation are read from the contained
   352      * input stream.
   353      *
   354      * @return     the next two bytes of this input stream, interpreted as a
   355      *             <code>char</code>.
   356      * @exception  EOFException  if this input stream reaches the end before
   357      *               reading two bytes.
   358      * @exception  IOException   the stream has been closed and the contained
   359      *             input stream does not support reading after close, or
   360      *             another I/O error occurs.
   361      * @see        java.io.FilterInputStream#in
   362      */
   363     public final char readChar() throws IOException {
   364         int ch1 = in.read();
   365         int ch2 = in.read();
   366         if ((ch1 | ch2) < 0)
   367             throw new EOFException();
   368         return (char)((ch1 << 8) + (ch2 << 0));
   369     }
   370 
   371     /**
   372      * See the general contract of the <code>readInt</code>
   373      * method of <code>DataInput</code>.
   374      * <p>
   375      * Bytes
   376      * for this operation are read from the contained
   377      * input stream.
   378      *
   379      * @return     the next four bytes of this input stream, interpreted as an
   380      *             <code>int</code>.
   381      * @exception  EOFException  if this input stream reaches the end before
   382      *               reading four bytes.
   383      * @exception  IOException   the stream has been closed and the contained
   384      *             input stream does not support reading after close, or
   385      *             another I/O error occurs.
   386      * @see        java.io.FilterInputStream#in
   387      */
   388     public final int readInt() throws IOException {
   389         int ch1 = in.read();
   390         int ch2 = in.read();
   391         int ch3 = in.read();
   392         int ch4 = in.read();
   393         if ((ch1 | ch2 | ch3 | ch4) < 0)
   394             throw new EOFException();
   395         return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
   396     }
   397 
   398     private byte readBuffer[] = new byte[8];
   399 
   400     /**
   401      * See the general contract of the <code>readLong</code>
   402      * method of <code>DataInput</code>.
   403      * <p>
   404      * Bytes
   405      * for this operation are read from the contained
   406      * input stream.
   407      *
   408      * @return     the next eight bytes of this input stream, interpreted as a
   409      *             <code>long</code>.
   410      * @exception  EOFException  if this input stream reaches the end before
   411      *               reading eight bytes.
   412      * @exception  IOException   the stream has been closed and the contained
   413      *             input stream does not support reading after close, or
   414      *             another I/O error occurs.
   415      * @see        java.io.FilterInputStream#in
   416      */
   417     public final long readLong() throws IOException {
   418         readFully(readBuffer, 0, 8);
   419         return (((long)readBuffer[0] << 56) +
   420                 ((long)(readBuffer[1] & 255) << 48) +
   421                 ((long)(readBuffer[2] & 255) << 40) +
   422                 ((long)(readBuffer[3] & 255) << 32) +
   423                 ((long)(readBuffer[4] & 255) << 24) +
   424                 ((readBuffer[5] & 255) << 16) +
   425                 ((readBuffer[6] & 255) <<  8) +
   426                 ((readBuffer[7] & 255) <<  0));
   427     }
   428 
   429     /**
   430      * See the general contract of the <code>readFloat</code>
   431      * method of <code>DataInput</code>.
   432      * <p>
   433      * Bytes
   434      * for this operation are read from the contained
   435      * input stream.
   436      *
   437      * @return     the next four bytes of this input stream, interpreted as a
   438      *             <code>float</code>.
   439      * @exception  EOFException  if this input stream reaches the end before
   440      *               reading four bytes.
   441      * @exception  IOException   the stream has been closed and the contained
   442      *             input stream does not support reading after close, or
   443      *             another I/O error occurs.
   444      * @see        java.io.DataInputStream#readInt()
   445      * @see        java.lang.Float#intBitsToFloat(int)
   446      */
   447     public final float readFloat() throws IOException {
   448         return Float.intBitsToFloat(readInt());
   449     }
   450 
   451     /**
   452      * See the general contract of the <code>readDouble</code>
   453      * method of <code>DataInput</code>.
   454      * <p>
   455      * Bytes
   456      * for this operation are read from the contained
   457      * input stream.
   458      *
   459      * @return     the next eight bytes of this input stream, interpreted as a
   460      *             <code>double</code>.
   461      * @exception  EOFException  if this input stream reaches the end before
   462      *               reading eight bytes.
   463      * @exception  IOException   the stream has been closed and the contained
   464      *             input stream does not support reading after close, or
   465      *             another I/O error occurs.
   466      * @see        java.io.DataInputStream#readLong()
   467      * @see        java.lang.Double#longBitsToDouble(long)
   468      */
   469     public final double readDouble() throws IOException {
   470         int hi = readInt();
   471         int low = readInt();
   472         return toDouble(hi, low);
   473     }
   474     
   475     @JavaScriptBody(args={ "hi", "low" },
   476         body=
   477           "if (low == 0) {\n"
   478         + "  if (hi === 0x7ff00000) return Number.POSITIVE_INFINITY;\n"
   479         + "  if (hi === 0xfff00000) return Number.NEGATIVE_INFINITY;\n"
   480         + "}\n"
   481         + "if (hi >= 0x7ff00000 && hi <= 0x7fffffff) return Number.NaN;\n"
   482         + "if (hi >= 0xfff00000 && hi <= 0xffffffff) return Number.NaN;\n"
   483         + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n"
   484         + "var e = (hi >> 20) & 0x7ff;\n"
   485         + "var to32 = low >> 0;\n"
   486         + "if (e === 0) {\n"
   487         + "  if (to32 & 0x80000000) {\n"
   488         + "    hi = hi << 1 + 1; low = low << 1;\n"
   489         + "  } else {\n"
   490         + "    hi = hi << 1; low = low << 1;\n"
   491         + "  }\n" 
   492         + "} else {\n"
   493         + "    hi = (hi & 0xfffff) | 0x100000;\n"
   494         + "}\n"
   495         + "to32 = low >> 0;\n"
   496         + "var m = Math.pow(2.0, 32) * hi + to32;\n"
   497         + "var r = s * m * Math.pow(2.0, e - 1075);\n"
   498         + "//throw 'exp: ' + e + ' sign: ' + s + ' hi:' + hi + ' low: ' + low + ' m: ' + m + ' r: ' + r;\n"
   499         + "return r;\n"
   500     )
   501     private static double toDouble(int hi, int low) {
   502         long both = hi;
   503         both = (both << 32) & low;
   504         return Double.doubleToLongBits(both);
   505     }
   506 
   507     private char lineBuffer[];
   508 
   509     /**
   510      * See the general contract of the <code>readLine</code>
   511      * method of <code>DataInput</code>.
   512      * <p>
   513      * Bytes
   514      * for this operation are read from the contained
   515      * input stream.
   516      *
   517      * @deprecated This method does not properly convert bytes to characters.
   518      * As of JDK&nbsp;1.1, the preferred way to read lines of text is via the
   519      * <code>BufferedReader.readLine()</code> method.  Programs that use the
   520      * <code>DataInputStream</code> class to read lines can be converted to use
   521      * the <code>BufferedReader</code> class by replacing code of the form:
   522      * <blockquote><pre>
   523      *     DataInputStream d =&nbsp;new&nbsp;DataInputStream(in);
   524      * </pre></blockquote>
   525      * with:
   526      * <blockquote><pre>
   527      *     BufferedReader d
   528      *          =&nbsp;new&nbsp;BufferedReader(new&nbsp;InputStreamReader(in));
   529      * </pre></blockquote>
   530      *
   531      * @return     the next line of text from this input stream.
   532      * @exception  IOException  if an I/O error occurs.
   533      * @see        java.io.BufferedReader#readLine()
   534      * @see        java.io.FilterInputStream#in
   535      */
   536     @Deprecated
   537     public final String readLine() throws IOException {
   538         char buf[] = lineBuffer;
   539 
   540         if (buf == null) {
   541             buf = lineBuffer = new char[128];
   542         }
   543 
   544         int room = buf.length;
   545         int offset = 0;
   546         int c;
   547 
   548 loop:   while (true) {
   549             switch (c = in.read()) {
   550               case -1:
   551               case '\n':
   552                 break loop;
   553 
   554               case '\r':
   555                 int c2 = in.read();
   556                 if ((c2 != '\n') && (c2 != -1)) {
   557                     if (!(in instanceof PushbackInputStream)) {
   558                         this.in = new PushbackInputStream(in);
   559                     }
   560                     ((PushbackInputStream)in).unread(c2);
   561                 }
   562                 break loop;
   563 
   564               default:
   565                 if (--room < 0) {
   566                     buf = new char[offset + 128];
   567                     room = buf.length - offset - 1;
   568                     arraycopy(lineBuffer, 0, buf, 0, offset);
   569                     lineBuffer = buf;
   570                 }
   571                 buf[offset++] = (char) c;
   572                 break;
   573             }
   574         }
   575         if ((c == -1) && (offset == 0)) {
   576             return null;
   577         }
   578         return String.copyValueOf(buf, 0, offset);
   579     }
   580 
   581     /**
   582      * See the general contract of the <code>readUTF</code>
   583      * method of <code>DataInput</code>.
   584      * <p>
   585      * Bytes
   586      * for this operation are read from the contained
   587      * input stream.
   588      *
   589      * @return     a Unicode string.
   590      * @exception  EOFException  if this input stream reaches the end before
   591      *               reading all the bytes.
   592      * @exception  IOException   the stream has been closed and the contained
   593      *             input stream does not support reading after close, or
   594      *             another I/O error occurs.
   595      * @exception  UTFDataFormatException if the bytes do not represent a valid
   596      *             modified UTF-8 encoding of a string.
   597      * @see        java.io.DataInputStream#readUTF(java.io.DataInput)
   598      */
   599     public final String readUTF() throws IOException {
   600         return readUTF(this);
   601     }
   602 
   603     /**
   604      * Reads from the
   605      * stream <code>in</code> a representation
   606      * of a Unicode  character string encoded in
   607      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a> format;
   608      * this string of characters is then returned as a <code>String</code>.
   609      * The details of the modified UTF-8 representation
   610      * are  exactly the same as for the <code>readUTF</code>
   611      * method of <code>DataInput</code>.
   612      *
   613      * @param      in   a data input stream.
   614      * @return     a Unicode string.
   615      * @exception  EOFException            if the input stream reaches the end
   616      *               before all the bytes.
   617      * @exception  IOException   the stream has been closed and the contained
   618      *             input stream does not support reading after close, or
   619      *             another I/O error occurs.
   620      * @exception  UTFDataFormatException  if the bytes do not represent a
   621      *               valid modified UTF-8 encoding of a Unicode string.
   622      * @see        java.io.DataInputStream#readUnsignedShort()
   623      */
   624     public final static String readUTF(DataInput in) throws IOException {
   625         int utflen = in.readUnsignedShort();
   626         byte[] bytearr = null;
   627         char[] chararr = null;
   628         if (in instanceof DataInputStream) {
   629             DataInputStream dis = (DataInputStream)in;
   630             if (dis.bytearr.length < utflen){
   631                 dis.bytearr = new byte[utflen*2];
   632                 dis.chararr = new char[utflen*2];
   633             }
   634             chararr = dis.chararr;
   635             bytearr = dis.bytearr;
   636         } else {
   637             bytearr = new byte[utflen];
   638             chararr = new char[utflen];
   639         }
   640 
   641         int c, char2, char3;
   642         int count = 0;
   643         int chararr_count=0;
   644 
   645         in.readFully(bytearr, 0, utflen);
   646 
   647         while (count < utflen) {
   648             c = (int) bytearr[count] & 0xff;
   649             if (c > 127) break;
   650             count++;
   651             chararr[chararr_count++]=(char)c;
   652         }
   653 
   654         while (count < utflen) {
   655             c = (int) bytearr[count] & 0xff;
   656             switch (c >> 4) {
   657                 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
   658                     /* 0xxxxxxx*/
   659                     count++;
   660                     chararr[chararr_count++]=(char)c;
   661                     break;
   662                 case 12: case 13:
   663                     /* 110x xxxx   10xx xxxx*/
   664                     count += 2;
   665                     if (count > utflen)
   666                         throw new UTFDataFormatException(
   667                             "malformed input: partial character at end");
   668                     char2 = (int) bytearr[count-1];
   669                     if ((char2 & 0xC0) != 0x80)
   670                         throw new UTFDataFormatException(
   671                             "malformed input around byte " + count);
   672                     chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
   673                                                     (char2 & 0x3F));
   674                     break;
   675                 case 14:
   676                     /* 1110 xxxx  10xx xxxx  10xx xxxx */
   677                     count += 3;
   678                     if (count > utflen)
   679                         throw new UTFDataFormatException(
   680                             "malformed input: partial character at end");
   681                     char2 = (int) bytearr[count-2];
   682                     char3 = (int) bytearr[count-1];
   683                     if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
   684                         throw new UTFDataFormatException(
   685                             "malformed input around byte " + (count-1));
   686                     chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |
   687                                                     ((char2 & 0x3F) << 6)  |
   688                                                     ((char3 & 0x3F) << 0));
   689                     break;
   690                 default:
   691                     /* 10xx xxxx,  1111 xxxx */
   692                     throw new UTFDataFormatException(
   693                         "malformed input around byte " + count);
   694             }
   695         }
   696         // The number of chars produced may be less than utflen
   697         return new String(chararr, 0, chararr_count);
   698     }
   699     static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) {
   700         while (count-- > 0) {
   701             dst[dstBegin++] = value[srcBegin++];
   702         }
   703     }
   704 }