Coverage Report - org.ini4j.spi.UnicodeInputStreamReader
 
Classes in this File Line Coverage Branch Coverage Complexity
UnicodeInputStreamReader
100%
23/23
83%
5/6
2.25
UnicodeInputStreamReader$Bom
92%
24/26
83%
10/12
2.25
 
 1  
 /*
 2  
  * Copyright 2005,2009 Ivan SZKIBA
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.ini4j.spi;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.InputStream;
 20  
 import java.io.InputStreamReader;
 21  
 import java.io.PushbackInputStream;
 22  
 import java.io.Reader;
 23  
 
 24  
 import java.nio.charset.Charset;
 25  
 
 26  
 class UnicodeInputStreamReader extends Reader
 27  
 {
 28  
     private static final int BOM_SIZE = 4;
 29  
 
 30  129
     private static enum Bom
 31  
     {
 32  1
         UTF32BE("UTF-32BE", new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xFE, (byte) 0xFF }),
 33  1
         UTF32LE("UTF-32LE", new byte[] { (byte) 0xFF, (byte) 0xFE, (byte) 0x00, (byte) 0x00 }),
 34  1
         UTF16BE("UTF-16BE", new byte[] { (byte) 0xFE, (byte) 0xFF }),
 35  1
         UTF16LE("UTF-16LE", new byte[] { (byte) 0xFF, (byte) 0xFE }),
 36  1
         UTF8("UTF-8", new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF });
 37  
         private final byte[] _bytes;
 38  
         private Charset _charset;
 39  
 
 40  
         @SuppressWarnings("PMD.ArrayIsStoredDirectly")
 41  
         private Bom(String charsetName, byte[] bytes)
 42  5
         {
 43  
             try
 44  
             {
 45  5
                 _charset = Charset.forName(charsetName);
 46  
             }
 47  0
             catch (Exception x)
 48  
             {
 49  0
                 _charset = null;
 50  5
             }
 51  
 
 52  5
             _bytes = bytes;
 53  5
         }
 54  
 
 55  
         private static Bom find(byte[] data)
 56  
         {
 57  55
             Bom ret = null;
 58  
 
 59  312
             for (Bom bom : values())
 60  
             {
 61  266
                 if (bom.supported() && bom.match(data))
 62  
                 {
 63  9
                     ret = bom;
 64  
 
 65  9
                     break;
 66  
                 }
 67  
             }
 68  
 
 69  55
             return ret;
 70  
         }
 71  
 
 72  
         private boolean match(byte[] data)
 73  
         {
 74  266
             boolean ok = true;
 75  
 
 76  294
             for (int i = 0; i < _bytes.length; i++)
 77  
             {
 78  285
                 if (data[i] != _bytes[i])
 79  
                 {
 80  257
                     ok = false;
 81  
 
 82  257
                     break;
 83  
                 }
 84  
             }
 85  
 
 86  266
             return ok;
 87  
         }
 88  
 
 89  
         private boolean supported()
 90  
         {
 91  266
             return _charset != null;
 92  
         }
 93  
     }
 94  
 
 95  
     private final Charset _defaultEncoding;
 96  
     private InputStreamReader _reader;
 97  
     private final PushbackInputStream _stream;
 98  
 
 99  
     UnicodeInputStreamReader(InputStream in, Charset defaultEnc)
 100  55
     {
 101  55
         _stream = new PushbackInputStream(in, BOM_SIZE);
 102  55
         _defaultEncoding = defaultEnc;
 103  55
     }
 104  
 
 105  
     public void close() throws IOException
 106  
     {
 107  43
         init();
 108  43
         _reader.close();
 109  43
     }
 110  
 
 111  
     public int read(char[] cbuf, int off, int len) throws IOException
 112  
     {
 113  100
         init();
 114  
 
 115  100
         return _reader.read(cbuf, off, len);
 116  
     }
 117  
 
 118  
     /**
 119  
      * Read-ahead four bytes and check for BOM marks. Extra bytes are
 120  
      * unread back to the stream, only BOM bytes are skipped.
 121  
      */
 122  
     protected void init() throws IOException
 123  
     {
 124  143
         if (_reader != null)
 125  
         {
 126  88
             return;
 127  
         }
 128  
 
 129  
         Charset encoding;
 130  55
         byte[] data = new byte[BOM_SIZE];
 131  
         int n;
 132  
         int unread;
 133  
 
 134  55
         n = _stream.read(data, 0, data.length);
 135  55
         Bom bom = Bom.find(data);
 136  
 
 137  55
         if (bom == null)
 138  
         {
 139  46
             encoding = _defaultEncoding;
 140  46
             unread = n;
 141  
         }
 142  
         else
 143  
         {
 144  9
             encoding = bom._charset;
 145  9
             unread = data.length - bom._bytes.length;
 146  
         }
 147  
 
 148  55
         if (unread > 0)
 149  
         {
 150  55
             _stream.unread(data, (n - unread), unread);
 151  
         }
 152  
 
 153  55
         _reader = new InputStreamReader(_stream, encoding);
 154  55
     }
 155  
 }