snappy-ruby 1.0.0 → 1.0.1

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/ext/snappy/snappy.c DELETED
@@ -1,282 +0,0 @@
1
- #include <ruby.h>
2
- #include <ruby/encoding.h>
3
- #include <snappy-c.h>
4
- #include <errno.h>
5
-
6
- static VALUE rb_mSnappy;
7
- static VALUE rb_eSnappyError;
8
-
9
- // Compression level validation
10
- #define MIN_COMPRESSION_LEVEL 1
11
- #define MAX_COMPRESSION_LEVEL 9
12
- #define DEFAULT_COMPRESSION_LEVEL 6
13
-
14
- /*
15
- * Compress a string using Snappy compression
16
- *
17
- * @param data [String] the data to compress
18
- * @param options [Hash] options hash
19
- * @option options [Integer] :level compression level (1-9, default: 6)
20
- * @return [String] compressed data
21
- */
22
- static VALUE rb_snappy_compress(int argc, VALUE *argv, VALUE self) {
23
- VALUE data, options;
24
- int level = DEFAULT_COMPRESSION_LEVEL;
25
-
26
- rb_scan_args(argc, argv, "11", &data, &options);
27
-
28
- // Validate input
29
- Check_Type(data, T_STRING);
30
-
31
- // Parse options
32
- if (!NIL_P(options)) {
33
- Check_Type(options, T_HASH);
34
- VALUE level_val = rb_hash_aref(options, ID2SYM(rb_intern("level")));
35
- if (!NIL_P(level_val)) {
36
- level = NUM2INT(level_val);
37
- if (level < MIN_COMPRESSION_LEVEL || level > MAX_COMPRESSION_LEVEL) {
38
- rb_raise(rb_eArgError, "compression level must be between %d and %d",
39
- MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL);
40
- }
41
- }
42
- }
43
-
44
- const char *input = RSTRING_PTR(data);
45
- size_t input_length = RSTRING_LEN(data);
46
-
47
- // Get maximum compressed length
48
- size_t max_compressed_length = snappy_max_compressed_length(input_length);
49
-
50
- // Allocate buffer for compressed data
51
- char *compressed = ALLOC_N(char, max_compressed_length);
52
- size_t compressed_length = max_compressed_length;
53
-
54
- // Perform compression
55
- snappy_status status = snappy_compress(input, input_length, compressed, &compressed_length);
56
-
57
- if (status != SNAPPY_OK) {
58
- xfree(compressed);
59
- rb_raise(rb_eSnappyError, "compression failed with status: %d", status);
60
- }
61
-
62
- // Create Ruby string with compressed data
63
- VALUE result = rb_str_new(compressed, compressed_length);
64
- xfree(compressed);
65
-
66
- return result;
67
- }
68
-
69
- /*
70
- * Decompress Snappy compressed data
71
- *
72
- * @param data [String] the compressed data
73
- * @return [String] decompressed data
74
- */
75
- static VALUE rb_snappy_decompress(VALUE self, VALUE data) {
76
- Check_Type(data, T_STRING);
77
-
78
- const char *compressed = RSTRING_PTR(data);
79
- size_t compressed_length = RSTRING_LEN(data);
80
-
81
- // Get uncompressed length
82
- size_t uncompressed_length;
83
- snappy_status status = snappy_uncompressed_length(compressed, compressed_length, &uncompressed_length);
84
-
85
- if (status != SNAPPY_OK) {
86
- rb_raise(rb_eSnappyError, "failed to get uncompressed length, status: %d", status);
87
- }
88
-
89
- // Allocate buffer for decompressed data
90
- char *uncompressed = ALLOC_N(char, uncompressed_length);
91
-
92
- // Perform decompression
93
- status = snappy_uncompress(compressed, compressed_length, uncompressed, &uncompressed_length);
94
-
95
- if (status != SNAPPY_OK) {
96
- xfree(uncompressed);
97
- rb_raise(rb_eSnappyError, "decompression failed with status: %d", status);
98
- }
99
-
100
- // Create Ruby string with decompressed data
101
- VALUE result = rb_str_new(uncompressed, uncompressed_length);
102
- xfree(uncompressed);
103
-
104
- // Try to set UTF-8 encoding if the data is valid UTF-8
105
- // Otherwise, keep it as binary (ASCII-8BIT)
106
- int utf8_index = rb_utf8_encindex();
107
- rb_enc_associate_index(result, utf8_index);
108
-
109
- // Check if the string is valid in the UTF-8 encoding
110
- // If not, fall back to binary encoding
111
- if (rb_enc_str_coderange(result) == ENC_CODERANGE_BROKEN) {
112
- rb_enc_associate_index(result, rb_ascii8bit_encindex());
113
- }
114
-
115
- return result;
116
- }
117
-
118
- /*
119
- * Compress a file using Snappy compression
120
- *
121
- * @param input_path [String] path to input file
122
- * @param output_path [String] path to output file
123
- * @param options [Hash] options hash
124
- * @option options [Integer] :level compression level (1-9, default: 6)
125
- */
126
- static VALUE rb_snappy_compress_file(int argc, VALUE *argv, VALUE self) {
127
- VALUE input_path, output_path, options;
128
- int level = DEFAULT_COMPRESSION_LEVEL;
129
-
130
- rb_scan_args(argc, argv, "21", &input_path, &output_path, &options);
131
-
132
- Check_Type(input_path, T_STRING);
133
- Check_Type(output_path, T_STRING);
134
-
135
- // Parse options
136
- if (!NIL_P(options)) {
137
- Check_Type(options, T_HASH);
138
- VALUE level_val = rb_hash_aref(options, ID2SYM(rb_intern("level")));
139
- if (!NIL_P(level_val)) {
140
- level = NUM2INT(level_val);
141
- if (level < MIN_COMPRESSION_LEVEL || level > MAX_COMPRESSION_LEVEL) {
142
- rb_raise(rb_eArgError, "compression level must be between %d and %d",
143
- MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL);
144
- }
145
- }
146
- }
147
-
148
- const char *input_file = StringValueCStr(input_path);
149
- const char *output_file = StringValueCStr(output_path);
150
-
151
- // Open input file
152
- FILE *in = fopen(input_file, "rb");
153
- if (!in) {
154
- rb_sys_fail(input_file);
155
- }
156
-
157
- // Get file size
158
- fseek(in, 0, SEEK_END);
159
- long file_size = ftell(in);
160
- fseek(in, 0, SEEK_SET);
161
-
162
- // Read file contents
163
- char *input_data = ALLOC_N(char, file_size);
164
- size_t bytes_read = fread(input_data, 1, file_size, in);
165
- fclose(in);
166
-
167
- if (bytes_read != file_size) {
168
- xfree(input_data);
169
- rb_raise(rb_eIOError, "failed to read complete file");
170
- }
171
-
172
- // Compress data
173
- size_t max_compressed_length = snappy_max_compressed_length(file_size);
174
- char *compressed = ALLOC_N(char, max_compressed_length);
175
- size_t compressed_length = max_compressed_length;
176
-
177
- snappy_status status = snappy_compress(input_data, file_size, compressed, &compressed_length);
178
- xfree(input_data);
179
-
180
- if (status != SNAPPY_OK) {
181
- xfree(compressed);
182
- rb_raise(rb_eSnappyError, "compression failed with status: %d", status);
183
- }
184
-
185
- // Write compressed data to output file
186
- FILE *out = fopen(output_file, "wb");
187
- if (!out) {
188
- xfree(compressed);
189
- rb_sys_fail(output_file);
190
- }
191
-
192
- size_t bytes_written = fwrite(compressed, 1, compressed_length, out);
193
- fclose(out);
194
- xfree(compressed);
195
-
196
- if (bytes_written != compressed_length) {
197
- rb_raise(rb_eIOError, "failed to write complete compressed data");
198
- }
199
-
200
- return Qnil;
201
- }
202
-
203
- /*
204
- * Decompress a Snappy compressed file
205
- *
206
- * @param input_path [String] path to compressed input file
207
- * @param output_path [String] path to decompressed output file
208
- */
209
- static VALUE rb_snappy_decompress_file(VALUE self, VALUE input_path, VALUE output_path) {
210
- Check_Type(input_path, T_STRING);
211
- Check_Type(output_path, T_STRING);
212
-
213
- const char *input_file = StringValueCStr(input_path);
214
- const char *output_file = StringValueCStr(output_path);
215
-
216
- // Open input file
217
- FILE *in = fopen(input_file, "rb");
218
- if (!in) {
219
- rb_sys_fail(input_file);
220
- }
221
-
222
- // Get file size
223
- fseek(in, 0, SEEK_END);
224
- long file_size = ftell(in);
225
- fseek(in, 0, SEEK_SET);
226
-
227
- // Read compressed file contents
228
- char *compressed_data = ALLOC_N(char, file_size);
229
- size_t bytes_read = fread(compressed_data, 1, file_size, in);
230
- fclose(in);
231
-
232
- if (bytes_read != file_size) {
233
- xfree(compressed_data);
234
- rb_raise(rb_eIOError, "failed to read complete file");
235
- }
236
-
237
- // Get uncompressed length
238
- size_t uncompressed_length;
239
- snappy_status status = snappy_uncompressed_length(compressed_data, file_size, &uncompressed_length);
240
-
241
- if (status != SNAPPY_OK) {
242
- xfree(compressed_data);
243
- rb_raise(rb_eSnappyError, "failed to get uncompressed length, status: %d", status);
244
- }
245
-
246
- // Decompress data
247
- char *uncompressed = ALLOC_N(char, uncompressed_length);
248
- status = snappy_uncompress(compressed_data, file_size, uncompressed, &uncompressed_length);
249
- xfree(compressed_data);
250
-
251
- if (status != SNAPPY_OK) {
252
- xfree(uncompressed);
253
- rb_raise(rb_eSnappyError, "decompression failed with status: %d", status);
254
- }
255
-
256
- // Write decompressed data to output file
257
- FILE *out = fopen(output_file, "wb");
258
- if (!out) {
259
- xfree(uncompressed);
260
- rb_sys_fail(output_file);
261
- }
262
-
263
- size_t bytes_written = fwrite(uncompressed, 1, uncompressed_length, out);
264
- fclose(out);
265
- xfree(uncompressed);
266
-
267
- if (bytes_written != uncompressed_length) {
268
- rb_raise(rb_eIOError, "failed to write complete decompressed data");
269
- }
270
-
271
- return Qnil;
272
- }
273
-
274
- void Init_snappy(void) {
275
- rb_mSnappy = rb_define_module("Snappy");
276
- rb_eSnappyError = rb_define_class_under(rb_mSnappy, "Error", rb_eStandardError);
277
-
278
- rb_define_singleton_method(rb_mSnappy, "compress", rb_snappy_compress, -1);
279
- rb_define_singleton_method(rb_mSnappy, "decompress", rb_snappy_decompress, 1);
280
- rb_define_singleton_method(rb_mSnappy, "compress_file", rb_snappy_compress_file, -1);
281
- rb_define_singleton_method(rb_mSnappy, "decompress_file", rb_snappy_decompress_file, 2);
282
- }