LCOV - code coverage report
Current view: directory - xpcom/io - nsStorageStream.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 243 186 76.5 %
Date: 2012-06-02 Functions: 38 29 76.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* vim:set ts=4 sts=4 sw=4 cin et: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1998-1999
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : /*
      42                 :  * The storage stream provides an internal buffer that can be filled by a
      43                 :  * client using a single output stream.  One or more independent input streams
      44                 :  * can be created to read the data out non-destructively.  The implementation
      45                 :  * uses a segmented buffer internally to avoid realloc'ing of large buffers,
      46                 :  * with the attendant performance loss and heap fragmentation.
      47                 :  */
      48                 : 
      49                 : #include "nsAlgorithm.h"
      50                 : #include "nsStorageStream.h"
      51                 : #include "nsSegmentedBuffer.h"
      52                 : #include "nsStreamUtils.h"
      53                 : #include "nsCOMPtr.h"
      54                 : #include "prbit.h"
      55                 : #include "nsIInputStream.h"
      56                 : #include "nsISeekableStream.h"
      57                 : #include "prlog.h"
      58                 : 
      59                 : #if defined(PR_LOGGING)
      60                 : //
      61                 : // Log module for StorageStream logging...
      62                 : //
      63                 : // To enable logging (see prlog.h for full details):
      64                 : //
      65                 : //    set NSPR_LOG_MODULES=StorageStreamLog:5
      66                 : //    set NSPR_LOG_FILE=nspr.log
      67                 : //
      68                 : // this enables PR_LOG_DEBUG level information and places all output in
      69                 : // the file nspr.log
      70                 : //
      71            1464 : static PRLogModuleInfo* sLog = PR_NewLogModule("nsStorageStream");
      72                 : #endif
      73                 : #define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
      74                 : 
      75            7820 : nsStorageStream::nsStorageStream()
      76                 :     : mSegmentedBuffer(0), mSegmentSize(0), mWriteInProgress(false),
      77            7820 :       mLastSegmentNum(-1), mWriteCursor(0), mSegmentEnd(0), mLogicalLength(0)
      78                 : {
      79            7820 :     LOG(("Creating nsStorageStream [%p].\n", this));
      80            7820 : }
      81                 : 
      82            7820 : nsStorageStream::~nsStorageStream()
      83                 : {
      84            7820 :     delete mSegmentedBuffer;
      85            7820 : }
      86                 : 
      87          163755 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageStream,
      88                 :                               nsIStorageStream,
      89                 :                               nsIOutputStream)
      90                 : 
      91                 : NS_IMETHODIMP
      92            7820 : nsStorageStream::Init(PRUint32 segmentSize, PRUint32 maxSize,
      93                 :                       nsIMemory *segmentAllocator)
      94                 : {
      95            7820 :     mSegmentedBuffer = new nsSegmentedBuffer();
      96            7820 :     if (!mSegmentedBuffer)
      97               0 :         return NS_ERROR_OUT_OF_MEMORY;
      98                 :     
      99            7820 :     mSegmentSize = segmentSize;
     100            7820 :     mSegmentSizeLog2 = PR_FloorLog2(segmentSize);
     101                 : 
     102                 :     // Segment size must be a power of two
     103            7820 :     if (mSegmentSize != ((PRUint32)1 << mSegmentSizeLog2))
     104               0 :         return NS_ERROR_INVALID_ARG;
     105                 : 
     106            7820 :     return mSegmentedBuffer->Init(segmentSize, maxSize, segmentAllocator);
     107                 : }
     108                 : 
     109                 : NS_IMETHODIMP
     110             781 : nsStorageStream::GetOutputStream(PRInt32 aStartingOffset, 
     111                 :                                  nsIOutputStream * *aOutputStream)
     112                 : {
     113             781 :     NS_ENSURE_ARG(aOutputStream);
     114             781 :     NS_ENSURE_TRUE(mSegmentedBuffer, NS_ERROR_NOT_INITIALIZED);
     115                 :     
     116             781 :     if (mWriteInProgress)
     117               0 :         return NS_ERROR_NOT_AVAILABLE;
     118                 : 
     119             781 :     nsresult rv = Seek(aStartingOffset);
     120             781 :     if (NS_FAILED(rv)) return rv;
     121                 : 
     122                 :     // Enlarge the last segment in the buffer so that it is the same size as
     123                 :     // all the other segments in the buffer.  (It may have been realloc'ed
     124                 :     // smaller in the Close() method.)
     125             781 :     if (mLastSegmentNum >= 0)
     126               2 :         if (mSegmentedBuffer->ReallocLastSegment(mSegmentSize)) {
     127                 :             // Need to re-Seek, since realloc changed segment base pointer
     128               2 :             rv = Seek(aStartingOffset);
     129               2 :             if (NS_FAILED(rv)) return rv;
     130                 :         }
     131                 : 
     132             781 :     NS_ADDREF(this);
     133             781 :     *aOutputStream = static_cast<nsIOutputStream*>(this);
     134             781 :     mWriteInProgress = true;
     135             781 :     return NS_OK;
     136                 : }
     137                 : 
     138                 : NS_IMETHODIMP
     139            8197 : nsStorageStream::Close()
     140                 : {
     141            8197 :     NS_ENSURE_TRUE(mSegmentedBuffer, NS_ERROR_NOT_INITIALIZED);
     142                 :     
     143            8197 :     mWriteInProgress = false;
     144                 :     
     145            8197 :     PRInt32 segmentOffset = SegOffset(mLogicalLength);
     146                 : 
     147                 :     // Shrink the final segment in the segmented buffer to the minimum size
     148                 :     // needed to contain the data, so as to conserve memory.
     149            8197 :     if (segmentOffset)
     150            8119 :         mSegmentedBuffer->ReallocLastSegment(segmentOffset);
     151                 :     
     152            8197 :     mWriteCursor = 0;
     153            8197 :     mSegmentEnd = 0;
     154                 : 
     155            8197 :     LOG(("nsStorageStream [%p] Close mWriteCursor=%x mSegmentEnd=%x\n",
     156                 :         this, mWriteCursor, mSegmentEnd));
     157                 : 
     158            8197 :     return NS_OK;
     159                 : }
     160                 : 
     161                 : NS_IMETHODIMP
     162               0 : nsStorageStream::Flush()
     163                 : {
     164               0 :     return NS_OK;
     165                 : }
     166                 : 
     167                 : NS_IMETHODIMP
     168          212886 : nsStorageStream::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
     169                 : {
     170          212886 :     NS_ENSURE_TRUE(mSegmentedBuffer, NS_ERROR_NOT_INITIALIZED);
     171                 :     
     172                 :     const char* readCursor;
     173                 :     PRUint32 count, availableInSegment, remaining;
     174          212886 :     nsresult rv = NS_OK;
     175                 : 
     176          212886 :     NS_ENSURE_ARG_POINTER(aNumWritten);
     177          212886 :     NS_ENSURE_ARG(aBuffer);
     178                 : 
     179          212886 :     LOG(("nsStorageStream [%p] Write mWriteCursor=%x mSegmentEnd=%x aCount=%d\n",
     180                 :         this, mWriteCursor, mSegmentEnd, aCount));
     181                 : 
     182          212886 :     remaining = aCount;
     183          212886 :     readCursor = aBuffer;
     184                 :     // If no segments have been created yet, create one even if we don't have
     185                 :     // to write any data; this enables creating an input stream which reads from
     186                 :     // the very end of the data for any amount of data in the stream (i.e.
     187                 :     // this stream contains N bytes of data and newInputStream(N) is called),
     188                 :     // even for N=0 (with the caveat that we require .write("", 0) be called to
     189                 :     // initialize internal buffers).
     190          212886 :     bool firstTime = mSegmentedBuffer->GetSegmentCount() == 0;
     191         4296130 :     while (remaining || NS_UNLIKELY(firstTime)) {
     192         3870358 :         firstTime = false;
     193         3870358 :         availableInSegment = mSegmentEnd - mWriteCursor;
     194         3870358 :         if (!availableInSegment) {
     195         3665984 :             mWriteCursor = mSegmentedBuffer->AppendNewSegment();
     196         3665984 :             if (!mWriteCursor) {
     197               0 :                 mSegmentEnd = 0;
     198               0 :                 rv = NS_ERROR_OUT_OF_MEMORY;
     199               0 :                 goto out;
     200                 :             }
     201         3665984 :             mLastSegmentNum++;
     202         3665984 :             mSegmentEnd = mWriteCursor + mSegmentSize;
     203         3665984 :             availableInSegment = mSegmentEnd - mWriteCursor;
     204         3665984 :             LOG(("nsStorageStream [%p] Write (new seg) mWriteCursor=%x mSegmentEnd=%x\n",
     205                 :                 this, mWriteCursor, mSegmentEnd));
     206                 :         }
     207                 :         
     208         3870358 :         count = NS_MIN(availableInSegment, remaining);
     209         3870358 :         memcpy(mWriteCursor, readCursor, count);
     210         3870358 :         remaining -= count;
     211         3870358 :         readCursor += count;
     212         3870358 :         mWriteCursor += count;
     213         3870358 :         LOG(("nsStorageStream [%p] Writing mWriteCursor=%x mSegmentEnd=%x count=%d\n",
     214                 :             this, mWriteCursor, mSegmentEnd, count));
     215                 :     };
     216                 : 
     217                 :  out:
     218          212886 :     *aNumWritten = aCount - remaining;
     219          212886 :     mLogicalLength += *aNumWritten;
     220                 : 
     221          212886 :     LOG(("nsStorageStream [%p] Wrote mWriteCursor=%x mSegmentEnd=%x numWritten=%d\n",
     222                 :         this, mWriteCursor, mSegmentEnd, *aNumWritten));
     223          212886 :     return rv;
     224                 : }
     225                 : 
     226                 : NS_IMETHODIMP 
     227               0 : nsStorageStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
     228                 : {
     229               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     230                 : }
     231                 : 
     232                 : NS_IMETHODIMP 
     233               0 : nsStorageStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
     234                 : {
     235               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     236                 : }
     237                 : 
     238                 : NS_IMETHODIMP 
     239               0 : nsStorageStream::IsNonBlocking(bool *aNonBlocking)
     240                 : {
     241               0 :     *aNonBlocking = false;
     242               0 :     return NS_OK;
     243                 : }
     244                 : 
     245                 : NS_IMETHODIMP
     246               0 : nsStorageStream::GetLength(PRUint32 *aLength)
     247                 : {
     248               0 :     NS_ENSURE_ARG(aLength);
     249               0 :     *aLength = mLogicalLength;
     250               0 :     return NS_OK;
     251                 : }
     252                 : 
     253                 : // Truncate the buffer by deleting the end segments
     254                 : NS_IMETHODIMP
     255             783 : nsStorageStream::SetLength(PRUint32 aLength)
     256                 : {
     257             783 :     NS_ENSURE_TRUE(mSegmentedBuffer, NS_ERROR_NOT_INITIALIZED);
     258                 :     
     259             783 :     if (mWriteInProgress)
     260               0 :         return NS_ERROR_NOT_AVAILABLE;
     261                 : 
     262             783 :     if (aLength > mLogicalLength)
     263               0 :         return NS_ERROR_INVALID_ARG;
     264                 : 
     265             783 :     PRInt32 newLastSegmentNum = SegNum(aLength);
     266             783 :     PRInt32 segmentOffset = SegOffset(aLength);
     267             783 :     if (segmentOffset == 0)
     268             779 :         newLastSegmentNum--;
     269                 : 
     270            1876 :     while (newLastSegmentNum < mLastSegmentNum) {
     271             310 :         mSegmentedBuffer->DeleteLastSegment();
     272             310 :         mLastSegmentNum--;
     273                 :     }
     274                 : 
     275             783 :     mLogicalLength = aLength;
     276             783 :     return NS_OK;
     277                 : }
     278                 : 
     279                 : NS_IMETHODIMP
     280            7890 : nsStorageStream::GetWriteInProgress(bool *aWriteInProgress)
     281                 : {
     282            7890 :     NS_ENSURE_ARG(aWriteInProgress);
     283                 : 
     284            7890 :     *aWriteInProgress = mWriteInProgress;
     285            7890 :     return NS_OK;
     286                 : }
     287                 : 
     288                 : NS_METHOD
     289             783 : nsStorageStream::Seek(PRInt32 aPosition)
     290                 : {
     291             783 :     NS_ENSURE_TRUE(mSegmentedBuffer, NS_ERROR_NOT_INITIALIZED);
     292                 :     
     293                 :     // An argument of -1 means "seek to end of stream"
     294             783 :     if (aPosition == -1)
     295               0 :         aPosition = mLogicalLength;
     296                 : 
     297                 :     // Seeking beyond the buffer end is illegal
     298             783 :     if ((PRUint32)aPosition > mLogicalLength)
     299               0 :         return NS_ERROR_INVALID_ARG;
     300                 : 
     301                 :     // Seeking backwards in the write stream results in truncation
     302             783 :     SetLength(aPosition);
     303                 : 
     304                 :     // Special handling for seek to start-of-buffer
     305             783 :     if (aPosition == 0) {
     306             779 :         mWriteCursor = 0;
     307             779 :         mSegmentEnd = 0;
     308             779 :         LOG(("nsStorageStream [%p] Seek mWriteCursor=%x mSegmentEnd=%x\n",
     309                 :             this, mWriteCursor, mSegmentEnd));
     310             779 :         return NS_OK;
     311                 :     }
     312                 : 
     313                 :     // Segment may have changed, so reset pointers
     314               4 :     mWriteCursor = mSegmentedBuffer->GetSegment(mLastSegmentNum);
     315               4 :     NS_ASSERTION(mWriteCursor, "null mWriteCursor");
     316               4 :     mSegmentEnd = mWriteCursor + mSegmentSize;
     317                 : 
     318                 :     // Adjust write cursor for current segment offset.  This test is necessary
     319                 :     // because SegNum may reference the next-to-be-allocated segment, in which
     320                 :     // case we need to be pointing at the end of the last segment.
     321               4 :     PRInt32 segmentOffset = SegOffset(aPosition);
     322               4 :     if (segmentOffset == 0 && (SegNum(aPosition) > (PRUint32) mLastSegmentNum))
     323               0 :         mWriteCursor = mSegmentEnd;
     324                 :     else
     325               4 :         mWriteCursor += segmentOffset;
     326                 :     
     327               4 :     LOG(("nsStorageStream [%p] Seek mWriteCursor=%x mSegmentEnd=%x\n",
     328                 :         this, mWriteCursor, mSegmentEnd));
     329               4 :     return NS_OK;
     330                 : }
     331                 : 
     332                 : ////////////////////////////////////////////////////////////////////////////////
     333                 : 
     334                 : // There can be many nsStorageInputStreams for a single nsStorageStream
     335                 : class nsStorageInputStream : public nsIInputStream
     336                 :                            , public nsISeekableStream
     337                 : {
     338                 : public:
     339            7641 :     nsStorageInputStream(nsStorageStream *aStorageStream, PRUint32 aSegmentSize)
     340                 :         : mStorageStream(aStorageStream), mReadCursor(0),
     341                 :           mSegmentEnd(0), mSegmentNum(0),
     342                 :           mSegmentSize(aSegmentSize), mLogicalCursor(0),
     343            7641 :           mStatus(NS_OK)
     344                 :         {
     345            7641 :         NS_ADDREF(mStorageStream);
     346            7641 :         }
     347                 : 
     348                 :     NS_DECL_ISUPPORTS
     349                 :     NS_DECL_NSIINPUTSTREAM
     350                 :     NS_DECL_NSISEEKABLESTREAM
     351                 : 
     352                 : private:
     353            7641 :     ~nsStorageInputStream()
     354            7641 :     {
     355            7641 :         NS_IF_RELEASE(mStorageStream);
     356            7641 :     }
     357                 : 
     358                 : protected:
     359                 :     NS_METHOD Seek(PRUint32 aPosition);
     360                 : 
     361                 :     friend class nsStorageStream;
     362                 : 
     363                 : private:
     364                 :     nsStorageStream* mStorageStream;
     365                 :     PRUint32         mReadCursor;    // Next memory location to read byte, or NULL
     366                 :     PRUint32         mSegmentEnd;    // One byte past end of current buffer segment
     367                 :     PRUint32         mSegmentNum;    // Segment number containing read cursor
     368                 :     PRUint32         mSegmentSize;   // All segments, except the last, are of this size
     369                 :     PRUint32         mLogicalCursor; // Logical offset into stream
     370                 :     nsresult         mStatus;
     371                 : 
     372            7638 :     PRUint32 SegNum(PRUint32 aPosition)    {return aPosition >> mStorageStream->mSegmentSizeLog2;}
     373            7638 :     PRUint32 SegOffset(PRUint32 aPosition) {return aPosition & (mSegmentSize - 1);}
     374                 : };
     375                 : 
     376           49808 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageInputStream,
     377                 :                               nsIInputStream,
     378                 :                               nsISeekableStream)
     379                 : 
     380                 : NS_IMETHODIMP
     381            7641 : nsStorageStream::NewInputStream(PRInt32 aStartingOffset, nsIInputStream* *aInputStream)
     382                 : {
     383            7641 :     NS_ENSURE_TRUE(mSegmentedBuffer, NS_ERROR_NOT_INITIALIZED);
     384                 : 
     385            7641 :     nsStorageInputStream *inputStream = new nsStorageInputStream(this, mSegmentSize);
     386            7641 :     if (!inputStream)
     387               0 :         return NS_ERROR_OUT_OF_MEMORY;
     388                 : 
     389            7641 :     NS_ADDREF(inputStream);
     390                 : 
     391            7641 :     nsresult rv = inputStream->Seek(aStartingOffset);
     392            7641 :     if (NS_FAILED(rv)) {
     393               0 :         NS_RELEASE(inputStream);
     394               0 :         return rv;
     395                 :     }
     396                 : 
     397            7641 :     *aInputStream = inputStream;
     398            7641 :     return NS_OK;
     399                 : }
     400                 : 
     401                 : NS_IMETHODIMP
     402             193 : nsStorageInputStream::Close()
     403                 : {
     404             193 :     mStatus = NS_BASE_STREAM_CLOSED;
     405             193 :     return NS_OK;
     406                 : }
     407                 : 
     408                 : NS_IMETHODIMP
     409            7385 : nsStorageInputStream::Available(PRUint32 *aAvailable)
     410                 : {
     411            7385 :     if (NS_FAILED(mStatus))
     412               0 :         return mStatus;
     413                 : 
     414            7385 :     *aAvailable = mStorageStream->mLogicalLength - mLogicalCursor;
     415            7385 :     return NS_OK;
     416                 : }
     417                 : 
     418                 : NS_IMETHODIMP
     419            7553 : nsStorageInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
     420                 : {
     421            7553 :     return ReadSegments(NS_CopySegmentToBuffer, aBuffer, aCount, aNumRead);
     422                 : }
     423                 : 
     424                 : NS_IMETHODIMP 
     425            7890 : nsStorageInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 aCount, PRUint32 *aNumRead)
     426                 : {
     427            7890 :     *aNumRead = 0;
     428            7890 :     if (mStatus == NS_BASE_STREAM_CLOSED)
     429               0 :         return NS_OK;
     430            7890 :     if (NS_FAILED(mStatus))
     431               0 :         return mStatus;
     432                 : 
     433                 :     PRUint32 count, availableInSegment, remainingCapacity, bytesConsumed;
     434                 :     nsresult rv;
     435                 : 
     436            7890 :     remainingCapacity = aCount;
     437         3680543 :     while (remainingCapacity) {
     438         3665259 :         availableInSegment = mSegmentEnd - mReadCursor;
     439         3665259 :         if (!availableInSegment) {
     440         3657564 :             PRUint32 available = mStorageStream->mLogicalLength - mLogicalCursor;
     441         3657564 :             if (!available)
     442             384 :                 goto out;
     443                 : 
     444         3657180 :             mSegmentNum++;
     445         3657180 :             mReadCursor = 0;
     446         3657180 :             mSegmentEnd = NS_MIN(mSegmentSize, available);
     447         3657180 :             availableInSegment = mSegmentEnd;
     448                 :         }
     449         3664875 :         const char *cur = mStorageStream->mSegmentedBuffer->GetSegment(mSegmentNum);
     450                 :         
     451         3664875 :         count = NS_MIN(availableInSegment, remainingCapacity);
     452                 :         rv = writer(this, closure, cur + mReadCursor, aCount - remainingCapacity,
     453         3664875 :                     count, &bytesConsumed);
     454         3664875 :         if (NS_FAILED(rv) || (bytesConsumed == 0))
     455             112 :           break;
     456         3664763 :         remainingCapacity -= bytesConsumed;
     457         3664763 :         mReadCursor += bytesConsumed;
     458         3664763 :         mLogicalCursor += bytesConsumed;
     459                 :     };
     460                 : 
     461                 :  out:
     462            7890 :     *aNumRead = aCount - remainingCapacity;
     463                 : 
     464            7890 :     bool isWriteInProgress = false;
     465            7890 :     if (NS_FAILED(mStorageStream->GetWriteInProgress(&isWriteInProgress)))
     466               0 :         isWriteInProgress = false;
     467                 : 
     468            7890 :     if (*aNumRead == 0 && isWriteInProgress)
     469               2 :         return NS_BASE_STREAM_WOULD_BLOCK;
     470                 : 
     471            7888 :     return NS_OK;
     472                 : }
     473                 : 
     474                 : NS_IMETHODIMP 
     475               2 : nsStorageInputStream::IsNonBlocking(bool *aNonBlocking)
     476                 : {
     477                 :     // TODO: This class should implement nsIAsyncInputStream so that callers
     478                 :     // have some way of dealing with NS_BASE_STREAM_WOULD_BLOCK errors.
     479                 :  
     480               2 :     *aNonBlocking = true;
     481               2 :     return NS_OK;
     482                 : }
     483                 : 
     484                 : NS_IMETHODIMP
     485               0 : nsStorageInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
     486                 : {
     487               0 :     if (NS_FAILED(mStatus))
     488               0 :         return mStatus;
     489                 : 
     490               0 :     PRInt64 pos = aOffset;
     491                 : 
     492               0 :     switch (aWhence) {
     493                 :     case NS_SEEK_SET:
     494               0 :         break;
     495                 :     case NS_SEEK_CUR:
     496               0 :         pos += mLogicalCursor;
     497               0 :         break;
     498                 :     case NS_SEEK_END:
     499               0 :         pos += mStorageStream->mLogicalLength;
     500               0 :         break;
     501                 :     default:
     502               0 :         NS_NOTREACHED("unexpected whence value");
     503               0 :         return NS_ERROR_UNEXPECTED;
     504                 :     }
     505               0 :     if (pos == PRInt64(mLogicalCursor))
     506               0 :         return NS_OK;
     507                 : 
     508               0 :     return Seek(pos);
     509                 : }
     510                 : 
     511                 : NS_IMETHODIMP
     512               0 : nsStorageInputStream::Tell(PRInt64 *aResult)
     513                 : {
     514               0 :     if (NS_FAILED(mStatus))
     515               0 :         return mStatus;
     516                 : 
     517               0 :     LL_UI2L(*aResult, mLogicalCursor);
     518               0 :     return NS_OK;
     519                 : }
     520                 : 
     521                 : NS_IMETHODIMP
     522               0 : nsStorageInputStream::SetEOF()
     523                 : {
     524               0 :     NS_NOTREACHED("nsStorageInputStream::SetEOF");
     525               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     526                 : }
     527                 : 
     528                 : NS_METHOD
     529            7641 : nsStorageInputStream::Seek(PRUint32 aPosition)
     530                 : {
     531            7641 :     PRUint32 length = mStorageStream->mLogicalLength;
     532            7641 :     if (aPosition > length)
     533               0 :         return NS_ERROR_INVALID_ARG;
     534                 : 
     535            7641 :     if (length == 0)
     536               3 :         return NS_OK;
     537                 : 
     538            7638 :     mSegmentNum = SegNum(aPosition);
     539            7638 :     mReadCursor = SegOffset(aPosition);
     540            7638 :     PRUint32 available = length - aPosition;
     541            7638 :     mSegmentEnd = mReadCursor + NS_MIN(mSegmentSize - mReadCursor, available);
     542            7638 :     mLogicalCursor = aPosition;
     543            7638 :     return NS_OK;
     544                 : }
     545                 : 
     546                 : nsresult
     547            7590 : NS_NewStorageStream(PRUint32 segmentSize, PRUint32 maxSize, nsIStorageStream **result)
     548                 : {
     549            7590 :     NS_ENSURE_ARG(result);
     550                 : 
     551            7590 :     nsStorageStream* storageStream = new nsStorageStream();
     552            7590 :     if (!storageStream) return NS_ERROR_OUT_OF_MEMORY;
     553                 :     
     554            7590 :     NS_ADDREF(storageStream);
     555            7590 :     nsresult rv = storageStream->Init(segmentSize, maxSize, nsnull);
     556            7590 :     if (NS_FAILED(rv)) {
     557               0 :         NS_RELEASE(storageStream);
     558               0 :         return rv;
     559                 :     }
     560            7590 :     *result = storageStream;
     561            7590 :     return NS_OK;
     562            4392 : }

Generated by: LCOV version 1.7