• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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