diff options
Diffstat (limited to 'linden/indra/llmessage/llbufferstream.cpp')
-rw-r--r-- | linden/indra/llmessage/llbufferstream.cpp | 96 |
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 | { |