Coverage Report - net.sf.jmatchparser.util.charset.CombinationCharset
 
Classes in this File Line Coverage Branch Coverage Complexity
CombinationCharset
100%
24/24
100%
14/14
3,857
CombinationCharset$Decoder
71%
23/32
62%
10/16
3,857
 
 1  
 /*
 2  
  * Copyright (c) 2010 - 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.CharsetDecoder;
 38  
 import java.nio.charset.CoderResult;
 39  
 import java.util.Map;
 40  
 
 41  7
 class CombinationCharset extends Table8BitCharset {
 42  
 
 43  
         private final String[] combinations;
 44  6
         private char[][] combinationsMap = null;
 45  6
         private float avgCharsPerByte = 0;
 46  
 
 47  
         protected CombinationCharset(String canonicalName, String[] aliases, String mapping, String... combinations) {
 48  6
                 super(canonicalName, aliases, mapping);
 49  6
                 this.combinations = combinations;
 50  6
         }
 51  
 
 52  
         @Override
 53  
         public CharsetDecoder newDecoder() {
 54  2
                 if (combinationsMap == null) {
 55  1
                         combinationsMap = new char[256][];
 56  1
                         int combinationCount = 0;
 57  14
                         for (String combination : combinations) {
 58  13
                                 int first = combination.charAt(0);
 59  13
                                 combinationsMap[first] = combination.substring(1).toCharArray();
 60  3341
                                 for (int i = 1; i < combination.length(); i++) {
 61  3328
                                         if (combination.charAt(i) != '\uFFFD') {
 62  165
                                                 combinationCount++;
 63  
                                         }
 64  
                                 }
 65  
                         }
 66  1
                         avgCharsPerByte = (combinationCount * 1 + (65536 - combinationCount) * 2) / 65536f / 2f;
 67  
                 }
 68  2
                 return new Decoder();
 69  
         }
 70  
 
 71  
         @Override
 72  
         protected void addExtraItemsToEncoderMap(Map<Character, byte[]> encoderMap) {
 73  14
                 for (String combination : combinations) {
 74  13
                         byte first = (byte) combination.charAt(0);
 75  3341
                         for (int i = 1; i < combination.length(); i++) {
 76  3328
                                 char c = combination.charAt(i);
 77  3328
                                 if (c != '\uFFFD') {
 78  165
                                         encoderMap.put(c, new byte[] { first, (byte) (i - 1) });
 79  
                                 }
 80  
                         }
 81  
                 }
 82  1
         }
 83  
 
 84  
         private class Decoder extends CharsetDecoder {
 85  
 
 86  2
                 private int lastByte = -1;
 87  
 
 88  2
                 protected Decoder() {
 89  2
                         super(CombinationCharset.this, avgCharsPerByte, 2);
 90  2
                 }
 91  
 
 92  
                 @Override
 93  
                 protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
 94  
                         while (true) {
 95  8
                                 if (in.remaining() == 0)
 96  3
                                         return CoderResult.UNDERFLOW;
 97  5
                                 if (out.remaining() == 0)
 98  0
                                         return CoderResult.OVERFLOW;
 99  5
                                 int b = in.get() & 0xFF;
 100  5
                                 if (lastByte != -1) {
 101  2
                                         char c = combinationsMap[lastByte][b];
 102  2
                                         if (c == '\uFFFD') {
 103  
                                                 // un-read the last character
 104  0
                                                 in.position(in.position() - 1);
 105  0
                                                 out.put(mapping.charAt(lastByte));
 106  
                                         } else {
 107  2
                                                 out.put(c);
 108  
                                         }
 109  2
                                         lastByte = -1;
 110  2
                                 } else if (combinationsMap[b] != null) {
 111  2
                                         lastByte = b;
 112  
                                 } else {
 113  1
                                         char c = mapping.charAt(b);
 114  1
                                         if (c == '\uFFFD') {
 115  0
                                                 in.position(in.position() - 1);
 116  0
                                                 return CoderResult.unmappableForLength(1);
 117  
                                         }
 118  1
                                         out.put(c);
 119  
                                 }
 120  5
                         }
 121  
                 }
 122  
 
 123  
                 @Override
 124  
                 protected CoderResult implFlush(CharBuffer out) {
 125  2
                         if (lastByte != -1) {
 126  0
                                 if (out.remaining() == 0)
 127  0
                                         return CoderResult.OVERFLOW;
 128  0
                                 out.put(mapping.charAt(lastByte));
 129  0
                                 lastByte = -1;
 130  
                         }
 131  2
                         return super.implFlush(out);
 132  
                 }
 133  
 
 134  
                 @Override
 135  
                 protected void implReset() {
 136  2
                         lastByte = -1;
 137  2
                 }
 138  
         }
 139  
 }