LCOV - code coverage report
Current view: top level - xpcom/io - SnappyCompressOutputStream.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 112 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/SnappyCompressOutputStream.h"
       8             : 
       9             : #include <algorithm>
      10             : #include "nsStreamUtils.h"
      11             : #include "snappy/snappy.h"
      12             : 
      13             : namespace mozilla {
      14             : 
      15           0 : NS_IMPL_ISUPPORTS(SnappyCompressOutputStream, nsIOutputStream);
      16             : 
      17             : // static
      18             : const size_t
      19             : SnappyCompressOutputStream::kMaxBlockSize = snappy::kBlockSize;
      20             : 
      21           0 : SnappyCompressOutputStream::SnappyCompressOutputStream(nsIOutputStream* aBaseStream,
      22           0 :                                                        size_t aBlockSize)
      23             :  : mBaseStream(aBaseStream)
      24           0 :  , mBlockSize(std::min(aBlockSize, kMaxBlockSize))
      25             :  , mNextByte(0)
      26             :  , mCompressedBufferLength(0)
      27           0 :  , mStreamIdentifierWritten(false)
      28             : {
      29           0 :   MOZ_ASSERT(mBlockSize > 0);
      30             : 
      31             :   // This implementation only supports sync base streams.  Verify this in debug
      32             :   // builds.  Note, this can be simpler than the check in
      33             :   // SnappyUncompressInputStream because we don't have to deal with the
      34             :   // nsStringInputStream oddness of being non-blocking and sync.
      35             : #ifdef DEBUG
      36             :   bool baseNonBlocking;
      37           0 :   nsresult rv = mBaseStream->IsNonBlocking(&baseNonBlocking);
      38           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
      39           0 :   MOZ_ASSERT(!baseNonBlocking);
      40             : #endif
      41           0 : }
      42             : 
      43             : size_t
      44           0 : SnappyCompressOutputStream::BlockSize() const
      45             : {
      46           0 :   return mBlockSize;
      47             : }
      48             : 
      49             : NS_IMETHODIMP
      50           0 : SnappyCompressOutputStream::Close()
      51             : {
      52           0 :   if (!mBaseStream) {
      53           0 :     return NS_OK;
      54             :   }
      55             : 
      56           0 :   nsresult rv = Flush();
      57           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
      58             : 
      59           0 :   mBaseStream->Close();
      60           0 :   mBaseStream = nullptr;
      61             : 
      62           0 :   mBuffer = nullptr;
      63           0 :   mCompressedBuffer = nullptr;
      64             : 
      65           0 :   return NS_OK;
      66             : }
      67             : 
      68             : NS_IMETHODIMP
      69           0 : SnappyCompressOutputStream::Flush()
      70             : {
      71           0 :   if (!mBaseStream) {
      72           0 :     return NS_BASE_STREAM_CLOSED;
      73             :   }
      74             : 
      75           0 :   nsresult rv = FlushToBaseStream();
      76           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
      77             : 
      78           0 :   mBaseStream->Flush();
      79             : 
      80           0 :   return NS_OK;
      81             : }
      82             : 
      83             : NS_IMETHODIMP
      84           0 : SnappyCompressOutputStream::Write(const char* aBuf, uint32_t aCount,
      85             :                                   uint32_t* aResultOut)
      86             : {
      87             :   return WriteSegments(NS_CopySegmentToBuffer, const_cast<char*>(aBuf), aCount,
      88           0 :                        aResultOut);
      89             : }
      90             : 
      91             : NS_IMETHODIMP
      92           0 : SnappyCompressOutputStream::WriteFrom(nsIInputStream*, uint32_t, uint32_t*)
      93             : {
      94           0 :   return NS_ERROR_NOT_IMPLEMENTED;
      95             : }
      96             : 
      97             : NS_IMETHODIMP
      98           0 : SnappyCompressOutputStream::WriteSegments(nsReadSegmentFun aReader,
      99             :                                           void* aClosure,
     100             :                                           uint32_t aCount,
     101             :                                           uint32_t* aBytesWrittenOut)
     102             : {
     103           0 :   *aBytesWrittenOut = 0;
     104             : 
     105           0 :   if (!mBaseStream) {
     106           0 :     return NS_BASE_STREAM_CLOSED;
     107             :   }
     108             : 
     109           0 :   if (!mBuffer) {
     110           0 :     mBuffer.reset(new (fallible) char[mBlockSize]);
     111           0 :     if (NS_WARN_IF(!mBuffer)) {
     112           0 :       return NS_ERROR_OUT_OF_MEMORY;
     113             :     }
     114             :   }
     115             : 
     116           0 :   while (aCount > 0) {
     117             :     // Determine how much space is left in our flat, uncompressed buffer.
     118           0 :     MOZ_ASSERT(mNextByte <= mBlockSize);
     119           0 :     uint32_t remaining = mBlockSize - mNextByte;
     120             : 
     121             :     // If it is full, then compress and flush the data to the base stream.
     122           0 :     if (remaining == 0) {
     123           0 :       nsresult rv = FlushToBaseStream();
     124           0 :       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     125             : 
     126             :       // Now the entire buffer should be available for copying.
     127           0 :       MOZ_ASSERT(!mNextByte);
     128           0 :       remaining = mBlockSize;
     129             :     }
     130             : 
     131           0 :     uint32_t numToRead = std::min(remaining, aCount);
     132           0 :     uint32_t numRead = 0;
     133             : 
     134           0 :     nsresult rv = aReader(this, aClosure, &mBuffer[mNextByte],
     135           0 :                           *aBytesWrittenOut, numToRead, &numRead);
     136             : 
     137             :     // As defined in nsIOutputStream.idl, do not pass reader func errors.
     138           0 :     if (NS_FAILED(rv)) {
     139           0 :       return NS_OK;
     140             :     }
     141             : 
     142             :     // End-of-file
     143           0 :     if (numRead == 0) {
     144           0 :       return NS_OK;
     145             :     }
     146             : 
     147           0 :     mNextByte += numRead;
     148           0 :     *aBytesWrittenOut += numRead;
     149           0 :     aCount -= numRead;
     150             :   }
     151             : 
     152           0 :   return NS_OK;
     153             : }
     154             : 
     155             : NS_IMETHODIMP
     156           0 : SnappyCompressOutputStream::IsNonBlocking(bool* aNonBlockingOut)
     157             : {
     158           0 :   *aNonBlockingOut = false;
     159           0 :   return NS_OK;
     160             : }
     161             : 
     162           0 : SnappyCompressOutputStream::~SnappyCompressOutputStream()
     163             : {
     164           0 :   Close();
     165           0 : }
     166             : 
     167             : nsresult
     168           0 : SnappyCompressOutputStream::FlushToBaseStream()
     169             : {
     170           0 :   MOZ_ASSERT(mBaseStream);
     171             : 
     172             :   // Lazily create the compressed buffer on our first flush.  This
     173             :   // allows us to report OOM during stream operation.  This buffer
     174             :   // will then get re-used until the stream is closed.
     175           0 :   if (!mCompressedBuffer) {
     176           0 :     mCompressedBufferLength = MaxCompressedBufferLength(mBlockSize);
     177           0 :     mCompressedBuffer.reset(new (fallible) char[mCompressedBufferLength]);
     178           0 :     if (NS_WARN_IF(!mCompressedBuffer)) {
     179           0 :       return NS_ERROR_OUT_OF_MEMORY;
     180             :     }
     181             :   }
     182             : 
     183             :   // The first chunk must be a StreamIdentifier chunk.  Write it out
     184             :   // if we have not done so already.
     185           0 :   nsresult rv = MaybeFlushStreamIdentifier();
     186           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     187             : 
     188             :   // Compress the data to our internal compressed buffer.
     189             :   size_t compressedLength;
     190           0 :   rv = WriteCompressedData(mCompressedBuffer.get(), mCompressedBufferLength,
     191           0 :                            mBuffer.get(), mNextByte, &compressedLength);
     192           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     193           0 :   MOZ_ASSERT(compressedLength > 0);
     194             : 
     195           0 :   mNextByte = 0;
     196             : 
     197             :   // Write the compressed buffer out to the base stream.
     198           0 :   uint32_t numWritten = 0;
     199           0 :   rv = WriteAll(mCompressedBuffer.get(), compressedLength, &numWritten);
     200           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     201           0 :   MOZ_ASSERT(compressedLength == numWritten);
     202             : 
     203           0 :   return NS_OK;
     204             : }
     205             : 
     206             : nsresult
     207           0 : SnappyCompressOutputStream::MaybeFlushStreamIdentifier()
     208             : {
     209           0 :   MOZ_ASSERT(mCompressedBuffer);
     210             : 
     211           0 :   if (mStreamIdentifierWritten) {
     212           0 :     return NS_OK;
     213             :   }
     214             : 
     215             :   // Build the StreamIdentifier in our compressed buffer.
     216             :   size_t compressedLength;
     217           0 :   nsresult rv = WriteStreamIdentifier(mCompressedBuffer.get(),
     218             :                                       mCompressedBufferLength,
     219           0 :                                       &compressedLength);
     220           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     221             : 
     222             :   // Write the compressed buffer out to the base stream.
     223           0 :   uint32_t numWritten = 0;
     224           0 :   rv = WriteAll(mCompressedBuffer.get(), compressedLength, &numWritten);
     225           0 :   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     226           0 :   MOZ_ASSERT(compressedLength == numWritten);
     227             : 
     228           0 :   mStreamIdentifierWritten = true;
     229             : 
     230           0 :   return NS_OK;
     231             : }
     232             : 
     233             : nsresult
     234           0 : SnappyCompressOutputStream::WriteAll(const char* aBuf, uint32_t aCount,
     235             :                                      uint32_t* aBytesWrittenOut)
     236             : {
     237           0 :   *aBytesWrittenOut = 0;
     238             : 
     239           0 :   if (!mBaseStream) {
     240           0 :     return NS_BASE_STREAM_CLOSED;
     241             :   }
     242             : 
     243           0 :   uint32_t offset = 0;
     244           0 :   while (aCount > 0) {
     245           0 :     uint32_t numWritten = 0;
     246           0 :     nsresult rv = mBaseStream->Write(aBuf + offset, aCount, &numWritten);
     247           0 :     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     248           0 :     offset += numWritten;
     249           0 :     aCount -= numWritten;
     250           0 :     *aBytesWrittenOut += numWritten;
     251             :   }
     252             : 
     253           0 :   return NS_OK;
     254             : }
     255             : 
     256             : } // namespace mozilla

Generated by: LCOV version 1.13