seven_zip_ruby 1.1.0 → 1.2.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.
@@ -25,7 +25,9 @@
25
25
 
26
26
 
27
27
  #include <ruby.h>
28
+ #ifdef HAVE_RUBY_THREAD_H
28
29
  #include <ruby/thread.h>
30
+ #endif
29
31
 
30
32
  #include <CPP/Common/MyCom.h>
31
33
  #include <CPP/Windows/PropVariant.h>
@@ -37,6 +39,21 @@
37
39
  #include "util_common.h"
38
40
 
39
41
 
42
+ #ifdef NO_RB_THREAD_CALL_WITHOUT_GVL
43
+ inline VALUE rb_thread_call_without_gvl(void *(*func)(void *data), void *data1,
44
+ rb_unblock_function_t *ubf, void *data2)
45
+ {
46
+ typedef VALUE (*func_t)(void *);
47
+
48
+ return rb_thread_blocking_region((func_t)func, data1, ubf, data2);
49
+ }
50
+ #endif
51
+
52
+ // For old compiler
53
+ #ifdef NO_NULLPTR
54
+ #define nullptr NULL
55
+ #endif
56
+
40
57
  namespace SevenZip
41
58
  {
42
59
 
@@ -105,33 +122,29 @@ class ArchiveBase
105
122
  public:
106
123
  ArchiveBase();
107
124
  ~ArchiveBase();
125
+ void setSelf(VALUE self);
126
+ VALUE self();
108
127
  void rubyEventLoop();
109
128
  static VALUE staticRubyEventLoop(void *p);
110
- bool runRubyAction(RubyAction action);
111
- void finishRubyAction();
112
- static void cancelAction(void *p);
113
- void cancelAction();
129
+ template<typename T> bool runRubyAction(T t);
114
130
  static VALUE runProtectedRubyAction(VALUE p);
115
131
 
132
+ protected:
133
+ void mark();
134
+ void prepareAction();
135
+
116
136
  template<typename T>
117
137
  void runNativeFunc(T func);
118
138
  template<typename T, typename U>
119
139
  bool runNativeFuncProtect(T func, U cancel);
120
- template<typename T>
121
- static void *staticRunFunctor(void *p);
122
- template<typename T>
123
- static void staticRunFunctor2(void *p);
124
- template<typename T>
125
- static VALUE staticRunFunctorForProtect(VALUE p);
126
-
127
- protected:
128
- void mark();
129
- void prepareAction();
130
140
 
131
141
  private:
132
142
  void startEventLoopThread();
133
143
  void terminateEventLoopThread();
144
+ void killEventLoopThread();
145
+ void finishRubyAction();
134
146
  bool runRubyActionImpl(RubyAction *action);
147
+ void cancelAction();
135
148
  virtual void setErrorState() = 0;
136
149
 
137
150
 
@@ -139,10 +152,11 @@ class ArchiveBase
139
152
  static RubyAction ACTION_END;
140
153
 
141
154
  private:
142
- RubyActionTuple *m_action_tuple;
155
+ RubyActionTuple * volatile m_action_tuple;
143
156
  Mutex m_action_mutex;
144
157
  ConditionVariable m_action_cond_var;
145
- bool m_event_loop_running;
158
+ volatile bool m_event_loop_running;
159
+ VALUE m_self;
146
160
 
147
161
  protected:
148
162
  RubyActionResult m_action_result;
@@ -151,65 +165,41 @@ class ArchiveBase
151
165
  template<typename T>
152
166
  void ArchiveBase::runNativeFunc(T func)
153
167
  {
154
- void *(*functor)(void *);
155
- functor = staticRunFunctor<T>;
156
-
157
168
  typedef std::function<void ()> func_type;
169
+
170
+ func_type functor = func;
171
+ func_type cancel = [&](){ cancelAction(); };
172
+
158
173
  func_type protected_func = [&](){
159
- rb_thread_call_without_gvl(functor, reinterpret_cast<void*>(&func),
160
- cancelAction, reinterpret_cast<void*>(this));
174
+ rb_thread_call_without_gvl(rubyCppUtilFunction1, reinterpret_cast<void*>(&functor),
175
+ rubyCppUtilFunction2, reinterpret_cast<void*>(&cancel));
161
176
  };
162
177
 
163
178
  int state = 0;
164
- rb_protect(staticRunFunctorForProtect<func_type>, reinterpret_cast<VALUE>(&protected_func), &state);
179
+ rb_protect(rubyCppUtilFunctionForProtect, reinterpret_cast<VALUE>(&protected_func), &state);
165
180
  if (state){
166
- throw RubyCppUtil::RubyException("Interrupted");
181
+ throw RubyCppUtil::RubyException(std::string("Interrupted"));
167
182
  }
168
183
  }
169
184
 
170
185
  template<typename T, typename U>
171
186
  bool ArchiveBase::runNativeFuncProtect(T func, U cancel)
172
187
  {
173
- void *(*functor)(void *);
174
- void (*functor2)(void *);
175
- functor = staticRunFunctor<T>;
176
- functor2 = staticRunFunctor2<U>;
177
-
178
188
  typedef std::function<void ()> func_type;
189
+
190
+ func_type functor1 = func;
191
+ func_type functor2 = cancel;
192
+
179
193
  func_type protected_func = [&](){
180
- rb_thread_call_without_gvl(functor, reinterpret_cast<void*>(&func),
181
- functor2, reinterpret_cast<void*>(&cancel));
194
+ rb_thread_call_without_gvl(rubyCppUtilFunction1, reinterpret_cast<void*>(&functor1),
195
+ rubyCppUtilFunction2, reinterpret_cast<void*>(&functor2));
182
196
  };
183
197
 
184
198
  int state = 0;
185
- rb_protect(staticRunFunctorForProtect<func_type>, reinterpret_cast<VALUE>(&protected_func), &state);
199
+ rb_protect(rubyCppUtilFunctionForProtect, reinterpret_cast<VALUE>(&protected_func), &state);
186
200
  return (state == 0);
187
201
  }
188
202
 
189
- template<typename T>
190
- void *ArchiveBase::staticRunFunctor(void *p)
191
- {
192
- T *t = reinterpret_cast<T*>(p);
193
- (*t)();
194
- return 0;
195
- }
196
-
197
- template<typename T>
198
- void ArchiveBase::staticRunFunctor2(void *p)
199
- {
200
- T *t = reinterpret_cast<T*>(p);
201
- (*t)();
202
- return;
203
- }
204
-
205
- template<typename T>
206
- VALUE ArchiveBase::staticRunFunctorForProtect(VALUE p)
207
- {
208
- T *t = reinterpret_cast<T*>(p);
209
- (*t)();
210
- return Qnil;
211
- }
212
-
213
203
  class ArchiveReader : public ArchiveBase
214
204
  {
215
205
  private:
@@ -487,6 +477,26 @@ class InStream : public IInStream, public CMyUnknownImp
487
477
  ArchiveBase *m_archive;
488
478
  };
489
479
 
480
+ class FileInStream : public IInStream, public CMyUnknownImp
481
+ {
482
+ public:
483
+ FileInStream(const std::string &filename, ArchiveBase *archive);
484
+ ~FileInStream();
485
+
486
+ MY_UNKNOWN_IMP1(IInStream)
487
+
488
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
489
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
490
+
491
+ private:
492
+ ArchiveBase *m_archive;
493
+ #ifdef USE_WIN32_FILE_API
494
+ HANDLE m_file_handle;
495
+ #else
496
+ std::ifstream m_file;
497
+ #endif
498
+ };
499
+
490
500
 
491
501
  class OutStream : public IOutStream, public CMyUnknownImp
492
502
  {
@@ -505,6 +515,23 @@ class OutStream : public IOutStream, public CMyUnknownImp
505
515
  ArchiveBase *m_archive;
506
516
  };
507
517
 
518
+ // Not implemented yet.
519
+ class FileOutStream : public IOutStream, public CMyUnknownImp
520
+ {
521
+ public:
522
+ FileOutStream(const std::string &filename, ArchiveBase *archive);
523
+
524
+ MY_UNKNOWN_IMP1(IOutStream)
525
+
526
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
527
+
528
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
529
+ STDMETHOD(SetSize)(UInt64 size);
530
+
531
+ private:
532
+ const std::string m_filename;
533
+ ArchiveBase *m_archive;
534
+ };
508
535
 
509
536
 
510
537
  ////////////////////////////////////////////////////////////////
@@ -0,0 +1,28 @@
1
+
2
+ #include <functional>
3
+
4
+ #include "util_common.h"
5
+
6
+ extern "C" VALUE rubyCppUtilFunctionForProtect(VALUE p)
7
+ {
8
+ typedef std::function<void ()> func_type;
9
+ func_type *func = reinterpret_cast<func_type*>(p);
10
+ (*func)();
11
+ return Qnil;
12
+ }
13
+
14
+ extern "C" void *rubyCppUtilFunction1(void *p)
15
+ {
16
+ typedef std::function<void ()> func_type;
17
+ func_type *func = reinterpret_cast<func_type*>(p);
18
+ (*func)();
19
+ return nullptr;
20
+ }
21
+
22
+ extern "C" void rubyCppUtilFunction2(void *p)
23
+ {
24
+ typedef std::function<void ()> func_type;
25
+ func_type *func = reinterpret_cast<func_type*>(p);
26
+ (*func)();
27
+ }
28
+
@@ -4,13 +4,18 @@
4
4
  #include <algorithm>
5
5
  #include <functional>
6
6
  #include <utility>
7
+ #include <string>
8
+ #include <iostream>
7
9
 
8
10
  #include <ruby.h>
9
11
 
12
+ extern "C" VALUE rubyCppUtilFunctionForProtect(VALUE p);
13
+ extern "C" void *rubyCppUtilFunction1(void *p);
14
+ extern "C" void rubyCppUtilFunction2(void *p);
15
+
10
16
  namespace RubyCppUtil
11
17
  {
12
18
 
13
-
14
19
  class RubyException
15
20
  {
16
21
  public:
@@ -34,6 +39,23 @@ class RubyException
34
39
  };
35
40
 
36
41
 
42
+ template<typename T>
43
+ void runRubyFunction(T func)
44
+ {
45
+ std::function<void ()> function = func;
46
+ int state = 0;
47
+ rb_protect(rubyCppUtilFunctionForProtect, reinterpret_cast<VALUE>(&function), &state);
48
+
49
+ if (state){
50
+ VALUE exception = rb_gv_get("$!");
51
+ if (!NIL_P(exception)){
52
+ throw RubyException(exception);
53
+ }
54
+ throw RubyException(std::string("Unknown exception"));
55
+ }
56
+ }
57
+
58
+
37
59
  template<typename T, VALUE (T::*func)()>
38
60
  VALUE wrappedFunction0(VALUE self)
39
61
  {
@@ -371,6 +393,7 @@ VALUE wrapInitialize(VALUE self)
371
393
  Data_Get_Struct(self, T, p);
372
394
  std::fill_n(reinterpret_cast<unsigned char*>(p), sizeof(T), ~INIT_MEMORY_VALUE);
373
395
  new(p) T();
396
+ p->setSelf(self);
374
397
 
375
398
  return Qnil;
376
399
  }
@@ -388,7 +411,7 @@ VALUE rb_define_wrapped_cpp_class(const char *name, VALUE super)
388
411
 
389
412
  VALUE cls = rb_define_class(name, super);
390
413
  rb_define_alloc_func(cls, alloc);
391
- rb_define_method(cls, "initialize", RUBY_METHOD_FUNC(init), 0);
414
+ rb_define_private_method(cls, "initialize", RUBY_METHOD_FUNC(init), 0);
392
415
  return cls;
393
416
  }
394
417
 
@@ -404,7 +427,7 @@ VALUE rb_define_wrapped_cpp_class_under(VALUE outer, const char *name, VALUE sup
404
427
 
405
428
  VALUE cls = rb_define_class_under(outer, name, super);
406
429
  rb_define_alloc_func(cls, alloc);
407
- rb_define_method(cls, "initialize", RUBY_METHOD_FUNC(init), 0);
430
+ rb_define_private_method(cls, "initialize", RUBY_METHOD_FUNC(init), 0);
408
431
  return cls;
409
432
  }
410
433
 
@@ -500,7 +500,6 @@ void ConvertTimeToFiletime(VALUE time, FILETIME *filetime)
500
500
 
501
501
  VALUE ConvertPropToValue(const PROPVARIANT &prop)
502
502
  {
503
- VALUE ret;
504
503
  switch(prop.vt){
505
504
  case VT_EMPTY:
506
505
  case VT_NULL:
@@ -121,8 +121,8 @@ class ConditionVariable
121
121
  private:
122
122
  HANDLE m_signal_event;
123
123
  HANDLE m_broadcast_event;
124
- unsigned int m_waiters_count;
125
124
  Mutex m_waiters_count_mutex;
125
+ unsigned int m_waiters_count;
126
126
  };
127
127
 
128
128
  }
@@ -1,16 +1,27 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require_relative("seven_zip_ruby/version")
3
+ require("seven_zip_ruby/version")
4
4
 
5
- Dir.chdir("#{__dir__}/seven_zip_ruby"){ require_relative("seven_zip_ruby/seven_zip_archive") }
5
+ external_lib = (RUBY_PLATFORM.downcase.match(/mswin|mingw/) ? "7z.dll" : "7z.so")
6
+ dir = $:.find do |i|
7
+ next File.file?(File.join(i, "seven_zip_ruby", external_lib))
8
+ end
9
+ raise "Failed to find 7z.dll or 7z.so" unless (dir)
10
+
11
+ Dir.chdir(File.join(dir, "seven_zip_ruby"))do
12
+ begin
13
+ version = RUBY_VERSION.match(/\d+\.\d+/)
14
+ require("seven_zip_ruby/#{version}/seven_zip_archive")
15
+ rescue LoadError
16
+ require("seven_zip_ruby/seven_zip_archive")
17
+ end
18
+ end
6
19
  raise "Failed to initialize SevenZipRuby" unless (defined?(SevenZipRuby::SevenZipReader))
7
20
 
8
- require_relative("seven_zip_ruby/seven_zip_reader")
9
- require_relative("seven_zip_ruby/seven_zip_writer")
10
- require_relative("seven_zip_ruby/archive_info")
11
- require_relative("seven_zip_ruby/update_info")
12
- require_relative("seven_zip_ruby/entry_info")
13
- require_relative("seven_zip_ruby/exception")
21
+ require("seven_zip_ruby/seven_zip_reader")
22
+ require("seven_zip_ruby/seven_zip_writer")
23
+ require("seven_zip_ruby/archive_info")
24
+ require("seven_zip_ruby/update_info")
25
+ require("seven_zip_ruby/entry_info")
26
+ require("seven_zip_ruby/exception")
14
27
 
15
- module SevenZipRuby
16
- end
@@ -4,11 +4,12 @@ module SevenZipRuby
4
4
  class EntryInfo
5
5
  def initialize(index, path, method, dir, encrypted, anti, size, pack_size, ctime, atime, mtime, attrib, crc)
6
6
  @index, @path, @method, @dir, @encrypted, @anti, @size, @pack_size, @ctime, @atime, @mtime, @attrib, @crc =
7
- index, Pathname(path.to_s.force_encoding(Encoding::UTF_8)).cleanpath, method, dir, encrypted, anti, size, pack_size, ctime, atime, mtime, attrib, crc
7
+ index, Pathname(path.to_s.force_encoding(Encoding::UTF_8)).cleanpath.to_s, method, dir, encrypted, anti, size, pack_size, ctime, atime, mtime, attrib, crc
8
8
  end
9
9
 
10
10
  attr_reader :index, :path, :method, :size, :pack_size, :ctime, :atime, :mtime, :attrib, :crc
11
11
  alias to_i index
12
+ alias crc32 crc
12
13
 
13
14
  def directory?
14
15
  return @dir
@@ -38,7 +39,7 @@ module SevenZipRuby
38
39
  else
39
40
  type = "file"
40
41
  end
41
- str = path.to_s.encode(Encoding::ASCII, invalid: :replace, undef: :replace, replace: "?")
42
+ str = path.encode(Encoding::ASCII, invalid: :replace, undef: :replace, replace: "?")
42
43
  return "#<EntryInfo: #{index}, #{type}, #{str}>"
43
44
  end
44
45
  end
@@ -28,6 +28,11 @@ module SevenZipRuby
28
28
  # end
29
29
  # end
30
30
  #
31
+ # # Extract archive 2
32
+ # SevenZipRuby::Reader.open_file("filename.7z") do |szr|
33
+ # szr.extract(:all, "path_to_dir")
34
+ # end
35
+ #
31
36
  # # Extract encrypted archive
32
37
  # File.open("filename.7z", "rb") do |file|
33
38
  # SevenZipRuby::Reader.open(file, password: "Password String") do |szr|
@@ -103,6 +108,40 @@ module SevenZipRuby
103
108
  end
104
109
  end
105
110
 
111
+
112
+ # Open 7zip archive to read.
113
+ #
114
+ # ==== Args
115
+ # +filename+ :: Filename of 7zip archive.
116
+ # +param+ :: Optional hash parameter. <tt>:password</tt> key represents password of this archive.
117
+ #
118
+ # ==== Examples
119
+ # # Open archive
120
+ # SevenZipRuby::SevenZipReader.open_file("filename.7z") do |szr|
121
+ # # Read and extract archive.
122
+ # end
123
+ #
124
+ # # Open encrypted archive
125
+ # SevenZipRuby::SevenZipReader.open_file("filename.7z", password: "PasswordOfArchive") do |szr|
126
+ # # Read and extract archive.
127
+ # end
128
+ #
129
+ # # Open without block.
130
+ # szr = SevenZipRuby::SevenZipReader.open_file("filename.7z")
131
+ # # Read and extract archive.
132
+ # szr.close
133
+ def open_file(filename, param = {}, &block) # :yield: szr
134
+ szr = self.new
135
+ szr.open_file(filename, param)
136
+ if (block)
137
+ block.call(szr)
138
+ szr.close
139
+ else
140
+ szr
141
+ end
142
+ end
143
+
144
+
106
145
  # Open and extract 7zip archive.
107
146
  #
108
147
  # ==== Args
@@ -167,6 +206,8 @@ module SevenZipRuby
167
206
  end
168
207
  end
169
208
 
209
+ undef initialize_copy, clone, dup
210
+
170
211
  # Open 7zip archive.
171
212
  #
172
213
  # ==== Args
@@ -187,6 +228,31 @@ module SevenZipRuby
187
228
  return self
188
229
  end
189
230
 
231
+ # Open 7zip archive file.
232
+ #
233
+ # ==== Args
234
+ # +filename+ :: Filename of 7zip archive.
235
+ # +param+ :: Optional hash parameter. <tt>:password</tt> key represents password of this archive.
236
+ #
237
+ # ==== Examples
238
+ # szr = SevenZipRuby::SevenZipReader.new
239
+ # szr.open_file("filename.7z")
240
+ # # ...
241
+ # szr.close
242
+ def open_file(filename, param = {})
243
+ @stream = File.open(filename, "rb")
244
+ self.open(@stream, param)
245
+ return self
246
+ end
247
+
248
+ def close
249
+ close_impl
250
+ if (@stream)
251
+ @stream.close
252
+ @stream = nil
253
+ end
254
+ end
255
+
190
256
  # Verify 7zip archive.
191
257
  #
192
258
  # ==== Args
@@ -252,9 +318,11 @@ module SevenZipRuby
252
318
  when Symbol
253
319
  raise SevenZipError.new("Argument error") unless (index == :all)
254
320
  return extract_all(path)
255
- when Array
321
+ when Enumerable
256
322
  index_list = index.map(&:to_i).sort.uniq
257
323
  extract_files_impl(index_list, file_proc(path))
324
+ when nil
325
+ raise ArgumentError.new("Invalid parameter index")
258
326
  else
259
327
  extract_impl(index.to_i, file_proc(path))
260
328
  end
@@ -328,7 +396,7 @@ module SevenZipRuby
328
396
  extract_all_impl(data_proc(ret, idx_prj))
329
397
  return ret
330
398
 
331
- when Array
399
+ when Enumerable
332
400
  index_list = index.map(&:to_i)
333
401
  idx_prj = Hash[*(index_list.each_with_index.map{ |idx, i| [ idx, i ] }.flatten)]
334
402
 
@@ -336,6 +404,9 @@ module SevenZipRuby
336
404
  extract_files_impl(index_list, data_proc(ret, idx_prj))
337
405
  return ret
338
406
 
407
+ when nil
408
+ raise ArgumentError.new("Invalid parameter index")
409
+
339
410
  else
340
411
  index = index.to_i
341
412
  item = entry(index)
@@ -360,14 +431,15 @@ module SevenZipRuby
360
431
  case(type)
361
432
  when :stream
362
433
  ret = nil
434
+ arg_path = Pathname(arg.path)
363
435
  if (arg.anti?)
364
- arg.path.rmtree if (arg.path.exist?)
436
+ arg_path.rmtree if (arg_path.exist?)
365
437
  elsif (arg.file?)
366
- path = arg.path.expand_path(base_dir)
438
+ path = arg_path.expand_path(base_dir)
367
439
  path.parent.mkpath
368
440
  ret = File.open(path, "wb")
369
441
  else
370
- path = arg.path.expand_path(base_dir)
442
+ path = arg_path.expand_path(base_dir)
371
443
  path.mkpath
372
444
  set_file_attribute(path.to_s, arg.attrib) if (arg.attrib)
373
445
  path.utime(arg.atime || path.atime, arg.mtime || path.mtime)
@@ -379,7 +451,7 @@ module SevenZipRuby
379
451
  raise InvalidArchive.new("Corrupted archive or invalid password") unless (arg[:success])
380
452
 
381
453
  unless (arg[:info].anti?)
382
- path = arg[:info].path.expand_path(base_dir)
454
+ path = Pathname(arg[:info].path).expand_path(base_dir)
383
455
  set_file_attribute(path.to_s, arg[:info].attrib) if (arg[:info].attrib)
384
456
  path.utime(arg[:info].atime || path.atime, arg[:info].mtime || path.mtime)
385
457
  end