async-ruby-zip 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,107 @@
1
+ #include "cfilesystem.h"
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+ #include <unistd.h>
6
+ #include <sys/stat.h>
7
+ #include <sys/types.h>
8
+
9
+
10
+ // Recursive directory creation
11
+ static void _mkdir(const char *dir, mode_t mode) {
12
+
13
+ char tmp[512];
14
+ char *p = NULL;
15
+ size_t len;
16
+
17
+ snprintf(tmp, sizeof(tmp),"%s",dir);
18
+ len = strlen(tmp);
19
+ if(tmp[len - 1] == '/')
20
+ tmp[len - 1] = 0;
21
+ for(p = tmp + 1; *p; p++)
22
+ if(*p == '/') {
23
+ *p = 0;
24
+ mkdir(tmp, mode);
25
+ *p = '/';
26
+ }
27
+ mkdir(tmp, S_IRWXU);
28
+ }
29
+
30
+
31
+ // Remove file or directory
32
+ void cfilesystem_remove(const char* filepath)
33
+ {
34
+ remove(filepath);
35
+ }
36
+
37
+ // Returns a positive value if path is found, otherwise 0
38
+ int cfilesystem_exists(const char* filepath)
39
+ {
40
+ return (access(filepath, F_OK) == 0 ? 1 : 0);
41
+ }
42
+
43
+ // Get the filename for the given file path
44
+ char* cfilesystem_filename(const char* filepath)
45
+ {
46
+ char* result = NULL;
47
+ char* last = strrchr(filepath, '/');
48
+ if(last)
49
+ {
50
+ result = strdup(last);
51
+ }
52
+
53
+ return result;
54
+ }
55
+
56
+ // Create directories
57
+ void cfilesystem_create_directories(const char* filepath)
58
+ {
59
+ _mkdir(filepath, S_IRWXU | S_IRWXG | S_IRWXO);
60
+ }
61
+
62
+ // Get a temporary filename.
63
+ char* cfilesystem_tempfilename()
64
+ {
65
+ char buffer[L_tmpnam];
66
+ tmpnam(buffer);
67
+ return strdup(buffer);
68
+ }
69
+
70
+ // Append one path to the other.
71
+ // Returns the combined path
72
+ char* cfilesystem_combine(const char* path1, const char* path2)
73
+ {
74
+ char* result = NULL;
75
+
76
+ if(!path1 && !path2) {
77
+ // no-op
78
+ }
79
+ else if(!path2 || !path2[0]) {
80
+ result = strdup(path1);
81
+ }
82
+ else if(!path1 || !path1[0]) {
83
+ result = strdup(path2);
84
+ }
85
+ else {
86
+ char* ptr;
87
+ size_t len1 = strlen(path1);
88
+ size_t len2 = strlen(path2);
89
+
90
+ size_t newlen = len1 + len2 + 1 + ((path1[len1 - 1] != '/' && path2[0] != '/') ? 1 : 0);
91
+ result = (char*)malloc(newlen);
92
+ ptr = result;
93
+
94
+ strcpy(ptr, path1);
95
+ ptr += len1;
96
+
97
+ if((ptr[-1] != '/') && (path2[0] != '/'))
98
+ {
99
+ ptr[0] = '/';
100
+ ++ptr;
101
+ }
102
+
103
+ strcpy(ptr, path2);
104
+ }
105
+
106
+ return result;
107
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef EXTRA_CFILESYSTEM_H
2
+ #define EXTRA_CFILESYSTEM_H
3
+
4
+ void cfilesystem_remove(const char* filepath);
5
+ int cfilesystem_exists(const char* filepath);
6
+ char* cfilesystem_filename(const char* filepath);
7
+ void cfilesystem_create_directories(const char* filepath);
8
+ char* cfilesystem_tempfilename();
9
+ char* cfilesystem_combine(const char* path1, const char* path2);
10
+
11
+ #endif
@@ -0,0 +1,10 @@
1
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
+
3
+ require "mkmf"
4
+
5
+ File::unlink("Makefile") if (File::exist?("Makefile"))
6
+
7
+ pkg_config("libzip")
8
+
9
+ have_header('zip.h')
10
+ create_makefile('async_zip_ext')
@@ -0,0 +1,62 @@
1
+ #include "task.h"
2
+ #include "carray.h"
3
+
4
+ VALUE cTask;
5
+
6
+ /* Get the source parameter */
7
+ static VALUE az_task_src(VALUE self)
8
+ {
9
+ return rb_iv_get(self, "@src");
10
+ }
11
+
12
+ /* Get the destination parameter */
13
+ static VALUE az_task_dst(VALUE self)
14
+ {
15
+ return rb_iv_get(self, "@dst");
16
+ }
17
+
18
+ /* Get the error parameter */
19
+ static VALUE az_task_error(VALUE self)
20
+ {
21
+ return rb_iv_get(self, "@error");
22
+ }
23
+
24
+ /* Get the files */
25
+ static VALUE az_task_files(VALUE self)
26
+ {
27
+ return rb_iv_get(self, "@files");
28
+ }
29
+
30
+
31
+ /* Initialize the object, called before the callback is invoked */
32
+ void az_task_init(VALUE self, const char* src_path, const char* dst_path, const char* err_str, const carray_str_t* files_arr)
33
+ {
34
+ rb_iv_set(self, "@src", (src_path ? rb_str_new2(src_path) : Qnil));
35
+ rb_iv_set(self, "@dst", (dst_path ? rb_str_new2(dst_path) : Qnil));
36
+ rb_iv_set(self, "@error", (err_str ? rb_str_new2(err_str) : Qnil));
37
+
38
+ // create an array
39
+ VALUE arr = rb_ary_new();
40
+ size_t len = carray_str_size(files_arr);
41
+ if(len > 0)
42
+ {
43
+ size_t i;
44
+ for(i = 0; i != len; ++i)
45
+ {
46
+ const char* s = carray_str_get(files_arr, i);
47
+ rb_ary_push(arr, rb_str_new2(s));
48
+ }
49
+ }
50
+ rb_iv_set(self, "@files", arr);
51
+ }
52
+
53
+
54
+ void init_async_zip_task()
55
+ {
56
+ cTask = rb_define_class_under(mAsyncZip, "Task", rb_cObject);
57
+
58
+ rb_define_method(cTask, "src", az_task_src, 0);
59
+ rb_define_method(cTask, "dst", az_task_dst, 0);
60
+ rb_define_method(cTask, "error", az_task_error, 0);
61
+ rb_define_method(cTask, "files", az_task_files, 0);
62
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef ASYNC_ZIP_TASK_H
2
+ #define ASYNC_ZIP_TASK_H
3
+
4
+ #include "async_zip.h"
5
+ #include "carray.h"
6
+
7
+ extern VALUE cTask;
8
+
9
+ void az_task_init(VALUE self, const char* src_path, const char* dst_path, const char* err_str, const carray_str_t* files_arr);
10
+
11
+ void init_async_zip_task();
12
+
13
+ #endif
@@ -0,0 +1,96 @@
1
+ #include "writer.h"
2
+ #include "archive_data.h"
3
+ #include <memory.h>
4
+ #include <stdlib.h>
5
+ #include <pthread.h>
6
+
7
+ pthread_t az_writer_thread;
8
+ pthread_once_t qt_once = PTHREAD_ONCE_INIT;
9
+
10
+ typedef struct _az_write_task_t
11
+ {
12
+ archive_func_t func;
13
+ void* data;
14
+ struct _az_write_task_t* next;
15
+ } az_write_task_t;
16
+
17
+
18
+ /* Queue of tasks for processing. */
19
+ pthread_mutex_t az_writer_mutex = PTHREAD_MUTEX_INITIALIZER;
20
+ pthread_cond_t az_writer_cond = PTHREAD_COND_INITIALIZER;
21
+ az_write_task_t* az_writer_queue = NULL;
22
+
23
+
24
+ /* Push new task to front of the queue */
25
+ static void az_write_task_queue_push(az_write_task_t* wtask)
26
+ {
27
+ wtask->next = az_writer_queue;
28
+ az_writer_queue = wtask;
29
+ }
30
+
31
+ /* Pop next task from the queue; Returns NULL, when the queue is empty */
32
+ static az_write_task_t* az_write_task_queue_pop(void)
33
+ {
34
+ az_write_task_t* wtask = az_writer_queue;
35
+ if(wtask)
36
+ {
37
+ az_writer_queue = wtask->next;
38
+ }
39
+
40
+ return wtask;
41
+ }
42
+
43
+
44
+ /* Task processing queue */
45
+ static void* az_writer_thread_func(void* data)
46
+ {
47
+ int is_running = 1;
48
+ az_write_task_t* wtask = NULL;
49
+
50
+ while(is_running)
51
+ {
52
+ pthread_mutex_lock(&az_writer_mutex);
53
+ while (is_running && (wtask = az_write_task_queue_pop()) == NULL)
54
+ {
55
+ pthread_cond_wait(&az_writer_cond, &az_writer_mutex);
56
+ }
57
+ pthread_mutex_unlock(&az_writer_mutex);
58
+
59
+ if(wtask)
60
+ {
61
+ if(wtask->func)
62
+ {
63
+ wtask->func(wtask->data);
64
+ }
65
+
66
+ free(wtask);
67
+ }
68
+ }
69
+
70
+ return NULL;
71
+ }
72
+
73
+
74
+ /* Initialize the writer thread. The thread will wait for tasks to process */
75
+ static void az_init_writer_thread(void)
76
+ {
77
+ pthread_create(&az_writer_thread, NULL, az_writer_thread_func, NULL);
78
+ pthread_detach(az_writer_thread);
79
+ }
80
+
81
+ /* asynchronously invoke the func with the provided data */
82
+ void az_enqueue_task(archive_func_t func, void* data)
83
+ {
84
+ pthread_once(&qt_once, az_init_writer_thread);
85
+
86
+ pthread_mutex_lock(&az_writer_mutex);
87
+
88
+ az_write_task_t* wtask = (az_write_task_t*)malloc(sizeof(az_write_task_t));
89
+ memset(wtask, 0, sizeof(az_write_task_t));
90
+ wtask->func = func;
91
+ wtask->data = data;
92
+ az_write_task_queue_push(wtask);
93
+
94
+ pthread_mutex_unlock(&az_writer_mutex);
95
+ pthread_cond_signal(&az_writer_cond);
96
+ }
@@ -0,0 +1,7 @@
1
+ #ifndef ASYNC_ZIP_WRITER_H
2
+ #define ASYNC_ZIP_WRITER_H
3
+
4
+ typedef void* (*archive_func_t)(void*);
5
+ void az_enqueue_task(archive_func_t func, void* data);
6
+
7
+ #endif
@@ -0,0 +1,5 @@
1
+ # Vips will print warnings to stdout unless this is set
2
+ ENV['IM_WARNING'] = "0"
3
+
4
+ require 'async_zip_ext'
5
+ require 'async_zip/version'
@@ -0,0 +1,3 @@
1
+ module AsyncZip
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: async-ruby-zip
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Grigoriy Chudnov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.12'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.12'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: jeweler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.8.3
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.8.3
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Non-blocking zip reading and writing for Ruby.
79
+ email: g.chudnov@gmail.com
80
+ executables: []
81
+ extensions:
82
+ - ext/extconf.rb
83
+ extra_rdoc_files:
84
+ - README.md
85
+ files:
86
+ - Gemfile.lock
87
+ - README.md
88
+ - async-ruby-zip-1.0.0.gem
89
+ - async-ruby-zip.gemspec
90
+ - ext/LICENSE
91
+ - ext/archive.c
92
+ - ext/archive.h
93
+ - ext/archive_data.c
94
+ - ext/archive_data.h
95
+ - ext/archive_data_fwd.h
96
+ - ext/async_zip.c
97
+ - ext/async_zip.h
98
+ - ext/callback.c
99
+ - ext/callback.h
100
+ - ext/carchive.c
101
+ - ext/carchive.h
102
+ - ext/carray.c
103
+ - ext/carray.h
104
+ - ext/cerror.c
105
+ - ext/cerror.h
106
+ - ext/cfilesystem.c
107
+ - ext/cfilesystem.h
108
+ - ext/extconf.rb
109
+ - ext/task.c
110
+ - ext/task.h
111
+ - ext/writer.c
112
+ - ext/writer.h
113
+ - lib/async_zip.rb
114
+ - lib/async_zip/version.rb
115
+ homepage: https://github.com/gchudnov/async-ruby-zip
116
+ licenses:
117
+ - MIT
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 1.8.24
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: async-ruby-zip is a ruby extension that zip files asynchronously.
140
+ test_files: []