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 }