LCOV - code coverage report
Current view: directory - xpcom/io - nsBinaryStream.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 313 243 77.6 %
Date: 2012-06-02 Functions: 56 43 76.8 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code, released
      16                 :  * March 31, 1998.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998-1999
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : /**
      40                 :  * This file contains implementations of the nsIBinaryInputStream and
      41                 :  * nsIBinaryOutputStream interfaces.  Together, these interfaces allows reading
      42                 :  * and writing of primitive data types (integers, floating-point values,
      43                 :  * booleans, etc.) to a stream in a binary, untagged, fixed-endianness format.
      44                 :  * This might be used, for example, to implement network protocols or to
      45                 :  * produce architecture-neutral binary disk files, i.e. ones that can be read
      46                 :  * and written by both big-endian and little-endian platforms.  Output is
      47                 :  * written in big-endian order (high-order byte first), as this is traditional
      48                 :  * network order.
      49                 :  *
      50                 :  * @See nsIBinaryInputStream
      51                 :  * @See nsIBinaryOutputStream
      52                 :  */
      53                 : #include <string.h>
      54                 : #include "nsBinaryStream.h"
      55                 : #include "nsCRT.h"
      56                 : #include "nsIStreamBufferAccess.h"
      57                 : #include "prlong.h"
      58                 : #include "nsString.h"
      59                 : #include "nsISerializable.h"
      60                 : #include "nsIClassInfo.h"
      61                 : #include "nsComponentManagerUtils.h"
      62                 : #include "nsIURI.h" // for NS_IURI_IID
      63                 : 
      64          110771 : NS_IMPL_ISUPPORTS3(nsBinaryOutputStream, nsIObjectOutputStream, nsIBinaryOutputStream, nsIOutputStream)
      65                 : 
      66                 : NS_IMETHODIMP
      67               0 : nsBinaryOutputStream::Flush() 
      68                 : { 
      69               0 :     NS_ENSURE_STATE(mOutputStream);
      70               0 :     return mOutputStream->Flush(); 
      71                 : }
      72                 : 
      73                 : NS_IMETHODIMP
      74            7383 : nsBinaryOutputStream::Close() 
      75                 : { 
      76            7383 :     NS_ENSURE_STATE(mOutputStream);
      77            7383 :     return mOutputStream->Close(); 
      78                 : }
      79                 : 
      80                 : NS_IMETHODIMP
      81           15662 : nsBinaryOutputStream::Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes)
      82                 : {
      83           15662 :     NS_ENSURE_STATE(mOutputStream);
      84           15662 :     return mOutputStream->Write(aBuf, aCount, aActualBytes);
      85                 : }
      86                 : 
      87                 : NS_IMETHODIMP
      88               0 : nsBinaryOutputStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
      89                 : {
      90               0 :     NS_NOTREACHED("WriteFrom");
      91               0 :     return NS_ERROR_NOT_IMPLEMENTED;
      92                 : }
      93                 : 
      94                 : NS_IMETHODIMP
      95               0 : nsBinaryOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
      96                 : {
      97               0 :     NS_NOTREACHED("WriteSegments");
      98               0 :     return NS_ERROR_NOT_IMPLEMENTED;
      99                 : }
     100                 : 
     101                 : NS_IMETHODIMP
     102               0 : nsBinaryOutputStream::IsNonBlocking(bool *aNonBlocking)
     103                 : {
     104               0 :     NS_ENSURE_STATE(mOutputStream);
     105               0 :     return mOutputStream->IsNonBlocking(aNonBlocking);
     106                 : }
     107                 : 
     108                 : nsresult
     109          177762 : nsBinaryOutputStream::WriteFully(const char *aBuf, PRUint32 aCount)
     110                 : {
     111          177762 :     NS_ENSURE_STATE(mOutputStream);
     112                 : 
     113                 :     nsresult rv;
     114                 :     PRUint32 bytesWritten;
     115                 : 
     116          177762 :     rv = mOutputStream->Write(aBuf, aCount, &bytesWritten);
     117          177762 :     if (NS_FAILED(rv)) return rv;
     118          177761 :     if (bytesWritten != aCount)
     119               0 :         return NS_ERROR_FAILURE;
     120          177761 :     return NS_OK;
     121                 : }
     122                 : 
     123                 : NS_IMETHODIMP
     124            8253 : nsBinaryOutputStream::SetOutputStream(nsIOutputStream *aOutputStream)
     125                 : {
     126            8253 :     NS_ENSURE_ARG_POINTER(aOutputStream);
     127            8253 :     mOutputStream = aOutputStream;
     128            8253 :     mBufferAccess = do_QueryInterface(aOutputStream);
     129            8253 :     return NS_OK;
     130                 : }
     131                 : 
     132                 : NS_IMETHODIMP
     133              46 : nsBinaryOutputStream::WriteBoolean(bool aBoolean)
     134                 : {
     135              46 :     return Write8(aBoolean);
     136                 : }
     137                 : 
     138                 : NS_IMETHODIMP
     139          118432 : nsBinaryOutputStream::Write8(PRUint8 aByte)
     140                 : {
     141          118432 :     return WriteFully((const char*)&aByte, sizeof aByte);
     142                 : }
     143                 : 
     144                 : NS_IMETHODIMP
     145           29600 : nsBinaryOutputStream::Write16(PRUint16 a16)
     146                 : {
     147           29600 :     a16 = NS_SWAP16(a16);
     148           29600 :     return WriteFully((const char*)&a16, sizeof a16);
     149                 : }
     150                 : 
     151                 : NS_IMETHODIMP
     152           29712 : nsBinaryOutputStream::Write32(PRUint32 a32)
     153                 : {
     154           29712 :     a32 = NS_SWAP32(a32);
     155           29712 :     return WriteFully((const char*)&a32, sizeof a32);
     156                 : }
     157                 : 
     158                 : NS_IMETHODIMP
     159               6 : nsBinaryOutputStream::Write64(PRUint64 a64)
     160                 : {
     161                 :     nsresult rv;
     162                 :     PRUint32 bytesWritten;
     163                 : 
     164               6 :     a64 = NS_SWAP64(a64);
     165               6 :     rv = Write(reinterpret_cast<char*>(&a64), sizeof a64, &bytesWritten);
     166               6 :     if (NS_FAILED(rv)) return rv;
     167               6 :     if (bytesWritten != sizeof a64)
     168               0 :         return NS_ERROR_FAILURE;
     169               6 :     return rv;
     170                 : }
     171                 : 
     172                 : NS_IMETHODIMP
     173               2 : nsBinaryOutputStream::WriteFloat(float aFloat)
     174                 : {
     175                 :     NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
     176                 :                  "False assumption about sizeof(float)");
     177               2 :     return Write32(*reinterpret_cast<PRUint32*>(&aFloat));
     178                 : }
     179                 : 
     180                 : NS_IMETHODIMP
     181               0 : nsBinaryOutputStream::WriteDouble(double aDouble)
     182                 : {
     183                 :     NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
     184                 :                  "False assumption about sizeof(double)");
     185               0 :     return Write64(*reinterpret_cast<PRUint64*>(&aDouble));
     186                 : }
     187                 : 
     188                 : NS_IMETHODIMP
     189              18 : nsBinaryOutputStream::WriteStringZ(const char *aString)
     190                 : {
     191                 :     PRUint32 length;
     192                 :     nsresult rv;
     193                 : 
     194              18 :     length = strlen(aString);
     195              18 :     rv = Write32(length);
     196              18 :     if (NS_FAILED(rv)) return rv;
     197              18 :     return WriteFully(aString, length);
     198                 : }
     199                 : 
     200                 : NS_IMETHODIMP
     201              10 : nsBinaryOutputStream::WriteWStringZ(const PRUnichar* aString)
     202                 : {
     203                 :     PRUint32 length, byteCount;
     204                 :     nsresult rv;
     205                 : 
     206              10 :     length = nsCRT::strlen(aString);
     207              10 :     rv = Write32(length);
     208              10 :     if (NS_FAILED(rv)) return rv;
     209                 : 
     210              10 :     if (length == 0)
     211               4 :         return NS_OK;
     212               6 :     byteCount = length * sizeof(PRUnichar);
     213                 : 
     214                 : #ifdef IS_BIG_ENDIAN
     215                 :     rv = WriteBytes(reinterpret_cast<const char*>(aString), byteCount);
     216                 : #else
     217                 :     // XXX use WriteSegments here to avoid copy!
     218                 :     PRUnichar *copy, temp[64];
     219               6 :     if (length <= 64) {
     220               6 :         copy = temp;
     221                 :     } else {
     222               0 :         copy = reinterpret_cast<PRUnichar*>(moz_malloc(byteCount));
     223               0 :         if (!copy)
     224               0 :             return NS_ERROR_OUT_OF_MEMORY;
     225                 :     }
     226               6 :     NS_ASSERTION((PRUptrdiff(aString) & 0x1) == 0, "aString not properly aligned");
     227             140 :     for (PRUint32 i = 0; i < length; i++)
     228             134 :         copy[i] = NS_SWAP16(aString[i]);
     229               6 :     rv = WriteBytes(reinterpret_cast<const char*>(copy), byteCount);
     230               6 :     if (copy != temp)
     231               0 :         moz_free(copy);
     232                 : #endif
     233                 : 
     234               6 :     return rv;
     235                 : }
     236                 : 
     237                 : NS_IMETHODIMP
     238               0 : nsBinaryOutputStream::WriteUtf8Z(const PRUnichar* aString)
     239                 : {
     240               0 :     return WriteStringZ(NS_ConvertUTF16toUTF8(aString).get());
     241                 : }
     242                 : 
     243                 : NS_IMETHODIMP
     244           15656 : nsBinaryOutputStream::WriteBytes(const char *aString, PRUint32 aLength)
     245                 : {
     246                 :     nsresult rv;
     247                 :     PRUint32 bytesWritten;
     248                 : 
     249           15656 :     rv = Write(aString, aLength, &bytesWritten);
     250           15656 :     if (NS_FAILED(rv)) return rv;
     251           15656 :     if (bytesWritten != aLength)
     252               0 :         return NS_ERROR_FAILURE;
     253           15656 :     return rv;
     254                 : }
     255                 : 
     256                 : NS_IMETHODIMP
     257             898 : nsBinaryOutputStream::WriteByteArray(PRUint8 *aBytes, PRUint32 aLength)
     258                 : {
     259             898 :     return WriteBytes(reinterpret_cast<char *>(aBytes), aLength);
     260                 : }
     261                 : 
     262                 : NS_IMETHODIMP
     263            7376 : nsBinaryOutputStream::WriteObject(nsISupports* aObject, bool aIsStrongRef)
     264                 : {
     265                 :     return WriteCompoundObject(aObject, NS_GET_IID(nsISupports),
     266            7376 :                                aIsStrongRef);
     267                 : }
     268                 : 
     269                 : NS_IMETHODIMP
     270               0 : nsBinaryOutputStream::WriteSingleRefObject(nsISupports* aObject)
     271                 : {
     272                 :     return WriteCompoundObject(aObject, NS_GET_IID(nsISupports),
     273               0 :                                true);
     274                 : }
     275                 : 
     276                 : NS_IMETHODIMP
     277            7393 : nsBinaryOutputStream::WriteCompoundObject(nsISupports* aObject,
     278                 :                                           const nsIID& aIID,
     279                 :                                           bool aIsStrongRef)
     280                 : {
     281                 :     // Can't deal with weak refs
     282            7393 :     NS_ENSURE_TRUE(aIsStrongRef, NS_ERROR_UNEXPECTED);
     283                 :     
     284           14786 :     nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(aObject);
     285            7393 :     NS_ENSURE_TRUE(classInfo, NS_ERROR_NOT_AVAILABLE);
     286                 : 
     287           14786 :     nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aObject);
     288            7393 :     NS_ENSURE_TRUE(serializable, NS_ERROR_NOT_AVAILABLE);
     289                 : 
     290                 :     nsCID cid;
     291            7393 :     classInfo->GetClassIDNoAlloc(&cid);
     292                 : 
     293            7393 :     nsresult rv = WriteID(cid);
     294            7393 :     NS_ENSURE_SUCCESS(rv, rv);
     295                 :     
     296            7393 :     rv = WriteID(aIID);
     297            7393 :     NS_ENSURE_SUCCESS(rv, rv);
     298                 : 
     299            7393 :     return serializable->Write(this);
     300                 : }
     301                 : 
     302                 : NS_IMETHODIMP
     303           14798 : nsBinaryOutputStream::WriteID(const nsIID& aIID)
     304                 : {
     305           14798 :     nsresult rv = Write32(aIID.m0);
     306           14798 :     NS_ENSURE_SUCCESS(rv, rv);
     307                 : 
     308           14798 :     rv = Write16(aIID.m1);
     309           14798 :     NS_ENSURE_SUCCESS(rv, rv);
     310                 : 
     311           14798 :     rv = Write16(aIID.m2);
     312           14798 :     NS_ENSURE_SUCCESS(rv, rv);
     313                 : 
     314          133182 :     for (int i = 0; i < 8; ++i) {
     315          118384 :         rv = Write8(aIID.m3[i]);
     316          118384 :         NS_ENSURE_SUCCESS(rv, rv);
     317                 :     }
     318                 : 
     319           14798 :     return NS_OK;
     320                 : }
     321                 : 
     322                 : NS_IMETHODIMP_(char*)
     323               0 : nsBinaryOutputStream::GetBuffer(PRUint32 aLength, PRUint32 aAlignMask)
     324                 : {
     325               0 :     if (mBufferAccess)
     326               0 :         return mBufferAccess->GetBuffer(aLength, aAlignMask);
     327               0 :     return nsnull;
     328                 : }
     329                 : 
     330                 : NS_IMETHODIMP_(void)
     331               0 : nsBinaryOutputStream::PutBuffer(char* aBuffer, PRUint32 aLength)
     332                 : {
     333               0 :     if (mBufferAccess)
     334               0 :         mBufferAccess->PutBuffer(aBuffer, aLength);
     335               0 : }
     336                 : 
     337          287113 : NS_IMPL_ISUPPORTS3(nsBinaryInputStream, nsIObjectInputStream, nsIBinaryInputStream, nsIInputStream)
     338                 : 
     339                 : NS_IMETHODIMP
     340           12026 : nsBinaryInputStream::Available(PRUint32* aResult)
     341                 : {
     342           12026 :     NS_ENSURE_STATE(mInputStream);
     343           12026 :     return mInputStream->Available(aResult);
     344                 : }
     345                 : 
     346                 : NS_IMETHODIMP
     347           35389 : nsBinaryInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
     348                 : {
     349           35389 :     NS_ENSURE_STATE(mInputStream);
     350                 : 
     351                 :     // mInputStream might give us short reads, so deal with that.
     352           35389 :     PRUint32 totalRead = 0;
     353                 : 
     354                 :     PRUint32 bytesRead;
     355           35398 :     do {
     356           35399 :         nsresult rv = mInputStream->Read(aBuffer, aCount, &bytesRead);
     357           35399 :         if (rv == NS_BASE_STREAM_WOULD_BLOCK && totalRead != 0) {
     358                 :             // We already read some data.  Return it.
     359               0 :             break;
     360                 :         }
     361                 :         
     362           35399 :         if (NS_FAILED(rv)) {
     363               1 :             return rv;
     364                 :         }
     365                 : 
     366           35398 :         totalRead += bytesRead;
     367           35398 :         aBuffer += bytesRead;
     368           35398 :         aCount -= bytesRead;
     369                 :     } while (aCount != 0 && bytesRead != 0);
     370                 : 
     371           35388 :     *aNumRead = totalRead;
     372                 :     
     373           35388 :     return NS_OK;
     374                 : }
     375                 : 
     376                 : 
     377                 : // when forwarding ReadSegments to mInputStream, we need to make sure
     378                 : // 'this' is being passed to the writer each time. To do this, we need
     379                 : // a thunking function which keeps the real input stream around.
     380                 : 
     381                 : // the closure wrapper
     382                 : struct ReadSegmentsClosure {
     383                 :     nsIInputStream* mRealInputStream;
     384                 :     void* mRealClosure;
     385                 :     nsWriteSegmentFun mRealWriter;
     386                 :     nsresult mRealResult;
     387                 :     PRUint32 mBytesRead;  // to properly implement aToOffset
     388                 : };
     389                 : 
     390                 : // the thunking function
     391                 : static NS_METHOD
     392              13 : ReadSegmentForwardingThunk(nsIInputStream* aStream,
     393                 :                            void *aClosure,
     394                 :                            const char* aFromSegment,
     395                 :                            PRUint32 aToOffset,
     396                 :                            PRUint32 aCount,
     397                 :                            PRUint32 *aWriteCount)
     398                 : {
     399                 :     ReadSegmentsClosure* thunkClosure =
     400              13 :         reinterpret_cast<ReadSegmentsClosure*>(aClosure);
     401                 : 
     402              13 :     NS_ASSERTION(NS_SUCCEEDED(thunkClosure->mRealResult),
     403                 :                  "How did this get to be a failure status?");
     404                 : 
     405                 :     thunkClosure->mRealResult =
     406                 :         thunkClosure->mRealWriter(thunkClosure->mRealInputStream,
     407                 :                                   thunkClosure->mRealClosure,
     408                 :                                   aFromSegment,
     409                 :                                   thunkClosure->mBytesRead + aToOffset,
     410              13 :                                   aCount, aWriteCount);
     411                 : 
     412              13 :     return thunkClosure->mRealResult;
     413                 : }
     414                 : 
     415                 : 
     416                 : NS_IMETHODIMP
     417              16 : nsBinaryInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
     418                 : {
     419              16 :     NS_ENSURE_STATE(mInputStream);
     420                 : 
     421              16 :     ReadSegmentsClosure thunkClosure = { this, closure, writer, NS_OK, 0 };
     422                 :     
     423                 :     // mInputStream might give us short reads, so deal with that.
     424                 :     PRUint32 bytesRead;
     425              16 :     do {
     426              16 :         nsresult rv = mInputStream->ReadSegments(ReadSegmentForwardingThunk,
     427                 :                                                  &thunkClosure,
     428              16 :                                                  count, &bytesRead);
     429                 : 
     430              16 :         if (rv == NS_BASE_STREAM_WOULD_BLOCK && thunkClosure.mBytesRead != 0) {
     431                 :             // We already read some data.  Return it.
     432               0 :             break;
     433                 :         }
     434                 :         
     435              16 :         if (NS_FAILED(rv)) {
     436               0 :             return rv;
     437                 :         }
     438                 : 
     439              16 :         thunkClosure.mBytesRead += bytesRead;
     440              16 :         count -= bytesRead;
     441                 :     } while (count != 0 && bytesRead != 0 &&
     442               0 :              NS_SUCCEEDED(thunkClosure.mRealResult));
     443                 : 
     444              16 :     *_retval = thunkClosure.mBytesRead;
     445                 : 
     446              16 :     return NS_OK;
     447                 : }
     448                 : 
     449                 : NS_IMETHODIMP
     450               0 : nsBinaryInputStream::IsNonBlocking(bool *aNonBlocking)
     451                 : {
     452               0 :     NS_ENSURE_STATE(mInputStream);
     453               0 :     return mInputStream->IsNonBlocking(aNonBlocking);
     454                 : }
     455                 : 
     456                 : NS_IMETHODIMP
     457              58 : nsBinaryInputStream::Close() 
     458                 : { 
     459              58 :     NS_ENSURE_STATE(mInputStream);
     460              58 :     return mInputStream->Close(); 
     461                 : }
     462                 : 
     463                 : NS_IMETHODIMP
     464           17110 : nsBinaryInputStream::SetInputStream(nsIInputStream *aInputStream)
     465                 : {
     466           17110 :     NS_ENSURE_ARG_POINTER(aInputStream);
     467           17110 :     mInputStream = aInputStream;
     468           17110 :     mBufferAccess = do_QueryInterface(aInputStream);
     469           17110 :     return NS_OK;
     470                 : }
     471                 : 
     472                 : NS_IMETHODIMP
     473              22 : nsBinaryInputStream::ReadBoolean(bool* aBoolean)
     474                 : {
     475                 :     PRUint8 byteResult;
     476              22 :     nsresult rv = Read8(&byteResult);
     477              22 :     if (NS_FAILED(rv)) return rv;
     478              21 :     *aBoolean = !!byteResult;
     479              21 :     return rv;
     480                 : }
     481                 : 
     482                 : NS_IMETHODIMP
     483           17198 : nsBinaryInputStream::Read8(PRUint8* aByte)
     484                 : {
     485                 :     nsresult rv;
     486                 :     PRUint32 bytesRead;
     487                 : 
     488           17198 :     rv = Read(reinterpret_cast<char*>(aByte), sizeof(*aByte), &bytesRead);
     489           17198 :     if (NS_FAILED(rv)) return rv;
     490           17198 :     if (bytesRead != 1)
     491              10 :         return NS_ERROR_FAILURE;
     492           17188 :     return rv;
     493                 : }
     494                 : 
     495                 : NS_IMETHODIMP
     496            2598 : nsBinaryInputStream::Read16(PRUint16* a16)
     497                 : {
     498                 :     nsresult rv;
     499                 :     PRUint32 bytesRead;
     500                 : 
     501            2598 :     rv = Read(reinterpret_cast<char*>(a16), sizeof *a16, &bytesRead);
     502            2598 :     if (NS_FAILED(rv)) return rv;
     503            2598 :     if (bytesRead != sizeof *a16)
     504               0 :         return NS_ERROR_FAILURE;
     505            2598 :     *a16 = NS_SWAP16(*a16);
     506            2598 :     return rv;
     507                 : }
     508                 : 
     509                 : NS_IMETHODIMP
     510            2692 : nsBinaryInputStream::Read32(PRUint32* a32)
     511                 : {
     512                 :     nsresult rv;
     513                 :     PRUint32 bytesRead;
     514                 : 
     515            2692 :     rv = Read(reinterpret_cast<char*>(a32), sizeof *a32, &bytesRead);
     516            2692 :     if (NS_FAILED(rv)) return rv;
     517            2692 :     if (bytesRead != sizeof *a32)
     518               0 :         return NS_ERROR_FAILURE;
     519            2692 :     *a32 = NS_SWAP32(*a32);
     520            2692 :     return rv;
     521                 : }
     522                 : 
     523                 : NS_IMETHODIMP
     524               6 : nsBinaryInputStream::Read64(PRUint64* a64)
     525                 : {
     526                 :     nsresult rv;
     527                 :     PRUint32 bytesRead;
     528                 : 
     529               6 :     rv = Read(reinterpret_cast<char*>(a64), sizeof *a64, &bytesRead);
     530               6 :     if (NS_FAILED(rv)) return rv;
     531               6 :     if (bytesRead != sizeof *a64)
     532               0 :         return NS_ERROR_FAILURE;
     533               6 :     *a64 = NS_SWAP64(*a64);
     534               6 :     return rv;
     535                 : }
     536                 : 
     537                 : NS_IMETHODIMP
     538               2 : nsBinaryInputStream::ReadFloat(float* aFloat)
     539                 : {
     540                 :     NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
     541                 :                  "False assumption about sizeof(float)");
     542               2 :     return Read32(reinterpret_cast<PRUint32*>(aFloat));
     543                 : }
     544                 : 
     545                 : NS_IMETHODIMP
     546               0 : nsBinaryInputStream::ReadDouble(double* aDouble)
     547                 : {
     548                 :     NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
     549                 :                  "False assumption about sizeof(double)");
     550               0 :     return Read64(reinterpret_cast<PRUint64*>(aDouble));
     551                 : }
     552                 : 
     553                 : static NS_METHOD
     554              11 : WriteSegmentToCString(nsIInputStream* aStream,
     555                 :                       void *aClosure,
     556                 :                       const char* aFromSegment,
     557                 :                       PRUint32 aToOffset,
     558                 :                       PRUint32 aCount,
     559                 :                       PRUint32 *aWriteCount)
     560                 : {
     561              11 :     nsACString* outString = static_cast<nsACString*>(aClosure);
     562                 : 
     563              11 :     outString->Append(aFromSegment, aCount);
     564                 : 
     565              11 :     *aWriteCount = aCount;
     566                 :     
     567              11 :     return NS_OK;
     568                 : }
     569                 : 
     570                 : NS_IMETHODIMP
     571              14 : nsBinaryInputStream::ReadCString(nsACString& aString)
     572                 : {
     573                 :     nsresult rv;
     574                 :     PRUint32 length, bytesRead;
     575                 : 
     576              14 :     rv = Read32(&length);
     577              14 :     if (NS_FAILED(rv)) return rv;
     578                 : 
     579              14 :     aString.Truncate();
     580              14 :     rv = ReadSegments(WriteSegmentToCString, &aString, length, &bytesRead);
     581              14 :     if (NS_FAILED(rv)) return rv;
     582                 :     
     583              14 :     if (bytesRead != length)
     584               0 :         return NS_ERROR_FAILURE;
     585                 : 
     586              14 :     return NS_OK;
     587                 : }
     588                 : 
     589                 : 
     590                 : // sometimes, WriteSegmentToString will be handed an odd-number of
     591                 : // bytes, which means we only have half of the last PRUnichar
     592                 : struct WriteStringClosure {
     593                 :     PRUnichar *mWriteCursor;
     594                 :     bool mHasCarryoverByte;
     595                 :     char mCarryoverByte;
     596                 : };
     597                 : 
     598                 : // there are a few cases we have to account for here:
     599                 : // * even length buffer, no carryover - easy, just append
     600                 : // * odd length buffer, no carryover - the last byte needs to be saved
     601                 : //                                     for carryover
     602                 : // * odd length buffer, with carryover - first byte needs to be used
     603                 : //                              with the carryover byte, and
     604                 : //                              the rest of the even length
     605                 : //                              buffer is appended as normal
     606                 : // * even length buffer, with carryover - the first byte needs to be
     607                 : //                              used with the previous carryover byte.
     608                 : //                              this gives you an odd length buffer,
     609                 : //                              so you have to save the last byte for
     610                 : //                              the next carryover
     611                 : 
     612                 : 
     613                 : // same version of the above, but with correct casting and endian swapping
     614                 : static NS_METHOD
     615               2 : WriteSegmentToString(nsIInputStream* aStream,
     616                 :                      void *aClosure,
     617                 :                      const char* aFromSegment,
     618                 :                      PRUint32 aToOffset,
     619                 :                      PRUint32 aCount,
     620                 :                      PRUint32 *aWriteCount)
     621                 : {
     622               2 :     NS_PRECONDITION(aCount > 0, "Why are we being told to write 0 bytes?");
     623                 :     NS_PRECONDITION(sizeof(PRUnichar) == 2, "We can't handle other sizes!");
     624                 : 
     625               2 :     WriteStringClosure* closure = static_cast<WriteStringClosure*>(aClosure);
     626               2 :     PRUnichar *cursor = closure->mWriteCursor;
     627                 : 
     628                 :     // we're always going to consume the whole buffer no matter what
     629                 :     // happens, so take care of that right now.. that allows us to
     630                 :     // tweak aCount later. Do NOT move this!
     631               2 :     *aWriteCount = aCount;
     632                 : 
     633                 :     // if the last Write had an odd-number of bytes read, then 
     634               2 :     if (closure->mHasCarryoverByte) {
     635                 :         // re-create the two-byte sequence we want to work with
     636               0 :         char bytes[2] = { closure->mCarryoverByte, *aFromSegment };
     637               0 :         *cursor = *(PRUnichar*)bytes;
     638                 :         // Now the little endianness dance
     639                 : #ifdef IS_LITTLE_ENDIAN
     640               0 :         *cursor = (PRUnichar) NS_SWAP16(*cursor);
     641                 : #endif
     642               0 :         ++cursor;
     643                 :         
     644                 :         // now skip past the first byte of the buffer.. code from here
     645                 :         // can assume normal operations, but should not assume aCount
     646                 :         // is relative to the ORIGINAL buffer
     647               0 :         ++aFromSegment;
     648               0 :         --aCount;
     649                 : 
     650               0 :         closure->mHasCarryoverByte = false;
     651                 :     }
     652                 :     
     653                 :     // this array is possibly unaligned... be careful how we access it!
     654                 :     const PRUnichar *unicodeSegment =
     655               2 :         reinterpret_cast<const PRUnichar*>(aFromSegment);
     656                 : 
     657                 :     // calculate number of full characters in segment (aCount could be odd!)
     658               2 :     PRUint32 segmentLength = aCount / sizeof(PRUnichar);
     659                 : 
     660                 :     // copy all data into our aligned buffer.  byte swap if necessary.
     661               2 :     memcpy(cursor, unicodeSegment, segmentLength * sizeof(PRUnichar));
     662               2 :     PRUnichar *end = cursor + segmentLength;
     663                 : #ifdef IS_LITTLE_ENDIAN
     664              12 :     for (; cursor < end; ++cursor)
     665              10 :         *cursor = (PRUnichar) NS_SWAP16(*cursor);
     666                 : #endif
     667               2 :     closure->mWriteCursor = end;
     668                 : 
     669                 :     // remember this is the modifed aCount and aFromSegment,
     670                 :     // so that will take into account the fact that we might have
     671                 :     // skipped the first byte in the buffer
     672               2 :     if (aCount % sizeof(PRUnichar) != 0) {
     673                 :         // we must have had a carryover byte, that we'll need the next
     674                 :         // time around
     675               0 :         closure->mCarryoverByte = aFromSegment[aCount - 1];
     676               0 :         closure->mHasCarryoverByte = true;
     677                 :     }
     678                 :     
     679               2 :     return NS_OK;
     680                 : }
     681                 : 
     682                 : 
     683                 : NS_IMETHODIMP
     684               2 : nsBinaryInputStream::ReadString(nsAString& aString)
     685                 : {
     686                 :     nsresult rv;
     687                 :     PRUint32 length, bytesRead;
     688                 : 
     689               2 :     rv = Read32(&length);
     690               2 :     if (NS_FAILED(rv)) return rv;
     691                 : 
     692               2 :     if (length == 0) {
     693               0 :       aString.Truncate();
     694               0 :       return NS_OK;
     695                 :     }
     696                 : 
     697                 :     // pre-allocate output buffer, and get direct access to buffer...
     698               2 :     if (!EnsureStringLength(aString, length))
     699               0 :         return NS_ERROR_OUT_OF_MEMORY;
     700                 : 
     701               2 :     nsAString::iterator start;
     702               2 :     aString.BeginWriting(start);
     703                 :     
     704                 :     WriteStringClosure closure;
     705               2 :     closure.mWriteCursor = start.get();
     706               2 :     closure.mHasCarryoverByte = false;
     707                 :     
     708                 :     rv = ReadSegments(WriteSegmentToString, &closure,
     709               2 :                       length*sizeof(PRUnichar), &bytesRead);
     710               2 :     if (NS_FAILED(rv)) return rv;
     711                 : 
     712               2 :     NS_ASSERTION(!closure.mHasCarryoverByte, "some strange stream corruption!");
     713                 :     
     714               2 :     if (bytesRead != length*sizeof(PRUnichar))
     715               0 :         return NS_ERROR_FAILURE;
     716                 : 
     717               2 :     return NS_OK;
     718                 : }
     719                 : 
     720                 : NS_IMETHODIMP
     721           12895 : nsBinaryInputStream::ReadBytes(PRUint32 aLength, char* *_rval)
     722                 : {
     723                 :     nsresult rv;
     724                 :     PRUint32 bytesRead;
     725                 :     char* s;
     726                 : 
     727           12895 :     s = reinterpret_cast<char*>(moz_malloc(aLength));
     728           12895 :     if (!s)
     729               0 :         return NS_ERROR_OUT_OF_MEMORY;
     730                 : 
     731           12895 :     rv = Read(s, aLength, &bytesRead);
     732           12895 :     if (NS_FAILED(rv)) {
     733               1 :         moz_free(s);
     734               1 :         return rv;
     735                 :     }
     736           12894 :     if (bytesRead != aLength) {
     737              25 :         moz_free(s);
     738              25 :         return NS_ERROR_FAILURE;
     739                 :     }
     740                 : 
     741           12869 :     *_rval = s;
     742           12869 :     return NS_OK;
     743                 : }
     744                 : 
     745                 : NS_IMETHODIMP
     746           10945 : nsBinaryInputStream::ReadByteArray(PRUint32 aLength, PRUint8* *_rval)
     747                 : {
     748           10945 :     return ReadBytes(aLength, reinterpret_cast<char **>(_rval));
     749                 : }
     750                 : 
     751                 : NS_IMETHODIMP
     752             648 : nsBinaryInputStream::ReadObject(bool aIsStrongRef, nsISupports* *aObject)
     753                 : {
     754                 :     nsCID cid;
     755                 :     nsIID iid;
     756             648 :     nsresult rv = ReadID(&cid);
     757             648 :     NS_ENSURE_SUCCESS(rv, rv);
     758                 : 
     759             648 :     rv = ReadID(&iid);
     760             648 :     NS_ENSURE_SUCCESS(rv, rv);
     761                 : 
     762                 :     // HACK: Intercept old (pre-gecko6) nsIURI IID, and replace with
     763                 :     // the updated IID, so that we're QI'ing to an actual interface.
     764                 :     // (As soon as we drop support for upgrading from pre-gecko6, we can
     765                 :     // remove this chunk.)
     766                 :     static const nsIID oldURIiid =
     767                 :         { 0x7a22cc0, 0xce5, 0x11d3,
     768                 :           { 0x93, 0x31, 0x0, 0x10, 0x4b, 0xa0, 0xfd, 0x40 }};
     769                 : 
     770                 :     // hackaround for bug 670542
     771                 :     static const nsIID oldURIiid2 =
     772                 :         { 0xd6d04c36, 0x0fa4, 0x4db3,
     773                 :           { 0xbe, 0x05, 0x4a, 0x18, 0x39, 0x71, 0x03, 0xe2 }};
     774                 : 
     775                 :     // hackaround for bug 682031
     776                 :     static const nsIID oldURIiid3 =
     777                 :         { 0x12120b20, 0x0929, 0x40e9,
     778                 :           { 0x88, 0xcf, 0x6e, 0x08, 0x76, 0x6e, 0x8b, 0x23 }};
     779                 : 
     780            1944 :     if (iid.Equals(oldURIiid) ||
     781             648 :         iid.Equals(oldURIiid2) ||
     782             648 :         iid.Equals(oldURIiid3)) {
     783               0 :         const nsIID newURIiid = NS_IURI_IID;
     784               0 :         iid = newURIiid;
     785                 :     }
     786                 :     // END HACK
     787                 : 
     788            1296 :     nsCOMPtr<nsISupports> object = do_CreateInstance(cid, &rv);
     789             648 :     NS_ENSURE_SUCCESS(rv, rv);
     790                 : 
     791            1296 :     nsCOMPtr<nsISerializable> serializable = do_QueryInterface(object);
     792             648 :     NS_ENSURE_TRUE(serializable, NS_ERROR_UNEXPECTED);
     793                 : 
     794             648 :     rv = serializable->Read(this);
     795             648 :     NS_ENSURE_SUCCESS(rv, rv);    
     796                 : 
     797             648 :     return object->QueryInterface(iid, reinterpret_cast<void**>(aObject));
     798                 : }
     799                 : 
     800                 : NS_IMETHODIMP
     801            1296 : nsBinaryInputStream::ReadID(nsID *aResult)
     802                 : {
     803            1296 :     nsresult rv = Read32(&aResult->m0);
     804            1296 :     NS_ENSURE_SUCCESS(rv, rv);
     805                 : 
     806            1296 :     rv = Read16(&aResult->m1);
     807            1296 :     NS_ENSURE_SUCCESS(rv, rv);
     808                 : 
     809            1296 :     rv = Read16(&aResult->m2);
     810            1296 :     NS_ENSURE_SUCCESS(rv, rv);
     811                 : 
     812           11664 :     for (int i = 0; i < 8; ++i) {
     813           10368 :         rv = Read8(&aResult->m3[i]);
     814           10368 :         NS_ENSURE_SUCCESS(rv, rv);
     815                 :     }
     816                 : 
     817            1296 :     return NS_OK;
     818                 : }
     819                 : 
     820                 : NS_IMETHODIMP_(char*)
     821               0 : nsBinaryInputStream::GetBuffer(PRUint32 aLength, PRUint32 aAlignMask)
     822                 : {
     823               0 :     if (mBufferAccess)
     824               0 :         return mBufferAccess->GetBuffer(aLength, aAlignMask);
     825               0 :     return nsnull;
     826                 : }
     827                 : 
     828                 : NS_IMETHODIMP_(void)
     829               0 : nsBinaryInputStream::PutBuffer(char* aBuffer, PRUint32 aLength)
     830                 : {
     831               0 :     if (mBufferAccess)
     832               0 :         mBufferAccess->PutBuffer(aBuffer, aLength);
     833               0 : }

Generated by: LCOV version 1.7