The union of the color and the node_number in the struct screen_char.
[elinks.git] / src / encoding / lzma.c
blob9b656920b394defdbf93751d929459d885a99b12
1 /* lzma encoding (ENCODING_LZMA) backend */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdio.h>
8 #include <string.h>
9 #include <sys/stat.h>
10 #ifdef HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
14 #include <lzma.h>
15 #include <errno.h>
17 #include "elinks.h"
19 #include "encoding/encoding.h"
20 #include "encoding/lzma.h"
21 #include "util/memory.h"
23 #define ELINKS_BZ_BUFFER_LENGTH 5000
25 #define ELINKS_LZMA_MEMORY_LIMIT (1024 * 1024 * 128)
27 struct lzma_enc_data {
28 lzma_stream flzma_stream;
29 int fdread;
30 int last_read:1;
31 int after_end:1;
32 unsigned char buf[ELINKS_BZ_BUFFER_LENGTH];
35 static int
36 lzma_open(struct stream_encoded *stream, int fd)
38 struct lzma_enc_data *data = mem_alloc(sizeof(*data));
39 int err;
41 stream->data = NULL;
42 if (!data) {
43 return -1;
46 memset(&data->flzma_stream, 0, sizeof(data->flzma_stream));
47 data->fdread = fd;
48 data->last_read = 0;
50 err = lzma_auto_decoder(&data->flzma_stream, ELINKS_LZMA_MEMORY_LIMIT, 0);
51 if (err != LZMA_OK) {
52 mem_free(data);
53 return -1;
56 stream->data = data;
58 return 0;
61 static int
62 lzma_read(struct stream_encoded *stream, unsigned char *buf, int len)
64 struct lzma_enc_data *data = (struct lzma_enc_data *) stream->data;
65 int err = 0;
67 if (!data) return -1;
69 assert(len > 0);
71 if (data->last_read) return 0;
73 data->flzma_stream.avail_out = len;
74 data->flzma_stream.next_out = buf;
76 do {
77 if (data->flzma_stream.avail_in == 0) {
78 int l = safe_read(data->fdread, data->buf,
79 ELINKS_BZ_BUFFER_LENGTH);
81 if (l == -1) {
82 if (errno == EAGAIN)
83 break;
84 else
85 return -1; /* I/O error */
86 } else if (l == 0) {
87 /* EOF. It is error: we wait for more bytes */
88 return -1;
91 data->flzma_stream.next_in = data->buf;
92 data->flzma_stream.avail_in = l;
95 err = lzma_code(&data->flzma_stream, LZMA_RUN);
96 if (err == LZMA_STREAM_END) {
97 data->last_read = 1;
98 break;
99 } else if (err != LZMA_OK) {
100 return -1;
102 } while (data->flzma_stream.avail_out > 0);
104 assert(len - data->flzma_stream.avail_out == data->flzma_stream.next_out - buf);
105 return len - data->flzma_stream.avail_out;
108 static unsigned char *
109 lzma_decode_buffer(struct stream_encoded *st, unsigned char *data, int len, int *new_len)
111 struct lzma_enc_data *enc_data = (struct lzma_enc_data *) st->data;
112 lzma_stream *stream = &enc_data->flzma_stream;
113 unsigned char *buffer = NULL;
114 int error;
116 *new_len = 0; /* default, left there if an error occurs */
118 stream->next_in = data;
119 stream->avail_in = len;
120 stream->total_out = 0;
122 if (lzma_auto_decoder(stream, ELINKS_LZMA_MEMORY_LIMIT, 0) != LZMA_OK)
123 return NULL;
125 do {
126 unsigned char *new_buffer;
127 size_t size = stream->total_out + MAX_STR_LEN;
129 new_buffer = mem_realloc(buffer, size);
130 if (!new_buffer) {
131 error = LZMA_MEM_ERROR;
132 break;
135 buffer = new_buffer;
136 stream->next_out = buffer + stream->total_out;
137 stream->avail_out = MAX_STR_LEN;
139 error = lzma_code(stream, LZMA_RUN);
140 if (error == LZMA_STREAM_END) {
141 error = LZMA_OK;
142 break;
144 } while (error == LZMA_OK && stream->avail_in > 0);
146 if (error == LZMA_STREAM_END) {
147 lzma_end(stream);
148 enc_data->after_end = 1;
149 error = LZMA_OK;
152 if (error == LZMA_OK) {
153 *new_len = stream->total_out;
154 return buffer;
155 } else {
156 if (buffer) mem_free(buffer);
157 return NULL;
161 static void
162 lzma_close(struct stream_encoded *stream)
164 struct lzma_enc_data *data = (struct lzma_enc_data *) stream->data;
166 if (data) {
167 if (!data->after_end) {
168 lzma_end(&data->flzma_stream);
170 if (data->fdread != -1) {
171 close(data->fdread);
173 mem_free(data);
174 stream->data = 0;
178 static const unsigned char *const lzma_extensions[] = { ".lzma", ".xz", NULL };
180 const struct decoding_backend lzma_decoding_backend = {
181 "lzma",
182 lzma_extensions,
183 lzma_open,
184 lzma_read,
185 lzma_decode_buffer,
186 lzma_close,