LCOV - code coverage report
Current view: directory - xpcom/io - nsStringStream.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 161 108 67.1 %
Date: 2012-06-02 Functions: 31 23 74.2 %

       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.org code.
      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
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   mcmullen@netscape.com (original author)
      25                 :  *   warren@netscape.com
      26                 :  *   alecf@netscape.com
      27                 :  *   scc@mozilla.org
      28                 :  *   david.gardiner@unisa.edu.au
      29                 :  *   fur@netscape.com
      30                 :  *   norris@netscape.com
      31                 :  *   pinkerton@netscape.com
      32                 :  *   davidm@netscape.com
      33                 :  *   sfraser@netscape.com
      34                 :  *   darin@netscape.com
      35                 :  *   bzbarsky@mit.edu
      36                 :  *
      37                 :  * Alternatively, the contents of this file may be used under the terms of
      38                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      39                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      40                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      41                 :  * of those above. If you wish to allow use of your version of this file only
      42                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      43                 :  * use your version of this file under the terms of the MPL, indicate your
      44                 :  * decision by deleting the provisions above and replace them with the notice
      45                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      46                 :  * the provisions above, a recipient may use your version of this file under
      47                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      48                 :  *
      49                 :  * ***** END LICENSE BLOCK ***** */
      50                 : 
      51                 : /**
      52                 :  * Based on original code from nsIStringStream.cpp
      53                 :  */
      54                 : 
      55                 : #include "IPC/IPCMessageUtils.h"
      56                 : 
      57                 : #include "nsStringStream.h"
      58                 : #include "nsStreamUtils.h"
      59                 : #include "nsReadableUtils.h"
      60                 : #include "nsISeekableStream.h"
      61                 : #include "nsISupportsPrimitives.h"
      62                 : #include "nsCRT.h"
      63                 : #include "prerror.h"
      64                 : #include "plstr.h"
      65                 : #include "nsIClassInfoImpl.h"
      66                 : #include "nsIIPCSerializable.h"
      67                 : 
      68                 : //-----------------------------------------------------------------------------
      69                 : // nsIStringInputStream implementation
      70                 : //-----------------------------------------------------------------------------
      71                 : 
      72                 : class nsStringInputStream : public nsIStringInputStream
      73                 :                           , public nsISeekableStream
      74                 :                           , public nsISupportsCString
      75                 :                           , public nsIIPCSerializable
      76                 : {
      77                 : public:
      78                 :     NS_DECL_ISUPPORTS
      79                 :     NS_DECL_NSIINPUTSTREAM
      80                 :     NS_DECL_NSISTRINGINPUTSTREAM
      81                 :     NS_DECL_NSISEEKABLESTREAM
      82                 :     NS_DECL_NSISUPPORTSPRIMITIVE
      83                 :     NS_DECL_NSISUPPORTSCSTRING
      84                 :     NS_DECL_NSIIPCSERIALIZABLE
      85                 : 
      86          202200 :     nsStringInputStream()
      87          202200 :     {
      88          202200 :         Clear();
      89          202200 :     }
      90                 : 
      91                 : private:
      92          202188 :     ~nsStringInputStream()
      93          202188 :     {}
      94                 : 
      95          793930 :     PRUint32 Length() const
      96                 :     {
      97          793930 :         return mData.Length();
      98                 :     }
      99                 : 
     100          399109 :     PRUint32 LengthRemaining() const
     101                 :     {
     102          399109 :         return Length() - mOffset;
     103                 :     }
     104                 : 
     105          202477 :     void Clear()
     106                 :     {
     107          202477 :         mData.SetIsVoid(true);
     108          202477 :     }
     109                 : 
     110          399111 :     bool Closed()
     111                 :     {
     112          399111 :         return mData.IsVoid();
     113                 :     }
     114                 : 
     115                 :     nsDependentCSubstring mData;
     116                 :     PRUint32 mOffset;
     117                 : };
     118                 : 
     119                 : // This class needs to support threadsafe refcounting since people often
     120                 : // allocate a string stream, and then read it from a background thread.
     121          615610 : NS_IMPL_THREADSAFE_ADDREF(nsStringInputStream)
     122          817786 : NS_IMPL_THREADSAFE_RELEASE(nsStringInputStream)
     123                 : 
     124                 : NS_IMPL_CLASSINFO(nsStringInputStream, NULL, nsIClassInfo::THREADSAFE,
     125                 :                   NS_STRINGINPUTSTREAM_CID)
     126          422760 : NS_IMPL_QUERY_INTERFACE5_CI(nsStringInputStream,
     127                 :                             nsIStringInputStream,
     128                 :                             nsIInputStream,
     129                 :                             nsISupportsCString,
     130                 :                             nsISeekableStream,
     131            1833 :                             nsIIPCSerializable)
     132             776 : NS_IMPL_CI_INTERFACE_GETTER5(nsStringInputStream,
     133                 :                              nsIStringInputStream,
     134                 :                              nsIInputStream,
     135                 :                              nsISupportsCString,
     136                 :                              nsISeekableStream,
     137             776 :                              nsIIPCSerializable)
     138                 : 
     139                 : /////////
     140                 : // nsISupportsCString implementation
     141                 : /////////
     142                 : 
     143                 : NS_IMETHODIMP
     144               0 : nsStringInputStream::GetType(PRUint16 *type)
     145                 : {
     146               0 :     *type = TYPE_CSTRING;
     147               0 :     return NS_OK;
     148                 : }
     149                 : 
     150                 : NS_IMETHODIMP
     151               0 : nsStringInputStream::GetData(nsACString &data)
     152                 : {
     153                 :     // The stream doesn't have any data when it is closed.  We could fake it
     154                 :     // and return an empty string here, but it seems better to keep this return
     155                 :     // value consistent with the behavior of the other 'getter' methods.
     156               0 :     NS_ENSURE_TRUE(!Closed(), NS_BASE_STREAM_CLOSED);
     157                 : 
     158               0 :     data.Assign(mData);
     159               0 :     return NS_OK;
     160                 : }
     161                 : 
     162                 : NS_IMETHODIMP
     163            1119 : nsStringInputStream::SetData(const nsACString &data)
     164                 : {
     165            1119 :     mData.Assign(data);
     166            1119 :     mOffset = 0;
     167            1119 :     return NS_OK;
     168                 : }
     169                 : 
     170                 : NS_IMETHODIMP
     171               0 : nsStringInputStream::ToString(char **result)
     172                 : {
     173                 :     // NOTE: This method may result in data loss, so we do not implement it.
     174               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     175                 : }
     176                 : 
     177                 : /////////
     178                 : // nsIStringInputStream implementation
     179                 : /////////
     180                 : 
     181                 : NS_IMETHODIMP
     182             709 : nsStringInputStream::SetData(const char *data, PRInt32 dataLen)
     183                 : {
     184             709 :     NS_ENSURE_ARG_POINTER(data);
     185             709 :     mData.Assign(data, dataLen);
     186             709 :     mOffset = 0;
     187             709 :     return NS_OK;
     188                 : }
     189                 : 
     190                 : NS_IMETHODIMP
     191             919 : nsStringInputStream::AdoptData(char *data, PRInt32 dataLen)
     192                 : {
     193             919 :     NS_ENSURE_ARG_POINTER(data);
     194             919 :     mData.Adopt(data, dataLen);
     195             919 :     mOffset = 0;
     196             919 :     return NS_OK;
     197                 : }
     198                 : 
     199                 : NS_IMETHODIMP
     200          204001 : nsStringInputStream::ShareData(const char *data, PRInt32 dataLen)
     201                 : {
     202          204001 :     NS_ENSURE_ARG_POINTER(data);
     203                 : 
     204          204001 :     if (dataLen < 0)
     205               2 :         dataLen = strlen(data);
     206                 : 
     207          204001 :     mData.Rebind(data, dataLen);
     208          204001 :     mOffset = 0;
     209          204001 :     return NS_OK;
     210                 : }
     211                 : 
     212                 : /////////
     213                 : // nsIInputStream implementation
     214                 : /////////
     215                 : 
     216                 : NS_IMETHODIMP
     217             277 : nsStringInputStream::Close()
     218                 : {
     219             277 :     Clear();
     220             277 :     return NS_OK;
     221                 : }
     222                 :     
     223                 : NS_IMETHODIMP
     224            4290 : nsStringInputStream::Available(PRUint32 *aLength)
     225                 : {
     226            4290 :     NS_ASSERTION(aLength, "null ptr");
     227                 : 
     228            4290 :     if (Closed())
     229               0 :         return NS_BASE_STREAM_CLOSED;
     230                 : 
     231            4290 :     *aLength = LengthRemaining();
     232            4290 :     return NS_OK;
     233                 : }
     234                 : 
     235                 : NS_IMETHODIMP
     236          386550 : nsStringInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
     237                 : {
     238          386550 :     NS_ASSERTION(aBuf, "null ptr");
     239          386550 :     return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aReadCount);
     240                 : }
     241                 : 
     242                 : NS_IMETHODIMP
     243          394819 : nsStringInputStream::ReadSegments(nsWriteSegmentFun writer, void *closure,
     244                 :                                   PRUint32 aCount, PRUint32 *result)
     245                 : {
     246          394819 :     NS_ASSERTION(result, "null ptr");
     247          394819 :     NS_ASSERTION(Length() >= mOffset, "bad stream state");
     248                 : 
     249          394819 :     if (Closed())
     250               0 :         return NS_BASE_STREAM_CLOSED;
     251                 : 
     252                 :     // We may be at end-of-file
     253          394819 :     PRUint32 maxCount = LengthRemaining();
     254          394819 :     if (maxCount == 0) {
     255            8961 :         *result = 0;
     256            8961 :         return NS_OK;
     257                 :     }
     258                 : 
     259          385858 :     if (aCount > maxCount)
     260            9092 :         aCount = maxCount;
     261          385858 :     nsresult rv = writer(this, closure, mData.BeginReading() + mOffset, 0, aCount, result);
     262          385858 :     if (NS_SUCCEEDED(rv)) {
     263          384126 :         NS_ASSERTION(*result <= aCount,
     264                 :                      "writer should not write more than we asked it to write");
     265          384126 :         mOffset += *result;
     266                 :     }
     267                 : 
     268                 :     // errors returned from the writer end here!
     269          385858 :     return NS_OK;
     270                 : }
     271                 :     
     272                 : NS_IMETHODIMP
     273               1 : nsStringInputStream::IsNonBlocking(bool *aNonBlocking)
     274                 : {
     275               1 :     *aNonBlocking = true;
     276               1 :     return NS_OK;
     277                 : }
     278                 : 
     279                 : /////////
     280                 : // nsISeekableStream implementation
     281                 : /////////
     282                 : 
     283                 : NS_IMETHODIMP 
     284               2 : nsStringInputStream::Seek(PRInt32 whence, PRInt64 offset)
     285                 : {
     286               2 :     if (Closed())
     287               0 :         return NS_BASE_STREAM_CLOSED;
     288                 : 
     289                 :     // Compute new stream position.  The given offset may be a negative value.
     290                 :  
     291               2 :     PRInt64 newPos = offset;
     292               2 :     switch (whence) {
     293                 :     case NS_SEEK_SET:
     294               2 :         break;
     295                 :     case NS_SEEK_CUR:
     296               0 :         newPos += mOffset;
     297               0 :         break;
     298                 :     case NS_SEEK_END:
     299               0 :         newPos += Length();
     300               0 :         break;
     301                 :     default:
     302               0 :         NS_ERROR("invalid whence");
     303               0 :         return NS_ERROR_INVALID_ARG;
     304                 :     }
     305                 : 
     306               2 :     NS_ENSURE_ARG(newPos >= 0);
     307               2 :     NS_ENSURE_ARG(newPos <= Length());
     308                 : 
     309               2 :     mOffset = (PRUint32)newPos;
     310               2 :     return NS_OK;
     311                 : }
     312                 : 
     313                 : NS_IMETHODIMP
     314               0 : nsStringInputStream::Tell(PRInt64* outWhere)
     315                 : {
     316               0 :     if (Closed())
     317               0 :         return NS_BASE_STREAM_CLOSED;
     318                 : 
     319               0 :     *outWhere = mOffset;
     320               0 :     return NS_OK;
     321                 : }
     322                 : 
     323                 : NS_IMETHODIMP
     324               0 : nsStringInputStream::SetEOF()
     325                 : {
     326               0 :     if (Closed())
     327               0 :         return NS_BASE_STREAM_CLOSED;
     328                 : 
     329               0 :     mOffset = Length();
     330               0 :     return NS_OK;
     331                 : }
     332                 : 
     333                 : /////////
     334                 : // nsIIPCSerializable implementation
     335                 : /////////
     336                 : 
     337                 : bool
     338               0 : nsStringInputStream::Read(const IPC::Message *aMsg, void **aIter)
     339                 : {
     340                 :     using IPC::ReadParam;
     341                 : 
     342               0 :     nsCString value;
     343                 : 
     344               0 :     if (!ReadParam(aMsg, aIter, &value))
     345               0 :         return false;
     346                 : 
     347               0 :     nsresult rv = SetData(value);
     348               0 :     if (NS_FAILED(rv))
     349               0 :         return false;
     350                 : 
     351               0 :     return true;
     352                 : }
     353                 : 
     354                 : void
     355               0 : nsStringInputStream::Write(IPC::Message *aMsg)
     356                 : {
     357                 :     using IPC::WriteParam;
     358                 : 
     359               0 :     WriteParam(aMsg, static_cast<const nsCString&>(PromiseFlatCString(mData)));
     360               0 : }
     361                 : 
     362                 : nsresult
     363            3818 : NS_NewByteInputStream(nsIInputStream** aStreamResult,
     364                 :                       const char* aStringToRead, PRInt32 aLength,
     365                 :                       nsAssignmentType aAssignment)
     366                 : {
     367            3818 :     NS_PRECONDITION(aStreamResult, "null out ptr");
     368                 : 
     369            3818 :     nsStringInputStream* stream = new nsStringInputStream();
     370            3818 :     if (! stream)
     371               0 :         return NS_ERROR_OUT_OF_MEMORY;
     372                 : 
     373            3818 :     NS_ADDREF(stream);
     374                 : 
     375                 :     nsresult rv;
     376            3818 :     switch (aAssignment) {
     377                 :     case NS_ASSIGNMENT_COPY:
     378               0 :         rv = stream->SetData(aStringToRead, aLength);
     379               0 :         break;
     380                 :     case NS_ASSIGNMENT_DEPEND:
     381            3818 :         rv = stream->ShareData(aStringToRead, aLength);
     382            3818 :         break;
     383                 :     case NS_ASSIGNMENT_ADOPT:
     384               0 :         rv = stream->AdoptData(const_cast<char*>(aStringToRead), aLength);
     385               0 :         break;
     386                 :     default:
     387               0 :         NS_ERROR("invalid assignment type");
     388               0 :         rv = NS_ERROR_INVALID_ARG;
     389                 :     }
     390                 :     
     391            3818 :     if (NS_FAILED(rv)) {
     392               0 :         NS_RELEASE(stream);
     393               0 :         return rv;
     394                 :     }
     395                 :     
     396            3818 :     *aStreamResult = stream;
     397            3818 :     return NS_OK;
     398                 : }
     399                 : 
     400                 : nsresult
     401               0 : NS_NewStringInputStream(nsIInputStream** aStreamResult,
     402                 :                         const nsAString& aStringToRead)
     403                 : {
     404               0 :     NS_LossyConvertUTF16toASCII data(aStringToRead); // truncates high-order bytes
     405               0 :     return NS_NewCStringInputStream(aStreamResult, data);
     406                 : }
     407                 : 
     408                 : nsresult
     409             273 : NS_NewCStringInputStream(nsIInputStream** aStreamResult,
     410                 :                          const nsACString& aStringToRead)
     411                 : {
     412             273 :     NS_PRECONDITION(aStreamResult, "null out ptr");
     413                 : 
     414             273 :     nsStringInputStream* stream = new nsStringInputStream();
     415             273 :     if (! stream)
     416               0 :         return NS_ERROR_OUT_OF_MEMORY;
     417                 : 
     418             273 :     NS_ADDREF(stream);
     419                 : 
     420             273 :     stream->SetData(aStringToRead);
     421                 : 
     422             273 :     *aStreamResult = stream;
     423             273 :     return NS_OK;
     424                 : }
     425                 : 
     426                 : // factory method for constructing a nsStringInputStream object
     427                 : nsresult
     428          198109 : nsStringInputStreamConstructor(nsISupports *outer, REFNSIID iid, void **result)
     429                 : {
     430          198109 :     *result = nsnull;
     431                 : 
     432          198109 :     NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
     433                 : 
     434          198109 :     nsStringInputStream *inst = new nsStringInputStream();
     435          198109 :     if (!inst)
     436               0 :         return NS_ERROR_OUT_OF_MEMORY;
     437                 : 
     438          198109 :     NS_ADDREF(inst);
     439          198109 :     nsresult rv = inst->QueryInterface(iid, result);
     440          198109 :     NS_RELEASE(inst);
     441                 : 
     442          198109 :     return rv;
     443                 : }

Generated by: LCOV version 1.7