mirror of
https://github.com/linux-apfs/linux-apfs-rw.git
synced 2026-08-18 02:19:59 -07:00
Compare commits
No files matched your search
@@ -14,9 +14,9 @@ apfs-y := btree.o compress.o dir.o extents.o file.o inode.o key.o libzbitmap.o \
|
||||
spaceman.o super.o symlink.o transaction.o unicode.o xattr.o xfield.o
|
||||
|
||||
# If you want mounts to be writable by default, run the build as:
|
||||
# make CONFIG=-DCONFIG_APFS_RW_ALWAYS
|
||||
# make APFS_CONFIG=-DCONFIG_APFS_RW_ALWAYS
|
||||
# This is risky and not generally recommended.
|
||||
ccflags-y += $(CONFIG)
|
||||
ccflags-y += $(APFS_CONFIG)
|
||||
|
||||
default:
|
||||
./genver.sh
|
||||
|
||||
+7
-2
@@ -57,10 +57,15 @@ Now you can just cd to the linux-apfs-rw directory and run::
|
||||
make
|
||||
|
||||
The resulting module is the apfs.ko file. Before you can use it you must insert
|
||||
it into the kernel, as well as its dependencies. Again as root::
|
||||
it into the kernel. Again as root::
|
||||
|
||||
insmod apfs.ko
|
||||
|
||||
If you get an "unknown symbol in module" error, run::
|
||||
|
||||
modprobe libcrc32c
|
||||
insmod apfs.ko
|
||||
|
||||
and then try the insmod command again.
|
||||
|
||||
Mount
|
||||
=====
|
||||
|
||||
@@ -44,10 +44,33 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags
|
||||
#endif
|
||||
|
||||
/* Compatibility wrapper around submit_bh() */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || RHEL_VERSION_GE(9, 2)
|
||||
#define apfs_submit_bh(op, op_flags, bh) submit_bh(op | op_flags, bh)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 2, 0)
|
||||
#define apfs_submit_bh(op, op_flags, bh) \
|
||||
do { \
|
||||
put_bh(bh); \
|
||||
if (op == REQ_OP_READ) \
|
||||
bh_submit(bh, op | op_flags, bh_end_read); \
|
||||
else \
|
||||
bh_submit(bh, op | op_flags, bh_end_write); \
|
||||
} while (0)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || RHEL_VERSION_GE(9, 2)
|
||||
#define apfs_submit_bh(op, op_flags, bh) \
|
||||
do { \
|
||||
if (op == REQ_OP_READ) \
|
||||
bh->b_end_io = end_buffer_read_sync; \
|
||||
else \
|
||||
bh->b_end_io = end_buffer_write_sync; \
|
||||
submit_bh(op | op_flags, bh); \
|
||||
} while (0)
|
||||
#else
|
||||
#define apfs_submit_bh(op, op_flags, bh) submit_bh(op, op_flags, bh)
|
||||
#define apfs_submit_bh(op, op_flags, bh) \
|
||||
do { \
|
||||
if (op == REQ_OP_READ) \
|
||||
bh->b_end_io = end_buffer_read_sync; \
|
||||
else \
|
||||
bh->b_end_io = end_buffer_write_sync; \
|
||||
submit_bh(op, op_flags, bh); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -380,6 +403,7 @@ struct apfs_sb_info {
|
||||
unsigned int s_vol_nr; /* Index of the volume in the sb list */
|
||||
kuid_t s_uid; /* uid to override on-disk uid */
|
||||
kgid_t s_gid; /* gid to override on-disk gid */
|
||||
unsigned int s_mount_opt;
|
||||
|
||||
struct apfs_crypto_state_val *s_dflt_pfk; /* default per-file key */
|
||||
|
||||
@@ -945,7 +969,7 @@ extern int apfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
unsigned int flags);
|
||||
extern int apfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
bool excl);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
extern int apfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t rdev);
|
||||
extern int apfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
@@ -955,11 +979,20 @@ extern int apfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
struct dentry *new_dentry, unsigned int flags);
|
||||
extern int apfs_create(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl);
|
||||
#else
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 15, 0)
|
||||
extern int apfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t rdev);
|
||||
extern int apfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode);
|
||||
extern int apfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags);
|
||||
extern int apfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl);
|
||||
#else
|
||||
extern int apfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t rdev);
|
||||
extern struct dentry *apfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode);
|
||||
extern int apfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags);
|
||||
@@ -1012,13 +1045,18 @@ extern struct inode *apfs_new_inode(struct inode *dir, umode_t mode,
|
||||
extern int apfs_create_inode_rec(struct super_block *sb, struct inode *inode,
|
||||
struct dentry *dentry);
|
||||
extern int apfs_inode_create_exclusive_dstream(struct inode *inode);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
|
||||
extern int __apfs_write_begin(const struct kiocb *iocb, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata);
|
||||
extern int __apfs_write_end(const struct kiocb *iocb, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata);
|
||||
#else
|
||||
extern int __apfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata);
|
||||
extern int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata);
|
||||
#endif
|
||||
extern int apfs_dstream_adj_refcnt(struct apfs_dstream_info *dstream, u32 delta);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
extern int apfs_setattr(struct dentry *dentry, struct iattr *iattr);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
extern int apfs_setattr(struct user_namespace *mnt_userns,
|
||||
struct dentry *dentry, struct iattr *iattr);
|
||||
#else
|
||||
@@ -1026,7 +1064,9 @@ extern int apfs_setattr(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry, struct iattr *iattr);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 0, 0)
|
||||
extern int apfs_update_time(struct inode *inode, enum fs_update_time time, unsigned int flags);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
|
||||
extern int apfs_update_time(struct inode *inode, struct timespec64 *time, int flags);
|
||||
#else
|
||||
extern int apfs_update_time(struct inode *inode, int flags);
|
||||
@@ -1040,7 +1080,7 @@ extern int apfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
extern int apfs_getattr(const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int query_flags);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
extern int apfs_getattr(struct user_namespace *mnt_userns,
|
||||
const struct path *path, struct kstat *stat, u32 request_mask,
|
||||
unsigned int query_flags);
|
||||
@@ -1052,7 +1092,11 @@ extern int apfs_getattr(struct mnt_idmap *idmap,
|
||||
|
||||
extern int apfs_crypto_adj_refcnt(struct super_block *sb, u64 crypto_id, int delta);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
|
||||
#define fileattr file_kattr
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0) || RHEL_VERSION_GE(9, 6)
|
||||
extern int apfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
|
||||
extern int apfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
||||
@@ -1194,6 +1238,37 @@ static inline void apfs_assert_query_is_valid(const struct apfs_query *query)
|
||||
ASSERT(apfs_node_is_root(apfs_query_root(query)));
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
|
||||
#define page_has_buffers(page) folio_buffers(page_folio(page))
|
||||
#endif
|
||||
|
||||
static inline int apfs_inode_state_read_once(struct inode *inode)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
|
||||
return inode_state_read_once(inode);
|
||||
#else
|
||||
return inode->i_state;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void apfs_inode_state_set_raw(struct inode *inode, int flags)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
|
||||
inode_state_set_raw(inode, flags);
|
||||
#else
|
||||
inode->i_state |= flags;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void apfs_inode_state_clear_raw(struct inode *inode, int flags)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
|
||||
inode_state_clear_raw(inode, flags);
|
||||
#else
|
||||
inode->i_state &= ~flags;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: the following are modified variants of buffer head functions that will
|
||||
* work with the shared block device for the container. The correct approach
|
||||
@@ -1272,7 +1347,7 @@ __apfs_getblk(struct super_block *sb, sector_t block)
|
||||
block -= nxi->nx_tier2_bno;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) && !RHEL_VERSION_GE(9, 8)
|
||||
return __getblk_gfp(info->blki_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
|
||||
#else
|
||||
return bdev_getblk(info->blki_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
|
||||
|
||||
@@ -422,7 +422,11 @@ static int apfs_compress_readpage(struct file *filp, struct page *page)
|
||||
loff_t off;
|
||||
|
||||
/* Mostly copied from ext4_read_inline_page() */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0)
|
||||
off = page_folio(page)->index << PAGE_SHIFT;
|
||||
#else
|
||||
off = page->index << PAGE_SHIFT;
|
||||
#endif
|
||||
addr = kmap(page);
|
||||
ret = apfs_compress_file_read_page(filp, addr, off);
|
||||
flush_dcache_page(page);
|
||||
|
||||
@@ -261,7 +261,7 @@ const struct file_operations apfs_dir_operations = {
|
||||
*
|
||||
* Returns the length of the key, or a negative error code in case of failure.
|
||||
*/
|
||||
static int apfs_build_dentry_unhashed_key(struct qstr *qname, u64 parent_id,
|
||||
static int apfs_build_dentry_unhashed_key(const struct qstr *qname, u64 parent_id,
|
||||
struct apfs_drec_key **key_p)
|
||||
{
|
||||
struct apfs_drec_key *key;
|
||||
@@ -290,7 +290,7 @@ static int apfs_build_dentry_unhashed_key(struct qstr *qname, u64 parent_id,
|
||||
*
|
||||
* Returns the length of the key, or a negative error code in case of failure.
|
||||
*/
|
||||
static int apfs_build_dentry_hashed_key(struct qstr *qname, u64 hash, u64 parent_id,
|
||||
static int apfs_build_dentry_hashed_key(const struct qstr *qname, u64 hash, u64 parent_id,
|
||||
struct apfs_drec_hashed_key **key_p)
|
||||
{
|
||||
struct apfs_drec_hashed_key *key;
|
||||
@@ -363,7 +363,7 @@ static int apfs_build_dentry_val(struct inode *inode, u64 sibling_id,
|
||||
*
|
||||
* Returns 0 on success or a negative error code in case of failure.
|
||||
*/
|
||||
static int apfs_create_dentry_rec(struct inode *inode, struct qstr *qname,
|
||||
static int apfs_create_dentry_rec(struct inode *inode, const struct qstr *qname,
|
||||
u64 parent_id, u64 sibling_id)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
@@ -426,7 +426,7 @@ static int apfs_build_sibling_val(struct dentry *dentry,
|
||||
struct apfs_sibling_val **val_p)
|
||||
{
|
||||
struct apfs_sibling_val *val;
|
||||
struct qstr *qname = &dentry->d_name;
|
||||
const struct qstr *qname = &dentry->d_name;
|
||||
u16 namelen = qname->len + 1; /* We count the null-termination */
|
||||
struct inode *parent = d_inode(dentry->d_parent);
|
||||
int val_len;
|
||||
@@ -698,7 +698,7 @@ out_abort:
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
int apfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
dev_t rdev)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
int apfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t rdev)
|
||||
#else
|
||||
@@ -716,7 +716,7 @@ int apfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
return apfs_mknod(dir, dentry, mode | S_IFDIR, 0 /* rdev */);
|
||||
}
|
||||
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
|
||||
int apfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
@@ -724,7 +724,7 @@ int apfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
return apfs_mknod(mnt_userns, dir, dentry, mode | S_IFDIR, 0 /* rdev */);
|
||||
}
|
||||
|
||||
#else
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 15, 0)
|
||||
|
||||
int apfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
@@ -732,6 +732,13 @@ int apfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return apfs_mknod(idmap, dir, dentry, mode | S_IFDIR, 0 /* rdev */);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct dentry *apfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return ERR_PTR(apfs_mknod(idmap, dir, dentry, mode | S_IFDIR, 0 /* rdev */));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -743,7 +750,7 @@ int apfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
return apfs_mknod(dir, dentry, mode, 0 /* rdev */);
|
||||
}
|
||||
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
|
||||
int apfs_create(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
@@ -1248,9 +1255,10 @@ static void __apfs_undo_unlink(struct dentry *dentry)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
inode->i_state |= I_LINKABLE; /* Silence warning about nlink 0->1 */
|
||||
/* Silence warning about nlink 0->1 */
|
||||
apfs_inode_state_set_raw(inode, I_LINKABLE);
|
||||
inc_nlink(inode);
|
||||
inode->i_state &= ~I_LINKABLE;
|
||||
apfs_inode_state_clear_raw(inode, I_LINKABLE);
|
||||
|
||||
apfs_undo_delete_dentry(dentry);
|
||||
}
|
||||
@@ -1373,7 +1381,7 @@ int apfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
int apfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry,
|
||||
unsigned int flags)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
int apfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
PACKAGE_NAME="linux-apfs-rw"
|
||||
PACKAGE_VERSION="0.3.13"
|
||||
PACKAGE_VERSION="0.3.21"
|
||||
|
||||
BUILT_MODULE_NAME[0]="apfs"
|
||||
DEST_MODULE_LOCATION[0]="/extra"
|
||||
|
||||
@@ -2298,7 +2298,6 @@ int apfs_nonsparse_dstream_read(struct apfs_dstream_info *dstream, void *buf, si
|
||||
if (!buffer_uptodate(bh)) {
|
||||
get_bh(bh);
|
||||
lock_buffer(bh);
|
||||
bh->b_end_io = end_buffer_read_sync;
|
||||
apfs_submit_bh(REQ_OP_READ, 0, bh);
|
||||
}
|
||||
}
|
||||
@@ -2365,7 +2364,6 @@ void apfs_nonsparse_dstream_preread(struct apfs_dstream_info *dstream)
|
||||
if (!buffer_uptodate(bh)) {
|
||||
get_bh(bh);
|
||||
lock_buffer(bh);
|
||||
bh->b_end_io = end_buffer_read_sync;
|
||||
apfs_submit_bh(REQ_OP_READ, 0, bh);
|
||||
}
|
||||
brelse(bh);
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
typedef int vm_fault_t;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
|
||||
static void wait_for_stable_page(struct page *page)
|
||||
{
|
||||
return folio_wait_stable(page_folio(page));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
|
||||
static vm_fault_t apfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
@@ -65,7 +72,11 @@ static vm_fault_t apfs_page_mkwrite(struct vm_fault *vmf)
|
||||
}
|
||||
|
||||
size = i_size_read(inode);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0)
|
||||
if (page_folio(page)->index == size >> PAGE_SHIFT)
|
||||
#else
|
||||
if (page->index == size >> PAGE_SHIFT)
|
||||
#endif
|
||||
len = size & ~PAGE_MASK;
|
||||
else
|
||||
len = PAGE_SIZE;
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
|
||||
#define MAX_PFK_LEN 512
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
|
||||
static struct page *grab_cache_page_write_begin(struct address_space *mapping, pgoff_t index)
|
||||
{
|
||||
return pagecache_get_page(mapping, index, FGP_WRITEBEGIN, mapping_gfp_mask(mapping));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || RHEL_VERSION_GE(9, 3)
|
||||
|
||||
static int apfs_read_folio(struct file *file, struct folio *folio)
|
||||
@@ -463,7 +470,11 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
|
||||
int __apfs_write_begin(const struct kiocb *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata)
|
||||
#else
|
||||
int __apfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata)
|
||||
#endif
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct apfs_dstream_info *dstream = &APFS_I(inode)->i_dstream;
|
||||
@@ -545,7 +556,6 @@ int __apfs_write_begin(struct file *file, struct address_space *mapping, loff_t
|
||||
if (buffer_mapped(bh) && !buffer_uptodate(bh)) {
|
||||
get_bh(bh);
|
||||
lock_buffer(bh);
|
||||
bh->b_end_io = end_buffer_read_sync;
|
||||
apfs_submit_bh(REQ_OP_READ, 0, bh);
|
||||
wait_on_buffer(bh);
|
||||
if (!buffer_uptodate(bh)) {
|
||||
@@ -577,7 +587,11 @@ out_put_page:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
|
||||
static int apfs_write_begin(const struct kiocb *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len,
|
||||
struct folio **foliop, void **fsdata)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
static int apfs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len,
|
||||
struct folio **foliop, void **fsdata)
|
||||
@@ -622,7 +636,11 @@ fail:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
|
||||
int __apfs_write_end(const struct kiocb *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata)
|
||||
#else
|
||||
int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata)
|
||||
#endif
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct apfs_dstream_info *dstream = &APFS_I(inode)->i_dstream;
|
||||
@@ -645,7 +663,11 @@ int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t po
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
|
||||
static int apfs_write_end(const struct kiocb *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int copied,
|
||||
struct folio *folio, void *fsdata)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||
static int apfs_write_end(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int copied,
|
||||
struct folio *folio, void *fsdata)
|
||||
@@ -1014,7 +1036,7 @@ struct inode *apfs_iget(struct super_block *sb, u64 cnid)
|
||||
inode = apfs_iget_locked(sb, cnid);
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (!(inode->i_state & I_NEW))
|
||||
if (!(apfs_inode_state_read_once(inode) & I_NEW))
|
||||
return inode;
|
||||
|
||||
down_read(&nxi->nx_big_sem);
|
||||
@@ -1071,7 +1093,7 @@ int apfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
int apfs_getattr(const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int query_flags)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
int apfs_getattr(struct user_namespace *mnt_userns,
|
||||
const struct path *path, struct kstat *stat, u32 request_mask,
|
||||
unsigned int query_flags)
|
||||
@@ -1103,7 +1125,7 @@ int apfs_getattr(struct mnt_idmap *idmap,
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
generic_fillattr(inode, stat);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
generic_fillattr(mnt_userns, inode, stat);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
|
||||
generic_fillattr(idmap, inode, stat);
|
||||
@@ -1126,7 +1148,7 @@ int apfs_getattr(struct mnt_idmap *idmap,
|
||||
*
|
||||
* Returns the length of the value, or a negative error code in case of failure.
|
||||
*/
|
||||
static int apfs_build_inode_val(struct inode *inode, struct qstr *qname,
|
||||
static int apfs_build_inode_val(struct inode *inode, const struct qstr *qname,
|
||||
struct apfs_inode_val **val_p)
|
||||
{
|
||||
struct apfs_inode_val *val;
|
||||
@@ -1875,7 +1897,7 @@ struct inode *apfs_new_inode(struct inode *dir, umode_t mode, dev_t rdev)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
inode_init_owner(inode, dir, mode);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
#else
|
||||
inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
|
||||
@@ -2023,7 +2045,7 @@ static int apfs_setsize(struct inode *inode, loff_t new_size)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
int apfs_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
int apfs_setattr(struct user_namespace *mnt_userns,
|
||||
struct dentry *dentry, struct iattr *iattr)
|
||||
#else
|
||||
@@ -2044,7 +2066,7 @@ int apfs_setattr(struct mnt_idmap *idmap,
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
err = setattr_prepare(dentry, iattr);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
err = setattr_prepare(&init_user_ns, dentry, iattr);
|
||||
#else
|
||||
err = setattr_prepare(&nop_mnt_idmap, dentry, iattr);
|
||||
@@ -2068,7 +2090,7 @@ int apfs_setattr(struct mnt_idmap *idmap,
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
|
||||
setattr_copy(inode, iattr);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
setattr_copy(&init_user_ns, inode, iattr);
|
||||
#else
|
||||
setattr_copy(&nop_mnt_idmap, inode, iattr);
|
||||
@@ -2086,7 +2108,9 @@ fail:
|
||||
}
|
||||
|
||||
/* TODO: this only seems to be necessary because ->write_inode() isn't firing */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 0, 0)
|
||||
int apfs_update_time(struct inode *inode, enum fs_update_time time, unsigned int flags)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
|
||||
int apfs_update_time(struct inode *inode, struct timespec64 *time, int flags)
|
||||
#else
|
||||
int apfs_update_time(struct inode *inode, int flags)
|
||||
@@ -2100,7 +2124,9 @@ int apfs_update_time(struct inode *inode, int flags)
|
||||
return err;
|
||||
apfs_inode_join_transaction(sb, inode);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 0, 0)
|
||||
generic_update_time(inode, time, flags);
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
generic_update_time(inode, time, flags);
|
||||
#else
|
||||
generic_update_time(inode, flags);
|
||||
@@ -2436,7 +2462,7 @@ static int apfs_ioc_setflags(struct file *file, int __user *arg)
|
||||
return err;
|
||||
}
|
||||
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && !RHEL_VERSION_GE(9, 6)
|
||||
|
||||
int apfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
|
||||
{
|
||||
|
||||
+25
-94
@@ -1,23 +1,24 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
* Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LZFSE_H
|
||||
#define LZFSE_H
|
||||
@@ -25,71 +26,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# define __attribute__(X)
|
||||
# pragma warning(disable : 4068)
|
||||
#endif
|
||||
|
||||
#if defined(LZFSE_DLL)
|
||||
# if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# if defined(LZFSE_DLL_EXPORTS)
|
||||
# define LZFSE_API __declspec(dllexport)
|
||||
# else
|
||||
# define LZFSE_API __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(LZFSE_API)
|
||||
# if __GNUC__ >= 4
|
||||
# define LZFSE_API __attribute__((visibility("default")))
|
||||
# else
|
||||
# define LZFSE_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*! @abstract Get the required scratch buffer size to compress using LZFSE. */
|
||||
size_t lzfse_encode_scratch_size(void);
|
||||
|
||||
/*! @abstract Compress a buffer using LZFSE.
|
||||
*
|
||||
* @param dst_buffer
|
||||
* Pointer to the first byte of the destination buffer.
|
||||
*
|
||||
* @param dst_size
|
||||
* Size of the destination buffer in bytes.
|
||||
*
|
||||
* @param src_buffer
|
||||
* Pointer to the first byte of the source buffer.
|
||||
*
|
||||
* @param src_size
|
||||
* Size of the source buffer in bytes.
|
||||
*
|
||||
* @param scratch_buffer
|
||||
* If non-NULL, a pointer to scratch space for the routine to use as workspace;
|
||||
* the routine may use up to lzfse_encode_scratch_size( ) bytes of workspace
|
||||
* during its operation, and will not perform any internal allocations. If
|
||||
* NULL, the routine may allocate its own memory to use during operation via
|
||||
* a single call to malloc( ), and will release it by calling free( ) prior
|
||||
* to returning. For most use, passing NULL is perfectly satisfactory, but if
|
||||
* you require strict control over allocation, you will want to pass an
|
||||
* explicit scratch buffer.
|
||||
*
|
||||
* @return
|
||||
* The number of bytes written to the destination buffer if the input is
|
||||
* successfully compressed. If the input cannot be compressed to fit into
|
||||
* the provided buffer, or an error occurs, zero is returned, and the
|
||||
* contents of dst_buffer are unspecified. */
|
||||
size_t lzfse_encode_buffer(uint8_t *__restrict dst_buffer,
|
||||
size_t dst_size,
|
||||
const uint8_t *__restrict src_buffer,
|
||||
size_t src_size,
|
||||
void *__restrict scratch_buffer);
|
||||
|
||||
/*! @abstract Get the required scratch buffer size to decompress using LZFSE. */
|
||||
size_t lzfse_decode_scratch_size(void);
|
||||
|
||||
@@ -122,15 +58,10 @@ size_t lzfse_decode_scratch_size(void);
|
||||
* successfully decompressed. If there is not enough space in the destination
|
||||
* buffer to hold the entire expanded output, only the first dst_size bytes
|
||||
* will be written to the buffer and dst_size is returned. Note that this
|
||||
* behavior differs from that of lzfse_encode_buffer. */
|
||||
size_t lzfse_decode_buffer(uint8_t *__restrict dst_buffer,
|
||||
size_t dst_size,
|
||||
const uint8_t *__restrict src_buffer,
|
||||
size_t src_size,
|
||||
void *__restrict scratch_buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
* behavior differs from that of lzfse_encode_buffer.
|
||||
*/
|
||||
size_t lzfse_decode_buffer(uint8_t *__restrict dst_buffer, size_t dst_size,
|
||||
const uint8_t *__restrict src_buffer, size_t src_size,
|
||||
void *__restrict scratch_buffer);
|
||||
|
||||
#endif /* LZFSE_H */
|
||||
+65
-59
@@ -1,74 +1,80 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// LZFSE decode API
|
||||
/* LZFSE decode API */
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include "lzfse.h"
|
||||
#include "lzfse_internal.h"
|
||||
|
||||
size_t lzfse_decode_scratch_size(void) { return sizeof(lzfse_decoder_state); }
|
||||
size_t lzfse_decode_scratch_size(void)
|
||||
{
|
||||
return sizeof(lzfse_decoder_state);
|
||||
}
|
||||
|
||||
static size_t lzfse_decode_buffer_with_scratch(uint8_t *__restrict dst_buffer,
|
||||
size_t dst_size, const uint8_t *__restrict src_buffer,
|
||||
size_t src_size, void *__restrict scratch_buffer) {
|
||||
int status;
|
||||
lzfse_decoder_state *s = (lzfse_decoder_state *)scratch_buffer;
|
||||
memset(s, 0x00, sizeof(*s));
|
||||
static size_t lzfse_decode_buffer_with_scratch(uint8_t *__restrict dst_buffer, size_t dst_size,
|
||||
const uint8_t *__restrict src_buffer,
|
||||
size_t src_size, void *__restrict scratch_buffer)
|
||||
{
|
||||
int status;
|
||||
lzfse_decoder_state *s = (lzfse_decoder_state *)scratch_buffer;
|
||||
|
||||
// Initialize state
|
||||
s->src = src_buffer;
|
||||
s->src_begin = src_buffer;
|
||||
s->src_end = s->src + src_size;
|
||||
s->dst = dst_buffer;
|
||||
s->dst_begin = dst_buffer;
|
||||
s->dst_end = dst_buffer + dst_size;
|
||||
memset(s, 0x00, sizeof(*s));
|
||||
|
||||
// Decode
|
||||
status = lzfse_decode(s);
|
||||
if (status == LZFSE_STATUS_DST_FULL)
|
||||
return dst_size;
|
||||
if (status != LZFSE_STATUS_OK)
|
||||
return 0; // failed
|
||||
return (size_t)(s->dst - dst_buffer); // bytes written
|
||||
/* Initialize state */
|
||||
s->src = src_buffer;
|
||||
s->src_begin = src_buffer;
|
||||
s->src_end = s->src + src_size;
|
||||
s->dst = dst_buffer;
|
||||
s->dst_begin = dst_buffer;
|
||||
s->dst_end = dst_buffer + dst_size;
|
||||
|
||||
/* Decode */
|
||||
status = lzfse_decode(s);
|
||||
if (status == LZFSE_STATUS_DST_FULL)
|
||||
return dst_size;
|
||||
if (status != LZFSE_STATUS_OK)
|
||||
return 0; /* failed */
|
||||
return (size_t)(s->dst - dst_buffer); /* bytes written */
|
||||
}
|
||||
|
||||
size_t lzfse_decode_buffer(uint8_t *__restrict dst_buffer, size_t dst_size,
|
||||
const uint8_t *__restrict src_buffer,
|
||||
size_t src_size, void *__restrict scratch_buffer) {
|
||||
int has_malloc = 0;
|
||||
size_t ret = 0;
|
||||
const uint8_t *__restrict src_buffer, size_t src_size,
|
||||
void *__restrict scratch_buffer)
|
||||
{
|
||||
int has_malloc = 0;
|
||||
size_t ret = 0;
|
||||
|
||||
// Deal with the possible NULL pointer
|
||||
if (scratch_buffer == NULL) {
|
||||
// +1 in case scratch size could be zero
|
||||
scratch_buffer = kmalloc(lzfse_decode_scratch_size() + 1, GFP_KERNEL);
|
||||
has_malloc = 1;
|
||||
}
|
||||
if (scratch_buffer == NULL)
|
||||
return 0;
|
||||
ret = lzfse_decode_buffer_with_scratch(dst_buffer,
|
||||
dst_size, src_buffer,
|
||||
src_size, scratch_buffer);
|
||||
if (has_malloc)
|
||||
kfree(scratch_buffer);
|
||||
return ret;
|
||||
/* Deal with the possible NULL pointer */
|
||||
if (scratch_buffer == NULL) {
|
||||
/* +1 in case scratch size could be zero */
|
||||
scratch_buffer = kmalloc(lzfse_decode_scratch_size() + 1, GFP_KERNEL);
|
||||
has_malloc = 1;
|
||||
}
|
||||
if (scratch_buffer == NULL)
|
||||
return 0;
|
||||
ret = lzfse_decode_buffer_with_scratch(dst_buffer, dst_size, src_buffer, src_size,
|
||||
scratch_buffer);
|
||||
if (has_malloc)
|
||||
kfree(scratch_buffer);
|
||||
return ret;
|
||||
}
|
||||
+647
-556
File diff suppressed because it is too large.
Load diff
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// LZFSE encode API
|
||||
|
||||
#include "lzfse.h"
|
||||
#include "lzfse_internal.h"
|
||||
|
||||
size_t lzfse_encode_scratch_size() {
|
||||
size_t s1 = sizeof(lzfse_encoder_state);
|
||||
size_t s2 = lzvn_encode_scratch_size();
|
||||
return (s1 > s2) ? s1 : s2; // max(lzfse,lzvn)
|
||||
}
|
||||
|
||||
size_t lzfse_encode_buffer_with_scratch(uint8_t *__restrict dst_buffer,
|
||||
size_t dst_size, const uint8_t *__restrict src_buffer,
|
||||
size_t src_size, void *__restrict scratch_buffer) {
|
||||
const size_t original_size = src_size;
|
||||
|
||||
// If input is really really small, go directly to uncompressed buffer
|
||||
// (because LZVN will refuse to encode it, and we will report a failure)
|
||||
if (src_size < LZVN_ENCODE_MIN_SRC_SIZE)
|
||||
goto try_uncompressed;
|
||||
|
||||
// If input is too small, try encoding with LZVN
|
||||
if (src_size < LZFSE_ENCODE_LZVN_THRESHOLD) {
|
||||
// need header + end-of-stream marker
|
||||
size_t extra_size = 4 + sizeof(lzvn_compressed_block_header);
|
||||
if (dst_size <= extra_size)
|
||||
goto try_uncompressed; // DST is really too small, give up
|
||||
|
||||
size_t sz = lzvn_encode_buffer(
|
||||
dst_buffer + sizeof(lzvn_compressed_block_header),
|
||||
dst_size - extra_size, src_buffer, src_size, scratch_buffer);
|
||||
if (sz == 0 || sz >= src_size)
|
||||
goto try_uncompressed; // failed, or no compression, fall back to
|
||||
// uncompressed block
|
||||
|
||||
// If we could encode, setup header and end-of-stream marker (we left room
|
||||
// for them, no need to test)
|
||||
lzvn_compressed_block_header header;
|
||||
header.magic = LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC;
|
||||
header.n_raw_bytes = (uint32_t)src_size;
|
||||
header.n_payload_bytes = (uint32_t)sz;
|
||||
memcpy(dst_buffer, &header, sizeof(header));
|
||||
store4(dst_buffer + sizeof(lzvn_compressed_block_header) + sz,
|
||||
LZFSE_ENDOFSTREAM_BLOCK_MAGIC);
|
||||
|
||||
return sz + extra_size;
|
||||
}
|
||||
|
||||
// Try encoding with LZFSE
|
||||
{
|
||||
lzfse_encoder_state *state = scratch_buffer;
|
||||
memset(state, 0x00, sizeof *state);
|
||||
if (lzfse_encode_init(state) != LZFSE_STATUS_OK)
|
||||
goto try_uncompressed;
|
||||
state->dst = dst_buffer;
|
||||
state->dst_begin = dst_buffer;
|
||||
state->dst_end = &dst_buffer[dst_size];
|
||||
state->src = src_buffer;
|
||||
state->src_encode_i = 0;
|
||||
|
||||
if (src_size >= 0xffffffffU) {
|
||||
// lzfse only uses 32 bits for offsets internally, so if the input
|
||||
// buffer is really huge, we need to process it in smaller chunks.
|
||||
// Note that we switch over to this path for sizes much smaller
|
||||
// 2GB because it's actually faster to change algorithms well before
|
||||
// it's necessary for correctness.
|
||||
// The first chunk, we just process normally.
|
||||
const lzfse_offset encoder_block_size = 262144;
|
||||
state->src_end = encoder_block_size;
|
||||
if (lzfse_encode_base(state) != LZFSE_STATUS_OK)
|
||||
goto try_uncompressed;
|
||||
src_size -= encoder_block_size;
|
||||
while (src_size >= encoder_block_size) {
|
||||
// All subsequent chunks require a translation to keep the offsets
|
||||
// from getting too big. Note that we are always going from
|
||||
// encoder_block_size up to 2*encoder_block_size so that the
|
||||
// offsets remain positive (as opposed to resetting to zero and
|
||||
// having negative offsets).
|
||||
state->src_end = 2 * encoder_block_size;
|
||||
if (lzfse_encode_base(state) != LZFSE_STATUS_OK)
|
||||
goto try_uncompressed;
|
||||
lzfse_encode_translate(state, encoder_block_size);
|
||||
src_size -= encoder_block_size;
|
||||
}
|
||||
// Set the end for the final chunk.
|
||||
state->src_end = encoder_block_size + (lzfse_offset)src_size;
|
||||
}
|
||||
// If the source buffer is small enough to use 32-bit offsets, we simply
|
||||
// encode the whole thing in a single chunk.
|
||||
else
|
||||
state->src_end = (lzfse_offset)src_size;
|
||||
// This is either the trailing chunk (if the source file is huge), or
|
||||
// the whole source file.
|
||||
if (lzfse_encode_base(state) != LZFSE_STATUS_OK)
|
||||
goto try_uncompressed;
|
||||
if (lzfse_encode_finish(state) != LZFSE_STATUS_OK)
|
||||
goto try_uncompressed;
|
||||
// No error occured, return compressed size.
|
||||
return state->dst - dst_buffer;
|
||||
}
|
||||
|
||||
try_uncompressed:
|
||||
// Compression failed for some reason. If we can fit the data into the
|
||||
// output buffer uncompressed, go ahead and do that instead.
|
||||
if (original_size + 12 <= dst_size && original_size < INT32_MAX) {
|
||||
uncompressed_block_header header = {.magic = LZFSE_UNCOMPRESSED_BLOCK_MAGIC,
|
||||
.n_raw_bytes = (uint32_t)src_size};
|
||||
uint8_t *dst_end = dst_buffer;
|
||||
memcpy(dst_end, &header, sizeof header);
|
||||
dst_end += sizeof header;
|
||||
memcpy(dst_end, src_buffer, original_size);
|
||||
dst_end += original_size;
|
||||
store4(dst_end, LZFSE_ENDOFSTREAM_BLOCK_MAGIC);
|
||||
dst_end += 4;
|
||||
return dst_end - dst_buffer;
|
||||
}
|
||||
|
||||
// Otherwise, there's nothing we can do, so return zero.
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t lzfse_encode_buffer(uint8_t *__restrict dst_buffer, size_t dst_size,
|
||||
const uint8_t *__restrict src_buffer,
|
||||
size_t src_size, void *__restrict scratch_buffer) {
|
||||
int has_malloc = 0;
|
||||
size_t ret = 0;
|
||||
|
||||
// Deal with the possible NULL pointer
|
||||
if (scratch_buffer == NULL) {
|
||||
// +1 in case scratch size could be zero
|
||||
scratch_buffer = malloc(lzfse_encode_scratch_size() + 1);
|
||||
has_malloc = 1;
|
||||
}
|
||||
if (scratch_buffer == NULL)
|
||||
return 0;
|
||||
ret = lzfse_encode_buffer_with_scratch(dst_buffer,
|
||||
dst_size, src_buffer,
|
||||
src_size, scratch_buffer);
|
||||
if (has_malloc)
|
||||
free(scratch_buffer);
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LZFSE_ENCODE_TABLES_H
|
||||
#define LZFSE_ENCODE_TABLES_H
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# define inline __inline
|
||||
#endif
|
||||
|
||||
static inline uint8_t l_base_from_value(int32_t value) {
|
||||
static const uint8_t sym[LZFSE_ENCODE_MAX_L_VALUE + 1] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16,
|
||||
16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19};
|
||||
return sym[value];
|
||||
}
|
||||
static inline uint8_t m_base_from_value(int32_t value) {
|
||||
static const uint8_t sym[LZFSE_ENCODE_MAX_M_VALUE + 1] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19};
|
||||
return sym[value];
|
||||
}
|
||||
|
||||
static inline uint8_t d_base_from_value(int32_t value) {
|
||||
static const uint8_t sym[64 * 4] = {
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,
|
||||
9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 18, 19, 20, 20, 21, 21,
|
||||
22, 22, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27,
|
||||
27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32,
|
||||
32, 32, 32, 33, 34, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, 40,
|
||||
41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44,
|
||||
44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46,
|
||||
47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 50, 51, 52, 52,
|
||||
53, 53, 54, 54, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58,
|
||||
59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61,
|
||||
61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63,
|
||||
0, 0, 0, 0};
|
||||
int index = 0;
|
||||
int in_range_k;
|
||||
in_range_k = (value >= 0 && value < 60);
|
||||
index |= (((value - 0) >> 0) + 0) & -in_range_k;
|
||||
in_range_k = (value >= 60 && value < 1020);
|
||||
index |= (((value - 60) >> 4) + 64) & -in_range_k;
|
||||
in_range_k = (value >= 1020 && value < 16380);
|
||||
index |= (((value - 1020) >> 8) + 128) & -in_range_k;
|
||||
in_range_k = (value >= 16380 && value < 262140);
|
||||
index |= (((value - 16380) >> 12) + 192) & -in_range_k;
|
||||
return sym[index & 255];
|
||||
}
|
||||
|
||||
#endif // LZFSE_ENCODE_TABLES_H
|
||||
+112
-203
@@ -1,217 +1,126 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
* Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "lzfse_internal.h"
|
||||
|
||||
// Initialize encoder table T[NSYMBOLS].
|
||||
// NSTATES = sum FREQ[i] is the number of states (a power of 2)
|
||||
// NSYMBOLS is the number of symbols.
|
||||
// FREQ[NSYMBOLS] is a normalized histogram of symbol frequencies, with FREQ[i]
|
||||
// >= 0.
|
||||
// Some symbols may have a 0 frequency. In that case, they should not be
|
||||
// present in the data.
|
||||
void fse_init_encoder_table(int nstates, int nsymbols,
|
||||
const uint16_t *__restrict freq,
|
||||
fse_encoder_entry *__restrict t) {
|
||||
int offset = 0; // current offset
|
||||
int n_clz = __builtin_clz(nstates);
|
||||
int i;
|
||||
for (i = 0; i < nsymbols; i++) {
|
||||
int f = (int)freq[i];
|
||||
int k;
|
||||
if (f == 0)
|
||||
continue; // skip this symbol, no occurrences
|
||||
k = __builtin_clz(f) - n_clz; // shift needed to ensure N <= (F<<K) < 2*N
|
||||
t[i].s0 = (int16_t)((f << k) - nstates);
|
||||
t[i].k = (int16_t)k;
|
||||
t[i].delta0 = (int16_t)(offset - f + (nstates >> k));
|
||||
t[i].delta1 = (int16_t)(offset - f + (nstates >> (k - 1)));
|
||||
offset += f;
|
||||
}
|
||||
/*
|
||||
* Initialize decoder table T[NSTATES].
|
||||
* NSTATES = sum FREQ[i] is the number of states (a power of 2)
|
||||
* NSYMBOLS is the number of symbols.
|
||||
* FREQ[NSYMBOLS] is a normalized histogram of symbol frequencies, with FREQ[i]
|
||||
* >= 0.
|
||||
* Some symbols may have a 0 frequency. In that case, they should not be
|
||||
* present in the data.
|
||||
*/
|
||||
int fse_init_decoder_table(int nstates, int nsymbols, const uint16_t *__restrict freq,
|
||||
int32_t *__restrict t)
|
||||
{
|
||||
int n_clz = __builtin_clz(nstates);
|
||||
int sum_of_freq = 0;
|
||||
int i, j0, j;
|
||||
|
||||
for (i = 0; i < nsymbols; i++) {
|
||||
int f = (int)freq[i];
|
||||
int k;
|
||||
|
||||
if (f == 0)
|
||||
continue; /* skip this symbol, no occurrences */
|
||||
|
||||
sum_of_freq += f;
|
||||
|
||||
if (sum_of_freq > nstates)
|
||||
return -1;
|
||||
|
||||
k = __builtin_clz(f) - n_clz; /* shift needed to ensure N <= (F<<K) < 2*N */
|
||||
j0 = ((2 * nstates) >> k) - f;
|
||||
|
||||
/* Initialize all states S reached by this symbol: OFFSET <= S < OFFSET + F */
|
||||
for (j = 0; j < f; j++) {
|
||||
fse_decoder_entry e;
|
||||
|
||||
e.symbol = (uint8_t)i;
|
||||
if (j < j0) {
|
||||
e.k = (int8_t)k;
|
||||
e.delta = (int16_t)(((f + j) << k) - nstates);
|
||||
} else {
|
||||
e.k = (int8_t)(k - 1);
|
||||
e.delta = (int16_t)((j - j0) << (k - 1));
|
||||
}
|
||||
|
||||
memcpy(t, &e, sizeof(e));
|
||||
t++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
// Initialize decoder table T[NSTATES].
|
||||
// NSTATES = sum FREQ[i] is the number of states (a power of 2)
|
||||
// NSYMBOLS is the number of symbols.
|
||||
// FREQ[NSYMBOLS] is a normalized histogram of symbol frequencies, with FREQ[i]
|
||||
// >= 0.
|
||||
// Some symbols may have a 0 frequency. In that case, they should not be
|
||||
// present in the data.
|
||||
int fse_init_decoder_table(int nstates, int nsymbols,
|
||||
const uint16_t *__restrict freq,
|
||||
int32_t *__restrict t) {
|
||||
int n_clz = __builtin_clz(nstates);
|
||||
int sum_of_freq = 0;
|
||||
int i, j0, j;
|
||||
for (i = 0; i < nsymbols; i++) {
|
||||
int f = (int)freq[i];
|
||||
int k;
|
||||
if (f == 0)
|
||||
continue; // skip this symbol, no occurrences
|
||||
/*
|
||||
* Initialize value decoder table T[NSTATES].
|
||||
* NSTATES = sum FREQ[i] is the number of states (a power of 2)
|
||||
* NSYMBOLS is the number of symbols.
|
||||
* FREQ[NSYMBOLS] is a normalized histogram of symbol frequencies, with FREQ[i]
|
||||
* >= 0.
|
||||
* SYMBOL_VBITS[NSYMBOLS] and SYMBOLS_VBASE[NSYMBOLS] are the number of value
|
||||
* bits to read and the base value for each symbol.
|
||||
* Some symbols may have a 0 frequency. In that case, they should not be
|
||||
* present in the data.
|
||||
*/
|
||||
void fse_init_value_decoder_table(int nstates, int nsymbols, const uint16_t *__restrict freq,
|
||||
const uint8_t *__restrict symbol_vbits,
|
||||
const int32_t *__restrict symbol_vbase,
|
||||
struct fse_value_decoder_entry *__restrict t)
|
||||
{
|
||||
int n_clz = __builtin_clz(nstates);
|
||||
int i;
|
||||
|
||||
sum_of_freq += f;
|
||||
for (i = 0; i < nsymbols; i++) {
|
||||
struct fse_value_decoder_entry ei = { 0 };
|
||||
int f = (int)freq[i];
|
||||
int k, j0, j;
|
||||
|
||||
if (sum_of_freq > nstates) {
|
||||
return -1;
|
||||
}
|
||||
if (f == 0)
|
||||
continue; /* skip this symbol, no occurrences */
|
||||
|
||||
k = __builtin_clz(f) - n_clz; // shift needed to ensure N <= (F<<K) < 2*N
|
||||
j0 = ((2 * nstates) >> k) - f;
|
||||
k = __builtin_clz(f) - n_clz; /* shift needed to ensure N <= (F<<K) < 2*N */
|
||||
j0 = ((2 * nstates) >> k) - f;
|
||||
|
||||
// Initialize all states S reached by this symbol: OFFSET <= S < OFFSET + F
|
||||
for (j = 0; j < f; j++) {
|
||||
fse_decoder_entry e;
|
||||
ei.value_bits = symbol_vbits[i];
|
||||
ei.vbase = symbol_vbase[i];
|
||||
|
||||
e.symbol = (uint8_t)i;
|
||||
if (j < j0) {
|
||||
e.k = (int8_t)k;
|
||||
e.delta = (int16_t)(((f + j) << k) - nstates);
|
||||
} else {
|
||||
e.k = (int8_t)(k - 1);
|
||||
e.delta = (int16_t)((j - j0) << (k - 1));
|
||||
}
|
||||
/* Initialize all states S reached by this symbol: OFFSET <= S < OFFSET + F */
|
||||
for (j = 0; j < f; j++) {
|
||||
struct fse_value_decoder_entry e = ei;
|
||||
|
||||
memcpy(t, &e, sizeof(e));
|
||||
t++;
|
||||
}
|
||||
}
|
||||
if (j < j0) {
|
||||
e.total_bits = (uint8_t)k + e.value_bits;
|
||||
e.delta = (int16_t)(((f + j) << k) - nstates);
|
||||
} else {
|
||||
e.total_bits = (uint8_t)(k - 1) + e.value_bits;
|
||||
e.delta = (int16_t)((j - j0) << (k - 1));
|
||||
}
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
// Initialize value decoder table T[NSTATES].
|
||||
// NSTATES = sum FREQ[i] is the number of states (a power of 2)
|
||||
// NSYMBOLS is the number of symbols.
|
||||
// FREQ[NSYMBOLS] is a normalized histogram of symbol frequencies, with FREQ[i]
|
||||
// >= 0.
|
||||
// SYMBOL_VBITS[NSYMBOLS] and SYMBOLS_VBASE[NSYMBOLS] are the number of value
|
||||
// bits to read and the base value for each symbol.
|
||||
// Some symbols may have a 0 frequency. In that case, they should not be
|
||||
// present in the data.
|
||||
void fse_init_value_decoder_table(int nstates, int nsymbols,
|
||||
const uint16_t *__restrict freq,
|
||||
const uint8_t *__restrict symbol_vbits,
|
||||
const int32_t *__restrict symbol_vbase,
|
||||
fse_value_decoder_entry *__restrict t) {
|
||||
int n_clz = __builtin_clz(nstates);
|
||||
int i;
|
||||
for (i = 0; i < nsymbols; i++) {
|
||||
fse_value_decoder_entry ei = {0};
|
||||
int f = (int)freq[i];
|
||||
int k, j0, j;
|
||||
if (f == 0)
|
||||
continue; // skip this symbol, no occurrences
|
||||
|
||||
k = __builtin_clz(f) - n_clz; // shift needed to ensure N <= (F<<K) < 2*N
|
||||
j0 = ((2 * nstates) >> k) - f;
|
||||
|
||||
ei.value_bits = symbol_vbits[i];
|
||||
ei.vbase = symbol_vbase[i];
|
||||
|
||||
// Initialize all states S reached by this symbol: OFFSET <= S < OFFSET + F
|
||||
for (j = 0; j < f; j++) {
|
||||
fse_value_decoder_entry e = ei;
|
||||
|
||||
if (j < j0) {
|
||||
e.total_bits = (uint8_t)k + e.value_bits;
|
||||
e.delta = (int16_t)(((f + j) << k) - nstates);
|
||||
} else {
|
||||
e.total_bits = (uint8_t)(k - 1) + e.value_bits;
|
||||
e.delta = (int16_t)((j - j0) << (k - 1));
|
||||
}
|
||||
|
||||
memcpy(t, &e, 8);
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove states from symbols until the correct number of states is used.
|
||||
static void fse_adjust_freqs(uint16_t *freq, int overrun, int nsymbols) {
|
||||
int shift;
|
||||
for (shift = 3; overrun != 0; shift--) {
|
||||
int sym;
|
||||
for (sym = 0; sym < nsymbols; sym++) {
|
||||
if (freq[sym] > 1) {
|
||||
int n = (freq[sym] - 1) >> shift;
|
||||
if (n > overrun)
|
||||
n = overrun;
|
||||
freq[sym] -= n;
|
||||
overrun -= n;
|
||||
if (overrun == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize a table T[NSYMBOLS] of occurrences to FREQ[NSYMBOLS].
|
||||
void fse_normalize_freq(int nstates, int nsymbols, const uint32_t *__restrict t,
|
||||
uint16_t *__restrict freq) {
|
||||
uint32_t s_count = 0;
|
||||
int remaining = nstates; // must be signed; this may become < 0
|
||||
int max_freq = 0;
|
||||
int max_freq_sym = 0;
|
||||
int shift = __builtin_clz(nstates) - 1;
|
||||
uint32_t highprec_step;
|
||||
int i;
|
||||
|
||||
// Compute the total number of symbol occurrences
|
||||
for (i = 0; i < nsymbols; i++)
|
||||
s_count += t[i];
|
||||
|
||||
if (s_count == 0)
|
||||
highprec_step = 0; // no symbols used
|
||||
else
|
||||
highprec_step = ((uint32_t)1 << 31) / s_count;
|
||||
|
||||
for (i = 0; i < nsymbols; i++) {
|
||||
|
||||
// Rescale the occurrence count to get the normalized frequency.
|
||||
// Round up if the fractional part is >= 0.5; otherwise round down.
|
||||
// For efficiency, we do this calculation using integer arithmetic.
|
||||
int f = (((t[i] * highprec_step) >> shift) + 1) >> 1;
|
||||
|
||||
// If a symbol was used, it must be given a nonzero normalized frequency.
|
||||
if (f == 0 && t[i] != 0)
|
||||
f = 1;
|
||||
|
||||
freq[i] = f;
|
||||
remaining -= f;
|
||||
|
||||
// Remember the maximum frequency and which symbol had it.
|
||||
if (f > max_freq) {
|
||||
max_freq = f;
|
||||
max_freq_sym = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If there remain states to be assigned, then just assign them to the most
|
||||
// frequent symbol. Alternatively, if we assigned more states than were
|
||||
// actually available, then either remove states from the most frequent symbol
|
||||
// (for minor overruns) or use the slower adjustment algorithm (for major
|
||||
// overruns).
|
||||
if (-remaining < (max_freq >> 2)) {
|
||||
freq[max_freq_sym] += remaining;
|
||||
} else {
|
||||
fse_adjust_freqs(freq, -remaining, nsymbols);
|
||||
}
|
||||
memcpy(t, &e, 8);
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
+344
-377
File diff suppressed because it is too large.
Load diff
+341
-469
File diff suppressed because it is too large.
Load diff
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// LZFSE command line tool
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L)
|
||||
# undef _POSIX_C_SOURCE
|
||||
# define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# if !defined(_CRT_NONSTDC_NO_DEPRECATE)
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif
|
||||
# if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif
|
||||
# if !defined(__clang__)
|
||||
# define inline __inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "lzfse.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/time.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Same as realloc(x,s), except x is freed when realloc fails
|
||||
static inline void *lzfse_reallocf(void *x, size_t s) {
|
||||
void *y = realloc(x, s);
|
||||
if (y == 0) {
|
||||
free(x);
|
||||
return 0;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static double get_time() {
|
||||
#if defined(_MSC_VER)
|
||||
LARGE_INTEGER count, freq;
|
||||
if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&count)) {
|
||||
return (double)count.QuadPart / (double)freq.QuadPart;
|
||||
}
|
||||
return 1.0e-3 * (double)GetTickCount();
|
||||
#else
|
||||
struct timeval tv;
|
||||
if (gettimeofday(&tv, 0) != 0) {
|
||||
perror("gettimeofday");
|
||||
exit(1);
|
||||
}
|
||||
return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------
|
||||
|
||||
enum { LZFSE_ENCODE = 0, LZFSE_DECODE };
|
||||
|
||||
void usage(int argc, char **argv) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Usage: %s -encode|-decode [-i input_file] [-o output_file] [-h] [-v]\n",
|
||||
argv[0]);
|
||||
}
|
||||
|
||||
#define USAGE(argc, argv) \
|
||||
do { \
|
||||
usage(argc, argv); \
|
||||
exit(0); \
|
||||
} while (0)
|
||||
#define USAGE_MSG(argc, argv, ...) \
|
||||
do { \
|
||||
usage(argc, argv); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *in_file = 0; // stdin
|
||||
const char *out_file = 0; // stdout
|
||||
int op = -1; // invalid op
|
||||
int verbosity = 0; // quiet
|
||||
|
||||
// Parse options
|
||||
for (int i = 1; i < argc;) {
|
||||
// no args
|
||||
const char *a = argv[i++];
|
||||
if (strcmp(a, "-h") == 0)
|
||||
USAGE(argc, argv);
|
||||
if (strcmp(a, "-v") == 0) {
|
||||
verbosity++;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(a, "-encode") == 0) {
|
||||
op = LZFSE_ENCODE;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(a, "-decode") == 0) {
|
||||
op = LZFSE_DECODE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// one arg
|
||||
const char **arg_var = 0;
|
||||
if (strcmp(a, "-i") == 0 && in_file == 0)
|
||||
arg_var = &in_file;
|
||||
else if (strcmp(a, "-o") == 0 && out_file == 0)
|
||||
arg_var = &out_file;
|
||||
if (arg_var != 0) {
|
||||
// Flag is recognized. Check if there is an argument.
|
||||
if (i == argc)
|
||||
USAGE_MSG(argc, argv, "Error: Missing arg after %s\n", a);
|
||||
*arg_var = argv[i++];
|
||||
continue;
|
||||
}
|
||||
|
||||
USAGE_MSG(argc, argv, "Error: invalid flag %s\n", a);
|
||||
}
|
||||
if (op < 0)
|
||||
USAGE_MSG(argc, argv, "Error: -encode|-decode required\n");
|
||||
|
||||
// Info
|
||||
if (verbosity > 0) {
|
||||
if (op == LZFSE_ENCODE)
|
||||
fprintf(stderr, "LZFSE encode\n");
|
||||
if (op == LZFSE_DECODE)
|
||||
fprintf(stderr, "LZFSE decode\n");
|
||||
fprintf(stderr, "Input: %s\n", in_file ? in_file : "stdin");
|
||||
fprintf(stderr, "Output: %s\n", out_file ? out_file : "stdout");
|
||||
}
|
||||
|
||||
// Load input
|
||||
size_t in_allocated = 0; // allocated in IN
|
||||
size_t in_size = 0; // used in IN
|
||||
uint8_t *in = 0; // input buffer
|
||||
int in_fd = -1; // input file desc
|
||||
|
||||
if (in_file != 0) {
|
||||
// If we have a file name, open it, and allocate the exact input size
|
||||
struct stat st;
|
||||
#if defined(_WIN32)
|
||||
in_fd = open(in_file, O_RDONLY | O_BINARY);
|
||||
#else
|
||||
in_fd = open(in_file, O_RDONLY);
|
||||
#endif
|
||||
if (in_fd < 0) {
|
||||
perror(in_file);
|
||||
exit(1);
|
||||
}
|
||||
if (fstat(in_fd, &st) != 0) {
|
||||
perror(in_file);
|
||||
exit(1);
|
||||
}
|
||||
if (st.st_size > SIZE_MAX) {
|
||||
fprintf(stderr, "File is too large\n");
|
||||
exit(1);
|
||||
}
|
||||
in_allocated = (size_t)st.st_size;
|
||||
} else {
|
||||
// Otherwise, read from stdin, and allocate to 1 MB, grow as needed
|
||||
in_allocated = 1 << 20;
|
||||
in_fd = 0;
|
||||
#if defined(_WIN32)
|
||||
if (setmode(in_fd, O_BINARY) == -1) {
|
||||
perror("setmode");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
in = (uint8_t *)malloc(in_allocated);
|
||||
if (in == 0) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// re-alloc if needed
|
||||
if (in_size == in_allocated) {
|
||||
if (in_allocated < (100 << 20))
|
||||
in_allocated <<= 1; // double it
|
||||
else
|
||||
in_allocated += (100 << 20); // or add 100 MB if already large
|
||||
in = lzfse_reallocf(in, in_allocated);
|
||||
if (in == 0) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ptrdiff_t r = read(in_fd, in + in_size, in_allocated - in_size);
|
||||
if (r < 0) {
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
if (r == 0)
|
||||
break; // end of file
|
||||
in_size += (size_t)r;
|
||||
}
|
||||
|
||||
if (in_file != 0) {
|
||||
close(in_fd);
|
||||
in_fd = -1;
|
||||
}
|
||||
|
||||
// Size info
|
||||
if (verbosity > 0) {
|
||||
fprintf(stderr, "Input size: %zu B\n", in_size);
|
||||
}
|
||||
|
||||
// Encode/decode
|
||||
// Compute size for result buffer; we assume here that encode shrinks size,
|
||||
// and that decode grows by no more than 4x. These are reasonable common-
|
||||
// case guidelines, but are not formally guaranteed to be satisfied.
|
||||
size_t out_allocated = (op == LZFSE_ENCODE) ? in_size : (4 * in_size);
|
||||
size_t out_size = 0;
|
||||
size_t aux_allocated = (op == LZFSE_ENCODE) ? lzfse_encode_scratch_size()
|
||||
: lzfse_decode_scratch_size();
|
||||
void *aux = aux_allocated ? malloc(aux_allocated) : 0;
|
||||
if (aux_allocated != 0 && aux == 0) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
uint8_t *out = (uint8_t *)malloc(out_allocated);
|
||||
if (out == 0) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
double c0 = get_time();
|
||||
while (1) {
|
||||
if (op == LZFSE_ENCODE)
|
||||
out_size = lzfse_encode_buffer(out, out_allocated, in, in_size, aux);
|
||||
else
|
||||
out_size = lzfse_decode_buffer(out, out_allocated, in, in_size, aux);
|
||||
|
||||
// If output buffer was too small, grow and retry.
|
||||
if (out_size == 0 || (op == LZFSE_DECODE && out_size == out_allocated)) {
|
||||
if (verbosity > 0)
|
||||
fprintf(stderr, "Output buffer was too small, increasing size...\n");
|
||||
out_allocated <<= 1;
|
||||
out = (uint8_t *)lzfse_reallocf(out, out_allocated);
|
||||
if (out == 0) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
double c1 = get_time();
|
||||
|
||||
if (verbosity > 0) {
|
||||
fprintf(stderr, "Output size: %zu B\n", out_size);
|
||||
size_t raw_size = (op == LZFSE_ENCODE) ? in_size : out_size;
|
||||
size_t compressed_size = (op == LZFSE_ENCODE) ? out_size : in_size;
|
||||
fprintf(stderr, "Compression ratio: %.3f\n",
|
||||
(double)raw_size / (double)compressed_size);
|
||||
double ns_per_byte = 1.0e9 * (c1 - c0) / (double)raw_size;
|
||||
double mb_per_s = (double)raw_size / 1024.0 / 1024.0 / (c1 - c0);
|
||||
fprintf(stderr, "Speed: %.2f ns/B, %.2f MB/s\n",ns_per_byte,mb_per_s);
|
||||
}
|
||||
|
||||
// Write output
|
||||
int out_fd = -1;
|
||||
if (out_file) {
|
||||
#if defined(_WIN32)
|
||||
out_fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
|
||||
S_IWRITE);
|
||||
#else
|
||||
out_fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
#endif
|
||||
if (out_fd < 0) {
|
||||
perror(out_file);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
out_fd = 1; // stdout
|
||||
#if defined(_WIN32)
|
||||
if (setmode(out_fd, O_BINARY) == -1) {
|
||||
perror("setmode");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for (size_t out_pos = 0; out_pos < out_size;) {
|
||||
ptrdiff_t w = write(out_fd, out + out_pos, out_size - out_pos);
|
||||
if (w < 0) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
if (w == 0) {
|
||||
fprintf(stderr, "Failed to write to output file\n");
|
||||
exit(1);
|
||||
}
|
||||
out_pos += (size_t)w;
|
||||
}
|
||||
if (out_file != 0) {
|
||||
close(out_fd);
|
||||
out_fd = -1;
|
||||
}
|
||||
|
||||
free(in);
|
||||
free(out);
|
||||
free(aux);
|
||||
return 0; // OK
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LZFSE_TUNABLES_H
|
||||
#define LZFSE_TUNABLES_H
|
||||
|
||||
// Parameters controlling details of the LZ-style match search. These values
|
||||
// may be modified to fine tune compression ratio vs. encoding speed, while
|
||||
// keeping the compressed format compatible with LZFSE. Note that
|
||||
// modifying them will also change the amount of work space required by
|
||||
// the encoder. The values here are those used in the compression library
|
||||
// on iOS and OS X.
|
||||
|
||||
// Number of bits for hash function to produce. Should be in the range
|
||||
// [10, 16]. Larger values reduce the number of false-positive found during
|
||||
// the match search, and expand the history table, which may allow additional
|
||||
// matches to be found, generally improving the achieved compression ratio.
|
||||
// Larger values also increase the workspace size, and make it less likely
|
||||
// that the history table will be present in cache, which reduces performance.
|
||||
#define LZFSE_ENCODE_HASH_BITS 14
|
||||
|
||||
// Number of positions to store for each line in the history table. May
|
||||
// be either 4 or 8. Using 8 doubles the size of the history table, which
|
||||
// increases the chance of finding matches (thus improving compression ratio),
|
||||
// but also increases the workspace size.
|
||||
#define LZFSE_ENCODE_HASH_WIDTH 4
|
||||
|
||||
// Match length in bytes to cause immediate emission. Generally speaking,
|
||||
// LZFSE maintains multiple candidate matches and waits to decide which match
|
||||
// to emit until more information is available. When a match exceeds this
|
||||
// threshold, it is emitted immediately. Thus, smaller values may give
|
||||
// somewhat better performance, and larger values may give somewhat better
|
||||
// compression ratios.
|
||||
#define LZFSE_ENCODE_GOOD_MATCH 40
|
||||
|
||||
// When the source buffer is very small, LZFSE doesn't compress as well as
|
||||
// some simpler algorithms. To maintain reasonable compression for these
|
||||
// cases, we transition to use LZVN instead if the size of the source buffer
|
||||
// is below this threshold.
|
||||
#define LZFSE_ENCODE_LZVN_THRESHOLD 4096
|
||||
|
||||
#endif // LZFSE_TUNABLES_H
|
||||
Loaded 20 of 30 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user