aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llbufferstream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmessage/llbufferstream.cpp')
-rw-r--r--linden/indra/llmessage/llbufferstream.cpp96
1 files changed, 79 insertions, 17 deletions
diff --git a/linden/indra/llmessage/llbufferstream.cpp b/linden/indra/llmessage/llbufferstream.cpp
index 7d899d6..4a4d892 100644
--- a/linden/indra/llmessage/llbufferstream.cpp
+++ b/linden/indra/llmessage/llbufferstream.cpp
@@ -6,6 +6,7 @@
6 * 6 *
7 * Copyright (c) 2005-2007, Linden Research, Inc. 7 * Copyright (c) 2005-2007, Linden Research, Inc.
8 * 8 *
9 * Second Life Viewer Source Code
9 * The source code in this file ("Source Code") is provided by Linden Lab 10 * 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 * 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 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -62,34 +63,64 @@ int LLBufferStreamBuf::underflow()
62 { 63 {
63 return EOF; 64 return EOF;
64 } 65 }
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 66
72 // Get iterator to full segment containing last_pos 67 LLBufferArray::segment_iterator_t iter;
73 // and construct sub-segment starting at last_pos. 68 LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
74 // Note: segment may != *it at this point 69 U8* last_pos = (U8*)gptr();
75 it = mBuffer->constructSegmentAfter(last_pos, segment); 70 LLSegment segment;
76 if(it == end) 71 if(last_pos)
72 {
73 // Back up into a piece of memory we know that we have
74 // allocated so that calls for the next segment based on
75 // 'after' will succeed.
76 --last_pos;
77 iter = mBuffer->splitAfter(last_pos);
78 if(iter != end)
79 {
80 // We need to clear the read segment just in case we have
81 // an early exit in the function and never collect the
82 // next segment. Calling eraseSegment() with the same
83 // segment twice is just like double deleting -- nothing
84 // good comes from it.
85 mBuffer->eraseSegment(iter++);
86 if(iter != end) segment = (*iter);
87 }
88 else
89 {
90 // This should never really happen, but somehow, the
91 // istream is telling the buf that it just finished
92 // reading memory that is not in the buf. I think this
93 // would only happen if there were a bug in the c++ stream
94 // class. Just bail.
95 // *TODO: can we set the fail bit on the stream somehow?
96 return EOF;
97 }
98 }
99 else
100 {
101 // Get iterator to full segment containing last_pos
102 // and construct sub-segment starting at last_pos.
103 // Note: segment may != *it at this point
104 iter = mBuffer->constructSegmentAfter(last_pos, segment);
105 }
106 if(iter == end)
77 { 107 {
78 return EOF; 108 return EOF;
79 } 109 }
80 110
81 // Iterate through segments to find a non-empty segment on input channel. 111 // Iterate through segments to find a non-empty segment on input channel.
82 while((!segment.isOnChannel(mChannels.in()) || (segment.size() == 0))) 112 while((!segment.isOnChannel(mChannels.in()) || (segment.size() == 0)))
83 { 113 {
84 ++it; 114 ++iter;
85 if(it == end) 115 if(iter == end)
86 { 116 {
87 return EOF; 117 return EOF;
88 } 118 }
89 119
90 segment = *it; 120 segment = *(iter);
91 } 121 }
92 122
123 // set up the stream to read from the next segment.
93 char* start = (char*)segment.data(); 124 char* start = (char*)segment.data();
94 setg(start, start, start + segment.size()); 125 setg(start, start, start + segment.size());
95 return *gptr(); 126 return *gptr();
@@ -144,12 +175,43 @@ int LLBufferStreamBuf::sync()
144 return return_value; 175 return return_value;
145 } 176 }
146 177
178 // This chunk of code is not necessary because typically, users of
179 // the stream will read until EOF. Therefore, underflow was called
180 // and the segment was discarded before the sync() was called in
181 // the destructor. Theoretically, we could keep some more data
182 // around and detect the rare case where an istream was deleted
183 // before reading to the end, but that will only leave behind some
184 // unavailable but still referenced memory. Also, if another
185 // istream is constructed, it will re-read that segment, and then
186 // discard it.
187 //U8* last_pos = (U8*)gptr();
188 //if(last_pos)
189 //{
190 // // Looks like we read something. Discard what we have read.
191 // // gptr() actually returns the currrent position, but we call
192 // // it last_pos because of how it is used in the split call
193 // // below.
194 // --last_pos;
195 // LLBufferArray::segment_iterator_t iter;
196 // iter = mBuffer->splitAfter(last_pos);
197 // if(iter != mBuffer->endSegment())
198 // {
199 // // We need to clear the read segment just in case we have
200 // // an early exit in the function and never collect the
201 // // next segment. Calling eraseSegment() with the same
202 // // segment twice is just like double deleting -- nothing
203 // // good comes from it.
204 // mBuffer->eraseSegment(iter);
205 // }
206 //}
207
147 // set the put pointer so that we force an overflow on the next 208 // set the put pointer so that we force an overflow on the next
148 // write. 209 // write.
149 U8* address = (U8*)pptr(); 210 U8* address = (U8*)pptr();
150 setp(NULL, NULL); 211 setp(NULL, NULL);
151 212
152 // *NOTE: I bet we could just --address. Need to think about that. 213 // *NOTE: I bet we could just --address if address is not NULL.
214 // Need to think about that.
153 address = mBuffer->seek(mChannels.out(), address, -1); 215 address = mBuffer->seek(mChannels.out(), address, -1);
154 if(address) 216 if(address)
155 { 217 {