2 * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
3 * Copyright (C) 2003 Sun Microsystems, Inc.
5 * This is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 #include "zrleoutstream.h"
24 #define ZRLE_IN_BUFFER_SIZE 16384
25 #define ZRLE_OUT_BUFFER_SIZE 1024
28 static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size)
30 buffer->ptr = buffer->start = malloc(size);
31 if (buffer->start == NULL) {
36 buffer->end = buffer->start + size;
41 static void zrleBufferFree(zrleBuffer *buffer)
45 buffer->start = buffer->ptr = buffer->end = NULL;
48 static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size)
52 size += buffer->end - buffer->start;
53 offset = ZRLE_BUFFER_LENGTH (buffer);
55 buffer->start = realloc(buffer->start, size);
60 buffer->end = buffer->start + size;
61 buffer->ptr = buffer->start + offset;
66 zrleOutStream *zrleOutStreamNew(void)
70 os = malloc(sizeof(zrleOutStream));
74 if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) {
79 if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) {
80 zrleBufferFree(&os->in);
85 os->zs.zalloc = Z_NULL;
86 os->zs.zfree = Z_NULL;
87 os->zs.opaque = Z_NULL;
88 if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
89 zrleBufferFree(&os->in);
97 void zrleOutStreamFree (zrleOutStream *os)
100 zrleBufferFree(&os->in);
101 zrleBufferFree(&os->out);
105 rfbBool zrleOutStreamFlush(zrleOutStream *os)
107 os->zs.next_in = os->in.start;
108 os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
111 rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in);
114 while (os->zs.avail_in != 0) {
118 if (os->out.ptr >= os->out.end &&
119 !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
120 rfbLog("zrleOutStreamFlush: failed to grow output buffer\n");
124 os->zs.next_out = os->out.ptr;
125 os->zs.avail_out = os->out.end - os->out.ptr;
128 rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n",
129 os->zs.avail_in, os->zs.avail_out);
132 if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) {
133 rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret);
138 rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n",
139 os->zs.next_out - os->out.ptr);
142 os->out.ptr = os->zs.next_out;
143 } while (os->zs.avail_out == 0);
146 os->in.ptr = os->in.start;
151 static int zrleOutStreamOverrun(zrleOutStream *os,
155 rfbLog("zrleOutStreamOverrun\n");
158 while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) {
159 os->zs.next_in = os->in.start;
160 os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
165 if (os->out.ptr >= os->out.end &&
166 !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
167 rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n");
171 os->zs.next_out = os->out.ptr;
172 os->zs.avail_out = os->out.end - os->out.ptr;
175 rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n",
176 os->zs.avail_in, os->zs.avail_out);
179 if ((ret = deflate(&os->zs, 0)) != Z_OK) {
180 rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret);
185 rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n",
186 os->zs.next_out - os->out.ptr);
189 os->out.ptr = os->zs.next_out;
190 } while (os->zs.avail_out == 0);
192 /* output buffer not full */
194 if (os->zs.avail_in == 0) {
195 os->in.ptr = os->in.start;
197 /* but didn't consume all the data? try shifting what's left to the
198 * start of the buffer.
200 rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n");
201 memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in);
202 os->in.ptr -= os->zs.next_in - os->in.start;
206 if (size > os->in.end - os->in.ptr)
207 size = os->in.end - os->in.ptr;
212 static int zrleOutStreamCheck(zrleOutStream *os, int size)
214 if (os->in.ptr + size > os->in.end) {
215 return zrleOutStreamOverrun(os, size);
220 void zrleOutStreamWriteBytes(zrleOutStream *os,
224 const zrle_U8* dataEnd = data + length;
225 while (data < dataEnd) {
226 int n = zrleOutStreamCheck(os, dataEnd - data);
227 memcpy(os->in.ptr, data, n);
233 void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u)
235 zrleOutStreamCheck(os, 1);
239 void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u)
241 zrleOutStreamCheck(os, 1);
245 void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u)
247 zrleOutStreamCheck(os, 2);
248 *os->in.ptr++ = ((zrle_U8*)&u)[0];
249 *os->in.ptr++ = ((zrle_U8*)&u)[1];
252 void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u)
254 zrleOutStreamCheck(os, 4);
255 *os->in.ptr++ = ((zrle_U8*)&u)[0];
256 *os->in.ptr++ = ((zrle_U8*)&u)[1];
257 *os->in.ptr++ = ((zrle_U8*)&u)[2];
258 *os->in.ptr++ = ((zrle_U8*)&u)[3];
261 void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u)
263 zrleOutStreamCheck(os, 3);
264 *os->in.ptr++ = ((zrle_U8*)&u)[0];
265 *os->in.ptr++ = ((zrle_U8*)&u)[1];
266 *os->in.ptr++ = ((zrle_U8*)&u)[2];
269 void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u)
271 zrleOutStreamCheck(os, 3);
272 *os->in.ptr++ = ((zrle_U8*)&u)[1];
273 *os->in.ptr++ = ((zrle_U8*)&u)[2];
274 *os->in.ptr++ = ((zrle_U8*)&u)[3];