1 /* Copyright 2015 Google Inc. All Rights Reserved. 2 3 Distributed under MIT license. 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 */ 6 7 package org.brotli.dec; 8 9 import java.nio.ByteBuffer; 10 11 /** 12 * Transformations on dictionary words. 13 */ 14 final class Transform { 15 16 static final int NUM_TRANSFORMS = 121; 17 private static final int[] TRANSFORMS = new int[NUM_TRANSFORMS * 3]; 18 private static final byte[] PREFIX_SUFFIX = new byte[217]; 19 private static final int[] PREFIX_SUFFIX_HEADS = new int[51]; 20 21 // Bundle of 0-terminated strings. 22 private static final String PREFIX_SUFFIX_SRC = "# #s #, #e #.# the #.com/#\u00C2\u00A0# of # and" 23 + " # in # to #\"#\">#\n#]# for # a # that #. # with #'# from # by #. The # on # as # is #ing" 24 + " #\n\t#:#ed #(# at #ly #=\"# of the #. This #,# not #er #al #='#ful #ive #less #est #ize #" 25 + "ous #"; 26 private static final String TRANSFORMS_SRC = " !! ! , *! &! \" ! ) * * - ! # ! #!*! " 27 + "+ ,$ ! - % . / # 0 1 . \" 2 3!* 4% ! # / 5 6 7 8 0 1 & $ 9 + : " 28 + " ; < ' != > ?! 4 @ 4 2 & A *# ( B C& ) % ) !*# *-% A +! *. D! %' & E *6 F " 29 + " G% ! *A *% H! D I!+! J!+ K +- *4! A L!*4 M N +6 O!*% +.! K *G P +%( ! G *D +D " 30 + " Q +# *K!*G!+D!+# +G +A +4!+% +K!+4!*D!+K!*K"; 31 unpackTransforms(byte[] prefixSuffix, int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc)32 private static void unpackTransforms(byte[] prefixSuffix, int[] prefixSuffixHeads, 33 int[] transforms, String prefixSuffixSrc, String transformsSrc) { 34 int n = prefixSuffixSrc.length(); 35 int index = 1; 36 for (int i = 0; i < n; ++i) { 37 char c = prefixSuffixSrc.charAt(i); 38 prefixSuffix[i] = (byte) c; 39 if (c == 35) { // == # 40 prefixSuffixHeads[index++] = i + 1; 41 prefixSuffix[i] = 0; 42 } 43 } 44 45 for (int i = 0; i < NUM_TRANSFORMS * 3; ++i) { 46 transforms[i] = transformsSrc.charAt(i) - 32; 47 } 48 } 49 50 static { unpackTransforms(PREFIX_SUFFIX, PREFIX_SUFFIX_HEADS, TRANSFORMS, PREFIX_SUFFIX_SRC, TRANSFORMS_SRC)51 unpackTransforms(PREFIX_SUFFIX, PREFIX_SUFFIX_HEADS, TRANSFORMS, PREFIX_SUFFIX_SRC, 52 TRANSFORMS_SRC); 53 } 54 transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer data, int wordOffset, int len, int transformIndex)55 static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer data, int wordOffset, 56 int len, int transformIndex) { 57 int offset = dstOffset; 58 int transformOffset = 3 * transformIndex; 59 int transformPrefix = PREFIX_SUFFIX_HEADS[TRANSFORMS[transformOffset]]; 60 int transformType = TRANSFORMS[transformOffset + 1]; 61 int transformSuffix = PREFIX_SUFFIX_HEADS[TRANSFORMS[transformOffset + 2]]; 62 63 // Copy prefix. 64 while (PREFIX_SUFFIX[transformPrefix] != 0) { 65 dst[offset++] = PREFIX_SUFFIX[transformPrefix++]; 66 } 67 68 // Copy trimmed word. 69 int omitFirst = transformType >= 12 ? (transformType - 11) : 0; 70 if (omitFirst > len) { 71 omitFirst = len; 72 } 73 wordOffset += omitFirst; 74 len -= omitFirst; 75 len -= transformType <= 9 ? transformType : 0; // Omit last. 76 int i = len; 77 while (i > 0) { 78 dst[offset++] = data.get(wordOffset++); 79 i--; 80 } 81 82 // Ferment. 83 if (transformType == 11 || transformType == 10) { 84 int uppercaseOffset = offset - len; 85 if (transformType == 10) { 86 len = 1; 87 } 88 while (len > 0) { 89 int tmp = dst[uppercaseOffset] & 0xFF; 90 if (tmp < 0xc0) { 91 if (tmp >= 97 && tmp <= 122) { // in [a..z] range 92 dst[uppercaseOffset] ^= (byte) 32; 93 } 94 uppercaseOffset += 1; 95 len -= 1; 96 } else if (tmp < 0xe0) { 97 dst[uppercaseOffset + 1] ^= (byte) 32; 98 uppercaseOffset += 2; 99 len -= 2; 100 } else { 101 dst[uppercaseOffset + 2] ^= (byte) 5; 102 uppercaseOffset += 3; 103 len -= 3; 104 } 105 } 106 } 107 108 // Copy suffix. 109 while (PREFIX_SUFFIX[transformSuffix] != 0) { 110 dst[offset++] = PREFIX_SUFFIX[transformSuffix++]; 111 } 112 113 return offset - dstOffset; 114 } 115 } 116