heatshrink 0.1.0

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,109 @@
1
+ #ifndef HEATSHRINK_ENCODER_H
2
+ #define HEATSHRINK_ENCODER_H
3
+
4
+ #include <stdint.h>
5
+ #include <stddef.h>
6
+ #include "heatshrink_common.h"
7
+ #include "heatshrink_config.h"
8
+
9
+ typedef enum {
10
+ HSER_SINK_OK, /* data sunk into input buffer */
11
+ HSER_SINK_ERROR_NULL=-1, /* NULL argument */
12
+ HSER_SINK_ERROR_MISUSE=-2, /* API misuse */
13
+ } HSE_sink_res;
14
+
15
+ typedef enum {
16
+ HSER_POLL_EMPTY, /* input exhausted */
17
+ HSER_POLL_MORE, /* poll again for more output */
18
+ HSER_POLL_ERROR_NULL=-1, /* NULL argument */
19
+ HSER_POLL_ERROR_MISUSE=-2, /* API misuse */
20
+ } HSE_poll_res;
21
+
22
+ typedef enum {
23
+ HSER_FINISH_DONE, /* encoding is complete */
24
+ HSER_FINISH_MORE, /* more output remaining; use poll */
25
+ HSER_FINISH_ERROR_NULL=-1, /* NULL argument */
26
+ } HSE_finish_res;
27
+
28
+ #if HEATSHRINK_DYNAMIC_ALLOC
29
+ #define HEATSHRINK_ENCODER_WINDOW_BITS(HSE) \
30
+ ((HSE)->window_sz2)
31
+ #define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(HSE) \
32
+ ((HSE)->lookahead_sz2)
33
+ #define HEATSHRINK_ENCODER_INDEX(HSE) \
34
+ ((HSE)->search_index)
35
+ struct hs_index {
36
+ uint16_t size;
37
+ int16_t index[];
38
+ };
39
+ #else
40
+ #define HEATSHRINK_ENCODER_WINDOW_BITS(_) \
41
+ (HEATSHRINK_STATIC_WINDOW_BITS)
42
+ #define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(_) \
43
+ (HEATSHRINK_STATIC_LOOKAHEAD_BITS)
44
+ #define HEATSHRINK_ENCODER_INDEX(HSE) \
45
+ (&(HSE)->search_index)
46
+ struct hs_index {
47
+ uint16_t size;
48
+ int16_t index[2 << HEATSHRINK_STATIC_WINDOW_BITS];
49
+ };
50
+ #endif
51
+
52
+ typedef struct {
53
+ uint16_t input_size; /* bytes in input buffer */
54
+ uint16_t match_scan_index;
55
+ uint16_t match_length;
56
+ uint16_t match_pos;
57
+ uint16_t outgoing_bits; /* enqueued outgoing bits */
58
+ uint8_t outgoing_bits_count;
59
+ uint8_t flags;
60
+ uint8_t state; /* current state machine node */
61
+ uint8_t current_byte; /* current byte of output */
62
+ uint8_t bit_index; /* current bit index */
63
+ #if HEATSHRINK_DYNAMIC_ALLOC
64
+ uint8_t window_sz2; /* 2^n size of window */
65
+ uint8_t lookahead_sz2; /* 2^n size of lookahead */
66
+ #if HEATSHRINK_USE_INDEX
67
+ struct hs_index *search_index;
68
+ #endif
69
+ /* input buffer and / sliding window for expansion */
70
+ uint8_t buffer[];
71
+ #else
72
+ #if HEATSHRINK_USE_INDEX
73
+ struct hs_index search_index;
74
+ #endif
75
+ /* input buffer and / sliding window for expansion */
76
+ uint8_t buffer[2 << HEATSHRINK_ENCODER_WINDOW_BITS(_)];
77
+ #endif
78
+ } heatshrink_encoder;
79
+
80
+ #if HEATSHRINK_DYNAMIC_ALLOC
81
+ /* Allocate a new encoder struct and its buffers.
82
+ * Returns NULL on error. */
83
+ heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
84
+ uint8_t lookahead_sz2);
85
+
86
+ /* Free an encoder. */
87
+ void heatshrink_encoder_free(heatshrink_encoder *hse);
88
+ #endif
89
+
90
+ /* Reset an encoder. */
91
+ void heatshrink_encoder_reset(heatshrink_encoder *hse);
92
+
93
+ /* Sink up to SIZE bytes from IN_BUF into the encoder.
94
+ * INPUT_SIZE is set to the number of bytes actually sunk (in case a
95
+ * buffer was filled.). */
96
+ HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse,
97
+ uint8_t *in_buf, size_t size, size_t *input_size);
98
+
99
+ /* Poll for output from the encoder, copying at most OUT_BUF_SIZE bytes into
100
+ * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */
101
+ HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse,
102
+ uint8_t *out_buf, size_t out_buf_size, size_t *output_size);
103
+
104
+ /* Notify the encoder that the input stream is finished.
105
+ * If the return value is HSER_FINISH_MORE, there is still more output, so
106
+ * call heatshrink_encoder_poll and repeat. */
107
+ HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse);
108
+
109
+ #endif
@@ -0,0 +1,98 @@
1
+ #include <ruby.h>
2
+ // TODO: debug
3
+ #include <stdio.h>
4
+
5
+ #include "heatshrink_encoder.h"
6
+ #include "heatshrink_decoder.h"
7
+
8
+ #define INPUT_BUFFER_SIZE 256
9
+
10
+ struct Buffer {
11
+ uint8_t *p;
12
+ size_t n;
13
+ };
14
+
15
+ // sink data from src buffer into xcoder
16
+ #define HSRUBY_SINK(K, kind, src, hsd) \
17
+ do { \
18
+ size_t nread; \
19
+ HS##K##_sink_res sres = \
20
+ heatshrink_##kind##_sink(hsx, src.p, src.n, &nread); \
21
+ if (sres < 0) \
22
+ rb_raise(rb_eRuntimeError, "Failed to sink data " #kind " %d.", sres); \
23
+ src.p += nread; \
24
+ src.n -= nread; \
25
+ } while (0);
26
+
27
+ // poll data from xcoder and append it to ruby string
28
+ #define HSRUBY_POLL_CAT(K, kind, hsx, str) \
29
+ HS##K##_poll_res pres; \
30
+ do { \
31
+ size_t nread; \
32
+ uint8_t buf[1024]; \
33
+ pres = heatshrink_##kind##_poll(hsx, buf, sizeof(buf), &nread); \
34
+ if (pres < 0) \
35
+ rb_raise(rb_eRuntimeError, "Failed to poll data %d.", pres); \
36
+ rb_str_cat(res, (char *)buf, nread); \
37
+ } while (pres == HS##K##R_POLL_MORE);
38
+
39
+ // finish xcoder
40
+ #define HSRUBY_FINISH(X, xcoder, hsx, res) \
41
+ HS##X##_finish_res fres; \
42
+ while (1) { \
43
+ fres = heatshrink_##xcoder##_finish(hsx); \
44
+ if (fres == HS##X##R_FINISH_DONE) \
45
+ break; \
46
+ if (fres < 0) \
47
+ rb_raise(rb_eRuntimeError, "Failed to finish %d.", fres); \
48
+ HSRUBY_POLL_CAT(X, xcoder, hsx, res); \
49
+ }
50
+
51
+ // alloc a decoder
52
+ #define HSRUBY_ALLOC_D(ibs, wsz2, lasz2) \
53
+ heatshrink_decoder_alloc(ibs, wsz2, lasz2)
54
+ // alloc an encoder
55
+ #define HSRUBY_ALLOC_E(ibs, wsz2, lasz2) heatshrink_encoder_alloc(wsz2, lasz2)
56
+ // free an xcoder
57
+ #define HSRUBY_FREE(X, xcoder, hsx) heatshrink_##xcoder##_free(hsx)
58
+
59
+ // encode/decode implementation
60
+ #define HSRUBY_IMPL(X, xcoder) \
61
+ Check_Type(data, T_STRING); \
62
+ Check_Type(window_sz2, T_FIXNUM); \
63
+ Check_Type(lookahead_sz2, T_FIXNUM); \
64
+ \
65
+ struct Buffer src = {(uint8_t *)RSTRING_PTR(data), RSTRING_LEN(data)}; \
66
+ VALUE res = rb_str_new(NULL, 0); \
67
+ \
68
+ int wsz2 = FIX2INT(window_sz2); \
69
+ int lasz2 = FIX2INT(lookahead_sz2); \
70
+ \
71
+ heatshrink_##xcoder *hsx = HSRUBY_ALLOC_##X(INPUT_BUFFER_SIZE, wsz2, lasz2); \
72
+ if (hsx == NULL) \
73
+ rb_raise(rb_eRuntimeError, "Failed to allocate " #xcoder "."); \
74
+ \
75
+ while (src.n) { \
76
+ HSRUBY_SINK(X, xcoder, src, hsx); \
77
+ HSRUBY_POLL_CAT(X, xcoder, hsx, res); \
78
+ } \
79
+ HSRUBY_FINISH(X, xcoder, hsx, res); \
80
+ HSRUBY_FREE(X, xcoder, hsx); \
81
+ return res;
82
+
83
+ static VALUE compress(VALUE self, VALUE data, VALUE window_sz2,
84
+ VALUE lookahead_sz2) {
85
+ HSRUBY_IMPL(E, encoder);
86
+ }
87
+
88
+ static VALUE uncompress(VALUE self, VALUE data, VALUE window_sz2,
89
+ VALUE lookahead_sz2) {
90
+ HSRUBY_IMPL(D, decoder);
91
+ }
92
+
93
+ void Init_heatshrink(void) {
94
+ VALUE mod = rb_define_module("Heatshrink");
95
+ mod = rb_define_module_under(mod, "Internal");
96
+ rb_define_module_function(mod, "compress", &compress, 3);
97
+ rb_define_module_function(mod, "uncompress", &uncompress, 3);
98
+ }
data/lib/heatshrink.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'heatshrink/heatshrink'
2
+
3
+ module Heatshrink
4
+ DEF_WINDOW_SZ2 = 11
5
+ DEF_LOOKAHEAD_SZ2 = 4
6
+
7
+ def self.compress data, window_sz2=DEF_WINDOW_SZ2, lookahead_sz2=DEF_LOOKAHEAD_SZ2
8
+ Internal.compress data, window_sz2, lookahead_sz2
9
+ end
10
+
11
+ def self.uncompress data, window_sz2=DEF_WINDOW_SZ2, lookahead_sz2=DEF_LOOKAHEAD_SZ2
12
+ Internal.uncompress data, window_sz2, lookahead_sz2
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heatshrink
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Scott Vokes
8
+ - Martin Nowak
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-02-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake-compiler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ description:
29
+ email: code@dawg.eu
30
+ executables: []
31
+ extensions:
32
+ - ext/heatshrink/extconf.rb
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ext/heatshrink/extconf.rb
36
+ - ext/heatshrink/heatshrink_common.h
37
+ - ext/heatshrink/heatshrink_config.h
38
+ - ext/heatshrink/heatshrink_decoder.c
39
+ - ext/heatshrink/heatshrink_decoder.h
40
+ - ext/heatshrink/heatshrink_encoder.c
41
+ - ext/heatshrink/heatshrink_encoder.h
42
+ - ext/heatshrink/heatshrink_ruby.c
43
+ - lib/heatshrink.rb
44
+ homepage: http://github.com/MartinNowak/heatshrink-ruby
45
+ licenses:
46
+ - ICS
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.5.2
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: data compression library for embedded/real-time systems
68
+ test_files: []