FreeBSD ZFS
The Zettabyte File System

lzjb.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 
00022 /*
00023  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
00024  */
00025 
00042 #include <sys/zfs_context.h>
00043 #include <sys/types.h>
00044 
00045 #define MATCH_BITS      6
00046 #define MATCH_MIN       3
00047 #define MATCH_MAX       ((1 << MATCH_BITS) + (MATCH_MIN - 1))
00048 #define OFFSET_MASK     ((1 << (16 - MATCH_BITS)) - 1)
00049 #define LEMPEL_SIZE     1024
00050 
00051 /*ARGSUSED*/
00052 size_t
00053 lzjb_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
00054 {
00055         uchar_t *src = s_start;
00056         uchar_t *dst = d_start;
00057         uchar_t *cpy, *copymap;
00058         int copymask = 1 << (NBBY - 1);
00059         int mlen, offset, hash;
00060         uint16_t *hp;
00061         uint16_t lempel[LEMPEL_SIZE] = { 0 };
00062 
00063         while (src < (uchar_t *)s_start + s_len) {
00064                 if ((copymask <<= 1) == (1 << NBBY)) {
00065                         if (dst >= (uchar_t *)d_start + d_len - 1 - 2 * NBBY)
00066                                 return (s_len);
00067                         copymask = 1;
00068                         copymap = dst;
00069                         *dst++ = 0;
00070                 }
00071                 if (src > (uchar_t *)s_start + s_len - MATCH_MAX) {
00072                         *dst++ = *src++;
00073                         continue;
00074                 }
00075                 hash = (src[0] << 16) + (src[1] << 8) + src[2];
00076                 hash += hash >> 9;
00077                 hash += hash >> 5;
00078                 hp = &lempel[hash & (LEMPEL_SIZE - 1)];
00079                 offset = (intptr_t)(src - *hp) & OFFSET_MASK;
00080                 *hp = (uint16_t)(uintptr_t)src;
00081                 cpy = src - offset;
00082                 if (cpy >= (uchar_t *)s_start && cpy != src &&
00083                     src[0] == cpy[0] && src[1] == cpy[1] && src[2] == cpy[2]) {
00084                         *copymap |= copymask;
00085                         for (mlen = MATCH_MIN; mlen < MATCH_MAX; mlen++)
00086                                 if (src[mlen] != cpy[mlen])
00087                                         break;
00088                         *dst++ = ((mlen - MATCH_MIN) << (NBBY - MATCH_BITS)) |
00089                             (offset >> NBBY);
00090                         *dst++ = (uchar_t)offset;
00091                         src += mlen;
00092                 } else {
00093                         *dst++ = *src++;
00094                 }
00095         }
00096         return (dst - (uchar_t *)d_start);
00097 }
00098 
00099 /*ARGSUSED*/
00100 int
00101 lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
00102 {
00103         uchar_t *src = s_start;
00104         uchar_t *dst = d_start;
00105         uchar_t *d_end = (uchar_t *)d_start + d_len;
00106         uchar_t *cpy, copymap;
00107         int copymask = 1 << (NBBY - 1);
00108 
00109         while (dst < d_end) {
00110                 if ((copymask <<= 1) == (1 << NBBY)) {
00111                         copymask = 1;
00112                         copymap = *src++;
00113                 }
00114                 if (copymap & copymask) {
00115                         int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
00116                         int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
00117                         src += 2;
00118                         if ((cpy = dst - offset) < (uchar_t *)d_start)
00119                                 return (-1);
00120                         while (--mlen >= 0 && dst < d_end)
00121                                 *dst++ = *cpy++;
00122                 } else {
00123                         *dst++ = *src++;
00124                 }
00125         }
00126         return (0);
00127 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines