qlzruby 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +50 -0
- data/ext/extconf.rb +16 -0
- data/ext/qlzruby.c +16 -118
- metadata +24 -11
- data/README.txt +0 -76
- data/ext/quicklz/quicklz.c +0 -948
data/README
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= QuickLZ/Ruby
|
2
|
+
|
3
|
+
Copyright (c) 2008 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
Ruby bindings for QuickLZ.
|
8
|
+
|
9
|
+
QuickLZ is a data compression library which gives fast compression.
|
10
|
+
|
11
|
+
== Source Code
|
12
|
+
|
13
|
+
https://bitbucket.org/winebarrel/quick-ruby
|
14
|
+
|
15
|
+
== Install
|
16
|
+
|
17
|
+
gem install qlzruby
|
18
|
+
|
19
|
+
== Example
|
20
|
+
|
21
|
+
require 'qlzruby'
|
22
|
+
require 'open-uri'
|
23
|
+
require 'stringio'
|
24
|
+
|
25
|
+
source = <<-EOS
|
26
|
+
London Bridge Is falling down,
|
27
|
+
Falling down, Falling down.
|
28
|
+
London Bridge Is falling down,
|
29
|
+
My fair lady.
|
30
|
+
EOS
|
31
|
+
|
32
|
+
comp_data = QuickLZ.compress(source)
|
33
|
+
decomp_data = QuickLZ.decompress(comp_data)
|
34
|
+
|
35
|
+
puts <<-EOS
|
36
|
+
- block compress -
|
37
|
+
uncompress size: #{source.length}
|
38
|
+
compress size: #{comp_data.length}
|
39
|
+
decompress size: #{decomp_data.length}
|
40
|
+
decompress success?: #{source == decomp_data}
|
41
|
+
EOS
|
42
|
+
|
43
|
+
=== QuickLZ
|
44
|
+
|
45
|
+
QuickLZ/Ruby contains QuickLZ.
|
46
|
+
|
47
|
+
QuickLZ is a data compression library which gives fast compression.
|
48
|
+
|
49
|
+
* http://www.quicklz.com/
|
50
|
+
* Copyright 2006-2008 Lasse Reinhold
|
data/ext/extconf.rb
CHANGED
@@ -1,2 +1,18 @@
|
|
1
1
|
require 'mkmf'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
def download(url)
|
5
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
6
|
+
dst = File.join(dir, File.basename(url))
|
7
|
+
|
8
|
+
open(url) do |src|
|
9
|
+
open(dst, 'w') do |f|
|
10
|
+
f << src.read
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
download 'http://www.quicklz.com/quicklz.h'
|
16
|
+
download 'http://www.quicklz.com/quicklz.c'
|
17
|
+
|
2
18
|
create_makefile('qlzruby')
|
data/ext/qlzruby.c
CHANGED
@@ -6,7 +6,7 @@ __declspec(dllexport) void Init_qlzruby(void);
|
|
6
6
|
#endif
|
7
7
|
|
8
8
|
#include <string.h>
|
9
|
-
#include "quicklz
|
9
|
+
#include "quicklz.h"
|
10
10
|
#include "ruby.h"
|
11
11
|
|
12
12
|
#ifndef RSTRING_PTR
|
@@ -26,155 +26,53 @@ __declspec(dllexport) void Init_qlzruby(void);
|
|
26
26
|
} \
|
27
27
|
} while(0)
|
28
28
|
|
29
|
-
#define VERSION "0.1.
|
29
|
+
#define VERSION "0.1.2"
|
30
30
|
#define DEFAULT_BLOCKSIZE 5120
|
31
31
|
#define HEADER_LEN 9
|
32
32
|
|
33
33
|
/* */
|
34
|
-
static VALUE
|
34
|
+
static VALUE qlzruby_compress(VALUE self, VALUE v_src) {
|
35
35
|
VALUE v_dst;
|
36
|
-
char *src, *dst
|
36
|
+
char *src, *dst;
|
37
|
+
qlz_state_compress *state_compress;
|
37
38
|
size_t len;
|
38
39
|
|
39
40
|
Check_Type(v_src, T_STRING);
|
40
41
|
src = RSTRING_PTR(v_src);
|
41
42
|
len = RSTRING_LEN(v_src);
|
43
|
+
state_compress = (qlz_state_compress *) xmalloc(sizeof(qlz_state_compress));
|
42
44
|
dst = xmalloc(len + 400);
|
43
|
-
|
44
|
-
memset(scratch, 0, SCRATCH_COMPRESS);
|
45
|
-
len = qlz_compress(src, dst, len, scratch);
|
45
|
+
len = qlz_compress(src, dst, len, state_compress);
|
46
46
|
v_dst = rb_str_new(dst, len);
|
47
|
-
xfree(
|
47
|
+
xfree(state_compress);
|
48
48
|
xfree(dst);
|
49
49
|
|
50
50
|
return v_dst;
|
51
51
|
}
|
52
52
|
|
53
53
|
/* */
|
54
|
-
static VALUE
|
54
|
+
static VALUE qlzruby_decompress(VALUE self, VALUE v_src) {
|
55
55
|
VALUE v_dst;
|
56
|
-
char *src, *dst
|
56
|
+
char *src, *dst;
|
57
|
+
qlz_state_decompress *state_decompress;
|
57
58
|
size_t len;
|
58
59
|
|
59
60
|
Check_Type(v_src, T_STRING);
|
60
61
|
src = RSTRING_PTR(v_src);
|
61
62
|
len = qlz_size_decompressed(src);
|
62
63
|
dst = xmalloc(len);
|
63
|
-
|
64
|
-
|
65
|
-
len = qlz_decompress(src, dst, scratch);
|
64
|
+
state_decompress = (qlz_state_decompress *) xmalloc(sizeof(qlz_state_decompress));
|
65
|
+
len = qlz_decompress(src, dst, state_decompress);
|
66
66
|
v_dst = rb_str_new(dst, len);
|
67
|
-
xfree(
|
67
|
+
xfree(state_decompress);
|
68
68
|
xfree(dst);
|
69
69
|
|
70
70
|
return v_dst;
|
71
71
|
}
|
72
72
|
|
73
|
-
/* */
|
74
|
-
static VALUE qlzruby_stream_compress(int argc, const VALUE *argv, VALUE self) {
|
75
|
-
VALUE in, out, blocksize, v_src, v_dst;
|
76
|
-
char *src, *dst, *scratch;
|
77
|
-
size_t len, i_blocksize;
|
78
|
-
|
79
|
-
rb_scan_args(argc, argv, "21", &in, &out, &blocksize);
|
80
|
-
Check_IO(in);
|
81
|
-
Check_IO(out);
|
82
|
-
|
83
|
-
if (NIL_P(blocksize)) {
|
84
|
-
blocksize = INT2FIX(DEFAULT_BLOCKSIZE);
|
85
|
-
i_blocksize = DEFAULT_BLOCKSIZE;
|
86
|
-
} else {
|
87
|
-
i_blocksize = NUM2LONG(blocksize);
|
88
|
-
|
89
|
-
if (i_blocksize < 1) {
|
90
|
-
blocksize = INT2FIX(DEFAULT_BLOCKSIZE);
|
91
|
-
i_blocksize = DEFAULT_BLOCKSIZE;
|
92
|
-
}
|
93
|
-
}
|
94
|
-
|
95
|
-
dst = alloca(i_blocksize + 400);
|
96
|
-
scratch = alloca(SCRATCH_COMPRESS);
|
97
|
-
memset(scratch, 0, SCRATCH_COMPRESS);
|
98
|
-
|
99
|
-
while (1) {
|
100
|
-
v_src = rb_funcall(in, rb_intern("read"), 1, blocksize);
|
101
|
-
|
102
|
-
if (NIL_P(v_src)) { break; }
|
103
|
-
|
104
|
-
src = RSTRING_PTR(v_src);
|
105
|
-
len = RSTRING_LEN(v_src);
|
106
|
-
|
107
|
-
if (len < 1) { break; }
|
108
|
-
|
109
|
-
len = qlz_compress(src, dst, len, scratch);
|
110
|
-
v_dst = rb_str_new(dst, len);
|
111
|
-
rb_funcall(out, rb_intern("write"), 1, v_dst);
|
112
|
-
}
|
113
|
-
|
114
|
-
return Qnil;
|
115
|
-
}
|
116
|
-
|
117
|
-
static size_t qlzruby_stream_decompress_block(VALUE in, VALUE out, char *scratch) {
|
118
|
-
VALUE v_header, v_src, v_dst;
|
119
|
-
char *header, *src, *dst;
|
120
|
-
size_t header_len, len;
|
121
|
-
|
122
|
-
v_header = rb_funcall(in, rb_intern("read"), 1, INT2FIX(HEADER_LEN));
|
123
|
-
|
124
|
-
if (NIL_P(v_header)) { return 0; }
|
125
|
-
|
126
|
-
header = RSTRING_PTR(v_header);
|
127
|
-
header_len = RSTRING_LEN(v_header);
|
128
|
-
|
129
|
-
if (header_len < HEADER_LEN) { return 0; }
|
130
|
-
|
131
|
-
len = qlz_size_compressed(header);
|
132
|
-
v_src = rb_funcall(in, rb_intern("read"), 1, INT2FIX(len - HEADER_LEN));
|
133
|
-
len = RSTRING_LEN(v_src);
|
134
|
-
|
135
|
-
if (len < 1) { return 0; }
|
136
|
-
|
137
|
-
len += HEADER_LEN;
|
138
|
-
src = alloca(len);
|
139
|
-
memcpy(src, header, HEADER_LEN);
|
140
|
-
memcpy(src + HEADER_LEN, RSTRING_PTR(v_src), len - HEADER_LEN);
|
141
|
-
|
142
|
-
len = qlz_size_decompressed(src);
|
143
|
-
dst = alloca(len);
|
144
|
-
len = qlz_decompress(src, dst, scratch);
|
145
|
-
v_dst = rb_str_new(dst, len);
|
146
|
-
rb_funcall(out, rb_intern("write"), 1, v_dst);
|
147
|
-
|
148
|
-
return len;
|
149
|
-
}
|
150
|
-
|
151
|
-
/* */
|
152
|
-
static VALUE qlzruby_stream_decompress(VALUE self, VALUE in, VALUE out) {
|
153
|
-
char *scratch;
|
154
|
-
|
155
|
-
Check_IO(in);
|
156
|
-
Check_IO(out);
|
157
|
-
|
158
|
-
scratch = alloca(SCRATCH_DECOMPRESS);
|
159
|
-
memset(scratch, 0, SCRATCH_DECOMPRESS);
|
160
|
-
|
161
|
-
while (1) {
|
162
|
-
int len = qlzruby_stream_decompress_block(in, out, scratch);
|
163
|
-
|
164
|
-
if (len < 1) {
|
165
|
-
break;
|
166
|
-
}
|
167
|
-
}
|
168
|
-
|
169
|
-
return Qnil;
|
170
|
-
|
171
|
-
}
|
172
|
-
|
173
73
|
void Init_qlzruby() {
|
174
74
|
VALUE QuickLZ = rb_define_module("QuickLZ");
|
175
75
|
rb_define_const(QuickLZ, "VERSION", rb_str_new2(VERSION));
|
176
|
-
rb_define_module_function(QuickLZ, "
|
177
|
-
rb_define_module_function(QuickLZ, "
|
178
|
-
rb_define_module_function(QuickLZ, "stream_compress", qlzruby_stream_compress, -1);
|
179
|
-
rb_define_module_function(QuickLZ, "stream_decompress", qlzruby_stream_decompress, 2);
|
76
|
+
rb_define_module_function(QuickLZ, "compress", qlzruby_compress, 1);
|
77
|
+
rb_define_module_function(QuickLZ, "decompress", qlzruby_decompress, 1);
|
180
78
|
}
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qlzruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- winebarrel
|
@@ -9,7 +15,7 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2011-01-13 00:00:00 +09:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
@@ -20,17 +26,18 @@ executables: []
|
|
20
26
|
extensions:
|
21
27
|
- ext/extconf.rb
|
22
28
|
extra_rdoc_files:
|
23
|
-
- README
|
29
|
+
- README
|
24
30
|
- ext/qlzruby.c
|
25
31
|
- LICENSE.txt
|
26
32
|
files:
|
27
33
|
- ext/qlzruby.c
|
28
|
-
- ext/quicklz/quicklz.c
|
29
34
|
- ext/extconf.rb
|
30
|
-
- README
|
35
|
+
- README
|
31
36
|
- LICENSE.txt
|
32
37
|
has_rdoc: true
|
33
|
-
homepage:
|
38
|
+
homepage: https://bitbucket.org/winebarrel/quick-ruby
|
39
|
+
licenses: []
|
40
|
+
|
34
41
|
post_install_message:
|
35
42
|
rdoc_options:
|
36
43
|
- --title
|
@@ -38,23 +45,29 @@ rdoc_options:
|
|
38
45
|
require_paths:
|
39
46
|
- lib
|
40
47
|
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
41
49
|
requirements:
|
42
50
|
- - ">="
|
43
51
|
- !ruby/object:Gem::Version
|
52
|
+
hash: 3
|
53
|
+
segments:
|
54
|
+
- 0
|
44
55
|
version: "0"
|
45
|
-
version:
|
46
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
47
58
|
requirements:
|
48
59
|
- - ">="
|
49
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
50
64
|
version: "0"
|
51
|
-
version:
|
52
65
|
requirements: []
|
53
66
|
|
54
|
-
rubyforge_project:
|
55
|
-
rubygems_version: 1.
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.3.7
|
56
69
|
signing_key:
|
57
|
-
specification_version:
|
70
|
+
specification_version: 3
|
58
71
|
summary: Ruby bindings for QuickLZ.
|
59
72
|
test_files: []
|
60
73
|
|
data/README.txt
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
= QuickLZ/Ruby
|
2
|
-
|
3
|
-
Copyright (c) 2008 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
4
|
-
|
5
|
-
== Description
|
6
|
-
|
7
|
-
Ruby bindings for QuickLZ.
|
8
|
-
|
9
|
-
QuickLZ is a data compression library which gives fast compression.
|
10
|
-
|
11
|
-
== Project Page
|
12
|
-
|
13
|
-
http://rubyforge.org/projects/qlzruby
|
14
|
-
|
15
|
-
== Install
|
16
|
-
|
17
|
-
gem install qlzruby
|
18
|
-
|
19
|
-
== Download
|
20
|
-
|
21
|
-
http://rubyforge.org/frs/?group_id=6766
|
22
|
-
|
23
|
-
== Example
|
24
|
-
|
25
|
-
require 'qlzruby'
|
26
|
-
require 'open-uri'
|
27
|
-
require 'stringio'
|
28
|
-
|
29
|
-
# block compress
|
30
|
-
source = <<-EOS
|
31
|
-
London Bridge Is falling down,
|
32
|
-
Falling down, Falling down.
|
33
|
-
London Bridge Is falling down,
|
34
|
-
My fair lady.
|
35
|
-
EOS
|
36
|
-
|
37
|
-
comp_data = QuickLZ.block_compress(source)
|
38
|
-
decomp_data = QuickLZ.block_decompress(comp_data)
|
39
|
-
|
40
|
-
puts <<-EOS
|
41
|
-
- block compress -
|
42
|
-
uncompress size: #{source.length}
|
43
|
-
compress size: #{comp_data.length}
|
44
|
-
decompress size: #{decomp_data.length}
|
45
|
-
decompress success?: #{source == decomp_data}
|
46
|
-
|
47
|
-
EOS
|
48
|
-
|
49
|
-
# stream compress
|
50
|
-
source = open('http://www.ruby-lang.org/') {|f| f.read }
|
51
|
-
source = StringIO.new(source)
|
52
|
-
comp_data = StringIO.new
|
53
|
-
|
54
|
-
QuickLZ.stream_compress(source, comp_data)
|
55
|
-
|
56
|
-
comp_data.seek(0)
|
57
|
-
decomp_data = StringIO.new
|
58
|
-
|
59
|
-
QuickLZ.stream_decompress(comp_data, decomp_data)
|
60
|
-
|
61
|
-
puts <<-EOS
|
62
|
-
- stream compress -
|
63
|
-
uncompress size: #{source.length}
|
64
|
-
compress size: #{comp_data.length}
|
65
|
-
decompress size: #{decomp_data.length}
|
66
|
-
decompress success?: #{source.string == decomp_data.string}
|
67
|
-
EOS
|
68
|
-
|
69
|
-
=== QuickLZ
|
70
|
-
|
71
|
-
QuickLZ/Ruby contains QuickLZ.
|
72
|
-
|
73
|
-
QuickLZ is a data compression library which gives fast compression.
|
74
|
-
|
75
|
-
* http://www.quicklz.com/
|
76
|
-
* Copyright 2006-2008 Lasse Reinhold
|
data/ext/quicklz/quicklz.c
DELETED
@@ -1,948 +0,0 @@
|
|
1
|
-
// QuickLZ data compression library
|
2
|
-
// Copyright (C) 2006-2007 Lasse Mikkel Reinhold
|
3
|
-
// lar@quicklz.com
|
4
|
-
//
|
5
|
-
// QuickLZ can be used for free under the GPL-1 or GPL-2 license (where anything
|
6
|
-
// released into public must be open source) or under a commercial license if such
|
7
|
-
// has been acquired (see http://www.quicklz.com/order.html). The commercial license
|
8
|
-
// does not cover derived or ported versions created by third parties under GPL.
|
9
|
-
|
10
|
-
// Version 1.31 final
|
11
|
-
#define QLZ_VERSION_MAJOR 1
|
12
|
-
#define QLZ_VERSION_MINOR 3
|
13
|
-
#define QLZ_VERSION_REVISION 1
|
14
|
-
|
15
|
-
// Set following flags according to the manual
|
16
|
-
#define COMPRESSION_LEVEL 0
|
17
|
-
#define STREAMING_MODE 960000
|
18
|
-
#define test_rle
|
19
|
-
#define speedup_incompressible
|
20
|
-
//#define memory_safe
|
21
|
-
|
22
|
-
// Public functions of QuickLZ
|
23
|
-
size_t qlz_decompress(const char *source, void *destination, char *scratch);
|
24
|
-
size_t qlz_compress(const void *source, char *destination, size_t size, char *scratch);
|
25
|
-
size_t qlz_size_decompressed(const char *source);
|
26
|
-
size_t qlz_size_compressed(const char *source);
|
27
|
-
int qlz_get_setting(int setting);
|
28
|
-
|
29
|
-
#include <string.h>
|
30
|
-
|
31
|
-
#if (defined(__X86__) || defined(__i386__) || defined(i386) || defined(_M_IX86) || defined(__386__) || defined(__x86_64__) || defined(_M_X64))
|
32
|
-
#define X86X64
|
33
|
-
#endif
|
34
|
-
|
35
|
-
// Compute SCRATCH_COMPRESS, SCRATCH_DECOMPRESS and constants used internally
|
36
|
-
#if COMPRESSION_LEVEL == 0 && defined(memory_safe)
|
37
|
-
#error memory_safe flag cannot be used with COMPRESSION_LEVEL 0
|
38
|
-
#endif
|
39
|
-
|
40
|
-
#define HASH_ENTRIES 4096
|
41
|
-
|
42
|
-
#if (COMPRESSION_LEVEL == 0 || COMPRESSION_LEVEL == 1 || COMPRESSION_LEVEL == 2)
|
43
|
-
#define AND 1
|
44
|
-
#elif (COMPRESSION_LEVEL == 3)
|
45
|
-
#define AND 0x7
|
46
|
-
#else
|
47
|
-
#error COMPRESSION_LEVEL must be 0, 1, 2 or 3
|
48
|
-
#endif
|
49
|
-
|
50
|
-
#define HASH_SIZE (AND + 1)*HASH_ENTRIES*sizeof(unsigned char *)
|
51
|
-
|
52
|
-
#ifdef STREAMING_MODE
|
53
|
-
#define STREAMING_MODE_VALUE STREAMING_MODE
|
54
|
-
#else
|
55
|
-
#define STREAMING_MODE_VALUE 0
|
56
|
-
#endif
|
57
|
-
|
58
|
-
#define STREAMING_MODE_ROUNDED ((STREAMING_MODE_VALUE >> 3) << 3)
|
59
|
-
|
60
|
-
#if (COMPRESSION_LEVEL > 1)
|
61
|
-
#define SCRATCH_COMPRESS HASH_SIZE + STREAMING_MODE_VALUE + 16 + HASH_ENTRIES
|
62
|
-
#else
|
63
|
-
#define SCRATCH_COMPRESS HASH_SIZE + STREAMING_MODE_VALUE + 16
|
64
|
-
#endif
|
65
|
-
|
66
|
-
#if (COMPRESSION_LEVEL == 0)
|
67
|
-
#define SCRATCH_DECOMPRESS HASH_ENTRIES*sizeof(unsigned char *) + 16 + STREAMING_MODE_VALUE
|
68
|
-
#else
|
69
|
-
#define SCRATCH_DECOMPRESS 16 + STREAMING_MODE_VALUE
|
70
|
-
#endif
|
71
|
-
|
72
|
-
int qlz_get_setting(int setting)
|
73
|
-
{
|
74
|
-
switch (setting)
|
75
|
-
{
|
76
|
-
case 0: return COMPRESSION_LEVEL;
|
77
|
-
case 1: return SCRATCH_COMPRESS;
|
78
|
-
case 2: return SCRATCH_DECOMPRESS;
|
79
|
-
case 3: return STREAMING_MODE_VALUE;
|
80
|
-
#ifdef test_rle
|
81
|
-
case 4: return 1;
|
82
|
-
#else
|
83
|
-
case 4: return 0;
|
84
|
-
#endif
|
85
|
-
#ifdef speedup_incompressible
|
86
|
-
case 5: return 1;
|
87
|
-
#else
|
88
|
-
case 5: return 0;
|
89
|
-
#endif
|
90
|
-
#ifdef memory_safe
|
91
|
-
case 6: return 1;
|
92
|
-
#else
|
93
|
-
case 6: return 0;
|
94
|
-
#endif
|
95
|
-
case 7: return QLZ_VERSION_MAJOR;
|
96
|
-
case 8: return QLZ_VERSION_MINOR;
|
97
|
-
case 9: return QLZ_VERSION_REVISION;
|
98
|
-
}
|
99
|
-
return -1;
|
100
|
-
}
|
101
|
-
|
102
|
-
__inline unsigned int hash_func(unsigned int i)
|
103
|
-
{
|
104
|
-
return ((i >> 12) ^ i) & 0x0fff;
|
105
|
-
}
|
106
|
-
|
107
|
-
__inline unsigned int fast_read(void const *src, unsigned int bytes)
|
108
|
-
{
|
109
|
-
#ifndef X86X64
|
110
|
-
unsigned char *p = (unsigned char*)src;
|
111
|
-
switch (bytes)
|
112
|
-
{
|
113
|
-
case 4:
|
114
|
-
return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24);
|
115
|
-
case 3:
|
116
|
-
return(*p | *(p + 1) << 8 | *(p + 2) << 16);
|
117
|
-
case 2:
|
118
|
-
return(*p | *(p + 1) << 8);
|
119
|
-
case 1:
|
120
|
-
return(*p);
|
121
|
-
}
|
122
|
-
return 0;
|
123
|
-
#else
|
124
|
-
if (bytes >= 1 && bytes <= 4)
|
125
|
-
return *((unsigned int*)src);
|
126
|
-
else
|
127
|
-
return 0;
|
128
|
-
#endif
|
129
|
-
}
|
130
|
-
|
131
|
-
__inline void fast_write(unsigned int f, void *dst, unsigned int bytes)
|
132
|
-
{
|
133
|
-
#ifndef X86X64
|
134
|
-
unsigned char *p = (unsigned char*)dst;
|
135
|
-
|
136
|
-
switch (bytes)
|
137
|
-
{
|
138
|
-
case 4:
|
139
|
-
*p = (unsigned char)f;
|
140
|
-
*(p + 1) = (unsigned char)(f >> 8);
|
141
|
-
*(p + 2) = (unsigned char)(f >> 16);
|
142
|
-
*(p + 3) = (unsigned char)(f >> 24);
|
143
|
-
return;
|
144
|
-
case 3:
|
145
|
-
*p = (unsigned char)f;
|
146
|
-
*(p + 1) = (unsigned char)(f >> 8);
|
147
|
-
*(p + 2) = (unsigned char)(f >> 16);
|
148
|
-
return;
|
149
|
-
case 2:
|
150
|
-
*p = (unsigned char)f;
|
151
|
-
*(p + 1) = (unsigned char)(f >> 8);
|
152
|
-
return;
|
153
|
-
case 1:
|
154
|
-
*p = (unsigned char)f;
|
155
|
-
return;
|
156
|
-
}
|
157
|
-
#else
|
158
|
-
switch (bytes)
|
159
|
-
{
|
160
|
-
case 4:
|
161
|
-
*((unsigned int*)dst) = f;
|
162
|
-
return;
|
163
|
-
case 3:
|
164
|
-
*((unsigned int*)dst) = f;
|
165
|
-
return;
|
166
|
-
case 2:
|
167
|
-
#if COMPRESSION_LEVEL == 0
|
168
|
-
// 2 byte writes are common in level 0
|
169
|
-
*((unsigned short int*)dst) = (unsigned short int)f;
|
170
|
-
#else
|
171
|
-
*((unsigned int*)dst) = f;
|
172
|
-
#endif
|
173
|
-
return;
|
174
|
-
case 1:
|
175
|
-
*((unsigned char*)dst) = (unsigned char)f;
|
176
|
-
return;
|
177
|
-
}
|
178
|
-
#endif
|
179
|
-
}
|
180
|
-
|
181
|
-
__inline void memcpy_up(unsigned char *dst, const unsigned char *src, unsigned int n)
|
182
|
-
{
|
183
|
-
// cannot be replaced by overlap handling of memmove() due to LZSS algorithm
|
184
|
-
#ifndef X86X64
|
185
|
-
|
186
|
-
if(n > 8 && src + n < dst)
|
187
|
-
memcpy(dst, src, n);
|
188
|
-
else
|
189
|
-
{
|
190
|
-
unsigned char *end = dst + n;
|
191
|
-
while(dst < end)
|
192
|
-
{
|
193
|
-
*dst = *src;
|
194
|
-
dst++;
|
195
|
-
src++;
|
196
|
-
}
|
197
|
-
}
|
198
|
-
#else
|
199
|
-
if (n < 5)
|
200
|
-
*((unsigned int*)dst) = *((unsigned int*)src);
|
201
|
-
else
|
202
|
-
{
|
203
|
-
unsigned char *end = dst + n;
|
204
|
-
while(dst < end)
|
205
|
-
{
|
206
|
-
*((unsigned int*)dst) = *((unsigned int*)src);
|
207
|
-
dst = dst + 4;
|
208
|
-
src = src + 4;
|
209
|
-
}
|
210
|
-
}
|
211
|
-
#endif
|
212
|
-
}
|
213
|
-
|
214
|
-
__inline unsigned int fast_read_safe(void const *src, unsigned int bytes, const unsigned char *invalid)
|
215
|
-
{
|
216
|
-
#ifdef memory_safe
|
217
|
-
if ((const unsigned char *)src + 4 > (const unsigned char *)invalid)
|
218
|
-
return 0xffffffff;
|
219
|
-
#endif
|
220
|
-
invalid = invalid;
|
221
|
-
return fast_read(src, bytes);
|
222
|
-
}
|
223
|
-
|
224
|
-
unsigned int qlz_compress_core(const void *source, unsigned char *destination, unsigned int size, const unsigned char *hashtable[][AND + 1], const unsigned char *first_valid, unsigned char *hash_counter)
|
225
|
-
{
|
226
|
-
const unsigned char *source_c = (const unsigned char*)source;
|
227
|
-
unsigned char *destination_c = (unsigned char*)destination;
|
228
|
-
const unsigned char *last_byte = source_c + size - 1;
|
229
|
-
const unsigned char *src = source_c;
|
230
|
-
unsigned char *cword_ptr = destination_c;
|
231
|
-
unsigned char *dst = destination_c + 4;
|
232
|
-
unsigned int cword_val = 1U << 31;
|
233
|
-
const unsigned char *guarantee_uncompressed = last_byte - 8;
|
234
|
-
|
235
|
-
#ifdef speedup_incompressible
|
236
|
-
unsigned char *prev_dst = dst;
|
237
|
-
const unsigned char *prev_src = src;
|
238
|
-
#endif
|
239
|
-
|
240
|
-
hash_counter = hash_counter;
|
241
|
-
first_valid = first_valid;
|
242
|
-
|
243
|
-
// save first 4 bytes uncompressed
|
244
|
-
while(src < source_c + 4 && src < guarantee_uncompressed)
|
245
|
-
{
|
246
|
-
cword_val = (cword_val >> 1);
|
247
|
-
*dst = *src;
|
248
|
-
dst++;
|
249
|
-
src++;
|
250
|
-
}
|
251
|
-
|
252
|
-
while(src < guarantee_uncompressed)
|
253
|
-
{
|
254
|
-
unsigned int fetch;
|
255
|
-
if ((cword_val & 1) == 1)
|
256
|
-
{
|
257
|
-
// check if destinationc pointer could exceed destination buffer
|
258
|
-
if (dst > destination_c + size)
|
259
|
-
return 0;
|
260
|
-
|
261
|
-
// store control word
|
262
|
-
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, 4);
|
263
|
-
cword_ptr = dst;
|
264
|
-
dst += 4;
|
265
|
-
cword_val = 1U << 31;
|
266
|
-
|
267
|
-
#ifdef speedup_incompressible
|
268
|
-
// check if source chunk is compressible
|
269
|
-
if (dst - prev_dst > src - prev_src && src > source_c + 1000)
|
270
|
-
{
|
271
|
-
int q;
|
272
|
-
for(q = 0; q < 30 && src + 31 < guarantee_uncompressed && dst + 35 < destination_c + size; q++)
|
273
|
-
{
|
274
|
-
|
275
|
-
#if(COMPRESSION_LEVEL == 0)
|
276
|
-
int w;
|
277
|
-
for(w = 0; w < 31; w++)
|
278
|
-
{
|
279
|
-
fetch = fast_read(src + w, 4);
|
280
|
-
*(unsigned int*)&hashtable[hash_func(fetch)][0] = fast_read(src + w, 4);
|
281
|
-
hashtable[hash_func(fetch)][1] = src + w;
|
282
|
-
}
|
283
|
-
#endif
|
284
|
-
fast_write((1U << 31), dst - 4, 4);
|
285
|
-
memcpy(dst, src, 31);
|
286
|
-
|
287
|
-
dst += 4*8 - 1 + 4;
|
288
|
-
src += 4*8 - 1;
|
289
|
-
prev_src = src;
|
290
|
-
prev_dst = dst;
|
291
|
-
cword_ptr = dst - 4;
|
292
|
-
}
|
293
|
-
}
|
294
|
-
#endif
|
295
|
-
}
|
296
|
-
#ifdef test_rle
|
297
|
-
// check for rle sequence
|
298
|
-
if (fast_read(src, 4) == fast_read(src + 1, 4))
|
299
|
-
{
|
300
|
-
const unsigned char *orig_src;
|
301
|
-
fetch = fast_read(src, 4);
|
302
|
-
orig_src = src;
|
303
|
-
do src = src + 4; while (src <= guarantee_uncompressed - 4 && fetch == fast_read(src, 4));
|
304
|
-
if((src - orig_src) <= 2047)
|
305
|
-
{
|
306
|
-
fast_write(((fetch & 0xff) << 16) | (unsigned int)((src - orig_src) << 4) | 15, dst, 4);
|
307
|
-
dst = dst + 3;
|
308
|
-
}
|
309
|
-
else
|
310
|
-
{
|
311
|
-
fast_write(((fetch & 0xff) << 16) | 15, dst, 4);
|
312
|
-
fast_write((unsigned int)(src - orig_src), dst + 3, 4);
|
313
|
-
dst = dst + 7;
|
314
|
-
}
|
315
|
-
cword_val = (cword_val >> 1) | (1 << 31);
|
316
|
-
}
|
317
|
-
else
|
318
|
-
#endif
|
319
|
-
{
|
320
|
-
const unsigned char *o;
|
321
|
-
unsigned int hash, matchlen;
|
322
|
-
|
323
|
-
#if(COMPRESSION_LEVEL < 2)
|
324
|
-
unsigned int cached;
|
325
|
-
|
326
|
-
fetch = fast_read(src, 4);
|
327
|
-
hash = hash_func(fetch);
|
328
|
-
|
329
|
-
cached = fetch ^ *(unsigned int*)&hashtable[hash][0];
|
330
|
-
*(unsigned int*)&hashtable[hash][0] = fetch;
|
331
|
-
|
332
|
-
o = hashtable[hash][1];
|
333
|
-
hashtable[hash][1] = src;
|
334
|
-
|
335
|
-
#else
|
336
|
-
unsigned char c;
|
337
|
-
unsigned int k, m;
|
338
|
-
const unsigned char *offset2 = 0;
|
339
|
-
|
340
|
-
fetch = fast_read(src, 4);
|
341
|
-
hash = hash_func(fetch);
|
342
|
-
|
343
|
-
matchlen = 0;
|
344
|
-
c = hash_counter[hash];
|
345
|
-
for(k = 0; k < AND + 1; k++)
|
346
|
-
{
|
347
|
-
o = hashtable[hash][(c - k) & AND];
|
348
|
-
if(o > first_valid && o < src - 3 && *(src + matchlen) == *(o + matchlen) && (fast_read(o, 3) & 0xffffff) == (fetch & 0xffffff) && src - o < 131071)
|
349
|
-
{
|
350
|
-
size_t remaining;
|
351
|
-
remaining = guarantee_uncompressed - src;
|
352
|
-
m = 3;
|
353
|
-
if (fast_read(o, 4) == fetch)
|
354
|
-
{
|
355
|
-
while(*(o + m) == *(src + m) && m < remaining)
|
356
|
-
m++;
|
357
|
-
}
|
358
|
-
if (m > matchlen)
|
359
|
-
{
|
360
|
-
matchlen = m;
|
361
|
-
offset2 = o;
|
362
|
-
}
|
363
|
-
}
|
364
|
-
}
|
365
|
-
o = offset2;
|
366
|
-
c = (hash_counter[hash] + 1) & AND;
|
367
|
-
hash_counter[hash] = c;
|
368
|
-
hashtable[hash][c] = src;
|
369
|
-
#endif
|
370
|
-
|
371
|
-
#if(COMPRESSION_LEVEL == 0)
|
372
|
-
if (o != 0 && (cached & 0xffffff) == 0 && src - o > 3)
|
373
|
-
#elif(COMPRESSION_LEVEL == 1)
|
374
|
-
if ((cached & 0xffffff) == 0 && o > first_valid && o < src - 3 && ((fast_read(o, 3) ^ fast_read(src, 3)) & 0xffffff) == 0 && src - o < 131071)
|
375
|
-
#elif(COMPRESSION_LEVEL > 1)
|
376
|
-
if(matchlen == 3)
|
377
|
-
#endif
|
378
|
-
{
|
379
|
-
unsigned int offset;
|
380
|
-
offset = (unsigned int)(src - o);
|
381
|
-
|
382
|
-
#if(COMPRESSION_LEVEL < 2)
|
383
|
-
if (cached & 0xffffffff)
|
384
|
-
#endif
|
385
|
-
{
|
386
|
-
#if (COMPRESSION_LEVEL > 2)
|
387
|
-
unsigned int u;
|
388
|
-
for(u = 1; u < 3; u++)
|
389
|
-
{
|
390
|
-
hash = hash_func(fast_read(src + u, 4));
|
391
|
-
c = (hash_counter[hash] + 1) & AND;
|
392
|
-
hash_counter[hash] = c;
|
393
|
-
hashtable[hash][c] = src + u;
|
394
|
-
}
|
395
|
-
#endif
|
396
|
-
|
397
|
-
#if (COMPRESSION_LEVEL == 0)
|
398
|
-
cword_val = (cword_val >> 1) | (1U << 31);
|
399
|
-
fast_write(3 | (hash << 4), dst, 2);
|
400
|
-
src += 3;
|
401
|
-
dst += 2;
|
402
|
-
#else
|
403
|
-
|
404
|
-
if(offset <= 63)
|
405
|
-
{
|
406
|
-
// encode lz match
|
407
|
-
*dst = (unsigned char)(offset << 2);
|
408
|
-
cword_val = (cword_val >> 1) | (1U << 31);
|
409
|
-
src += 3;
|
410
|
-
dst++;
|
411
|
-
}
|
412
|
-
else if (offset <= 16383)
|
413
|
-
{
|
414
|
-
// encode lz match
|
415
|
-
unsigned int f = (offset << 2) | 1;
|
416
|
-
fast_write(f, dst, 2);
|
417
|
-
cword_val = (cword_val >> 1) | (1U << 31);
|
418
|
-
src += 3;
|
419
|
-
dst += 2;
|
420
|
-
}
|
421
|
-
else
|
422
|
-
{
|
423
|
-
// encode literal
|
424
|
-
*dst = *src;
|
425
|
-
src++;
|
426
|
-
dst++;
|
427
|
-
cword_val = (cword_val >> 1);
|
428
|
-
}
|
429
|
-
#endif
|
430
|
-
}
|
431
|
-
#if(COMPRESSION_LEVEL > 1)
|
432
|
-
}
|
433
|
-
else if(matchlen > 3)
|
434
|
-
{
|
435
|
-
#elif(COMPRESSION_LEVEL < 2)
|
436
|
-
else
|
437
|
-
#endif
|
438
|
-
{
|
439
|
-
// encode lz match
|
440
|
-
unsigned int offset;
|
441
|
-
|
442
|
-
#if(COMPRESSION_LEVEL < 2)
|
443
|
-
const unsigned char *old_src = src;
|
444
|
-
offset = (unsigned int)(src - o);
|
445
|
-
cword_val = (cword_val >> 1) | (1U << 31);
|
446
|
-
|
447
|
-
src += 3;
|
448
|
-
while(*(o + (src - old_src)) == *src && src < guarantee_uncompressed)
|
449
|
-
src++;
|
450
|
-
matchlen = (unsigned int)(src - old_src);
|
451
|
-
#else
|
452
|
-
unsigned int u;
|
453
|
-
offset = (unsigned int)(src - o);
|
454
|
-
cword_val = (cword_val >> 1) | (1U << 31);
|
455
|
-
|
456
|
-
#if (COMPRESSION_LEVEL > 2)
|
457
|
-
for(u = 1; u < matchlen; u++)
|
458
|
-
#else
|
459
|
-
for(u = 1; u < matchlen && u < 5; u++)
|
460
|
-
#endif
|
461
|
-
{
|
462
|
-
hash = hash_func(fast_read(src + u, 4));
|
463
|
-
c = (hash_counter[hash] + 1) & AND;
|
464
|
-
hash_counter[hash] = c;
|
465
|
-
hashtable[hash][c] = src + u;
|
466
|
-
}
|
467
|
-
src += matchlen;
|
468
|
-
#endif
|
469
|
-
|
470
|
-
#if (COMPRESSION_LEVEL == 0)
|
471
|
-
if (matchlen < 15)
|
472
|
-
{
|
473
|
-
fast_write(matchlen | (hash << 4), dst, 2);
|
474
|
-
dst += 2;
|
475
|
-
}
|
476
|
-
else if (matchlen < 255)
|
477
|
-
{
|
478
|
-
fast_write(hash << 4, dst, 2);
|
479
|
-
*(dst + 2) = (unsigned char)matchlen;
|
480
|
-
dst += 3;
|
481
|
-
}
|
482
|
-
else
|
483
|
-
{
|
484
|
-
fast_write(hash << 4, dst, 2);
|
485
|
-
*(dst + 2) = 0;
|
486
|
-
fast_write(matchlen, dst + 3, 4);
|
487
|
-
dst += 7;
|
488
|
-
}
|
489
|
-
#else
|
490
|
-
if (matchlen <= 18 && offset <= 1023)
|
491
|
-
{
|
492
|
-
unsigned int f = ((matchlen - 3) << 2) | (offset << 6) | 2;
|
493
|
-
fast_write(f, dst, 2);
|
494
|
-
dst += 2;
|
495
|
-
}
|
496
|
-
|
497
|
-
else if(matchlen <= 34 && offset <= 65535)
|
498
|
-
{
|
499
|
-
unsigned int f = ((matchlen - 3) << 3) | (offset << 8) | 3;
|
500
|
-
fast_write(f, dst, 3);
|
501
|
-
dst += 3;
|
502
|
-
}
|
503
|
-
else if (matchlen >= 3)
|
504
|
-
{
|
505
|
-
if (matchlen <= 2050)
|
506
|
-
{
|
507
|
-
unsigned int f = ((matchlen - 3) << 4) | (offset << 15) | 7;
|
508
|
-
fast_write(f, dst, 4);
|
509
|
-
dst += 4;
|
510
|
-
}
|
511
|
-
else
|
512
|
-
{
|
513
|
-
fast_write(7, dst, 4);
|
514
|
-
fast_write(matchlen, dst + 4, 4);
|
515
|
-
fast_write(offset, dst + 8, 4);
|
516
|
-
dst += 12;
|
517
|
-
}
|
518
|
-
}
|
519
|
-
#endif
|
520
|
-
}
|
521
|
-
}
|
522
|
-
|
523
|
-
else
|
524
|
-
{
|
525
|
-
// encode literal
|
526
|
-
*dst = *src;
|
527
|
-
src++;
|
528
|
-
dst++;
|
529
|
-
cword_val = (cword_val >> 1);
|
530
|
-
}
|
531
|
-
}
|
532
|
-
}
|
533
|
-
|
534
|
-
// save last source bytes as literals
|
535
|
-
while (src <= last_byte)
|
536
|
-
{
|
537
|
-
if ((cword_val & 1) == 1)
|
538
|
-
{
|
539
|
-
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, 4);
|
540
|
-
cword_ptr = dst;
|
541
|
-
dst += 4;
|
542
|
-
cword_val = 1U << 31;
|
543
|
-
}
|
544
|
-
|
545
|
-
if (src < last_byte - 2 && src > source_c + 3)
|
546
|
-
{
|
547
|
-
hashtable[hash_func(fast_read(src, 4))][1] = src;
|
548
|
-
*(unsigned int*)&hashtable[hash_func(fast_read(src, 4))][0] = fast_read(src, 4);
|
549
|
-
}
|
550
|
-
*dst = *src;
|
551
|
-
src++;
|
552
|
-
dst++;
|
553
|
-
|
554
|
-
cword_val = (cword_val >> 1);
|
555
|
-
}
|
556
|
-
|
557
|
-
while((cword_val & 1) != 1)
|
558
|
-
cword_val = (cword_val >> 1);
|
559
|
-
|
560
|
-
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, 4);
|
561
|
-
|
562
|
-
// min. size must be 9 bytes so that the qlz_size functions can take 9 bytes as argument
|
563
|
-
if (dst - destination_c < 9)
|
564
|
-
return 9;
|
565
|
-
else
|
566
|
-
return (unsigned int)(dst - destination_c);
|
567
|
-
}
|
568
|
-
|
569
|
-
size_t qlz_decompress_core(const unsigned char *source, void *destination, size_t size, size_t source_size, unsigned char *first_valid, const unsigned char *hashtable[])
|
570
|
-
{
|
571
|
-
const unsigned char *source_c = (const unsigned char*)source;
|
572
|
-
unsigned char *destination_c = (unsigned char*)destination;
|
573
|
-
const unsigned char *src = source_c;
|
574
|
-
unsigned char *dst = destination_c;
|
575
|
-
const unsigned char* last_byte_successor = destination_c + size;
|
576
|
-
unsigned int cword_val = 1;
|
577
|
-
const unsigned int bitlut[16] = {4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
|
578
|
-
const unsigned char *guaranteed_uncompressed = last_byte_successor - 4;
|
579
|
-
unsigned char *last_hashed = destination_c + 3;
|
580
|
-
|
581
|
-
first_valid = first_valid;
|
582
|
-
last_hashed = last_hashed;
|
583
|
-
hashtable = hashtable;
|
584
|
-
|
585
|
-
// prevent spurious memory read on a source with size < 4
|
586
|
-
if (dst >= guaranteed_uncompressed)
|
587
|
-
{
|
588
|
-
src += 4;
|
589
|
-
while(dst < last_byte_successor)
|
590
|
-
{
|
591
|
-
*dst = *src;
|
592
|
-
dst++;
|
593
|
-
src++;
|
594
|
-
}
|
595
|
-
|
596
|
-
return (unsigned int)(dst - destination_c);
|
597
|
-
}
|
598
|
-
|
599
|
-
|
600
|
-
for(;;)
|
601
|
-
{
|
602
|
-
unsigned int fetch;
|
603
|
-
|
604
|
-
if (cword_val == 1)
|
605
|
-
{
|
606
|
-
// fetch control word
|
607
|
-
cword_val = fast_read_safe(src, 4, source_c + source_size) | (1U << 31);
|
608
|
-
src += 4;
|
609
|
-
}
|
610
|
-
|
611
|
-
fetch = fast_read_safe(src, 4, source_c + source_size);
|
612
|
-
|
613
|
-
// check if we must decode lz match
|
614
|
-
if ((cword_val & 1) == 1)
|
615
|
-
{
|
616
|
-
unsigned int matchlen;
|
617
|
-
|
618
|
-
#if(COMPRESSION_LEVEL == 0)
|
619
|
-
unsigned int hash;
|
620
|
-
const unsigned char *offset2;
|
621
|
-
|
622
|
-
cword_val = cword_val >> 1;
|
623
|
-
|
624
|
-
if((fetch & 0xf) != 15)
|
625
|
-
{
|
626
|
-
hash = (fetch >> 4) & 0xfff;
|
627
|
-
offset2 = hashtable[hash];
|
628
|
-
|
629
|
-
if((fetch & 0xf) != 0)
|
630
|
-
{
|
631
|
-
matchlen = (fetch & 0xf);
|
632
|
-
src += 2;
|
633
|
-
}
|
634
|
-
else if((fetch & 0x00ff0000) != 0)
|
635
|
-
{
|
636
|
-
matchlen = *(src + 2);
|
637
|
-
src += 3;
|
638
|
-
}
|
639
|
-
else
|
640
|
-
{
|
641
|
-
matchlen = fast_read(src + 3, 4);
|
642
|
-
src += 7;
|
643
|
-
}
|
644
|
-
memcpy_up(dst, offset2, matchlen);
|
645
|
-
while(last_hashed < dst)
|
646
|
-
{
|
647
|
-
last_hashed++;
|
648
|
-
hashtable[hash_func(fast_read(last_hashed, 4))] = last_hashed;
|
649
|
-
}
|
650
|
-
dst += matchlen;
|
651
|
-
last_hashed = dst - 1;
|
652
|
-
}
|
653
|
-
|
654
|
-
#else
|
655
|
-
unsigned int offset;
|
656
|
-
cword_val = cword_val >> 1;
|
657
|
-
|
658
|
-
if ((fetch & 3) == 0)
|
659
|
-
{
|
660
|
-
offset = (fetch & 0xff) >> 2;
|
661
|
-
#ifdef memory_safe
|
662
|
-
if (3 > (unsigned int)(guaranteed_uncompressed - dst) || offset > (unsigned int)(dst - first_valid))
|
663
|
-
return 0;
|
664
|
-
#endif
|
665
|
-
memcpy_up(dst, dst - offset, 3);
|
666
|
-
dst += 3;
|
667
|
-
src++;
|
668
|
-
}
|
669
|
-
else if ((fetch & 2) == 0)
|
670
|
-
{
|
671
|
-
offset = (fetch & 0xffff) >> 2;
|
672
|
-
#ifdef memory_safe
|
673
|
-
if (3 > (unsigned int)(guaranteed_uncompressed - dst) || offset > (unsigned int)(dst - first_valid))
|
674
|
-
return 0;
|
675
|
-
#endif
|
676
|
-
memcpy_up(dst, dst - offset, 3);
|
677
|
-
dst += 3;
|
678
|
-
src += 2;
|
679
|
-
}
|
680
|
-
else if ((fetch & 1) == 0)
|
681
|
-
{
|
682
|
-
offset = (fetch & 0xffff) >> 6;
|
683
|
-
matchlen = ((fetch >> 2) & 15) + 3;
|
684
|
-
#ifdef memory_safe
|
685
|
-
if (matchlen > (unsigned int)(guaranteed_uncompressed - dst) || offset > (unsigned int)(dst - first_valid))
|
686
|
-
return 0;
|
687
|
-
#endif
|
688
|
-
memcpy_up(dst, dst - offset, matchlen);
|
689
|
-
src += 2;
|
690
|
-
dst += matchlen;
|
691
|
-
}
|
692
|
-
else if ((fetch & 4) == 0)
|
693
|
-
{
|
694
|
-
offset = (fetch & 0xffffff) >> 8;
|
695
|
-
matchlen = ((fetch >> 3) & 31) + 3;
|
696
|
-
#ifdef memory_safe
|
697
|
-
if (matchlen > (unsigned int)(guaranteed_uncompressed - dst) || offset > (unsigned int)(dst - first_valid))
|
698
|
-
return 0;
|
699
|
-
#endif
|
700
|
-
memcpy_up(dst, dst - offset, matchlen);
|
701
|
-
src += 3;
|
702
|
-
dst += matchlen;
|
703
|
-
}
|
704
|
-
else if ((fetch & 8) == 0)
|
705
|
-
{
|
706
|
-
offset = (fetch >> 15);
|
707
|
-
if (offset != 0)
|
708
|
-
{
|
709
|
-
matchlen = ((fetch >> 4) & 2047) + 3;
|
710
|
-
src += 4;
|
711
|
-
}
|
712
|
-
else
|
713
|
-
{
|
714
|
-
matchlen = fast_read_safe(src + 4, 4, source_c + source_size);
|
715
|
-
offset = fast_read_safe(src + 8, 4, source_c + source_size);
|
716
|
-
src += 12;
|
717
|
-
}
|
718
|
-
#ifdef memory_safe
|
719
|
-
if (matchlen > (unsigned int)(guaranteed_uncompressed - dst) || offset > (unsigned int)(dst - first_valid))
|
720
|
-
return 0;
|
721
|
-
#endif
|
722
|
-
memcpy_up(dst, dst - offset, matchlen);
|
723
|
-
dst += matchlen;
|
724
|
-
}
|
725
|
-
#endif
|
726
|
-
else
|
727
|
-
{
|
728
|
-
// decode rle sequence
|
729
|
-
unsigned char rle_char;
|
730
|
-
rle_char = (unsigned char)(fetch >> 16);
|
731
|
-
matchlen = ((fetch >> 4) & 0xfff);
|
732
|
-
|
733
|
-
if(matchlen != 0)
|
734
|
-
src += 3;
|
735
|
-
else
|
736
|
-
{
|
737
|
-
matchlen = fast_read_safe(src + 3, 4, source_c + source_size);
|
738
|
-
src += 7;
|
739
|
-
}
|
740
|
-
|
741
|
-
#ifdef memory_safe
|
742
|
-
if(matchlen > (unsigned int)(guaranteed_uncompressed - dst))
|
743
|
-
return 0;
|
744
|
-
#endif
|
745
|
-
memset(dst, rle_char, matchlen);
|
746
|
-
|
747
|
-
#if(COMPRESSION_LEVEL == 0)
|
748
|
-
while(last_hashed < dst - 1)
|
749
|
-
{
|
750
|
-
last_hashed++;
|
751
|
-
hashtable[hash_func(fast_read(last_hashed, 4))] = last_hashed;
|
752
|
-
}
|
753
|
-
last_hashed = dst - 1 + matchlen;
|
754
|
-
#endif
|
755
|
-
dst += matchlen;
|
756
|
-
}
|
757
|
-
}
|
758
|
-
else
|
759
|
-
{
|
760
|
-
// decode literal
|
761
|
-
#ifdef memory_safe
|
762
|
-
if (4 > destination_c + size - dst || src > source_c + source_size + 4)
|
763
|
-
return 0;
|
764
|
-
#endif
|
765
|
-
memcpy_up(dst, src, 4);
|
766
|
-
|
767
|
-
dst += bitlut[cword_val & 0xf];
|
768
|
-
src += bitlut[cword_val & 0xf];
|
769
|
-
cword_val = cword_val >> (bitlut[cword_val & 0xf]);
|
770
|
-
|
771
|
-
#if(COMPRESSION_LEVEL == 0)
|
772
|
-
while(last_hashed < dst - 3)
|
773
|
-
{
|
774
|
-
last_hashed++;
|
775
|
-
hashtable[hash_func(fast_read(last_hashed, 4))] = last_hashed;
|
776
|
-
}
|
777
|
-
#endif
|
778
|
-
if (dst >= guaranteed_uncompressed)
|
779
|
-
{
|
780
|
-
// decode last literals and exit
|
781
|
-
while(dst < last_byte_successor)
|
782
|
-
{
|
783
|
-
if (cword_val == 1)
|
784
|
-
{
|
785
|
-
src += 4;
|
786
|
-
cword_val = 1U << 31;
|
787
|
-
}
|
788
|
-
if (1 > destination_c + size - dst)
|
789
|
-
return 0;
|
790
|
-
|
791
|
-
*dst = *src;
|
792
|
-
dst++;
|
793
|
-
src++;
|
794
|
-
cword_val = cword_val >> 1;
|
795
|
-
}
|
796
|
-
|
797
|
-
#if(COMPRESSION_LEVEL == 0)
|
798
|
-
while(last_hashed < last_byte_successor - 4)
|
799
|
-
{
|
800
|
-
last_hashed++;
|
801
|
-
hashtable[hash_func(fast_read(last_hashed, 4))] = last_hashed;
|
802
|
-
}
|
803
|
-
#endif
|
804
|
-
if((src - 1) - source_c > 8) // 8 bytes comp. size excessive len is ok
|
805
|
-
return 0;
|
806
|
-
else if(dst - destination_c - size == 0)
|
807
|
-
return size;
|
808
|
-
else
|
809
|
-
return 0;
|
810
|
-
}
|
811
|
-
}
|
812
|
-
}
|
813
|
-
}
|
814
|
-
|
815
|
-
size_t qlz_size_decompressed(const char *source)
|
816
|
-
{
|
817
|
-
unsigned int n, r;
|
818
|
-
n = (((*source) & 2) == 2) ? 4 : 1;
|
819
|
-
r = fast_read(source + 1 + n, n);
|
820
|
-
r = r & (0xffffffff >> ((4 - n)*8));
|
821
|
-
return r;
|
822
|
-
}
|
823
|
-
|
824
|
-
size_t qlz_size_compressed(const char *source)
|
825
|
-
{
|
826
|
-
unsigned int n, r;
|
827
|
-
n = (((*source) & 2) == 2) ? 4 : 1;
|
828
|
-
r = fast_read(source + 1, n);
|
829
|
-
r = r & (0xffffffff >> ((4 - n)*8));
|
830
|
-
return r;
|
831
|
-
}
|
832
|
-
|
833
|
-
size_t qlz_compress(const void *source, char *destination, size_t size, char *scratch)
|
834
|
-
{
|
835
|
-
// 1-8 bytes for aligning (not 0-7!); 8 bytes for buffersize (padds on 32 bit cpu); HASH_SIZE hash table; STREAMING_MODE_ROUNDED bytes streambuffer; optional HASH_ENTRIES byte hash counter
|
836
|
-
unsigned char *buffer_aligned = (unsigned char *)scratch + 8 - (((size_t)scratch) % 8);
|
837
|
-
const unsigned char *(*hashtable)[AND + 1] = (const unsigned char *(*)[AND + 1])(buffer_aligned + 8);
|
838
|
-
size_t *buffersize = (size_t *)buffer_aligned;
|
839
|
-
unsigned char *streambuffer = buffer_aligned + 8 + HASH_SIZE;
|
840
|
-
unsigned int r;
|
841
|
-
unsigned int compressed, base;
|
842
|
-
unsigned char *hash_counter = streambuffer + STREAMING_MODE_ROUNDED;
|
843
|
-
|
844
|
-
if(size == 0 || size > 0xffffffff)
|
845
|
-
return 0;
|
846
|
-
|
847
|
-
#if (COMPRESSION_LEVEL == 0 && STREAMING_MODE_ROUNDED == 0)
|
848
|
-
memset((void *)hashtable, 0, HASH_SIZE);
|
849
|
-
#endif
|
850
|
-
|
851
|
-
if(size < 216)
|
852
|
-
base = 3;
|
853
|
-
else
|
854
|
-
base = 9;
|
855
|
-
|
856
|
-
// if not STREAMING_MODE, then STREAMING_MODE_ROUNDED == 0 and first case (streaming buffer full) is executed unconditionally, functioning as block comp.
|
857
|
-
if (*buffersize + size - 1 >= STREAMING_MODE_ROUNDED)
|
858
|
-
{
|
859
|
-
#if (COMPRESSION_LEVEL == 0 && STREAMING_MODE_ROUNDED != 0)
|
860
|
-
memset((void *)hashtable, 0, HASH_SIZE);
|
861
|
-
#endif
|
862
|
-
|
863
|
-
r = base + qlz_compress_core(source, (unsigned char*)destination + base, (unsigned int)size, hashtable, (const unsigned char*)source, hash_counter);
|
864
|
-
#if (COMPRESSION_LEVEL == 0 && STREAMING_MODE_ROUNDED != 0)
|
865
|
-
memset((void *)hashtable, 0, HASH_SIZE);
|
866
|
-
#endif
|
867
|
-
|
868
|
-
if(r == base)
|
869
|
-
{
|
870
|
-
memcpy(destination + base, source, size);
|
871
|
-
r = (unsigned int)size + base;
|
872
|
-
compressed = 0;
|
873
|
-
}
|
874
|
-
else
|
875
|
-
compressed = 1;
|
876
|
-
*buffersize = 0;
|
877
|
-
}
|
878
|
-
else
|
879
|
-
{
|
880
|
-
memcpy(streambuffer + *buffersize, source, size);
|
881
|
-
r = base + qlz_compress_core(streambuffer + *buffersize, (unsigned char*)destination + base, (unsigned int)size, hashtable, streambuffer, hash_counter);
|
882
|
-
|
883
|
-
if(r == base)
|
884
|
-
{
|
885
|
-
memcpy(destination + base, streambuffer + *buffersize, size);
|
886
|
-
r = (unsigned int)size + base;
|
887
|
-
compressed = 0;
|
888
|
-
|
889
|
-
memset((void*)hashtable, 0, HASH_SIZE);
|
890
|
-
}
|
891
|
-
else
|
892
|
-
compressed = 1;
|
893
|
-
*buffersize += size;
|
894
|
-
}
|
895
|
-
|
896
|
-
if(base == 3)
|
897
|
-
{
|
898
|
-
*destination = (unsigned char)(0 | compressed);
|
899
|
-
*(destination + 1) = (unsigned char)r;
|
900
|
-
*(destination + 2) = (unsigned char)size;
|
901
|
-
}
|
902
|
-
else
|
903
|
-
{
|
904
|
-
*destination = (unsigned char)(2 | compressed);
|
905
|
-
fast_write(r, destination + 1, 4);
|
906
|
-
fast_write((unsigned int)size, destination + 5, 4);
|
907
|
-
}
|
908
|
-
|
909
|
-
#if (COMPRESSION_LEVEL == 0)
|
910
|
-
*destination = (*destination) | 4;
|
911
|
-
#endif
|
912
|
-
|
913
|
-
return (size_t)r;
|
914
|
-
}
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
size_t qlz_decompress(const char *source, void *destination, char *scratch)
|
919
|
-
{
|
920
|
-
// 1-8 bytes for aligning (not 0-7!); 8 bytes for buffersize (padds on 32bit cpu); STREAMING_MODE_ROUNDED streambuffer; HASH_SIZE hash table
|
921
|
-
unsigned char *buffer_aligned = (unsigned char *)scratch + 8 - (((size_t)scratch) % 8);
|
922
|
-
size_t *buffersize = (size_t *)buffer_aligned;
|
923
|
-
unsigned int headerlen = 2*((((*source) & 2) == 2) ? 4 : 1) + 1; // get header len
|
924
|
-
|
925
|
-
unsigned char *streambuffer = buffer_aligned + 8;
|
926
|
-
const unsigned char **hashtable = (const unsigned char **)(streambuffer + STREAMING_MODE_ROUNDED);
|
927
|
-
|
928
|
-
size_t dsiz = qlz_size_decompressed((char *)source);
|
929
|
-
size_t csiz = qlz_size_compressed((char *)source);
|
930
|
-
if (*buffersize + qlz_size_decompressed((char *)source) - 1 >= STREAMING_MODE_ROUNDED)
|
931
|
-
{
|
932
|
-
if((*source & 1) == 1)
|
933
|
-
qlz_decompress_core((const unsigned char *)source + headerlen, destination, dsiz, csiz, (unsigned char*)destination, hashtable);
|
934
|
-
else
|
935
|
-
memcpy(destination, source + headerlen, dsiz);
|
936
|
-
*buffersize = 0;
|
937
|
-
}
|
938
|
-
else
|
939
|
-
{
|
940
|
-
if((*source & 1) == 1)
|
941
|
-
qlz_decompress_core((const unsigned char *)source + headerlen, streambuffer + *buffersize, dsiz, csiz, streambuffer, hashtable);
|
942
|
-
else
|
943
|
-
memcpy(streambuffer + *buffersize, source + headerlen, dsiz);
|
944
|
-
memcpy(destination, streambuffer + *buffersize, dsiz);
|
945
|
-
*buffersize += dsiz;
|
946
|
-
}
|
947
|
-
return dsiz;
|
948
|
-
}
|