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
151
152
153
154
155
156
157
158
|
/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data
// Representation).
//
#ifndef __RDR_OUTSTREAM_H__
#define __RDR_OUTSTREAM_H__
#include <stdint.h>
#include <string.h> // for memcpy
#include <rdr/Exception.h>
#include <rdr/InStream.h>
namespace rdr {
class OutStream {
protected:
OutStream() : ptr(nullptr), end(nullptr), corked(false) {}
public:
virtual ~OutStream() {}
// avail() returns the number of bytes that currently be written to the
// stream without any risk of blocking.
inline size_t avail()
{
return end - ptr;
}
// writeU/SN() methods write unsigned and signed N-bit integers.
inline void writeU8( uint8_t u) { check(1); *ptr++ = u; }
inline void writeU16(uint16_t u) { check(2); *ptr++ = u >> 8;
*ptr++ = (uint8_t)u; }
inline void writeU32(uint32_t u) { check(4); *ptr++ = u >> 24;
*ptr++ = u >> 16;
*ptr++ = u >> 8;
*ptr++ = u; }
inline void writeS8( int8_t s) { writeU8((uint8_t)s); }
inline void writeS16(int16_t s) { writeU16((uint16_t)s); }
inline void writeS32(int32_t s) { writeU32((uint32_t)s); }
inline void pad(size_t bytes) {
while (bytes-- > 0) writeU8(0);
}
// writeBytes() writes an exact number of bytes.
void writeBytes(const uint8_t* data, size_t length) {
while (length > 0) {
check(1);
size_t n = length;
if (length > avail())
n = avail();
memcpy(ptr, data, n);
ptr += n;
data = (uint8_t*)data + n;
length -= n;
}
}
// copyBytes() efficiently transfers data between streams
void copyBytes(InStream* is, size_t length) {
while (length > 0) {
check(1);
size_t n = length;
if (length > avail())
n = avail();
is->readBytes(ptr, n);
ptr += n;
length -= n;
}
}
// writeOpaqueN() writes a quantity without byte-swapping.
inline void writeOpaque8( uint8_t u) { writeU8(u); }
inline void writeOpaque16(uint16_t u) { check(2);
*ptr++ = ((uint8_t*)&u)[0];
*ptr++ = ((uint8_t*)&u)[1]; }
inline void writeOpaque32(uint32_t u) { check(4);
*ptr++ = ((uint8_t*)&u)[0];
*ptr++ = ((uint8_t*)&u)[1];
*ptr++ = ((uint8_t*)&u)[2];
*ptr++ = ((uint8_t*)&u)[3]; }
// length() returns the length of the stream.
virtual size_t length() = 0;
// flush() requests that the stream be flushed.
virtual void flush() {}
// cork() requests that the stream coalesces flushes in an efficient way
virtual void cork(bool enable) { corked = enable; if (!enable) flush(); }
// getptr() and setptr() are "dirty" methods which allow you direct access
// to the buffer. This is useful for a stream which is a wrapper around an
// some other stream API. Note that setptr() should not called with a value
// larger than the bytes actually written as doing so can result in
// security issues. Use pad() in such cases instead.
inline uint8_t* getptr(size_t length) { check(length); return ptr; }
inline void setptr(size_t length) { if (length > avail())
throw Exception("Output stream overflow");
ptr += length; }
private:
inline void check(size_t length)
{
if (length > avail())
overrun(length);
}
// overrun() is implemented by a derived class to cope with buffer overrun.
// It ensures there are at least needed bytes of buffer space.
virtual void overrun(size_t needed) = 0;
protected:
uint8_t* ptr;
uint8_t* end;
bool corked;
};
}
#endif
|