forked from IronLanguages/ironpython3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCompress.cs
More file actions
150 lines (123 loc) · 4.86 KB
/
Compress.cs
File metadata and controls
150 lines (123 loc) · 4.86 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
//
// Copyright 2008-2010 Jeff Hardy
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using ComponentAce.Compression.Libs.ZLib;
using IronPython.Runtime;
using IronPython.Runtime.Operations;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
namespace IronPython.Zlib
{
[PythonType]
public class Compress
{
private const int Z_OK = ZlibModule.Z_OK;
private const int Z_BUF_ERROR = ZlibModule.Z_BUF_ERROR;
private const int Z_STREAM_END = ZlibModule.Z_STREAM_END;
private const int Z_NO_FLUSH = ZlibModule.Z_NO_FLUSH;
private const int Z_FINISH = ZlibModule.Z_FINISH;
internal Compress(int level, int method, int wbits, int memlevel, int strategy)
{
zst = new ZStream();
int err = zst.DeflateInit(level, wbits);
switch(err)
{
case ZlibModule.Z_OK:
break;
case ZlibModule.Z_STREAM_ERROR:
throw PythonOps.ValueError("Invalid initialization option");
default:
throw ZlibModule.zlib_error(this.zst, err, "while creating compression object");
}
}
[Documentation(@"compress(data) -- Return a string containing data compressed.
After calling this function, some of the input data may still
be stored in internal buffers for later processing.
Call the flush() method to clear these buffers.")]
public Bytes compress([BytesConversion]IList<byte> data)
{
byte[] input = data.ToArray();
byte[] output = new byte[ZlibModule.DEFAULTALLOC];
long start_total_out = zst.total_out;
zst.next_in = input;
zst.next_in_index = 0;
zst.avail_in = input.Length;
zst.next_out = output;
zst.next_out_index = 0;
zst.avail_out = output.Length;
int err = zst.deflate(Z_NO_FLUSH);
while(err == Z_OK && zst.avail_out == 0)
{
int length = output.Length;
Array.Resize(ref output, output.Length * 2);
zst.next_out = output;
zst.avail_out = length;
err = zst.deflate(Z_NO_FLUSH);
}
if(err != Z_OK && err != Z_BUF_ERROR)
{
throw ZlibModule.zlib_error(this.zst, err, "while compressing");
}
return GetBytes(output, 0, (int)(zst.total_out - start_total_out));
}
[Documentation(@"flush( [mode] ) -- Return a string containing any remaining compressed data.
mode can be one of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH; the
default value used when mode is not specified is Z_FINISH.
If mode == Z_FINISH, the compressor object can no longer be used after
calling the flush() method. Otherwise, more data can still be compressed.")]
public Bytes flush(int mode=Z_FINISH)
{
byte[] output = new byte[ZlibModule.DEFAULTALLOC];
if(mode == Z_NO_FLUSH)
{
return Bytes.Empty;
}
long start_total_out = zst.total_out;
zst.avail_in = 0;
zst.next_out = output;
zst.next_out_index = 0;
zst.avail_out = output.Length;
int err = zst.deflate((FlushStrategy)mode);
while(err == Z_OK && zst.avail_out == 0)
{
int old_length = output.Length;
Array.Resize(ref output, output.Length * 2);
zst.next_out = output;
zst.avail_out = old_length;
err = zst.deflate((FlushStrategy)mode);
}
if(err == Z_STREAM_END && mode == Z_FINISH)
{
err = zst.deflateEnd();
if(err != Z_OK)
{
throw ZlibModule.zlib_error(this.zst, err, "from deflateEnd()");
}
}
else if(err != Z_OK && err != Z_BUF_ERROR)
{
throw ZlibModule.zlib_error(this.zst, err, "while flushing");
}
return GetBytes(output, 0, (int)(zst.total_out - start_total_out));
}
//[Documentation("copy() -- Return a copy of the compression object.")]
//public Compress copy()
//{
// throw new NotImplementedException();
//}
private ZStream zst;
private static Bytes GetBytes(byte[] bytes, int index, int count)
{
var res = new byte[count];
Array.Copy(bytes, index, res, 0, count);
return Bytes.Make(res);
}
}
}