Home | History | Annotate | Download | only in dec
      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 
     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 {
     51     unpackTransforms(PREFIX_SUFFIX, PREFIX_SUFFIX_HEADS, TRANSFORMS, PREFIX_SUFFIX_SRC,
     52         TRANSFORMS_SRC);
     53   }
     54 
     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