Coverage Report - net.sf.jmatchparser.util.charset.Table8BitCharset
 
Classes in this File Line Coverage Branch Coverage Complexity
Table8BitCharset
63%
26/41
33%
10/30
3,875
Table8BitCharset$Decoder
76%
10/13
66%
4/6
3,875
 
 1  
 /*
 2  
  * Copyright (c) 2009 - 2011 Michael Schierl
 3  
  * 
 4  
  * All rights reserved.
 5  
  * 
 6  
  * Redistribution and use in source and binary forms, with or without
 7  
  * modification, are permitted provided that the following conditions
 8  
  * are met:
 9  
  * 
 10  
  * - Redistributions of source code must retain the above copyright notice,
 11  
  *   this list of conditions and the following disclaimer.
 12  
  *   
 13  
  * - Redistributions in binary form must reproduce the above copyright
 14  
  *   notice, this list of conditions and the following disclaimer in the
 15  
  *   documentation and/or other materials provided with the distribution.
 16  
  *   
 17  
  * - Neither name of the copyright holders nor the names of its
 18  
  *   contributors may be used to endorse or promote products derived from
 19  
  *   this software without specific prior written permission.
 20  
  *   
 21  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND THE CONTRIBUTORS
 22  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 23  
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 24  
  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 25  
  * HOLDERS OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 26  
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 27  
  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 28  
  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 29  
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 30  
  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 31  
  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32  
  */
 33  
 package net.sf.jmatchparser.util.charset;
 34  
 
 35  
 import java.nio.ByteBuffer;
 36  
 import java.nio.CharBuffer;
 37  
 import java.nio.charset.Charset;
 38  
 import java.nio.charset.CharsetDecoder;
 39  
 import java.nio.charset.CharsetEncoder;
 40  
 import java.nio.charset.CoderResult;
 41  
 import java.util.Arrays;
 42  
 import java.util.HashMap;
 43  
 import java.util.Map;
 44  
 
 45  
 class Table8BitCharset extends Charset {
 46  
 
 47  
         protected final String mapping;
 48  151
         private Map<Character, byte[]> encoderMap = null;
 49  151
         private float avgBytesPerChar = 0, maxBytesPerChar = 0;
 50  151
         private byte[] replacement = null;
 51  
 
 52  
         protected Table8BitCharset(String canonicalName, String[] aliases, String mapping) {
 53  151
                 super(canonicalName, aliases);
 54  151
                 this.mapping = mapping;
 55  151
         }
 56  
 
 57  
         @Override
 58  
         public boolean contains(Charset cs) {
 59  0
                 return cs == this;
 60  
         }
 61  
 
 62  
         @Override
 63  
         public CharsetDecoder newDecoder() {
 64  4
                 return new Decoder();
 65  
         }
 66  
 
 67  
         @Override
 68  
         public CharsetEncoder newEncoder() {
 69  3
                 if (encoderMap == null) {
 70  3
                         encoderMap = new HashMap<Character, byte[]>();
 71  771
                         for (int i = 0; i < 256; i++) {
 72  768
                                 char c = mapping.charAt(i);
 73  768
                                 if (c != '\uFFFD') {
 74  500
                                         encoderMap.put(c, new byte[] { (byte) i });
 75  
                                 }
 76  
                         }
 77  3
                         addExtraItemsToEncoderMap(encoderMap);
 78  3
                         int sumLength = 0, count = 0;
 79  3
                         for (byte[] value : encoderMap.values()) {
 80  685
                                 if (value.length > maxBytesPerChar)
 81  4
                                         maxBytesPerChar = value.length;
 82  685
                                 count++;
 83  685
                                 sumLength += value.length;
 84  
                         }
 85  3
                         avgBytesPerChar = sumLength / (float) count;
 86  3
                         replacement = findReplacement();
 87  
                 }
 88  3
                 return new MapBasedEncoder(this, encoderMap, avgBytesPerChar, maxBytesPerChar, replacement);
 89  
         }
 90  
 
 91  
         private byte[] findReplacement() {
 92  3
                 byte[] replacement = new byte[] { (byte) '?' };
 93  3
                 if (Arrays.equals(encoderMap.get('?'), replacement))
 94  3
                         return replacement;
 95  0
                 for (byte[] value : encoderMap.values()) {
 96  0
                         if (Arrays.equals(value, replacement))
 97  0
                                 return replacement;
 98  
                 }
 99  0
                 replacement = encoderMap.get('?');
 100  0
                 if (replacement == null) {
 101  0
                         for (byte[] value : encoderMap.values()) {
 102  0
                                 if (replacement == null)
 103  0
                                         replacement = value;
 104  0
                                 else if (value.length < replacement.length)
 105  0
                                         replacement = value;
 106  0
                                 else if (value.length == replacement.length && value[0] > replacement[0])
 107  0
                                         replacement = value;
 108  
                         }
 109  
                 }
 110  0
                 return replacement;
 111  
         }
 112  
 
 113  
         protected void addExtraItemsToEncoderMap(Map<Character, byte[]> encoderMap) {
 114  0
         }
 115  
 
 116  
         private class Decoder extends CharsetDecoder {
 117  
 
 118  4
                 protected Decoder() {
 119  4
                         super(Table8BitCharset.this, 1, 1);
 120  4
                 }
 121  
 
 122  
                 @Override
 123  
                 protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
 124  
                         while (true) {
 125  778
                                 if (in.remaining() == 0)
 126  8
                                         return CoderResult.UNDERFLOW;
 127  770
                                 if (out.remaining() == 0)
 128  0
                                         return CoderResult.OVERFLOW;
 129  770
                                 char c = mapping.charAt(in.get() & 0xFF);
 130  770
                                 if (c == '\uFFFD') {
 131  0
                                         in.position(in.position() - 1);
 132  0
                                         return CoderResult.unmappableForLength(1);
 133  
                                 }
 134  770
                                 out.put(c);
 135  770
                         }
 136  
                 }
 137  
         }
 138  
 }