File: writer.rb

package info (click to toggle)
ruby-ffi-libarchive 1.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 216 kB
  • sloc: ruby: 1,336; makefile: 9
file content (135 lines) | stat: -rw-r--r-- 3,368 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
module Archive
  class Writer < BaseArchive
    private_class_method :new

    def self.open_filename(file_name, compression, format)
      if block_given?
        writer = open_filename file_name, compression, format
        begin
          yield writer
        ensure
          writer.close
        end
      else
        new file_name: file_name, compression: compression, format: format
      end
    end

    def self.open_memory(string, compression, format)
      if block_given?
        writer = open_memory string, compression, format
        begin
          yield writer
        ensure
          writer.close
        end
      else
        if compression.is_a? String
          compression = -1
        end
        new memory: string, compression: compression, format: format
      end
    end

    def initialize(params = {})
      super C.method(:archive_write_new), C.method(:archive_write_finish)

      compression = params[:compression]
      case compression
      when Symbol
        compression = Archive.const_get("COMPRESSION_#{compression.to_s.upcase}".to_sym)
      end

      format = params[:format]
      case format
      when Symbol
        format = Archive.const_get("FORMAT_#{format.to_s.upcase}".to_sym)
      end

      raise Error, @archive if C.archive_write_set_compression(archive, compression) != C::OK

      raise Error, @archive if C.archive_write_set_format(archive, format) != C::OK

      if params[:file_name]
        raise Error, @archive if C.archive_write_open_filename(archive, params[:file_name]) != C::OK
      elsif params[:memory]
        if C.archive_write_get_bytes_in_last_block(@archive) == -1
          C.archive_write_set_bytes_in_last_block(archive, 1)
        end
        @data = write_callback params[:memory]
        raise Error, @archive if C.archive_write_open(archive, nil,
          nil,
          @data,
          nil) != C::OK
      end
    rescue
      close
      raise
    end

    def write_callback(data)
      proc do |_ar, _client, buffer, length|
        data.concat buffer.get_bytes(0, length)
        length
      end
    end
    private :write_callback

    def new_entry
      entry = Entry.new
      if block_given?
        begin
          result = yield entry
        ensure
          entry.close
        end
        result
      else
        entry
      end
    end

    def add_entry
      raise ArgumentError, "No block given" unless block_given?

      entry = Entry.new
      data = yield entry
      if data
        entry.size = data.bytesize
        write_header entry
        write_data data
      else
        write_header entry
      end
      nil
    ensure
      entry.close
    end

    def write_data(*args)
      if block_given?
        raise ArgumentError, "wrong number of argument (#{args.size} for 0)" if args.size > 0

        ar = archive
        len = 0
        loop do
          str = yield
          if (n = C.archive_write_data(ar, str, str.bytesize)) < 1
            return len
          end

          len += n
        end
      else
        raise ArgumentError, "wrong number of argument (#{args.size}) for 1)" if args.size != 1

        str = args[0]
        C.archive_write_data(archive, str, str.bytesize)
      end
    end

    def write_header(entry)
      raise Error, @archive if C.archive_write_header(archive, entry.entry) != C::OK
    end
  end
end