aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llbufferstream.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/llbufferstream.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llmessage/llbufferstream.cpp')
-rw-r--r--linden/indra/llmessage/llbufferstream.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llbufferstream.cpp b/linden/indra/llmessage/llbufferstream.cpp
new file mode 100644
index 0000000..7d899d6
--- /dev/null
+++ b/linden/indra/llmessage/llbufferstream.cpp
@@ -0,0 +1,284 @@
1/**
2 * @file llbufferstream.cpp
3 * @author Phoenix
4 * @date 2005-10-10
5 * @brief Implementation of the buffer iostream classes
6 *
7 * Copyright (c) 2005-2007, Linden Research, Inc.
8 *
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception
20 *
21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above,
23 * and agree to abide by those obligations.
24 *
25 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
26 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27 * COMPLETENESS OR PERFORMANCE.
28 */
29
30#include "linden_common.h"
31#include "llbufferstream.h"
32
33#include "llbuffer.h"
34#include "llmemtype.h"
35
36static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4;
37
38/*
39 * LLBufferStreamBuf
40 */
41LLBufferStreamBuf::LLBufferStreamBuf(
42 const LLChannelDescriptors& channels,
43 LLBufferArray* buffer) :
44 mChannels(channels),
45 mBuffer(buffer)
46{
47 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
48}
49
50LLBufferStreamBuf::~LLBufferStreamBuf()
51{
52 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
53 sync();
54}
55
56// virtual
57int LLBufferStreamBuf::underflow()
58{
59 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
60 //lldebugs << "LLBufferStreamBuf::underflow()" << llendl;
61 if(!mBuffer)
62 {
63 return EOF;
64 }
65 LLSegment segment;
66 LLBufferArray::segment_iterator_t it;
67 U8* last_pos = (U8*)gptr();
68 if(last_pos) --last_pos;
69
70 LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
71
72 // Get iterator to full segment containing last_pos
73 // and construct sub-segment starting at last_pos.
74 // Note: segment may != *it at this point
75 it = mBuffer->constructSegmentAfter(last_pos, segment);
76 if(it == end)
77 {
78 return EOF;
79 }
80
81 // Iterate through segments to find a non-empty segment on input channel.
82 while((!segment.isOnChannel(mChannels.in()) || (segment.size() == 0)))
83 {
84 ++it;
85 if(it == end)
86 {
87 return EOF;
88 }
89
90 segment = *it;
91 }
92
93 char* start = (char*)segment.data();
94 setg(start, start, start + segment.size());
95 return *gptr();
96}
97
98// virtual
99int LLBufferStreamBuf::overflow(int c)
100{
101 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
102 if(!mBuffer)
103 {
104 return EOF;
105 }
106 if(EOF == c)
107 {
108 // if someone puts an EOF, I suppose we should sync and return
109 // success.
110 if(0 == sync())
111 {
112 return 1;
113 }
114 else
115 {
116 return EOF;
117 }
118 }
119
120 // since we got here, we have a buffer, and we have a character to
121 // put on it.
122 LLBufferArray::segment_iterator_t it;
123 it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);
124 if(it != mBuffer->endSegment())
125 {
126 char* start = (char*)(*it).data();
127 (*start) = (char)(c);
128 setp(start + 1, start + (*it).size());
129 return c;
130 }
131 else
132 {
133 return EOF;
134 }
135}
136
137// virtual
138int LLBufferStreamBuf::sync()
139{
140 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
141 int return_value = -1;
142 if(!mBuffer)
143 {
144 return return_value;
145 }
146
147 // set the put pointer so that we force an overflow on the next
148 // write.
149 U8* address = (U8*)pptr();
150 setp(NULL, NULL);
151
152 // *NOTE: I bet we could just --address. Need to think about that.
153 address = mBuffer->seek(mChannels.out(), address, -1);
154 if(address)
155 {
156 LLBufferArray::segment_iterator_t it;
157 it = mBuffer->splitAfter(address);
158 LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
159 if(it != end)
160 {
161 ++it;
162 if(it != end)
163 {
164 mBuffer->eraseSegment(it);
165 }
166 return_value = 0;
167 }
168 }
169 else
170 {
171 // nothing was put on the buffer, so the sync() is a no-op.
172 return_value = 0;
173 }
174 return return_value;
175}
176
177// virtual
178#if( LL_WINDOWS || __GNUC__ > 2)
179LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff(
180 LLBufferStreamBuf::off_type off,
181 std::ios::seekdir way,
182 std::ios::openmode which)
183#else
184streampos LLBufferStreamBuf::seekoff(
185 streamoff off,
186 std::ios::seekdir way,
187 std::ios::openmode which)
188#endif
189{
190 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
191 if(!mBuffer
192 || ((way == std::ios::beg) && (off < 0))
193 || ((way == std::ios::end) && (off > 0)))
194 {
195 return -1;
196 }
197 U8* address = NULL;
198 if(which & std::ios::in)
199 {
200 U8* base_addr = NULL;
201 switch(way)
202 {
203 case std::ios::end:
204 base_addr = (U8*)LLBufferArray::npos;
205 break;
206 case std::ios::cur:
207 // get the current get pointer and adjust it for buffer
208 // array semantics.
209 base_addr = (U8*)gptr();
210 break;
211 case std::ios::beg:
212 default:
213 // NULL is fine
214 break;
215 }
216 address = mBuffer->seek(mChannels.in(), base_addr, off);
217 if(address)
218 {
219 LLBufferArray::segment_iterator_t iter;
220 iter = mBuffer->getSegment(address);
221 char* start = (char*)(*iter).data();
222 setg(start, (char*)address, start + (*iter).size());
223 }
224 else
225 {
226 address = (U8*)(-1);
227 }
228 }
229 if(which & std::ios::out)
230 {
231 U8* base_addr = NULL;
232 switch(way)
233 {
234 case std::ios::end:
235 base_addr = (U8*)LLBufferArray::npos;
236 break;
237 case std::ios::cur:
238 // get the current put pointer and adjust it for buffer
239 // array semantics.
240 base_addr = (U8*)pptr();
241 break;
242 case std::ios::beg:
243 default:
244 // NULL is fine
245 break;
246 }
247 address = mBuffer->seek(mChannels.out(), base_addr, off);
248 if(address)
249 {
250 LLBufferArray::segment_iterator_t iter;
251 iter = mBuffer->getSegment(address);
252 setp((char*)address, (char*)(*iter).data() + (*iter).size());
253 }
254 else
255 {
256 address = (U8*)(-1);
257 }
258 }
259
260#if( LL_WINDOWS || __GNUC__ > 2 )
261 S32 rv = (S32)(intptr_t)address;
262 return (pos_type)rv;
263#else
264 return (streampos)address;
265#endif
266}
267
268
269/*
270 * LLBufferStream
271 */
272LLBufferStream::LLBufferStream(
273 const LLChannelDescriptors& channels,
274 LLBufferArray* buffer) :
275 std::iostream(&mStreamBuf),
276 mStreamBuf(channels, buffer)
277{
278 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
279}
280
281LLBufferStream::~LLBufferStream()
282{
283 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
284}