yaz0 0.3.0 → 0.4.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.
@@ -0,0 +1,197 @@
1
+ #include <string.h>
2
+ #include <stdio.h>
3
+ #include "libyaz0.h"
4
+
5
+ int yaz0ModeDecompress(Yaz0Stream* s)
6
+ {
7
+ memset(s, 0, sizeof(*s));
8
+ s->mode = MODE_DECOMPRESS;
9
+ return YAZ0_OK;
10
+ }
11
+
12
+ void loadAux(Yaz0Stream* stream, uint32_t size)
13
+ {
14
+ if (stream->sizeIn - stream->cursorIn < size)
15
+ size = stream->sizeIn - stream->cursorIn;
16
+ for (uint32_t i = 0; i < size; i++)
17
+ stream->auxBuf[stream->auxSize++] = stream->in[stream->cursorIn++];
18
+ }
19
+
20
+ int flush(Yaz0Stream* stream)
21
+ {
22
+ size_t chunkSize;
23
+ size_t outSize;
24
+
25
+ if (stream->window_start == stream->window_end)
26
+ return YAZ0_OK;
27
+ if (stream->cursorOut >= stream->sizeOut)
28
+ return YAZ0_NEED_AVAIL_OUT;
29
+ outSize = stream->sizeOut - stream->cursorOut;
30
+ if (stream->window_start > stream->window_end)
31
+ {
32
+ /* Wrap around - we will need 2 copies */
33
+ chunkSize = WINDOW_SIZE - stream->window_start;
34
+ if (chunkSize > outSize)
35
+ chunkSize = outSize;
36
+ memcpy(stream->out + stream->cursorOut, stream->window + stream->window_start, chunkSize);
37
+ stream->cursorOut += chunkSize;
38
+ stream->window_start += chunkSize;
39
+ stream->window_start %= WINDOW_SIZE;
40
+ outSize -= chunkSize;
41
+ }
42
+ /* Copy the rest */
43
+ chunkSize = stream->window_end - stream->window_start;
44
+ if (chunkSize > outSize)
45
+ chunkSize = outSize;
46
+ memcpy(stream->out + stream->cursorOut, stream->window + stream->window_start, chunkSize);
47
+ stream->cursorOut += chunkSize;
48
+ stream->window_start += chunkSize;
49
+ return YAZ0_OK;
50
+ }
51
+
52
+ static int yaz0_ReadHeaders(Yaz0Stream* stream)
53
+ {
54
+ loadAux(stream, 16 - stream->auxSize);
55
+ if (stream->auxSize < 16)
56
+ return YAZ0_NEED_AVAIL_IN;
57
+ if (memcmp(stream->auxBuf, "Yaz0", 4))
58
+ return YAZ0_BAD_MAGIC;
59
+ stream->decompSize = swap32(*(uint32_t*)&stream->auxBuf[4]);
60
+ stream->auxSize = 0;
61
+ return YAZ0_OK;
62
+ }
63
+
64
+ static uint32_t windowFreeSize(Yaz0Stream* stream)
65
+ {
66
+ uint32_t size;
67
+ if (stream->window_start > stream->window_end)
68
+ size = WINDOW_SIZE - stream->window_start + stream->window_end;
69
+ else
70
+ size = stream->window_end - stream->window_start;
71
+ return WINDOW_SIZE - size;
72
+ }
73
+
74
+ static int ensureWindowFree(Yaz0Stream* stream)
75
+ {
76
+ static const uint32_t maxSize = 0x111 * 8;
77
+
78
+ if (windowFreeSize(stream) <= maxSize)
79
+ {
80
+ flush(stream);
81
+ if (windowFreeSize(stream) <= maxSize)
82
+ return YAZ0_NEED_AVAIL_OUT;
83
+ }
84
+ return YAZ0_OK;
85
+ }
86
+
87
+ int yaz0_DoDecompress(Yaz0Stream* stream)
88
+ {
89
+ uint8_t groupBit;
90
+ uint8_t byte;
91
+ int ret;
92
+ uint16_t n;
93
+ uint16_t r;
94
+ for (;;)
95
+ {
96
+ /* No group and no EOF - We need to read */
97
+ if (stream->groupCount == 0)
98
+ {
99
+ /* Before we read, we eant to ensure the window is large enough */
100
+ /* This will avoid a lot of checks and let us write the whole group */
101
+ ret = ensureWindowFree(stream);
102
+ if (ret)
103
+ return ret;
104
+ if (stream->cursorIn >= stream->sizeIn)
105
+ return YAZ0_NEED_AVAIL_IN;
106
+ stream->groupHeader = stream->in[stream->cursorIn++];
107
+ stream->groupCount = 8;
108
+ }
109
+
110
+ /* We have a group! */
111
+ while (stream->groupCount)
112
+ {
113
+ /* Get the group bit */
114
+ groupBit = stream->groupHeader & (1 << (stream->groupCount - 1));
115
+ if (groupBit)
116
+ {
117
+ /* Group bit is 1 - direct write */
118
+ if (stream->cursorIn >= stream->sizeIn)
119
+ return YAZ0_NEED_AVAIL_IN;
120
+
121
+ /* Everything ok, copy the byte */
122
+ byte = stream->in[stream->cursorIn++];
123
+ stream->window[stream->window_end++] = byte;
124
+ stream->window_end %= WINDOW_SIZE;
125
+ stream->totalOut++;
126
+ }
127
+ else
128
+ {
129
+ if (stream->auxSize < 2)
130
+ {
131
+ loadAux(stream, 2 - stream->auxSize);
132
+ if (stream->auxSize < 2)
133
+ return YAZ0_NEED_AVAIL_IN;
134
+ }
135
+ /* Do we need 2 or 3 bytes? */
136
+ n = ((uint8_t)stream->auxBuf[0]) >> 4;
137
+ if (!n)
138
+ {
139
+ /* We have a large chunk */
140
+ loadAux(stream, 1);
141
+ if (stream->auxSize < 3)
142
+ return YAZ0_NEED_AVAIL_IN;
143
+ n = (uint8_t)stream->auxBuf[2] + 0x12;
144
+ }
145
+ else
146
+ {
147
+ /* We have a small chunk */
148
+ n = ((uint8_t)stream->auxBuf[0] >> 4) + 2;
149
+ }
150
+ r = ((uint16_t)(((uint8_t)stream->auxBuf[0] & 0x0f) << 8) | ((uint8_t)stream->auxBuf[1]));
151
+ r++;
152
+ /* Reset the aux buffer */
153
+ uint32_t cursor = (stream->window_end + WINDOW_SIZE - r) % WINDOW_SIZE;
154
+ for (int i = 0; i < n; ++i)
155
+ {
156
+ stream->window[stream->window_end++] = stream->window[cursor++];
157
+ stream->window_end %= WINDOW_SIZE;
158
+ cursor %= WINDOW_SIZE;
159
+ }
160
+ stream->auxSize = 0;
161
+ stream->totalOut += n;
162
+ }
163
+ stream->groupCount--;
164
+ /* Check for EOF */
165
+ if (stream->totalOut >= stream->decompSize)
166
+ return YAZ0_OK;
167
+ }
168
+ }
169
+ }
170
+
171
+ int yaz0_RunDecompress(Yaz0Stream* stream)
172
+ {
173
+ int ret;
174
+
175
+ /* Check the headers */
176
+ if (!stream->headersDone)
177
+ {
178
+ ret = yaz0_ReadHeaders(stream);
179
+ if (ret)
180
+ return ret;
181
+ stream->headersDone = 1;
182
+ }
183
+
184
+ if (stream->totalOut < stream->decompSize)
185
+ {
186
+ /* We did not decompress everything */
187
+ ret = yaz0_DoDecompress(stream);
188
+ if (ret)
189
+ return ret;
190
+ }
191
+
192
+ /* We did decompress everything */
193
+ flush(stream);
194
+ if (stream->window_start != stream->window_end)
195
+ return YAZ0_NEED_AVAIL_OUT;
196
+ return YAZ0_OK;
197
+ }
@@ -0,0 +1,64 @@
1
+ #include <stdlib.h>
2
+ #include "libyaz0.h"
3
+
4
+ int yaz0Init(Yaz0Stream** ptr)
5
+ {
6
+ Yaz0Stream* s;
7
+
8
+ s = malloc(sizeof(*s));
9
+ if (!s)
10
+ return YAZ0_OUT_OF_MEMORY;
11
+ s->mode = MODE_NONE;
12
+ s->cursorOut = 0;
13
+ s->decompSize = 0;
14
+ *ptr = s;
15
+ return YAZ0_OK;
16
+ }
17
+
18
+ int yaz0Destroy(Yaz0Stream* stream)
19
+ {
20
+ free(stream);
21
+ return YAZ0_OK;
22
+ }
23
+
24
+ int yaz0Run(Yaz0Stream* s)
25
+ {
26
+ switch (s->mode)
27
+ {
28
+ case MODE_NONE:
29
+ return YAZ0_OK;
30
+ case MODE_DECOMPRESS:
31
+ return yaz0_RunDecompress(s);
32
+ case MODE_COMPRESS:
33
+ return yaz0_RunCompress(s);
34
+ default:
35
+ unreachable();
36
+ }
37
+ }
38
+
39
+ int yaz0Input(Yaz0Stream* stream, const void* data, uint32_t size)
40
+ {
41
+ stream->in = data;
42
+ stream->sizeIn = size;
43
+ stream->cursorIn = 0;
44
+
45
+ return YAZ0_OK;
46
+ }
47
+
48
+ int yaz0Output(Yaz0Stream* stream, void* data, uint32_t size)
49
+ {
50
+ stream->out = data;
51
+ stream->sizeOut = size;
52
+ stream->cursorOut = 0;
53
+ return YAZ0_OK;
54
+ }
55
+
56
+ uint32_t yaz0OutputChunkSize(const Yaz0Stream* stream)
57
+ {
58
+ return stream->cursorOut;
59
+ }
60
+
61
+ uint32_t yaz0DecompressedSize(const Yaz0Stream* stream)
62
+ {
63
+ return stream->decompSize;
64
+ }
@@ -0,0 +1,49 @@
1
+ #ifndef LIBYAZ0_H
2
+ #define LIBYAZ0_H
3
+
4
+ #include <stdint.h>
5
+ #include <yaz0.h>
6
+
7
+ #define MODE_NONE 0
8
+ #define MODE_DECOMPRESS 1
9
+ #define MODE_COMPRESS 2
10
+
11
+ #define WINDOW_SIZE 0x4000
12
+ #define HASH_MAX_ENTRIES 0x8000
13
+ #define HASH_REBUILD 0x3000
14
+
15
+ #define likely(x) (__builtin_expect((x),1))
16
+ #define unlikely(x) (__builtin_expect((x),0))
17
+ #define unreachable() __builtin_unreachable()
18
+
19
+ struct Yaz0Stream
20
+ {
21
+ int mode;
22
+ int headersDone;
23
+ int level;
24
+ uint32_t decompSize;
25
+ uint32_t totalOut;
26
+ const uint8_t* in;
27
+ uint8_t* out;
28
+ uint32_t sizeIn;
29
+ uint32_t sizeOut;
30
+ uint32_t cursorIn;
31
+ uint32_t cursorOut;
32
+ uint8_t auxBuf[16];
33
+ uint8_t auxSize;
34
+ uint8_t groupHeader;
35
+ uint8_t groupCount;
36
+ uint32_t window_start;
37
+ uint32_t window_end;
38
+ uint8_t window[WINDOW_SIZE];
39
+ uint32_t htSize;
40
+ uint32_t htHashes[HASH_MAX_ENTRIES];
41
+ uint32_t htEntries[HASH_MAX_ENTRIES];
42
+ };
43
+
44
+ int yaz0_RunDecompress(Yaz0Stream* stream);
45
+ int yaz0_RunCompress(Yaz0Stream* stream);
46
+
47
+ uint32_t swap32(uint32_t v);
48
+
49
+ #endif /* LIBYAZ0_H */
@@ -0,0 +1,6 @@
1
+ #include "libyaz0.h"
2
+
3
+ uint32_t swap32(uint32_t in)
4
+ {
5
+ return ((in & 0xFF) << 24) | ((in & 0xFF00) << 8) | ((in & 0xFF0000) >> 8) | ((in & 0xFF000000) >> 24);
6
+ }
@@ -0,0 +1,14 @@
1
+ require "bundler/setup"
2
+ require "yaz0"
3
+
4
+ RSpec.configure do |config|
5
+ # Enable flags like --only-failures and --next-failure
6
+ config.example_status_persistence_file_path = ".rspec_status"
7
+
8
+ # Disable RSpec exposing methods globally on `Module` and `main`
9
+ config.disable_monkey_patching!
10
+
11
+ config.expect_with :rspec do |c|
12
+ c.syntax = :expect
13
+ end
14
+ end
data/spec/yaz0_spec.rb ADDED
@@ -0,0 +1,39 @@
1
+ RSpec.describe Yaz0 do
2
+ it "has a version number" do
3
+ expect(Yaz0::VERSION).not_to be nil
4
+ end
5
+
6
+ it "can compress" do
7
+ expect(Yaz0.compress("Hello, world")).to be_a(String)
8
+ end
9
+
10
+ it "can decompress" do
11
+ expect(Yaz0.decompress(Yaz0.compress("Hello, world!"))).to eq("Hello, world!")
12
+ end
13
+
14
+ it "works on very redundent string" do
15
+ a = "A" * 8192
16
+ a_compressed = Yaz0.compress(a)
17
+ expect(a_compressed.size).to be < a.size
18
+ expect(Yaz0.decompress(a_compressed)).to eq(a)
19
+ end
20
+
21
+ it "compresses identically" do
22
+ data0 = Yaz0.compress("A" * 8192)
23
+ data1 = Yaz0.compress("A" * 8192)
24
+ expect(data0).to eq(data1)
25
+ end
26
+
27
+ it "decompresses identically" do
28
+ cdata = Yaz0.compress("A" * 8192)
29
+ data0 = Yaz0.decompress(cdata)
30
+ data1 = Yaz0.decompress(cdata)
31
+ expect(data0).to eq(data1)
32
+
33
+ cdata0 = Yaz0.compress("A" * 8192)
34
+ cdata1 = Yaz0.compress("A" * 8192)
35
+ data0 = Yaz0.decompress(cdata0)
36
+ data1 = Yaz0.decompress(cdata1)
37
+ expect(data0).to eq(data1)
38
+ end
39
+ end
data/yaz0.gemspec CHANGED
@@ -14,9 +14,19 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  # Specify which files should be added to the gem when it is released.
16
16
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
- end
17
+ spec.files = Dir[
18
+ "ext/**/*",
19
+ "lib/**/*",
20
+ "spec/**/*",
21
+ "libyaz0/include/**/*",
22
+ "libyaz0/src/libyaz0/**/*",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "Gemfile",
26
+ "Rakefile",
27
+ "yaz0.gemspec",
28
+ ".rspec"
29
+ ]
20
30
  spec.bindir = "exe"
21
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
32
  spec.require_paths = ["lib"]
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaz0
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nax
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-19 00:00:00.000000000 Z
11
+ date: 2022-08-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description:
13
+ description:
14
14
  email:
15
15
  - max@bacoux.com
16
16
  executables: []
@@ -18,30 +18,33 @@ extensions:
18
18
  - ext/yaz0/extconf.rb
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - ".gitignore"
22
21
  - ".rspec"
23
- - ".travis.yml"
24
22
  - Gemfile
25
23
  - LICENSE.txt
26
24
  - README.md
27
25
  - Rakefile
28
- - bin/console
29
- - bin/setup
30
- - ext/yaz0/buffer.c
31
- - ext/yaz0/compress.c
32
- - ext/yaz0/decompress.c
26
+ - ext/yaz0/ext_yaz0.c
27
+ - ext/yaz0/ext_yaz0.h
33
28
  - ext/yaz0/extconf.rb
34
- - ext/yaz0/yaz0.c
35
- - ext/yaz0/yaz0.h
36
29
  - lib/yaz0.rb
37
30
  - lib/yaz0/version.rb
31
+ - lib/yaz0/yaz0.so
32
+ - libyaz0/include/yaz0.h
33
+ - libyaz0/src/libyaz0/CMakeLists.txt
34
+ - libyaz0/src/libyaz0/compress.c
35
+ - libyaz0/src/libyaz0/decompress.c
36
+ - libyaz0/src/libyaz0/libyaz0.c
37
+ - libyaz0/src/libyaz0/libyaz0.h
38
+ - libyaz0/src/libyaz0/util.c
39
+ - spec/spec_helper.rb
40
+ - spec/yaz0_spec.rb
38
41
  - yaz0.gemspec
39
42
  homepage: https://github.com/Nax/ruby-yaz0
40
43
  licenses:
41
44
  - MIT
42
45
  metadata:
43
46
  source_code_uri: https://github.com/Nax/ruby-yaz0
44
- post_install_message:
47
+ post_install_message:
45
48
  rdoc_options: []
46
49
  require_paths:
47
50
  - lib
@@ -56,8 +59,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
59
  - !ruby/object:Gem::Version
57
60
  version: '0'
58
61
  requirements: []
59
- rubygems_version: 3.1.2
60
- signing_key:
62
+ rubygems_version: 3.3.19
63
+ signing_key:
61
64
  specification_version: 4
62
65
  summary: Compress and decompress Yaz0 data.
63
66
  test_files: []
data/.gitignore DELETED
@@ -1,19 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- *.bundle
10
- *.so
11
- *.o
12
- *.a
13
- mkmf.log
14
-
15
- # rspec failure tracking
16
- .rspec_status
17
-
18
- /vendor
19
- /Gemfile.lock
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.6.3
6
- before_install: gem install bundler -v 2.1.4
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "yaz0"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/ext/yaz0/buffer.c DELETED
@@ -1,29 +0,0 @@
1
- #include <stdlib.h>
2
- #include <string.h>
3
- #include <stdio.h>
4
- #include "yaz0.h"
5
-
6
- void yaz0BufferAlloc(Yaz0Buffer *buf, size_t cap)
7
- {
8
- buf->size = 0;
9
- buf->capacity = cap;
10
- buf->data = malloc(cap);
11
- }
12
-
13
- void yaz0BufferFree(Yaz0Buffer *buf)
14
- {
15
- free(buf->data);
16
- buf->data = NULL;
17
- }
18
-
19
- void yaz0BufferWrite(Yaz0Buffer *buf, const void *data, size_t len)
20
- {
21
- while (buf->size + len > buf->capacity)
22
- {
23
- buf->capacity = buf->capacity + buf->capacity / 2;
24
- buf->data = realloc(buf->data, buf->capacity);
25
- }
26
-
27
- memcpy(buf->data + buf->size, data, len);
28
- buf->size += len;
29
- }