View Javadoc

    1   /*
    2    * Copyright 2009 Red Hat, Inc.
    3    *
    4    * Red Hat licenses this file to you under the Apache License, version 2.0
    5    * (the "License"); you may not use this file except in compliance with the
    6    * License.  You may obtain a copy of the License at:
    7    *
    8    *    http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  /*
    17  Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
    18
    19  Redistribution and use in source and binary forms, with or without
    20  modification, are permitted provided that the following conditions are met:
    21
    22    1. Redistributions of source code must retain the above copyright notice,
    23       this list of conditions and the following disclaimer.
    24
    25    2. Redistributions in binary form must reproduce the above copyright
    26       notice, this list of conditions and the following disclaimer in
    27       the documentation and/or other materials provided with the distribution.
    28
    29    3. The names of the authors may not be used to endorse or promote products
    30       derived from this software without specific prior written permission.
    31
    32  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    33  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    34  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
    35  INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
    36  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    37  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    38  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    39  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    40  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    41  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    42   */
    43  /*
    44   * This program is based on zlib-1.1.3, so all credit should go authors
    45   * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
    46   * and contributors of zlib.
    47   */
    48
    49  package org.jboss.netty.util.internal.jzlib;
    50
    51  final class InfCodes {
    52
    53      private static final int[] inflate_mask = { 0x00000000, 0x00000001,
    54              0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f,
    55              0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
    56              0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff };
    57
    58      // waiting for "i:"=input,
    59      //             "o:"=output,
    60      //             "x:"=nothing
    61      private static final int START = 0;   // x: set up for LEN
    62      private static final int LEN = 1;     // i: get length/literal/eob next
    63      private static final int LENEXT = 2;  // i: getting length extra (have base)
    64      private static final int DIST = 3;    // i: get distance next
    65      private static final int DISTEXT = 4; // i: getting distance extra
    66      private static final int COPY = 5;    // o: copying bytes in window, waiting for space
    67      private static final int LIT = 6;     // o: got literal, waiting for output space
    68      private static final int WASH = 7;    // o: got eob, possibly still output waiting
    69      private static final int END = 8;     // x: got eob and all data flushed
    70      private static final int BADCODE = 9; // x: got error
    71      private int mode; // current inflate_codes mode
    72      // mode dependent information
    73      private int len;
    74      private int[] tree; // pointer into tree
    75      private int tree_index = 0;
    76      private int need; // bits needed
    77      private int lit;
    78      // if EXT or COPY, where and how much
    79      private int get; // bits to get for extra
    80      private int dist; // distance back to copy from
    81      private byte lbits; // ltree bits decoded per branch
    82      private byte dbits; // dtree bits decoder per branch
    83      private int[] ltree; // literal/length/eob tree
    84      private int ltree_index; // literal/length/eob tree
    85      private int[] dtree; // distance tree
    86      private int dtree_index; // distance tree
    87
    88      InfCodes() {
    89          super();
    90      }
    91
    92      void init(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index) {
    93          mode = START;
    94          lbits = (byte) bl;
    95          dbits = (byte) bd;
    96          ltree = tl;
    97          ltree_index = tl_index;
    98          dtree = td;
    99          dtree_index = td_index;
    100         tree = null;
    101     }
    102
    103     int proc(InfBlocks s, ZStream z, int r) {
    104         int j; // temporary storage
    105         int tindex; // temporary pointer
    106         int e; // extra bits or operation
    107         int b = 0; // bit buffer
    108         int k = 0; // bits in bit buffer
    109         int p = 0; // input data pointer
    110         int n; // bytes available there
    111         int q; // output window write pointer
    112         int m; // bytes to end of window or read pointer
    113         int f; // pointer to copy strings from
    114
    115         // copy input/output information to locals (UPDATE macro restores)
    116         p = z.next_in_index;
    117         n = z.avail_in;
    118         b = s.bitb;
    119         k = s.bitk;
    120         q = s.write;
    121         m = q < s.read? s.read - q - 1 : s.end - q;
    122
    123         // process input and output based on current state
    124         while (true) {
    125             switch (mode) {
    126             // waiting for "i:"=input, "o:"=output, "x:"=nothing
    127             case START: // x: set up for LEN
    128                 if (m >= 258 && n >= 10) {
    129
    130                     s.bitb = b;
    131                     s.bitk = k;
    132                     z.avail_in = n;
    133                     z.total_in += p - z.next_in_index;
    134                     z.next_in_index = p;
    135                     s.write = q;
    136                     r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree,
    137                             dtree_index, s, z);
    138
    139                     p = z.next_in_index;
    140                     n = z.avail_in;
    141                     b = s.bitb;
    142                     k = s.bitk;
    143                     q = s.write;
    144                     m = q < s.read? s.read - q - 1 : s.end - q;
    145
    146                     if (r != JZlib.Z_OK) {
    147                         mode = r == JZlib.Z_STREAM_END? WASH : BADCODE;
    148                         break;
    149                     }
    150                 }
    151                 need = lbits;
    152                 tree = ltree;
    153                 tree_index = ltree_index;
    154
    155                 mode = LEN;
    156             case LEN: // i: get length/literal/eob next
    157                 j = need;
    158
    159                 while (k < j) {
    160                     if (n != 0) {
    161                         r = JZlib.Z_OK;
    162                     } else {
    163
    164                         s.bitb = b;
    165                         s.bitk = k;
    166                         z.avail_in = n;
    167                         z.total_in += p - z.next_in_index;
    168                         z.next_in_index = p;
    169                         s.write = q;
    170                         return s.inflate_flush(z, r);
    171                     }
    172                     n --;
    173                     b |= (z.next_in[p ++] & 0xff) << k;
    174                     k += 8;
    175                 }
    176
    177                 tindex = (tree_index + (b & inflate_mask[j])) * 3;
    178
    179                 b >>>= tree[tindex + 1];
    180                 k -= tree[tindex + 1];
    181
    182                 e = tree[tindex];
    183
    184                 if (e == 0) { // literal
    185                     lit = tree[tindex + 2];
    186                     mode = LIT;
    187                     break;
    188                 }
    189                 if ((e & 16) != 0) { // length
    190                     get = e & 15;
    191                     len = tree[tindex + 2];
    192                     mode = LENEXT;
    193                     break;
    194                 }
    195                 if ((e & 64) == 0) { // next table
    196                     need = e;
    197                     tree_index = tindex / 3 + tree[tindex + 2];
    198                     break;
    199                 }
    200                 if ((e & 32) != 0) { // end of block
    201                     mode = WASH;
    202                     break;
    203                 }
    204                 mode = BADCODE; // invalid code
    205                 z.msg = "invalid literal/length code";
    206                 r = JZlib.Z_DATA_ERROR;
    207
    208                 s.bitb = b;
    209                 s.bitk = k;
    210                 z.avail_in = n;
    211                 z.total_in += p - z.next_in_index;
    212                 z.next_in_index = p;
    213                 s.write = q;
    214                 return s.inflate_flush(z, r);
    215
    216             case LENEXT: // i: getting length extra (have base)
    217                 j = get;
    218
    219                 while (k < j) {
    220                     if (n != 0) {
    221                         r = JZlib.Z_OK;
    222                     } else {
    223
    224                         s.bitb = b;
    225                         s.bitk = k;
    226                         z.avail_in = n;
    227                         z.total_in += p - z.next_in_index;
    228                         z.next_in_index = p;
    229                         s.write = q;
    230                         return s.inflate_flush(z, r);
    231                     }
    232                     n --;
    233                     b |= (z.next_in[p ++] & 0xff) << k;
    234                     k += 8;
    235                 }
    236
    237                 len += b & inflate_mask[j];
    238
    239                 b >>= j;
    240                 k -= j;
    241
    242                 need = dbits;
    243                 tree = dtree;
    244                 tree_index = dtree_index;
    245                 mode = DIST;
    246             case DIST: // i: get distance next
    247                 j = need;
    248
    249                 while (k < j) {
    250                     if (n != 0) {
    251                         r = JZlib.Z_OK;
    252                     } else {
    253
    254                         s.bitb = b;
    255                         s.bitk = k;
    256                         z.avail_in = n;
    257                         z.total_in += p - z.next_in_index;
    258                         z.next_in_index = p;
    259                         s.write = q;
    260                         return s.inflate_flush(z, r);
    261                     }
    262                     n --;
    263                     b |= (z.next_in[p ++] & 0xff) << k;
    264                     k += 8;
    265                 }
    266
    267                 tindex = (tree_index + (b & inflate_mask[j])) * 3;
    268
    269                 b >>= tree[tindex + 1];
    270                 k -= tree[tindex + 1];
    271
    272                 e = tree[tindex];
    273                 if ((e & 16) != 0) { // distance
    274                     get = e & 15;
    275                     dist = tree[tindex + 2];
    276                     mode = DISTEXT;
    277                     break;
    278                 }
    279                 if ((e & 64) == 0) { // next table
    280                     need = e;
    281                     tree_index = tindex / 3 + tree[tindex + 2];
    282                     break;
    283                 }
    284                 mode = BADCODE; // invalid code
    285                 z.msg = "invalid distance code";
    286                 r = JZlib.Z_DATA_ERROR;
    287
    288                 s.bitb = b;
    289                 s.bitk = k;
    290                 z.avail_in = n;
    291                 z.total_in += p - z.next_in_index;
    292                 z.next_in_index = p;
    293                 s.write = q;
    294                 return s.inflate_flush(z, r);
    295
    296             case DISTEXT: // i: getting distance extra
    297                 j = get;
    298
    299                 while (k < j) {
    300                     if (n != 0) {
    301                         r = JZlib.Z_OK;
    302                     } else {
    303
    304                         s.bitb = b;
    305                         s.bitk = k;
    306                         z.avail_in = n;
    307                         z.total_in += p - z.next_in_index;
    308                         z.next_in_index = p;
    309                         s.write = q;
    310                         return s.inflate_flush(z, r);
    311                     }
    312                     n --;
    313                     b |= (z.next_in[p ++] & 0xff) << k;
    314                     k += 8;
    315                 }
    316
    317                 dist += b & inflate_mask[j];
    318
    319                 b >>= j;
    320                 k -= j;
    321
    322                 mode = COPY;
    323             case COPY: // o: copying bytes in window, waiting for space
    324                 f = q - dist;
    325                 while (f < 0) { // modulo window size-"while" instead
    326                     f += s.end; // of "if" handles invalid distances
    327                 }
    328                 while (len != 0) {
    329
    330                     if (m == 0) {
    331                         if (q == s.end && s.read != 0) {
    332                             q = 0;
    333                             m = q < s.read? s.read - q - 1 : s.end - q;
    334                         }
    335                         if (m == 0) {
    336                             s.write = q;
    337                             r = s.inflate_flush(z, r);
    338                             q = s.write;
    339                             m = q < s.read? s.read - q - 1 : s.end - q;
    340
    341                             if (q == s.end && s.read != 0) {
    342                                 q = 0;
    343                                 m = q < s.read? s.read - q - 1 : s.end - q;
    344                             }
    345
    346                             if (m == 0) {
    347                                 s.bitb = b;
    348                                 s.bitk = k;
    349                                 z.avail_in = n;
    350                                 z.total_in += p - z.next_in_index;
    351                                 z.next_in_index = p;
    352                                 s.write = q;
    353                                 return s.inflate_flush(z, r);
    354                             }
    355                         }
    356                     }
    357
    358                     s.window[q ++] = s.window[f ++];
    359                     m --;
    360
    361                     if (f == s.end) {
    362                         f = 0;
    363                     }
    364                     len --;
    365                 }
    366                 mode = START;
    367                 break;
    368             case LIT: // o: got literal, waiting for output space
    369                 if (m == 0) {
    370                     if (q == s.end && s.read != 0) {
    371                         q = 0;
    372                         m = q < s.read? s.read - q - 1 : s.end - q;
    373                     }
    374                     if (m == 0) {
    375                         s.write = q;
    376                         r = s.inflate_flush(z, r);
    377                         q = s.write;
    378                         m = q < s.read? s.read - q - 1 : s.end - q;
    379
    380                         if (q == s.end && s.read != 0) {
    381                             q = 0;
    382                             m = q < s.read? s.read - q - 1 : s.end - q;
    383                         }
    384                         if (m == 0) {
    385                             s.bitb = b;
    386                             s.bitk = k;
    387                             z.avail_in = n;
    388                             z.total_in += p - z.next_in_index;
    389                             z.next_in_index = p;
    390                             s.write = q;
    391                             return s.inflate_flush(z, r);
    392                         }
    393                     }
    394                 }
    395                 r = JZlib.Z_OK;
    396
    397                 s.window[q ++] = (byte) lit;
    398                 m --;
    399
    400                 mode = START;
    401                 break;
    402             case WASH: // o: got eob, possibly more output
    403                 if (k > 7) { // return unused byte, if any
    404                     k -= 8;
    405                     n ++;
    406                     p --; // can always return one
    407                 }
    408
    409                 s.write = q;
    410                 r = s.inflate_flush(z, r);
    411                 q = s.write;
    412
    413                 if (s.read != s.write) {
    414                     s.bitb = b;
    415                     s.bitk = k;
    416                     z.avail_in = n;
    417                     z.total_in += p - z.next_in_index;
    418                     z.next_in_index = p;
    419                     s.write = q;
    420                     return s.inflate_flush(z, r);
    421                 }
    422                 mode = END;
    423             case END:
    424                 r = JZlib.Z_STREAM_END;
    425                 s.bitb = b;
    426                 s.bitk = k;
    427                 z.avail_in = n;
    428                 z.total_in += p - z.next_in_index;
    429                 z.next_in_index = p;
    430                 s.write = q;
    431                 return s.inflate_flush(z, r);
    432
    433             case BADCODE: // x: got error
    434
    435                 r = JZlib.Z_DATA_ERROR;
    436
    437                 s.bitb = b;
    438                 s.bitk = k;
    439                 z.avail_in = n;
    440                 z.total_in += p - z.next_in_index;
    441                 z.next_in_index = p;
    442                 s.write = q;
    443                 return s.inflate_flush(z, r);
    444
    445             default:
    446                 r = JZlib.Z_STREAM_ERROR;
    447
    448                 s.bitb = b;
    449                 s.bitk = k;
    450                 z.avail_in = n;
    451                 z.total_in += p - z.next_in_index;
    452                 z.next_in_index = p;
    453                 s.write = q;
    454                 return s.inflate_flush(z, r);
    455             }
    456         }
    457     }
    458
    459     // Called with number of bytes left to write in window at least 258
    460     // (the maximum string length) and number of input bytes available
    461     // at least ten.  The ten bytes are six bytes for the longest length/
    462     // distance pair plus four bytes for overloading the bit buffer.
    463
    464     int inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td,
    465             int td_index, InfBlocks s, ZStream z) {
    466         int t; // temporary pointer
    467         int[] tp; // temporary pointer
    468         int tp_index; // temporary pointer
    469         int e; // extra bits or operation
    470         int b; // bit buffer
    471         int k; // bits in bit buffer
    472         int p; // input data pointer
    473         int n; // bytes available there
    474         int q; // output window write pointer
    475         int m; // bytes to end of window or read pointer
    476         int ml; // mask for literal/length tree
    477         int md; // mask for distance tree
    478         int c; // bytes to copy
    479         int d; // distance back to copy from
    480         int r; // copy source pointer
    481
    482         int tp_index_t_3; // (tp_index+t)*3
    483
    484         // load input, output, bit values
    485         p = z.next_in_index;
    486         n = z.avail_in;
    487         b = s.bitb;
    488         k = s.bitk;
    489         q = s.write;
    490         m = q < s.read? s.read - q - 1 : s.end - q;
    491
    492         // initialize masks
    493         ml = inflate_mask[bl];
    494         md = inflate_mask[bd];
    495
    496         // do until not enough input or output space for fast loop
    497         do { // assume called with m >= 258 && n >= 10
    498             // get literal/length code
    499             while (k < 20) { // max bits for literal/length code
    500                 n --;
    501                 b |= (z.next_in[p ++] & 0xff) << k;
    502                 k += 8;
    503             }
    504
    505             t = b & ml;
    506             tp = tl;
    507             tp_index = tl_index;
    508             tp_index_t_3 = (tp_index + t) * 3;
    509             if ((e = tp[tp_index_t_3]) == 0) {
    510                 b >>= tp[tp_index_t_3 + 1];
    511                 k -= tp[tp_index_t_3 + 1];
    512
    513                 s.window[q ++] = (byte) tp[tp_index_t_3 + 2];
    514                 m --;
    515                 continue;
    516             }
    517             do {
    518
    519                 b >>= tp[tp_index_t_3 + 1];
    520                 k -= tp[tp_index_t_3 + 1];
    521
    522                 if ((e & 16) != 0) {
    523                     e &= 15;
    524                     c = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
    525
    526                     b >>= e;
    527                     k -= e;
    528
    529                     // decode distance base of block to copy
    530                     while (k < 15) { // max bits for distance code
    531                         n --;
    532                         b |= (z.next_in[p ++] & 0xff) << k;
    533                         k += 8;
    534                     }
    535
    536                     t = b & md;
    537                     tp = td;
    538                     tp_index = td_index;
    539                     tp_index_t_3 = (tp_index + t) * 3;
    540                     e = tp[tp_index_t_3];
    541
    542                     do {
    543
    544                         b >>= tp[tp_index_t_3 + 1];
    545                         k -= tp[tp_index_t_3 + 1];
    546
    547                         if ((e & 16) != 0) {
    548                             // get extra bits to add to distance base
    549                             e &= 15;
    550                             while (k < e) { // get extra bits (up to 13)
    551                                 n --;
    552                                 b |= (z.next_in[p ++] & 0xff) << k;
    553                                 k += 8;
    554                             }
    555
    556                             d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
    557
    558                             b >>= e;
    559                             k -= e;
    560
    561                             // do the copy
    562                             m -= c;
    563                             if (q >= d) { // offset before dest
    564                                 //  just copy
    565                                 r = q - d;
    566                                 if (q - r > 0 && 2 > q - r) {
    567                                     s.window[q ++] = s.window[r ++]; // minimum count is three,
    568                                     s.window[q ++] = s.window[r ++]; // so unroll loop a little
    569                                     c -= 2;
    570                                 } else {
    571                                     System.arraycopy(s.window, r, s.window, q,
    572                                             2);
    573                                     q += 2;
    574                                     r += 2;
    575                                     c -= 2;
    576                                 }
    577                             } else { // else offset after destination
    578                                 r = q - d;
    579                                 do {
    580                                     r += s.end; // force pointer in window
    581                                 } while (r < 0); // covers invalid distances
    582                                 e = s.end - r;
    583                                 if (c > e) { // if source crosses,
    584                                     c -= e; // wrapped copy
    585                                     if (q - r > 0 && e > q - r) {
    586                                         do {
    587                                             s.window[q ++] = s.window[r ++];
    588                                         } while (-- e != 0);
    589                                     } else {
    590                                         System.arraycopy(s.window, r, s.window,
    591                                                 q, e);
    592                                         q += e;
    593                                         r += e;
    594                                         e = 0;
    595                                     }
    596                                     r = 0; // copy rest from start of window
    597                                 }
    598
    599                             }
    600
    601                             // copy all or what's left
    602                             if (q - r > 0 && c > q - r) {
    603                                 do {
    604                                     s.window[q ++] = s.window[r ++];
    605                                 } while (-- c != 0);
    606                             } else {
    607                                 System.arraycopy(s.window, r, s.window, q, c);
    608                                 q += c;
    609                                 r += c;
    610                                 c = 0;
    611                             }
    612                             break;
    613                         } else if ((e & 64) == 0) {
    614                             t += tp[tp_index_t_3 + 2];
    615                             t += b & inflate_mask[e];
    616                             tp_index_t_3 = (tp_index + t) * 3;
    617                             e = tp[tp_index_t_3];
    618                         } else {
    619                             z.msg = "invalid distance code";
    620
    621                             c = z.avail_in - n;
    622                             c = k >> 3 < c? k >> 3 : c;
    623                             n += c;
    624                             p -= c;
    625                             k -= c << 3;
    626
    627                             s.bitb = b;
    628                             s.bitk = k;
    629                             z.avail_in = n;
    630                             z.total_in += p - z.next_in_index;
    631                             z.next_in_index = p;
    632                             s.write = q;
    633
    634                             return JZlib.Z_DATA_ERROR;
    635                         }
    636                     } while (true);
    637                     break;
    638                 }
    639
    640                 if ((e & 64) == 0) {
    641                     t += tp[tp_index_t_3 + 2];
    642                     t += b & inflate_mask[e];
    643                     tp_index_t_3 = (tp_index + t) * 3;
    644                     if ((e = tp[tp_index_t_3]) == 0) {
    645
    646                         b >>= tp[tp_index_t_3 + 1];
    647                         k -= tp[tp_index_t_3 + 1];
    648
    649                         s.window[q ++] = (byte) tp[tp_index_t_3 + 2];
    650                         m --;
    651                         break;
    652                     }
    653                 } else if ((e & 32) != 0) {
    654
    655                     c = z.avail_in - n;
    656                     c = k >> 3 < c? k >> 3 : c;
    657                     n += c;
    658                     p -= c;
    659                     k -= c << 3;
    660
    661                     s.bitb = b;
    662                     s.bitk = k;
    663                     z.avail_in = n;
    664                     z.total_in += p - z.next_in_index;
    665                     z.next_in_index = p;
    666                     s.write = q;
    667
    668                     return JZlib.Z_STREAM_END;
    669                 } else {
    670                     z.msg = "invalid literal/length code";
    671
    672                     c = z.avail_in - n;
    673                     c = k >> 3 < c? k >> 3 : c;
    674                     n += c;
    675                     p -= c;
    676                     k -= c << 3;
    677
    678                     s.bitb = b;
    679                     s.bitk = k;
    680                     z.avail_in = n;
    681                     z.total_in += p - z.next_in_index;
    682                     z.next_in_index = p;
    683                     s.write = q;
    684
    685                     return JZlib.Z_DATA_ERROR;
    686                 }
    687             } while (true);
    688         } while (m >= 258 && n >= 10);
    689
    690         // not enough input or output--restore pointers and return
    691         c = z.avail_in - n;
    692         c = k >> 3 < c? k >> 3 : c;
    693         n += c;
    694         p -= c;
    695         k -= c << 3;
    696
    697         s.bitb = b;
    698         s.bitk = k;
    699         z.avail_in = n;
    700         z.total_in += p - z.next_in_index;
    701         z.next_in_index = p;
    702         s.write = q;
    703
    704         return JZlib.Z_OK;
    705     }
    706 }