mspack_rb 0.1.5 → 0.1.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c69d841d0a58a91453d2b8ebd9f3a91030b67c64
4
- data.tar.gz: c087616dcf7d380e2c635f9e07d056b77c632c85
3
+ metadata.gz: 7f9c40d23c5867b56e2fa1b1960fd31309cfa799
4
+ data.tar.gz: 642ae95857d11d712c584a11b2f20ba0b2daeca3
5
5
  SHA512:
6
- metadata.gz: 86224b683f84c19b88445c65587d9cbca548a20e398b0681f1fb9fecf2d4467f4711abcb410b4c85cc4eec42895f28ba229425a4ff5d8a0052258be199385a03
7
- data.tar.gz: 67bba4649f8e0be72c7fbe2791e35c65f3ffcd8321d69564639ef358335e7a31363c0ce71fed9fe98ff1281ff6fbbc23f21b4d166a1bb2839b42b8f54774d7cc
6
+ metadata.gz: 508fd382485b88754746f25ff1bae5006a68306c5ced69a141e52c053470a2c89d6014cb8999f2ea7a261f5e9a535eb4cf5fffd40b46322ef013ca0bc7199f68
7
+ data.tar.gz: 64dd35882e4fa5fbfa80c147ad422ec30d83caf27d89df1ea130ec743d2e2bb02889b64287b9855375ebbda35851bf155f095b66b8dae948a10beb83b6ad564b
data/.gitignore CHANGED
@@ -1,10 +1,14 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
+ /.byebug_history
4
+
3
5
  /Gemfile.lock
4
6
  /_yardoc/
7
+
5
8
  /coverage/
6
9
  /doc/
7
10
  /pkg/
8
11
  /spec/reports/
9
12
  /tmp/
10
- /lib/mspack/mspack.bundle
13
+
14
+ /lib/mspack_native.bundle
data/README.md CHANGED
@@ -2,14 +2,24 @@
2
2
 
3
3
  ### A simple Ruby native extension gem wrapper for [libmspack](https://www.cabextract.org.uk/libmspack/)
4
4
 
5
- Requires libmspack to be installed, and currently, only basic CHM
6
- extraction has been implemented.
5
+ Requires libmspack to be installed, and currently, only CHM extraction has been
6
+ implemented.
7
7
 
8
8
  The gem is available over at [https://rubygems.org/gems/mspack_rb](https://rubygems.org/gems/mspack_rb).
9
9
 
10
10
  ### Usage:
11
11
  require 'mspack'
12
12
 
13
+ # Extract all files to disk
13
14
  dcom = Mspack::ChmDecompressor.new
14
15
  header = dcom.open('path/to/a/chm/file')
15
16
  header.each_file { |file| dcom.extract(file, out_path) }
17
+ dcom.close(header)
18
+
19
+ # Extract a specific file by name
20
+ fast_open_header = dcom.fast_open('path/to/a/chm/file')
21
+ file = dcom.fast_find(fast_open_header, '/index.html')
22
+ dcom.extract(file) unless file.nil?
23
+
24
+ # check last error
25
+ p 'w00t' if dcom.last_error == :ok
@@ -1,35 +1,109 @@
1
1
  #include "chm_decompressor.h"
2
+ #include "mspack_native.h"
3
+ #include "chm_decompressor_header.h"
4
+ #include "chm_decompressor_file.h"
2
5
 
3
6
  #include <mspack.h>
4
7
 
5
- VALUE ChmDecom = Qnil;
6
- VALUE ChmDHeader = Qnil;
7
- VALUE ChmDFile = Qnil;
8
+ /*
9
+ * utility methods
10
+ */
11
+
12
+ static inline VALUE _error_code_sym(int code) {
13
+ const char *str;
14
+
15
+ switch (code) {
16
+ case MSPACK_ERR_OK:
17
+ str = "ok";
18
+ break;
19
+ case MSPACK_ERR_ARGS:
20
+ str = "args";
21
+ break;
22
+ case MSPACK_ERR_OPEN:
23
+ str = "open";
24
+ break;
25
+ case MSPACK_ERR_READ:
26
+ str = "read";
27
+ break;
28
+ case MSPACK_ERR_WRITE:
29
+ str = "write";
30
+ break;
31
+ case MSPACK_ERR_SEEK:
32
+ str = "seek";
33
+ break;
34
+ case MSPACK_ERR_NOMEMORY:
35
+ str = "no_memory";
36
+ break;
37
+ case MSPACK_ERR_SIGNATURE:
38
+ str = "signature";
39
+ break;
40
+ case MSPACK_ERR_DATAFORMAT:
41
+ str = "data_format";
42
+ break;
43
+ case MSPACK_ERR_CHECKSUM:
44
+ str = "checksum";
45
+ break;
46
+ case MSPACK_ERR_CRUNCH:
47
+ str = "crunch";
48
+ break;
49
+ case MSPACK_ERR_DECRUNCH:
50
+ str = "decrunch";
51
+ break;
52
+ default:
53
+ str = "unknown";
54
+ }
8
55
 
9
- void chmd_deallocate(void *decom) {
10
- mspack_destroy_chm_decompressor(decom);
56
+ return ID2SYM(rb_intern(str));
11
57
  }
12
58
 
13
- VALUE chmd_allocate(VALUE self) {
14
- struct mschm_decompressor *decom = mspack_create_chm_decompressor(NULL);
15
- return Data_Wrap_Struct(self, NULL, chmd_deallocate, decom);
16
- }
59
+ static inline VALUE _open(VALUE self, VALUE path, int fast_bool) {
60
+ Check_Type(path, T_STRING);
17
61
 
18
- VALUE chmd_open(VALUE self, VALUE path) {
19
62
  struct mschm_decompressor *decom;
20
63
  Data_Get_Struct(self, struct mschm_decompressor, decom);
21
- struct mschmd_header *header = decom->open(decom, StringValueCStr(path));
64
+
65
+ struct mschmd_header *header;
66
+
67
+ if (fast_bool) {
68
+ header = decom->fast_open(decom, StringValueCStr(path));
69
+ }
70
+ else {
71
+ header = decom->open(decom, StringValueCStr(path));
72
+ }
22
73
 
23
74
  if (!header) {
24
75
  return Qnil;
25
76
  }
26
77
 
27
- VALUE headerObj = rb_obj_alloc(ChmDHeader);
28
- rb_obj_call_init(headerObj, 0, NULL);
29
- return Data_Wrap_Struct(ChmDHeader, NULL, NULL, header);
78
+ VALUE headerObj = Data_Wrap_Struct(ChmDHeader, NULL, NULL, header);
79
+ VALUE is_fast_open = fast_bool ? Qtrue : Qfalse;
80
+ rb_iv_set(headerObj, "is_fast_open", is_fast_open);
81
+
82
+ return headerObj;
83
+ }
84
+
85
+ /*
86
+ * decompressor
87
+ */
88
+
89
+ void chmd_deallocate(void *decom) {
90
+ mspack_destroy_chm_decompressor(decom);
91
+ }
92
+
93
+ VALUE chmd_allocate(VALUE self) {
94
+ struct mschm_decompressor *decom = mspack_create_chm_decompressor(NULL);
95
+ return Data_Wrap_Struct(self, NULL, chmd_deallocate, decom);
96
+ }
97
+
98
+ VALUE chmd_open(VALUE self, VALUE path) {
99
+ return _open(self, path, 0);
30
100
  }
31
101
 
32
102
  VALUE chmd_close(VALUE self, VALUE header) {
103
+ if (!CLASS_OF(header) == ChmDHeader) {
104
+ rb_raise(rb_eTypeError, "Parameter must be a CHM decompression header");
105
+ }
106
+
33
107
  struct mschm_decompressor *decom;
34
108
  Data_Get_Struct(self, struct mschm_decompressor, decom);
35
109
 
@@ -41,50 +115,61 @@ VALUE chmd_close(VALUE self, VALUE header) {
41
115
  }
42
116
 
43
117
  VALUE chmd_extract_to_path(VALUE self, VALUE file, VALUE outputPath) {
118
+ if (!CLASS_OF(file) == ChmDFile) {
119
+ rb_raise(rb_eTypeError, "First parameter must be a CHM decompression file");
120
+ }
121
+
122
+ Check_Type(outputPath, T_STRING);
123
+
44
124
  struct mschm_decompressor *decom;
45
125
  Data_Get_Struct(self, struct mschm_decompressor, decom);
46
126
 
47
127
  struct mschmd_file *filePtr;
48
128
  Data_Get_Struct(file, struct mschmd_file, filePtr);
49
-
50
129
  const char *pathStr = StringValueCStr(outputPath);
51
- return decom->extract(decom, filePtr, pathStr) == MSPACK_ERR_OK ?
52
- Qtrue : Qfalse;
53
- }
54
130
 
55
- VALUE chmd_header_filename(VALUE self) {
56
- struct mschmd_header *header;
57
- Data_Get_Struct(self, struct mschmd_header, header);
58
- return rb_str_new2(header->filename);
131
+ int result = decom->extract(decom, filePtr, pathStr);
132
+ return result == MSPACK_ERR_OK ? Qtrue : Qfalse;
59
133
  }
60
134
 
61
- VALUE chmd_header_files(VALUE self) {
62
- struct mschmd_header *header;
63
- Data_Get_Struct(self, struct mschmd_header, header);
64
-
65
- VALUE fileObj = rb_obj_alloc(ChmDFile);
66
- rb_obj_call_init(fileObj, 0, NULL);
67
- return Data_Wrap_Struct(ChmDFile, NULL, NULL, header->files);
135
+ VALUE chmd_last_error(VALUE self) {
136
+ struct mschm_decompressor *decom;
137
+ Data_Get_Struct(self, struct mschm_decompressor, decom);
138
+
139
+ int error = decom->last_error(decom);
140
+ return _error_code_sym(error);
68
141
  }
69
142
 
70
- VALUE chmd_file_filename(VALUE self) {
71
- struct mschmd_file *file;
72
- Data_Get_Struct(self, struct mschmd_file, file);
73
- return rb_str_new2(file->filename);
143
+ VALUE chmd_fast_open(VALUE self, VALUE path) {
144
+ return _open(self, path, 1);
74
145
  }
75
146
 
76
- VALUE chmd_file_next(VALUE self) {
77
- struct mschmd_file *file;
78
- Data_Get_Struct(self, struct mschmd_file, file);
79
- struct mschmd_file *next = file->next;
147
+ VALUE chmd_fast_find(VALUE self, VALUE header, VALUE filename) {
148
+ struct mschm_decompressor *decom;
149
+ Data_Get_Struct(self, struct mschm_decompressor, decom);
150
+
151
+ struct mschmd_header *headerPtr;
152
+ Data_Get_Struct(header, struct mschmd_header, headerPtr);
153
+
154
+ const char *filenameStr = StringValueCStr(filename);
80
155
 
81
- if (next == NULL) {
156
+ int structSize = sizeof(struct mschmd_file);
157
+ struct mschmd_file *file = malloc(structSize);
158
+
159
+ int result =
160
+ decom->fast_find(decom, headerPtr, filenameStr, file, structSize);
161
+
162
+ if (result != MSPACK_ERR_OK || file->length == 0) {
163
+ free(file);
82
164
  return Qnil;
83
- }
165
+ }
84
166
 
85
- VALUE nextObj = rb_obj_alloc(ChmDFile);
86
- rb_obj_call_init(nextObj, 0, NULL);
87
- return Data_Wrap_Struct(ChmDFile, NULL, NULL, next);
167
+ file->filename = malloc(sizeof(char) * strlen(filenameStr) + 1);
168
+ strcpy(file->filename, filenameStr);
169
+
170
+ VALUE fileObj = Data_Wrap_Struct(ChmDFile, NULL, NULL, file);
171
+ rb_iv_set(fileObj, "is_fast_find", Qtrue);
172
+ return fileObj;
88
173
  }
89
174
 
90
175
  void Init_chm_decompressor() {
@@ -93,12 +178,7 @@ void Init_chm_decompressor() {
93
178
  rb_define_method(ChmDecom, "open", chmd_open, 1);
94
179
  rb_define_method(ChmDecom, "close", chmd_close, 1);
95
180
  rb_define_method(ChmDecom, "extract_to_path", chmd_extract_to_path, 2);
96
-
97
- ChmDHeader = rb_define_class_under(ChmDecom, "Header", rb_cObject);
98
- rb_define_method(ChmDHeader, "filename", chmd_header_filename, 0);
99
- rb_define_method(ChmDHeader, "files", chmd_header_files, 0);
100
-
101
- ChmDFile = rb_define_class_under(ChmDecom, "File", rb_cObject);
102
- rb_define_method(ChmDFile, "filename", chmd_file_filename, 0);
103
- rb_define_method(ChmDFile, "next", chmd_file_next, 0);
181
+ rb_define_method(ChmDecom, "last_error", chmd_last_error, 0);
182
+ rb_define_method(ChmDecom, "fast_open", chmd_fast_open, 1);
183
+ rb_define_method(ChmDecom, "fast_find", chmd_fast_find, 2);
104
184
  }
@@ -1,11 +1,7 @@
1
1
  #ifndef CHM_DECOMPRESSOR_H
2
2
  #define CHM_DECOMPRESSOR_H
3
3
 
4
- #include "mspack_native.h"
5
-
6
- extern VALUE ChmDecom;
7
- extern VALUE ChmDHeader;
8
- extern VALUE ChmDFile;
4
+ #include <ruby.h>
9
5
 
10
6
  void Init_chm_decompressor();
11
7
 
@@ -0,0 +1,52 @@
1
+ #include "chm_decompressor_file.h"
2
+ #include "mspack_native.h"
3
+
4
+ #include <mspack.h>
5
+
6
+ void chmd_file_free(void *ptr) {
7
+ struct mschmd_file *file = (struct mschmd_file *)ptr;
8
+
9
+ if (file->length == 0) { // only free if it was created in fast_find
10
+ //if (file->filename) {
11
+ // free(file->filename);
12
+ //}
13
+
14
+ free(file);
15
+ }
16
+ }
17
+
18
+ VALUE chmd_file_filename(VALUE self) {
19
+ struct mschmd_file *file;
20
+ Data_Get_Struct(self, struct mschmd_file, file);
21
+
22
+ if (!file->filename) {
23
+ return Qnil;
24
+ }
25
+
26
+ return rb_str_new2(file->filename);
27
+ }
28
+
29
+ VALUE chmd_file_next(VALUE self) {
30
+ struct mschmd_file *file;
31
+ Data_Get_Struct(self, struct mschmd_file, file);
32
+ struct mschmd_file *next = file->next;
33
+
34
+ if (!next) {
35
+ return Qnil;
36
+ }
37
+
38
+ VALUE nextObj = Data_Wrap_Struct(ChmDFile, NULL, chmd_file_free, next);
39
+ rb_iv_set(nextObj, "is_fast_find", Qfalse);
40
+ return nextObj;
41
+ }
42
+
43
+ VALUE chmd_file_is_fast_find(VALUE self) {
44
+ return rb_iv_get(self, "is_fast_find");
45
+ }
46
+
47
+ void Init_chm_decompressor_file() {
48
+ ChmDFile = rb_define_class_under(ChmDecom, "File", rb_cObject);
49
+ rb_define_method(ChmDFile, "filename", chmd_file_filename, 0);
50
+ rb_define_method(ChmDFile, "next", chmd_file_next, 0);
51
+ rb_define_method(ChmDFile, "fast_find?", chmd_file_is_fast_find, 0);
52
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef CHM_DECOMPRESSOR_FILE_H
2
+ #define CHM_DECOMPRESSOR_FILE_H
3
+
4
+ #include <ruby.h>
5
+
6
+ void Init_chm_decompressor_file();
7
+
8
+ #endif
@@ -0,0 +1,34 @@
1
+ #include "chm_decompressor_header.h"
2
+ #include "mspack_native.h"
3
+
4
+ #include <mspack.h>
5
+
6
+ VALUE chmd_header_filename(VALUE self) {
7
+ struct mschmd_header *header;
8
+ Data_Get_Struct(self, struct mschmd_header, header);
9
+ return rb_str_new2(header->filename);
10
+ }
11
+
12
+ VALUE chmd_header_files(VALUE self) {
13
+ struct mschmd_header *header;
14
+ Data_Get_Struct(self, struct mschmd_header, header);
15
+
16
+ if (!header->files) {
17
+ return Qnil;
18
+ }
19
+
20
+ VALUE file = Data_Wrap_Struct(ChmDFile, NULL, NULL, header->files);
21
+ rb_iv_set(file, "is_fast_find", Qfalse);
22
+ return file;
23
+ }
24
+
25
+ VALUE chmd_header_is_fast_open(VALUE self) {
26
+ return rb_iv_get(self, "is_fast_open");
27
+ }
28
+
29
+ void Init_chm_decompressor_header() {
30
+ ChmDHeader = rb_define_class_under(ChmDecom, "Header", rb_cObject);
31
+ rb_define_method(ChmDHeader, "filename", chmd_header_filename, 0);
32
+ rb_define_method(ChmDHeader, "files", chmd_header_files, 0);
33
+ rb_define_method(ChmDHeader, "fast_open?", chmd_header_is_fast_open, 0);
34
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef CHM_DECOMPRESSOR_HEADER_H
2
+ #define CHM_DECOMPRESSOR_HEADER_H
3
+
4
+ #include <ruby.h>
5
+
6
+ void Init_chm_decompressor_header();
7
+
8
+ #endif
@@ -1,9 +1,14 @@
1
1
  #include "mspack_native.h"
2
2
  #include "chm_decompressor.h"
3
+ #include "chm_decompressor_file.h"
4
+ #include "chm_decompressor_header.h"
3
5
 
4
6
  #include <mspack.h>
5
7
 
6
8
  VALUE Mspack = Qnil;
9
+ VALUE ChmDecom = Qnil;
10
+ VALUE ChmDHeader = Qnil;
11
+ VALUE ChmDFile = Qnil;
7
12
 
8
13
  VALUE mspack_test() {
9
14
  int result;
@@ -16,4 +21,6 @@ void Init_mspack_native() {
16
21
  rb_define_singleton_method(Mspack, "test", mspack_test, 0);
17
22
 
18
23
  Init_chm_decompressor();
24
+ Init_chm_decompressor_header();
25
+ Init_chm_decompressor_file();
19
26
  }
@@ -4,5 +4,8 @@
4
4
  #include <ruby.h>
5
5
 
6
6
  extern VALUE Mspack;
7
+ extern VALUE ChmDecom;
8
+ extern VALUE ChmDHeader;
9
+ extern VALUE ChmDFile;
7
10
 
8
11
  #endif
@@ -36,7 +36,6 @@ module Mspack
36
36
  index += 1
37
37
  end
38
38
  end
39
-
40
39
  end
41
40
 
42
41
 
@@ -1,3 +1,3 @@
1
1
  module Mspack
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.6"
3
3
  end
data/lib/mspack.rb CHANGED
@@ -12,6 +12,10 @@ module Mspack
12
12
  # Raises an error if the final, expanded path is outside of dir.
13
13
  # Returns the expanded file path.
14
14
  def self.ensure_path(filename, dir)
15
+ unless filename.is_a?(String) && dir.is_a?(String)
16
+ raise TypeError, 'both parameters must be strings'
17
+ end
18
+
15
19
  raise PathError, "#{dir} is not a directory" unless ::File.directory?(dir)
16
20
  raise PathError, "#{dir} is not writable" unless ::File.writable?(dir)
17
21
 
data/mspack.gemspec CHANGED
@@ -23,9 +23,13 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
  spec.extensions << 'ext/mspack_native/extconf.rb'
25
25
 
26
- spec.add_development_dependency "bundler", "~> 1.13"
27
- spec.add_development_dependency "rake", "~> 10.0"
28
- spec.add_development_dependency "rake-compiler", "~> 1.0"
29
- spec.add_development_dependency "rspec", "~> 3.0"
30
- spec.add_development_dependency "guard-rspec", "~> 4.7"
26
+ spec.add_development_dependency 'bundler', '~> 1.13'
27
+
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rake-compiler', '~> 1.0'
30
+
31
+ spec.add_development_dependency 'rspec', '~> 3.0'
32
+ spec.add_development_dependency 'guard-rspec','~> 4.7'
33
+
34
+ spec.add_development_dependency 'byebug'
31
35
  end
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.1.5
4
+ version: 0.1.6
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-04 00:00:00.000000000 Z
11
+ date: 2017-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '4.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: A ruby gem wrapper for libmspack
84
98
  email:
85
99
  - 8enwilliams@gmail.com
@@ -99,13 +113,16 @@ files:
99
113
  - bin/setup
100
114
  - ext/mspack_native/chm_decompressor.c
101
115
  - ext/mspack_native/chm_decompressor.h
116
+ - ext/mspack_native/chm_decompressor_file.c
117
+ - ext/mspack_native/chm_decompressor_file.h
118
+ - ext/mspack_native/chm_decompressor_header.c
119
+ - ext/mspack_native/chm_decompressor_header.h
102
120
  - ext/mspack_native/extconf.rb
103
121
  - ext/mspack_native/mspack_native.c
104
122
  - ext/mspack_native/mspack_native.h
105
123
  - lib/mspack.rb
106
124
  - lib/mspack/chm_decompressor.rb
107
125
  - lib/mspack/version.rb
108
- - lib/mspack_native.bundle
109
126
  - mspack.gemspec
110
127
  homepage: https://github.com/benjineering/mspack_rb
111
128
  licenses:
Binary file