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
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/
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
16 * The Original Code is Mozilla.
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.
23 * Darin Fisher <darin@meer.net>
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.
37 * ***** END LICENSE BLOCK ***** */
40 #define ENABLE_STRING_STATS
43 #ifdef ENABLE_STRING_STATS
48 #include "nsSubstring.h"
50 #include "nsStringBuffer.h"
51 #include "nsDependentString.h"
55 // ---------------------------------------------------------------------------
57 static const PRUnichar gNullChar
= 0;
59 const char* nsCharTraits
<char> ::sEmptyBuffer
= (const char*) &gNullChar
;
60 const PRUnichar
* nsCharTraits
<PRUnichar
>::sEmptyBuffer
= &gNullChar
;
62 // ---------------------------------------------------------------------------
64 #ifdef ENABLE_STRING_STATS
69 : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {}
73 // this is a hack to suppress duplicate string stats printing
74 // in seamonkey as a result of the string code being linked
75 // into seamonkey and libxpcom! :-(
76 if (!mAllocCount
&& !mAdoptCount
)
79 printf("nsStringStats\n");
80 printf(" => mAllocCount: % 10d\n", mAllocCount
);
81 printf(" => mReallocCount: % 10d\n", mReallocCount
);
82 printf(" => mFreeCount: % 10d", mFreeCount
);
83 if (mAllocCount
> mFreeCount
)
84 printf(" -- LEAKED %d !!!\n", mAllocCount
- mFreeCount
);
87 printf(" => mShareCount: % 10d\n", mShareCount
);
88 printf(" => mAdoptCount: % 10d\n", mAdoptCount
);
89 printf(" => mAdoptFreeCount: % 10d", mAdoptFreeCount
);
90 if (mAdoptCount
> mAdoptFreeCount
)
91 printf(" -- LEAKED %d !!!\n", mAdoptCount
- mAdoptFreeCount
);
97 PRInt32 mReallocCount
;
101 PRInt32 mAdoptFreeCount
;
103 static nsStringStats gStringStats
;
104 #define STRING_STAT_INCREMENT(_s) PR_AtomicIncrement(&gStringStats.m ## _s ## Count)
106 #define STRING_STAT_INCREMENT(_s)
109 // ---------------------------------------------------------------------------
112 ReleaseData( void* data
, PRUint32 flags
)
114 if (flags
& nsSubstring::F_SHARED
)
116 nsStringBuffer::FromData(data
)->Release();
118 else if (flags
& nsSubstring::F_OWNED
)
120 nsMemory::Free(data
);
121 STRING_STAT_INCREMENT(AdoptFree
);
122 #ifdef NS_BUILD_REFCNT_LOGGING
123 // Treat this as destruction of a "StringAdopt" object for leak
124 // tracking purposes.
125 NS_LogDtor(data
, "StringAdopt", 1);
126 #endif // NS_BUILD_REFCNT_LOGGING
128 // otherwise, nothing to do.
131 // ---------------------------------------------------------------------------
133 // XXX or we could make nsStringBuffer be a friend of nsTAString
135 class nsAStringAccessor
: public nsAString
138 nsAStringAccessor(); // NOT IMPLEMENTED
141 char_type
*data() const { return mData
; }
142 size_type
length() const { return mLength
; }
143 PRUint32
flags() const { return mFlags
; }
145 void set(char_type
*data
, size_type len
, PRUint32 flags
)
147 ReleaseData(mData
, mFlags
);
154 class nsACStringAccessor
: public nsACString
157 nsACStringAccessor(); // NOT IMPLEMENTED
160 char_type
*data() const { return mData
; }
161 size_type
length() const { return mLength
; }
162 PRUint32
flags() const { return mFlags
; }
164 void set(char_type
*data
, size_type len
, PRUint32 flags
)
166 ReleaseData(mData
, mFlags
);
173 // ---------------------------------------------------------------------------
176 nsStringBuffer::AddRef()
178 PR_AtomicIncrement(&mRefCount
);
179 STRING_STAT_INCREMENT(Share
);
180 NS_LOG_ADDREF(this, mRefCount
, "nsStringBuffer", sizeof(*this));
184 nsStringBuffer::Release()
186 PRInt32 count
= PR_AtomicDecrement(&mRefCount
);
187 NS_LOG_RELEASE(this, count
, "nsStringBuffer");
190 STRING_STAT_INCREMENT(Free
);
191 free(this); // we were allocated with |malloc|
196 * Alloc returns a pointer to a new string header with set capacity.
199 nsStringBuffer::Alloc(size_t size
)
201 NS_ASSERTION(size
!= 0, "zero capacity allocation not allowed");
203 nsStringBuffer
*hdr
=
204 (nsStringBuffer
*) malloc(sizeof(nsStringBuffer
) + size
);
207 STRING_STAT_INCREMENT(Alloc
);
210 hdr
->mStorageSize
= size
;
211 NS_LOG_ADDREF(hdr
, 1, "nsStringBuffer", sizeof(*hdr
));
217 nsStringBuffer::Realloc(nsStringBuffer
* hdr
, size_t size
)
219 STRING_STAT_INCREMENT(Realloc
);
221 NS_ASSERTION(size
!= 0, "zero capacity allocation not allowed");
223 // no point in trying to save ourselves if we hit this assertion
224 NS_ASSERTION(!hdr
->IsReadonly(), "|Realloc| attempted on readonly string");
226 // Treat this as a release and addref for refcounting purposes, since we
227 // just asserted that the refcound is 1. If we don't do that, refcount
228 // logging will claim we've leaked all sorts of stuff.
229 NS_LOG_RELEASE(hdr
, 0, "nsStringBuffer");
231 hdr
= (nsStringBuffer
*) realloc(hdr
, sizeof(nsStringBuffer
) + size
);
233 NS_LOG_ADDREF(hdr
, 1, "nsStringBuffer", sizeof(*hdr
));
234 hdr
->mStorageSize
= size
;
241 nsStringBuffer::FromString(const nsAString
& str
)
243 const nsAStringAccessor
* accessor
=
244 static_cast<const nsAStringAccessor
*>(&str
);
246 if (!(accessor
->flags() & nsSubstring::F_SHARED
))
249 return FromData(accessor
->data());
253 nsStringBuffer::FromString(const nsACString
& str
)
255 const nsACStringAccessor
* accessor
=
256 static_cast<const nsACStringAccessor
*>(&str
);
258 if (!(accessor
->flags() & nsCSubstring::F_SHARED
))
261 return FromData(accessor
->data());
265 nsStringBuffer::ToString(PRUint32 len
, nsAString
&str
)
267 PRUnichar
* data
= static_cast<PRUnichar
*>(Data());
269 nsAStringAccessor
* accessor
= static_cast<nsAStringAccessor
*>(&str
);
270 NS_ASSERTION(data
[len
] == PRUnichar(0), "data should be null terminated");
272 // preserve class flags
273 PRUint32 flags
= accessor
->flags();
274 flags
= (flags
& 0xFFFF0000) | nsSubstring::F_SHARED
| nsSubstring::F_TERMINATED
;
277 accessor
->set(data
, len
, flags
);
281 nsStringBuffer::ToString(PRUint32 len
, nsACString
&str
)
283 char* data
= static_cast<char*>(Data());
285 nsACStringAccessor
* accessor
= static_cast<nsACStringAccessor
*>(&str
);
286 NS_ASSERTION(data
[len
] == char(0), "data should be null terminated");
288 // preserve class flags
289 PRUint32 flags
= accessor
->flags();
290 flags
= (flags
& 0xFFFF0000) | nsCSubstring::F_SHARED
| nsCSubstring::F_TERMINATED
;
293 accessor
->set(data
, len
, flags
);
296 // ---------------------------------------------------------------------------
299 // define nsSubstring
300 #include "string-template-def-unichar.h"
301 #include "nsTSubstring.cpp"
302 #include "string-template-undef.h"
304 // define nsCSubstring
305 #include "string-template-def-char.h"
306 #include "nsTSubstring.cpp"
307 #include "string-template-undef.h"
309 // Check that internal and external strings have the same size.
310 // See https://bugzilla.mozilla.org/show_bug.cgi?id=430581
313 #include "nsXPCOMStrings.h"
315 PR_STATIC_ASSERT(sizeof(nsStringContainer_base
) == sizeof(nsSubstring
));