00001
00034 #include "linden_common.h"
00035 #include "llbufferstream.h"
00036
00037 #include "llbuffer.h"
00038 #include "llmemtype.h"
00039
00040 static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4;
00041
00042
00043
00044
00045 LLBufferStreamBuf::LLBufferStreamBuf(
00046 const LLChannelDescriptors& channels,
00047 LLBufferArray* buffer) :
00048 mChannels(channels),
00049 mBuffer(buffer)
00050 {
00051 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00052 }
00053
00054 LLBufferStreamBuf::~LLBufferStreamBuf()
00055 {
00056 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00057 sync();
00058 }
00059
00060
00061 int LLBufferStreamBuf::underflow()
00062 {
00063 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00064
00065 if(!mBuffer)
00066 {
00067 return EOF;
00068 }
00069
00070 LLBufferArray::segment_iterator_t iter;
00071 LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
00072 U8* last_pos = (U8*)gptr();
00073 LLSegment segment;
00074 if(last_pos)
00075 {
00076
00077
00078
00079 --last_pos;
00080 iter = mBuffer->splitAfter(last_pos);
00081 if(iter != end)
00082 {
00083
00084
00085
00086
00087
00088 mBuffer->eraseSegment(iter++);
00089 if(iter != end) segment = (*iter);
00090 }
00091 else
00092 {
00093
00094
00095
00096
00097
00098
00099 return EOF;
00100 }
00101 }
00102 else
00103 {
00104
00105
00106
00107 iter = mBuffer->constructSegmentAfter(last_pos, segment);
00108 }
00109 if(iter == end)
00110 {
00111 return EOF;
00112 }
00113
00114
00115 while((!segment.isOnChannel(mChannels.in()) || (segment.size() == 0)))
00116 {
00117 ++iter;
00118 if(iter == end)
00119 {
00120 return EOF;
00121 }
00122
00123 segment = *(iter);
00124 }
00125
00126
00127 char* start = (char*)segment.data();
00128 setg(start, start, start + segment.size());
00129 return *gptr();
00130 }
00131
00132
00133 int LLBufferStreamBuf::overflow(int c)
00134 {
00135 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00136 if(!mBuffer)
00137 {
00138 return EOF;
00139 }
00140 if(EOF == c)
00141 {
00142
00143
00144 if(0 == sync())
00145 {
00146 return 1;
00147 }
00148 else
00149 {
00150 return EOF;
00151 }
00152 }
00153
00154
00155
00156 LLBufferArray::segment_iterator_t it;
00157 it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);
00158 if(it != mBuffer->endSegment())
00159 {
00160 char* start = (char*)(*it).data();
00161 (*start) = (char)(c);
00162 setp(start + 1, start + (*it).size());
00163 return c;
00164 }
00165 else
00166 {
00167 return EOF;
00168 }
00169 }
00170
00171
00172 int LLBufferStreamBuf::sync()
00173 {
00174 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00175 int return_value = -1;
00176 if(!mBuffer)
00177 {
00178 return return_value;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 U8* address = (U8*)pptr();
00214 setp(NULL, NULL);
00215
00216
00217
00218 address = mBuffer->seek(mChannels.out(), address, -1);
00219 if(address)
00220 {
00221 LLBufferArray::segment_iterator_t it;
00222 it = mBuffer->splitAfter(address);
00223 LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
00224 if(it != end)
00225 {
00226 ++it;
00227 if(it != end)
00228 {
00229 mBuffer->eraseSegment(it);
00230 }
00231 return_value = 0;
00232 }
00233 }
00234 else
00235 {
00236
00237 return_value = 0;
00238 }
00239 return return_value;
00240 }
00241
00242
00243 #if( LL_WINDOWS || __GNUC__ > 2)
00244 LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff(
00245 LLBufferStreamBuf::off_type off,
00246 std::ios::seekdir way,
00247 std::ios::openmode which)
00248 #else
00249 streampos LLBufferStreamBuf::seekoff(
00250 streamoff off,
00251 std::ios::seekdir way,
00252 std::ios::openmode which)
00253 #endif
00254 {
00255 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00256 if(!mBuffer
00257 || ((way == std::ios::beg) && (off < 0))
00258 || ((way == std::ios::end) && (off > 0)))
00259 {
00260 return -1;
00261 }
00262 U8* address = NULL;
00263 if(which & std::ios::in)
00264 {
00265 U8* base_addr = NULL;
00266 switch(way)
00267 {
00268 case std::ios::end:
00269 base_addr = (U8*)LLBufferArray::npos;
00270 break;
00271 case std::ios::cur:
00272
00273
00274 base_addr = (U8*)gptr();
00275 break;
00276 case std::ios::beg:
00277 default:
00278
00279 break;
00280 }
00281 address = mBuffer->seek(mChannels.in(), base_addr, off);
00282 if(address)
00283 {
00284 LLBufferArray::segment_iterator_t iter;
00285 iter = mBuffer->getSegment(address);
00286 char* start = (char*)(*iter).data();
00287 setg(start, (char*)address, start + (*iter).size());
00288 }
00289 else
00290 {
00291 address = (U8*)(-1);
00292 }
00293 }
00294 if(which & std::ios::out)
00295 {
00296 U8* base_addr = NULL;
00297 switch(way)
00298 {
00299 case std::ios::end:
00300 base_addr = (U8*)LLBufferArray::npos;
00301 break;
00302 case std::ios::cur:
00303
00304
00305 base_addr = (U8*)pptr();
00306 break;
00307 case std::ios::beg:
00308 default:
00309
00310 break;
00311 }
00312 address = mBuffer->seek(mChannels.out(), base_addr, off);
00313 if(address)
00314 {
00315 LLBufferArray::segment_iterator_t iter;
00316 iter = mBuffer->getSegment(address);
00317 setp((char*)address, (char*)(*iter).data() + (*iter).size());
00318 }
00319 else
00320 {
00321 address = (U8*)(-1);
00322 }
00323 }
00324
00325 #if( LL_WINDOWS || __GNUC__ > 2 )
00326 S32 rv = (S32)(intptr_t)address;
00327 return (pos_type)rv;
00328 #else
00329 return (streampos)address;
00330 #endif
00331 }
00332
00333
00334
00335
00336
00337 LLBufferStream::LLBufferStream(
00338 const LLChannelDescriptors& channels,
00339 LLBufferArray* buffer) :
00340 std::iostream(&mStreamBuf),
00341 mStreamBuf(channels, buffer)
00342 {
00343 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00344 }
00345
00346 LLBufferStream::~LLBufferStream()
00347 {
00348 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00349 }