mspack_rb 0.1.7 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/mspack_native/chm_decompressor.c +71 -31
- data/ext/mspack_native/chm_decompressor_file.c +8 -0
- data/ext/mspack_native/io_system.c +176 -0
- data/ext/mspack_native/io_system.h +33 -0
- data/lib/mspack/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7344a42572aaac8736edceaa4b344f7ae61125bf
|
4
|
+
data.tar.gz: 05fcde6d525e3e7814212b00cd7987dcd8d7e94d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e43ac5361052d84ec4d166c202022dfd4938c95595856e1b8215ca3e29dd69541e3e266e6bcd58db7c4e0a908cd29a84bc523d633c3396fa496fb126fea49aa2
|
7
|
+
data.tar.gz: c47aa65dc8dba1e5a632090d1f1c9e6a9358bca907ea36899df79b594380ae5c72315ca8ff7152decdaf3989777a88b0f0fa95511df70f639af660d76d9a8743
|
@@ -1,10 +1,19 @@
|
|
1
1
|
#include "chm_decompressor.h"
|
2
|
+
|
2
3
|
#include "mspack_native.h"
|
4
|
+
|
3
5
|
#include "chm_decompressor_header.h"
|
4
6
|
#include "chm_decompressor_file.h"
|
5
7
|
|
8
|
+
#include "io_system.h"
|
9
|
+
|
6
10
|
#include <mspack.h>
|
7
11
|
|
12
|
+
struct decom_wrapper {
|
13
|
+
struct mschm_decompressor *decom;
|
14
|
+
struct mspack_system *system;
|
15
|
+
};
|
16
|
+
|
8
17
|
/*
|
9
18
|
* utility methods
|
10
19
|
*/
|
@@ -59,16 +68,16 @@ static inline VALUE _error_code_sym(int code) {
|
|
59
68
|
static inline VALUE _open(VALUE self, VALUE path, int fast_bool) {
|
60
69
|
Check_Type(path, T_STRING);
|
61
70
|
|
62
|
-
struct
|
63
|
-
Data_Get_Struct(self, struct
|
71
|
+
struct decom_wrapper *wrapper;
|
72
|
+
Data_Get_Struct(self, struct decom_wrapper, wrapper);
|
64
73
|
|
65
74
|
struct mschmd_header *header;
|
66
75
|
|
67
76
|
if (fast_bool) {
|
68
|
-
header = decom->fast_open(decom, StringValueCStr(path));
|
77
|
+
header = wrapper->decom->fast_open(wrapper->decom, StringValueCStr(path));
|
69
78
|
}
|
70
79
|
else {
|
71
|
-
header = decom->open(decom, StringValueCStr(path));
|
80
|
+
header = wrapper->decom->open(wrapper->decom, StringValueCStr(path));
|
72
81
|
}
|
73
82
|
|
74
83
|
if (!header) {
|
@@ -86,13 +95,17 @@ static inline VALUE _open(VALUE self, VALUE path, int fast_bool) {
|
|
86
95
|
* decompressor
|
87
96
|
*/
|
88
97
|
|
89
|
-
void chmd_deallocate(void *
|
90
|
-
mspack_destroy_chm_decompressor(decom);
|
98
|
+
void chmd_deallocate(void *wrapper) {
|
99
|
+
mspack_destroy_chm_decompressor(((struct decom_wrapper *)wrapper)->decom);
|
100
|
+
free(((struct decom_wrapper *)wrapper)->system);
|
101
|
+
free((struct decom_wrapper *)wrapper);
|
91
102
|
}
|
92
103
|
|
93
104
|
VALUE chmd_allocate(VALUE self) {
|
94
|
-
struct
|
95
|
-
|
105
|
+
struct decom_wrapper *wrapper = malloc(sizeof(struct decom_wrapper));
|
106
|
+
wrapper->system = io_system();
|
107
|
+
wrapper->decom = mspack_create_chm_decompressor(wrapper->system);
|
108
|
+
return Data_Wrap_Struct(self, NULL, chmd_deallocate, wrapper);
|
96
109
|
}
|
97
110
|
|
98
111
|
VALUE chmd_open(VALUE self, VALUE path) {
|
@@ -104,39 +117,65 @@ VALUE chmd_close(VALUE self, VALUE header) {
|
|
104
117
|
rb_raise(rb_eTypeError, "Parameter must be a CHM decompression header");
|
105
118
|
}
|
106
119
|
|
107
|
-
struct
|
108
|
-
Data_Get_Struct(self, struct
|
120
|
+
struct decom_wrapper *wrapper;
|
121
|
+
Data_Get_Struct(self, struct decom_wrapper, wrapper);
|
109
122
|
|
110
123
|
struct mschmd_header *headerPtr;
|
111
124
|
Data_Get_Struct(header, struct mschmd_header, headerPtr);
|
112
125
|
|
113
|
-
decom->close(decom, headerPtr);
|
126
|
+
wrapper->decom->close(wrapper->decom, headerPtr);
|
114
127
|
return Qnil;
|
115
128
|
}
|
116
129
|
|
117
|
-
|
130
|
+
/*
|
131
|
+
* Form 1:
|
132
|
+
* extract_to_path(file, outputPath)
|
133
|
+
*
|
134
|
+
* Form 2:
|
135
|
+
* extract_to_path(file) { |data_chunk| do_something(data_chunk) }
|
136
|
+
*/
|
137
|
+
VALUE chmd_extract_to_path(int argc, VALUE* argv, VALUE self) {
|
138
|
+
VALUE file;
|
139
|
+
VALUE outputPath;
|
140
|
+
rb_scan_args(argc, argv, "11", &file, &outputPath);
|
141
|
+
const char *pathStr;
|
142
|
+
|
118
143
|
if (!CLASS_OF(file) == ChmDFile) {
|
119
144
|
rb_raise(rb_eTypeError, "First parameter must be a CHM decompression file");
|
120
145
|
}
|
121
146
|
|
122
|
-
|
147
|
+
if (argc == 1) {
|
148
|
+
rb_need_block();
|
123
149
|
|
124
|
-
|
125
|
-
|
150
|
+
VALUE block;
|
151
|
+
block = rb_block_proc();
|
126
152
|
|
127
|
-
|
128
|
-
|
129
|
-
|
153
|
+
VALUE blockName = rb_funcall(block, rb_intern("to_s"), 0);
|
154
|
+
pathStr = StringValueCStr(blockName);
|
155
|
+
add_block(&blockName, &block);
|
156
|
+
}
|
157
|
+
else {
|
158
|
+
Check_Type(outputPath, T_STRING);
|
159
|
+
pathStr = StringValueCStr(outputPath);
|
160
|
+
}
|
161
|
+
|
162
|
+
struct decom_wrapper *wrapper;
|
163
|
+
Data_Get_Struct(self, struct decom_wrapper, wrapper);
|
164
|
+
|
165
|
+
struct chmd_file_wrapper *headerWrapper;
|
166
|
+
Data_Get_Struct(file, struct chmd_file_wrapper, headerWrapper);
|
167
|
+
|
168
|
+
int result =
|
169
|
+
wrapper->decom->extract(wrapper->decom, headerWrapper->file, pathStr);
|
130
170
|
|
131
|
-
int result = decom->extract(decom, wrapper->file, pathStr);
|
132
171
|
return result == MSPACK_ERR_OK ? Qtrue : Qfalse;
|
133
172
|
}
|
134
173
|
|
135
174
|
VALUE chmd_last_error(VALUE self) {
|
136
|
-
struct
|
137
|
-
Data_Get_Struct(self, struct
|
175
|
+
struct decom_wrapper *wrapper;
|
176
|
+
Data_Get_Struct(self, struct decom_wrapper, wrapper);
|
138
177
|
|
139
|
-
int error = decom->last_error(decom);
|
178
|
+
int error = wrapper->decom->last_error(wrapper->decom);
|
140
179
|
return _error_code_sym(error);
|
141
180
|
}
|
142
181
|
|
@@ -145,8 +184,8 @@ VALUE chmd_fast_open(VALUE self, VALUE path) {
|
|
145
184
|
}
|
146
185
|
|
147
186
|
VALUE chmd_fast_find(VALUE self, VALUE header, VALUE filename) {
|
148
|
-
struct
|
149
|
-
Data_Get_Struct(self, struct
|
187
|
+
struct decom_wrapper *wrapper;
|
188
|
+
Data_Get_Struct(self, struct decom_wrapper, wrapper);
|
150
189
|
|
151
190
|
struct mschmd_header *headerPtr;
|
152
191
|
Data_Get_Struct(header, struct mschmd_header, headerPtr);
|
@@ -156,8 +195,8 @@ VALUE chmd_fast_find(VALUE self, VALUE header, VALUE filename) {
|
|
156
195
|
int structSize = sizeof(struct mschmd_file);
|
157
196
|
struct mschmd_file *file = malloc(structSize);
|
158
197
|
|
159
|
-
int result =
|
160
|
-
|
198
|
+
int result = wrapper->decom->fast_find(
|
199
|
+
wrapper->decom, headerPtr, filenameStr, file, structSize);
|
161
200
|
|
162
201
|
if (result != MSPACK_ERR_OK || file->length == 0) {
|
163
202
|
free(file);
|
@@ -167,11 +206,12 @@ VALUE chmd_fast_find(VALUE self, VALUE header, VALUE filename) {
|
|
167
206
|
file->filename = malloc(sizeof(char) * strlen(filenameStr) + 1);
|
168
207
|
strcpy(file->filename, filenameStr);
|
169
208
|
|
170
|
-
struct chmd_file_wrapper *
|
171
|
-
|
172
|
-
|
209
|
+
struct chmd_file_wrapper *fileWrapper =
|
210
|
+
malloc(sizeof(struct chmd_file_wrapper));
|
211
|
+
fileWrapper->is_fast_find = 1;
|
212
|
+
fileWrapper->file = file;
|
173
213
|
|
174
|
-
return Data_Wrap_Struct(ChmDFile, NULL, chmd_file_free,
|
214
|
+
return Data_Wrap_Struct(ChmDFile, NULL, chmd_file_free, fileWrapper);
|
175
215
|
}
|
176
216
|
|
177
217
|
void Init_chm_decompressor() {
|
@@ -179,7 +219,7 @@ void Init_chm_decompressor() {
|
|
179
219
|
rb_define_alloc_func(ChmDecom, chmd_allocate);
|
180
220
|
rb_define_method(ChmDecom, "open", chmd_open, 1);
|
181
221
|
rb_define_method(ChmDecom, "close", chmd_close, 1);
|
182
|
-
rb_define_method(ChmDecom, "extract_to_path", chmd_extract_to_path,
|
222
|
+
rb_define_method(ChmDecom, "extract_to_path", chmd_extract_to_path, -1);
|
183
223
|
rb_define_method(ChmDecom, "last_error", chmd_last_error, 0);
|
184
224
|
rb_define_method(ChmDecom, "fast_open", chmd_fast_open, 1);
|
185
225
|
rb_define_method(ChmDecom, "fast_find", chmd_fast_find, 2);
|
@@ -39,12 +39,19 @@ VALUE chmd_file_next(VALUE self) {
|
|
39
39
|
|
40
40
|
struct chmd_file_wrapper *next_wrapper =
|
41
41
|
malloc(sizeof(struct chmd_file_wrapper));
|
42
|
+
|
42
43
|
next_wrapper->is_fast_find = 0;
|
43
44
|
next_wrapper->file = next;
|
44
45
|
|
45
46
|
return Data_Wrap_Struct(ChmDFile, NULL, chmd_file_free, next_wrapper);
|
46
47
|
}
|
47
48
|
|
49
|
+
VALUE chmd_file_length(VALUE self) {
|
50
|
+
struct chmd_file_wrapper *wrapper;
|
51
|
+
Data_Get_Struct(self, struct chmd_file_wrapper, wrapper);
|
52
|
+
return LONG2FIX(wrapper->file->length);
|
53
|
+
}
|
54
|
+
|
48
55
|
VALUE chmd_file_is_fast_find(VALUE self) {
|
49
56
|
struct chmd_file_wrapper *wrapper;
|
50
57
|
Data_Get_Struct(self, struct chmd_file_wrapper, wrapper);
|
@@ -55,5 +62,6 @@ void Init_chm_decompressor_file() {
|
|
55
62
|
ChmDFile = rb_define_class_under(ChmDecom, "File", rb_cObject);
|
56
63
|
rb_define_method(ChmDFile, "filename", chmd_file_filename, 0);
|
57
64
|
rb_define_method(ChmDFile, "next", chmd_file_next, 0);
|
65
|
+
rb_define_method(ChmDFile, "length", chmd_file_length, 0);
|
58
66
|
rb_define_method(ChmDFile, "fast_find?", chmd_file_is_fast_find, 0);
|
59
67
|
}
|
@@ -0,0 +1,176 @@
|
|
1
|
+
#include "io_system.h"
|
2
|
+
#include "chm_decompressor.h"
|
3
|
+
|
4
|
+
#include <stdarg.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <string.h>
|
7
|
+
|
8
|
+
#define IO_SYSTEM_MAX_BLOCKS 5
|
9
|
+
|
10
|
+
union io_file_value {
|
11
|
+
FILE *file;
|
12
|
+
VALUE *block;
|
13
|
+
};
|
14
|
+
|
15
|
+
struct io_file {
|
16
|
+
char *name; // only used for block handle
|
17
|
+
union io_file_value value;
|
18
|
+
};
|
19
|
+
|
20
|
+
struct io_file *blocks[IO_SYSTEM_MAX_BLOCKS];
|
21
|
+
|
22
|
+
inline struct io_file *pop_block(const char *name) {
|
23
|
+
for (int i = 0; i < IO_SYSTEM_MAX_BLOCKS - 1; ++i) {
|
24
|
+
struct io_file *block = blocks[i];
|
25
|
+
|
26
|
+
if (block) {
|
27
|
+
if (strcmp(name, block->name) == 0) {
|
28
|
+
blocks[i] = NULL;
|
29
|
+
return block;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
return NULL;
|
35
|
+
}
|
36
|
+
|
37
|
+
struct mspack_file *
|
38
|
+
io_open(struct mspack_system *self, const char *filename, int mode) {
|
39
|
+
struct io_file *block = NULL;
|
40
|
+
|
41
|
+
if (mode != MSPACK_SYS_OPEN_READ) {
|
42
|
+
block = pop_block(filename);
|
43
|
+
}
|
44
|
+
|
45
|
+
if (block) {
|
46
|
+
return (struct mspack_file *)block;
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
const char *modeStr;
|
50
|
+
|
51
|
+
switch (mode) {
|
52
|
+
case MSPACK_SYS_OPEN_READ:
|
53
|
+
modeStr = "r";
|
54
|
+
break;
|
55
|
+
case MSPACK_SYS_OPEN_WRITE:
|
56
|
+
modeStr = "w";
|
57
|
+
break;
|
58
|
+
case MSPACK_SYS_OPEN_UPDATE:
|
59
|
+
modeStr = "w+";
|
60
|
+
break;
|
61
|
+
case MSPACK_SYS_OPEN_APPEND:
|
62
|
+
modeStr = "a+";
|
63
|
+
break;
|
64
|
+
default:
|
65
|
+
return NULL;
|
66
|
+
}
|
67
|
+
|
68
|
+
struct io_file *file = malloc(sizeof(struct io_file));
|
69
|
+
file->value.file = fopen(filename, modeStr);
|
70
|
+
file->name = NULL;
|
71
|
+
|
72
|
+
if (file->value.file) {
|
73
|
+
return (struct mspack_file *)file;
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
free(file);
|
77
|
+
return NULL;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
void io_close(struct mspack_file *file) {
|
83
|
+
if (!((struct io_file *)file)->name) {
|
84
|
+
fclose(((struct io_file *)file)->value.file);
|
85
|
+
}
|
86
|
+
else {
|
87
|
+
free(((struct io_file *)file)->name);
|
88
|
+
}
|
89
|
+
|
90
|
+
free(file);
|
91
|
+
}
|
92
|
+
|
93
|
+
int io_read(struct mspack_file *file, void *buffer, int bytes) {
|
94
|
+
return (int)fread(buffer, 1, bytes, ((struct io_file *)file)->value.file);
|
95
|
+
}
|
96
|
+
|
97
|
+
int io_write(struct mspack_file *file, void *buffer, int bytes) {
|
98
|
+
if (!((struct io_file *)file)->name) {
|
99
|
+
return (int)fwrite(buffer, 1, bytes, ((struct io_file *)file)->value.file);
|
100
|
+
}
|
101
|
+
else {
|
102
|
+
VALUE fixnum;
|
103
|
+
int *intBuffer = buffer;
|
104
|
+
VALUE data = rb_ary_new2(bytes);
|
105
|
+
|
106
|
+
for (int i = 0; i < bytes; ++i) {
|
107
|
+
fixnum = LONG2FIX(intBuffer[i]);
|
108
|
+
rb_ary_push(data, fixnum);
|
109
|
+
}
|
110
|
+
|
111
|
+
VALUE *block;
|
112
|
+
block = ((struct io_file *)file)->value.block;
|
113
|
+
rb_funcall(*block, rb_intern("yield"), 1, data);
|
114
|
+
return bytes;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
int io_seek(struct mspack_file *file, off_t offset, int mode) {
|
119
|
+
return fseek(((struct io_file *)file)->value.file, offset, mode);
|
120
|
+
}
|
121
|
+
|
122
|
+
off_t io_tell(struct mspack_file *file) {
|
123
|
+
return ftell(((struct io_file *)file)->value.file);
|
124
|
+
}
|
125
|
+
|
126
|
+
void io_message(struct mspack_file *file, const char *format, ...) {
|
127
|
+
va_list args;
|
128
|
+
va_start(args, format);
|
129
|
+
vprintf(format, args);
|
130
|
+
va_end(args);
|
131
|
+
}
|
132
|
+
|
133
|
+
void *io_alloc(struct mspack_system *self, size_t bytes) {
|
134
|
+
return malloc(bytes);
|
135
|
+
}
|
136
|
+
|
137
|
+
void io_free(void *ptr) {
|
138
|
+
free(ptr);
|
139
|
+
}
|
140
|
+
|
141
|
+
void io_copy(void *src, void *dest, size_t bytes) {
|
142
|
+
memcpy(dest, src, bytes);
|
143
|
+
}
|
144
|
+
|
145
|
+
struct mspack_system *io_system() {
|
146
|
+
struct mspack_system *system = malloc(sizeof(struct mspack_system));
|
147
|
+
system->open = io_open;
|
148
|
+
system->close = io_close;
|
149
|
+
system->read = io_read;
|
150
|
+
system->write = io_write;
|
151
|
+
system->seek = io_seek;
|
152
|
+
system->tell = io_tell;
|
153
|
+
system->message = io_message;
|
154
|
+
system->alloc = io_alloc;
|
155
|
+
system->free = io_free;
|
156
|
+
system->copy = io_copy;
|
157
|
+
system->null_ptr = NULL;
|
158
|
+
return system;
|
159
|
+
}
|
160
|
+
|
161
|
+
// TODO: chuck an error if we're full
|
162
|
+
void add_block(VALUE *name, VALUE *block) {
|
163
|
+
for (int i = 0; i < IO_SYSTEM_MAX_BLOCKS - 1; ++i) {
|
164
|
+
|
165
|
+
if (!blocks[i]) {
|
166
|
+
struct io_file *file = malloc(sizeof(struct io_file));
|
167
|
+
file->value.block = block;
|
168
|
+
|
169
|
+
const char *nameStr = StringValueCStr(*name);
|
170
|
+
file->name = malloc(sizeof(char) * strlen(nameStr) + 1);
|
171
|
+
strcpy(file->name, nameStr);
|
172
|
+
|
173
|
+
blocks[i] = file;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#ifndef IO_SYSTEM_H
|
2
|
+
#define IO_SYSTEM_H
|
3
|
+
|
4
|
+
#include <mspack.h>
|
5
|
+
#include <ruby.h>
|
6
|
+
|
7
|
+
struct mspack_file *
|
8
|
+
io_open(struct mspack_system *self, const char *filename, int mode);
|
9
|
+
|
10
|
+
void io_close(struct mspack_file *file);
|
11
|
+
|
12
|
+
int io_read(struct mspack_file *file, void *buffer, int bytes);
|
13
|
+
|
14
|
+
int io_write(struct mspack_file *file, void *buffer, int bytes);
|
15
|
+
|
16
|
+
int io_seek(struct mspack_file *file, off_t offset, int mode);
|
17
|
+
|
18
|
+
off_t io_tell(struct mspack_file *file);
|
19
|
+
|
20
|
+
void io_message(struct mspack_file *file, const char *format, ...);
|
21
|
+
|
22
|
+
void *io_alloc(struct mspack_system *self, size_t bytes);
|
23
|
+
|
24
|
+
void io_free(void *ptr);
|
25
|
+
|
26
|
+
void io_copy(void *src, void *dest, size_t bytes);
|
27
|
+
|
28
|
+
|
29
|
+
struct mspack_system *io_system();
|
30
|
+
|
31
|
+
void add_block(VALUE *name, VALUE *block);
|
32
|
+
|
33
|
+
#endif
|
data/lib/mspack/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mspack_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -118,6 +118,8 @@ files:
|
|
118
118
|
- ext/mspack_native/chm_decompressor_header.c
|
119
119
|
- ext/mspack_native/chm_decompressor_header.h
|
120
120
|
- ext/mspack_native/extconf.rb
|
121
|
+
- ext/mspack_native/io_system.c
|
122
|
+
- ext/mspack_native/io_system.h
|
121
123
|
- ext/mspack_native/mspack_native.c
|
122
124
|
- ext/mspack_native/mspack_native.h
|
123
125
|
- lib/mspack.rb
|