1 /*
   2  * Copyright (c) 2012, 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 jdk.internal.util.xml.impl;
  27 
  28 import java.io.Reader;
  29 import java.io.InputStream;
  30 import java.io.IOException;
  31 
  32 /**
  33  * UTF-16 encoded stream reader.
  34  */
  35 public class ReaderUTF16 extends Reader {
  36 
  37     private InputStream is;
  38     private char bo;
  39 
  40     /**
  41      * Constructor.
  42      *
  43      * Byte order argument can be: 'l' for little-endian or 'b' for big-endian.
  44      *
  45      * @param is A byte input stream.
  46      * @param bo A byte order in the input stream. 
  47      */
  48     public ReaderUTF16(InputStream is, char bo) {
  49         switch (bo) {
  50             case 'l':
  51                 break;
  52 
  53             case 'b':
  54                 break;
  55 
  56             default:
  57                 throw new IllegalArgumentException("");
  58         }
  59         this.bo = bo;
  60         this.is = is;
  61     }
  62 
  63     /**
  64      * Reads characters into a portion of an array.
  65      *
  66      * @param cbuf Destination buffer.
  67      * @param off Offset at which to start storing characters.
  68      * @param len Maximum number of characters to read.
  69      * @exception IOException If any IO errors occur.
  70      */
  71     public int read(char[] cbuf, int off, int len) throws IOException {
  72         int num = 0;
  73         int val;
  74         if (bo == 'b') {
  75             while (num < len) {
  76                 if ((val = is.read()) < 0) {
  77                     return (num != 0) ? num : -1;
  78                 }
  79                 cbuf[off++] = (char) ((val << 8) | (is.read() & 0xff));
  80                 num++;
  81             }
  82         } else {
  83             while (num < len) {
  84                 if ((val = is.read()) < 0) {
  85                     return (num != 0) ? num : -1;
  86                 }
  87                 cbuf[off++] = (char) ((is.read() << 8) | (val & 0xff));
  88                 num++;
  89             }
  90         }
  91         return num;
  92     }
  93 
  94     /**
  95      * Reads a single character.
  96      *
  97      * @return The character read, as an integer in the range 0 to 65535 
  98      *  (0x0000-0xffff), or -1 if the end of the stream has been reached.
  99      * @exception IOException If any IO errors occur.
 100      */
 101     public int read() throws IOException {
 102         int val;
 103         if ((val = is.read()) < 0) {
 104             return -1;
 105         }
 106         if (bo == 'b') {
 107             val = (char) ((val << 8) | (is.read() & 0xff));
 108         } else {
 109             val = (char) ((is.read() << 8) | (val & 0xff));
 110         }
 111         return val;
 112     }
 113 
 114     /**
 115      * Closes the stream.
 116      *
 117      * @exception IOException If any IO errors occur.
 118      */
 119     public void close() throws IOException {
 120         is.close();
 121     }
 122 }