LCOV - code coverage report
Current view: directory - xpcom/string/src - nsSubstring.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 115 85 73.9 %
Date: 2012-06-02 Functions: 22 14 63.6 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       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.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is IBM Corporation.
      19                 :  * Portions created by IBM Corporation are Copyright (C) 2003
      20                 :  * IBM Corporation. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Darin Fisher <darin@meer.net>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * 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                 : #ifdef DEBUG
      40                 : #define ENABLE_STRING_STATS
      41                 : #endif
      42                 : 
      43                 : #ifdef ENABLE_STRING_STATS
      44                 : #include <stdio.h>
      45                 : #endif
      46                 : 
      47                 : #include <stdlib.h>
      48                 : #include "nsSubstring.h"
      49                 : #include "nsString.h"
      50                 : #include "nsStringBuffer.h"
      51                 : #include "nsDependentString.h"
      52                 : #include "nsMemory.h"
      53                 : #include "pratom.h"
      54                 : #include "prprf.h"
      55                 : #include "nsStaticAtom.h"
      56                 : 
      57                 : // ---------------------------------------------------------------------------
      58                 : 
      59                 : static PRUnichar gNullChar = 0;
      60                 : 
      61                 : char*      nsCharTraits<char>     ::sEmptyBuffer = (char*) &gNullChar;
      62                 : PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer =         &gNullChar;
      63                 : 
      64                 : // ---------------------------------------------------------------------------
      65                 : 
      66                 : #ifdef ENABLE_STRING_STATS
      67                 : class nsStringStats
      68                 :   {
      69                 :     public:
      70            1464 :       nsStringStats()
      71            1464 :         : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {}
      72                 : 
      73            1487 :       ~nsStringStats()
      74                 :         {
      75                 :           // this is a hack to suppress duplicate string stats printing
      76                 :           // in seamonkey as a result of the string code being linked
      77                 :           // into seamonkey and libxpcom! :-(
      78            1487 :           if (!mAllocCount && !mAdoptCount)
      79              40 :             return;
      80                 : 
      81            1447 :           printf("nsStringStats\n");
      82            1447 :           printf(" => mAllocCount:     % 10d\n", mAllocCount);
      83            1447 :           printf(" => mReallocCount:   % 10d\n", mReallocCount);
      84            1447 :           printf(" => mFreeCount:      % 10d", mFreeCount);
      85            1447 :           if (mAllocCount > mFreeCount)
      86              40 :             printf("  --  LEAKED %d !!!\n", mAllocCount - mFreeCount);
      87                 :           else
      88            1407 :             printf("\n");
      89            1447 :           printf(" => mShareCount:     % 10d\n", mShareCount);
      90            1447 :           printf(" => mAdoptCount:     % 10d\n", mAdoptCount);
      91            1447 :           printf(" => mAdoptFreeCount: % 10d", mAdoptFreeCount);
      92            1447 :           if (mAdoptCount > mAdoptFreeCount)
      93               3 :             printf("  --  LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount);
      94                 :           else
      95            1444 :             printf("\n");
      96            1487 :         }
      97                 : 
      98                 :       PRInt32 mAllocCount;
      99                 :       PRInt32 mReallocCount;
     100                 :       PRInt32 mFreeCount;
     101                 :       PRInt32 mShareCount;
     102                 :       PRInt32 mAdoptCount;
     103                 :       PRInt32 mAdoptFreeCount;
     104                 :   };
     105            1464 : static nsStringStats gStringStats;
     106                 : #define STRING_STAT_INCREMENT(_s) PR_ATOMIC_INCREMENT(&gStringStats.m ## _s ## Count)
     107                 : #else
     108                 : #define STRING_STAT_INCREMENT(_s)
     109                 : #endif
     110                 : 
     111                 : // ---------------------------------------------------------------------------
     112                 : 
     113                 : inline void
     114        96041591 : ReleaseData( void* data, PRUint32 flags )
     115                 :   {
     116        96041591 :     if (flags & nsSubstring::F_SHARED)
     117                 :       {
     118        15727237 :         nsStringBuffer::FromData(data)->Release();
     119                 :       }
     120        80314354 :     else if (flags & nsSubstring::F_OWNED)
     121                 :       {
     122          238003 :         nsMemory::Free(data);
     123          238003 :         STRING_STAT_INCREMENT(AdoptFree);
     124                 : #ifdef NS_BUILD_REFCNT_LOGGING
     125                 :         // Treat this as destruction of a "StringAdopt" object for leak
     126                 :         // tracking purposes.
     127          238003 :         NS_LogDtor(data, "StringAdopt", 1);
     128                 : #endif // NS_BUILD_REFCNT_LOGGING
     129                 :       }
     130                 :     // otherwise, nothing to do.
     131        96041603 :   }
     132                 : 
     133                 : // ---------------------------------------------------------------------------
     134                 : 
     135                 : // XXX or we could make nsStringBuffer be a friend of nsTAString
     136                 : 
     137                 : class nsAStringAccessor : public nsAString
     138                 :   {
     139                 :     private:
     140                 :       nsAStringAccessor(); // NOT IMPLEMENTED
     141                 : 
     142                 :     public:
     143          113385 :       char_type  *data() const   { return mData; }
     144                 :       size_type   length() const { return mLength; }
     145         4649360 :       PRUint32    flags() const  { return mFlags; }
     146                 : 
     147         3257140 :       void set(char_type *data, size_type len, PRUint32 flags)
     148                 :         {
     149         3257140 :           ReleaseData(mData, mFlags);
     150         3257140 :           mData = data;
     151         3257140 :           mLength = len;
     152         3257140 :           mFlags = flags;
     153         3257140 :         }
     154                 :   };
     155                 : 
     156                 : class nsACStringAccessor : public nsACString
     157                 :   {
     158                 :     private:
     159                 :       nsACStringAccessor(); // NOT IMPLEMENTED
     160                 : 
     161                 :     public:
     162               0 :       char_type  *data() const   { return mData; }
     163                 :       size_type   length() const { return mLength; }
     164               0 :       PRUint32    flags() const  { return mFlags; }
     165                 : 
     166               0 :       void set(char_type *data, size_type len, PRUint32 flags)
     167                 :         {
     168               0 :           ReleaseData(mData, mFlags);
     169               0 :           mData = data;
     170               0 :           mLength = len;
     171               0 :           mFlags = flags;
     172               0 :         }
     173                 :   };
     174                 : 
     175                 : // ---------------------------------------------------------------------------
     176                 : 
     177                 : void
     178        11588833 : nsStringBuffer::AddRef()
     179                 :   {
     180        11588833 :     PR_ATOMIC_INCREMENT(&mRefCount);
     181        11588833 :     STRING_STAT_INCREMENT(Share);
     182        11588833 :     NS_LOG_ADDREF(this, mRefCount, "nsStringBuffer", sizeof(*this));
     183        11588833 :   }
     184                 : 
     185                 : void
     186        19097888 : nsStringBuffer::Release()
     187                 :   {
     188        19097888 :     PRInt32 count = PR_ATOMIC_DECREMENT(&mRefCount);
     189        19097888 :     NS_LOG_RELEASE(this, count, "nsStringBuffer");
     190        19097941 :     if (count == 0)
     191                 :       {
     192         7510498 :         STRING_STAT_INCREMENT(Free);
     193         7510498 :         free(this); // we were allocated with |malloc|
     194                 :       }
     195        19097941 :   }
     196                 : 
     197                 :   /**
     198                 :    * Alloc returns a pointer to a new string header with set capacity.
     199                 :    */
     200                 : nsStringBuffer*
     201         7513918 : nsStringBuffer::Alloc(size_t size)
     202                 :   {
     203         7513918 :     NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
     204         7513922 :     NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(PRUint32(-1)) &&
     205                 :                  sizeof(nsStringBuffer) + size > size,
     206                 :                  "mStorageSize will truncate");
     207                 : 
     208                 :     nsStringBuffer *hdr =
     209         7513922 :         (nsStringBuffer *) malloc(sizeof(nsStringBuffer) + size);
     210         7514145 :     if (hdr)
     211                 :       {
     212         7514143 :         STRING_STAT_INCREMENT(Alloc);
     213                 : 
     214         7514143 :         hdr->mRefCount = 1;
     215         7514143 :         hdr->mStorageSize = size;
     216         7514143 :         NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
     217                 :       }
     218         7514152 :     return hdr;
     219                 :   }
     220                 : 
     221                 : nsStringBuffer*
     222          557702 : nsStringBuffer::Realloc(nsStringBuffer* hdr, size_t size)
     223                 :   {
     224          557702 :     STRING_STAT_INCREMENT(Realloc);
     225                 : 
     226          557702 :     NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
     227          557702 :     NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(PRUint32(-1)) &&
     228                 :                  sizeof(nsStringBuffer) + size > size,
     229                 :                  "mStorageSize will truncate");
     230                 : 
     231                 :     // no point in trying to save ourselves if we hit this assertion
     232          557702 :     NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
     233                 : 
     234                 :     // Treat this as a release and addref for refcounting purposes, since we
     235                 :     // just asserted that the refcount is 1.  If we don't do that, refcount
     236                 :     // logging will claim we've leaked all sorts of stuff.
     237          557702 :     NS_LOG_RELEASE(hdr, 0, "nsStringBuffer");
     238                 :     
     239          557702 :     hdr = (nsStringBuffer*) realloc(hdr, sizeof(nsStringBuffer) + size);
     240          557702 :     if (hdr) {
     241          557702 :       NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
     242          557702 :       hdr->mStorageSize = size;
     243                 :     }
     244                 : 
     245          557702 :     return hdr;
     246                 :   }
     247                 : 
     248                 : nsStringBuffer*
     249         1392220 : nsStringBuffer::FromString(const nsAString& str)
     250                 :   {
     251                 :     const nsAStringAccessor* accessor =
     252         1392220 :         static_cast<const nsAStringAccessor*>(&str);
     253                 : 
     254         1392220 :     if (!(accessor->flags() & nsSubstring::F_SHARED))
     255         1278835 :       return nsnull;
     256                 : 
     257          113385 :     return FromData(accessor->data());
     258                 :   }
     259                 : 
     260                 : nsStringBuffer*
     261               0 : nsStringBuffer::FromString(const nsACString& str)
     262                 :   {
     263                 :     const nsACStringAccessor* accessor =
     264               0 :         static_cast<const nsACStringAccessor*>(&str);
     265                 : 
     266               0 :     if (!(accessor->flags() & nsCSubstring::F_SHARED))
     267               0 :       return nsnull;
     268                 : 
     269               0 :     return FromData(accessor->data());
     270                 :   }
     271                 : 
     272                 : void
     273         3257140 : nsStringBuffer::ToString(PRUint32 len, nsAString &str,
     274                 :                          bool aMoveOwnership)
     275                 :   {
     276         3257140 :     PRUnichar* data = static_cast<PRUnichar*>(Data());
     277                 : 
     278         3257140 :     nsAStringAccessor* accessor = static_cast<nsAStringAccessor*>(&str);
     279         3257140 :     NS_ASSERTION(data[len] == PRUnichar(0), "data should be null terminated");
     280                 : 
     281                 :     // preserve class flags
     282         3257140 :     PRUint32 flags = accessor->flags();
     283         3257140 :     flags = (flags & 0xFFFF0000) | nsSubstring::F_SHARED | nsSubstring::F_TERMINATED;
     284                 : 
     285         3257140 :     if (!aMoveOwnership) {
     286         3256676 :       AddRef();
     287                 :     }
     288         3257140 :     accessor->set(data, len, flags);
     289         3257140 :   }
     290                 : 
     291                 : void
     292               0 : nsStringBuffer::ToString(PRUint32 len, nsACString &str,
     293                 :                          bool aMoveOwnership)
     294                 :   {
     295               0 :     char* data = static_cast<char*>(Data());
     296                 : 
     297               0 :     nsACStringAccessor* accessor = static_cast<nsACStringAccessor*>(&str);
     298               0 :     NS_ASSERTION(data[len] == char(0), "data should be null terminated");
     299                 : 
     300                 :     // preserve class flags
     301               0 :     PRUint32 flags = accessor->flags();
     302               0 :     flags = (flags & 0xFFFF0000) | nsCSubstring::F_SHARED | nsCSubstring::F_TERMINATED;
     303                 : 
     304               0 :     if (!aMoveOwnership) {
     305               0 :       AddRef();
     306                 :     }
     307               0 :     accessor->set(data, len, flags);
     308               0 :   }
     309                 : 
     310                 : size_t
     311               0 : nsStringBuffer::SizeOfIncludingThisMustBeUnshared(nsMallocSizeOfFun aMallocSizeOf) const
     312                 :   {
     313               0 :     NS_ASSERTION(!IsReadonly(),
     314                 :                  "shared StringBuffer in SizeOfIncludingThisMustBeUnshared");
     315               0 :     return aMallocSizeOf(this);
     316                 :   }
     317                 : 
     318                 : size_t
     319               0 : nsStringBuffer::SizeOfIncludingThisIfUnshared(nsMallocSizeOfFun aMallocSizeOf) const
     320                 :   {
     321               0 :     if (!IsReadonly())
     322                 :       {
     323               0 :         return SizeOfIncludingThisMustBeUnshared(aMallocSizeOf);
     324                 :       }
     325               0 :     return 0;
     326                 :   }
     327                 : 
     328                 : // ---------------------------------------------------------------------------
     329                 : 
     330                 : 
     331                 :   // define nsSubstring
     332                 : #include "string-template-def-unichar.h"
     333                 : #include "nsTSubstring.cpp"
     334                 : #include "string-template-undef.h"
     335                 : 
     336                 :   // define nsCSubstring
     337                 : #include "string-template-def-char.h"
     338                 : #include "nsTSubstring.cpp"
     339                 : #include "string-template-undef.h"
     340                 : 
     341                 : // Check that internal and external strings have the same size.
     342                 : // See https://bugzilla.mozilla.org/show_bug.cgi?id=430581
     343                 : 
     344                 : #include "prlog.h"
     345                 : #include "nsXPCOMStrings.h"
     346                 : 
     347            4392 : PR_STATIC_ASSERT(sizeof(nsStringContainer_base) == sizeof(nsSubstring));

Generated by: LCOV version 1.7