Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
258dc9fead This commit was manufactured by cvs2svn to create branch 'src'.
git-svn-id: svn://10.0.0.236/branches/src@33658 18797224-902f-48f8-a5cc-f745e15eee43
1999-06-03 23:10:01 +00:00
280 changed files with 18627 additions and 119276 deletions

View File

@@ -1,15 +0,0 @@
# List of modules to check out. Format is
# module, (tag), (date)
# where tag and date are optional (non-trailing commas are required)
#
# Examples:
# mozilla/nsprpub, NSPRPUB_CLIENT_BRANCH
# mozilla/gc, , 10/25/2000 12:00:00
#
mozilla/nsprpub, NSPRPUB_CLIENT_BRANCH
mozilla/security/nss, NSS_CLIENT_TAG
mozilla/security/psm,
DirectorySDKSourceC, LDAPCSDK_40_BRANCH
mozilla/lib/mac/Instrumentation
SeaMonkeyAll STRING_081_BRANCH

File diff suppressed because it is too large Load Diff

View File

@@ -1,792 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsHTMLContentSerializer.h"
#include "nsIDOMElement.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "nsParserCIID.h"
#include "nsIServiceManager.h"
#include "nsIDocumentEncoder.h"
#include "nsLayoutAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsEscape.h"
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
#define kIndentStr NS_LITERAL_STRING(" ")
#define kMozStr "_moz"
#define kLessThan NS_LITERAL_STRING("<")
#define kGreaterThan NS_LITERAL_STRING(">")
#define kEndTag NS_LITERAL_STRING("</")
static const PRInt32 kLongLineLen = 128;
nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
{
nsHTMLContentSerializer* it = new nsHTMLContentSerializer();
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(NS_GET_IID(nsIContentSerializer), (void**)aSerializer);
}
nsHTMLContentSerializer::nsHTMLContentSerializer()
{
mColPos = 0;
mIndent = 0;
mInBody = PR_FALSE;
mInCDATA = PR_FALSE;
}
nsHTMLContentSerializer::~nsHTMLContentSerializer()
{
}
nsresult
nsHTMLContentSerializer::GetParserService(nsIParserService** aParserService)
{
if (!mParserService) {
nsresult rv;
mParserService = do_GetService(kParserServiceCID, &rv);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
CallQueryInterface(mParserService.get(), aParserService);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
nsIAtom* aCharSet)
{
mFlags = aFlags;
if (!aWrapColumn) {
mMaxColumn = 72;
}
else {
mMaxColumn = aWrapColumn;
}
mDoFormat = (mFlags & nsIDocumentEncoder::OutputFormatted) ? PR_TRUE
: PR_FALSE;
mBodyOnly = (mFlags & nsIDocumentEncoder::OutputBodyOnly) ? PR_TRUE
: PR_FALSE;
// Set the line break character:
if ((mFlags & nsIDocumentEncoder::OutputCRLineBreak)
&& (mFlags & nsIDocumentEncoder::OutputLFLineBreak)) { // Windows/mail
mLineBreak.AssignWithConversion("\r\n");
}
else if (mFlags & nsIDocumentEncoder::OutputCRLineBreak) { // Mac
mLineBreak.AssignWithConversion("\r");
}
else if (mFlags & nsIDocumentEncoder::OutputLFLineBreak) { // Unix/DOM
mLineBreak.AssignWithConversion("\n");
}
else {
mLineBreak.AssignWithConversion(NS_LINEBREAK); // Platform/default
}
mPreLevel = 0;
mIsLatin1 = PR_FALSE;
if (aCharSet) {
const PRUnichar *charset;
aCharSet->GetUnicode(&charset);
if (NS_LITERAL_STRING("ISO-8859-1").Equals(charset)) {
mIsLatin1 = PR_TRUE;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLContentSerializer::AppendText(nsIDOMText* aText,
PRInt32 aStartOffset,
PRInt32 aEndOffset,
nsAWritableString& aStr)
{
NS_ENSURE_ARG(aText);
nsAutoString data;
nsresult rv;
rv = AppendTextData((nsIDOMNode*)aText, aStartOffset,
aEndOffset, data, PR_TRUE, PR_FALSE);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
PRInt32 lastNewlineOffset = kNotFound;
PRBool hasLongLines = HasLongLines(data, lastNewlineOffset);
if (mPreLevel || (!mDoFormat && !hasLongLines) ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
AppendToString(data, aStr);
if (lastNewlineOffset != kNotFound) {
mColPos = data.Length() - lastNewlineOffset;
}
}
else {
AppendToStringWrapped(data, aStr, PR_FALSE);
}
return NS_OK;
}
void
nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
nsIAtom* aTagName,
nsAWritableString& aStr)
{
nsresult rv;
PRInt32 index, count;
nsAutoString nameStr, valueStr;
PRInt32 namespaceID;
nsCOMPtr<nsIAtom> attrName, attrPrefix;
aContent->GetAttributeCount(count);
for (index = 0; index < count; index++) {
aContent->GetAttributeNameAt(index,
namespaceID,
*getter_AddRefs(attrName),
*getter_AddRefs(attrPrefix));
// Filter out any attribute starting with _moz
nsXPIDLString sharedName;
attrName->GetUnicode(getter_Shares(sharedName));
if (nsCRT::strncmp(sharedName,
NS_ConvertASCIItoUCS2(kMozStr),
sizeof(kMozStr)-1) == 0) {
continue;
}
aContent->GetAttribute(namespaceID, attrName, valueStr);
//
// Filter out special case of <br type="_moz"> or <br _moz*>,
// used by the editor. Bug 16988. Yuck.
//
if ((aTagName == nsHTMLAtoms::br) &&
(attrName.get() == nsHTMLAtoms::type) &&
(valueStr.EqualsWithConversion(kMozStr, PR_FALSE, sizeof(kMozStr)-1))) {
continue;
}
// Make all links absolute when converting only the selection:
if ((mFlags & nsIDocumentEncoder::OutputAbsoluteLinks) &&
((attrName.get() == nsHTMLAtoms::href) ||
(attrName.get() == nsHTMLAtoms::src))) {
// Would be nice to handle OBJECT and APPLET tags,
// but that gets more complicated since we have to
// search the tag list for CODEBASE as well.
// For now, just leave them relative.
nsCOMPtr<nsIDocument> document;
aContent->GetDocument(*getter_AddRefs(document));
if (document) {
nsCOMPtr<nsIURI> uri = dont_AddRef(document->GetDocumentURL());
if (uri) {
nsAutoString absURI;
rv = NS_MakeAbsoluteURI(absURI, valueStr, uri);
if (NS_SUCCEEDED(rv)) {
valueStr = absURI;
}
}
}
}
attrName->ToString(nameStr);
SerializeAttr(nsAutoString(), nameStr, valueStr, aStr);
}
}
NS_IMETHODIMP
nsHTMLContentSerializer::AppendElementStart(nsIDOMElement *aElement,
nsAWritableString& aStr)
{
NS_ENSURE_ARG(aElement);
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (!content) return NS_ERROR_FAILURE;
// The _moz_dirty attribute is emitted by the editor to
// indicate that this element should be pretty printed
// even if we're not in pretty printing mode
PRBool hasDirtyAttr = HasDirtyAttr(content);
nsCOMPtr<nsIAtom> name;
content->GetTag(*getter_AddRefs(name));
if (name.get() == nsHTMLAtoms::body) {
mInBody = PR_TRUE;
}
if (LineBreakBeforeOpen(name, hasDirtyAttr)) {
AppendToString(mLineBreak, aStr);
mColPos = 0;
}
StartIndentation(name, hasDirtyAttr, aStr);
if ((name.get() == nsHTMLAtoms::pre) ||
(name.get() == nsHTMLAtoms::script) ||
(name.get() == nsHTMLAtoms::style)) {
mPreLevel++;
}
AppendToString(kLessThan, aStr);
nsXPIDLString sharedName;
name->GetUnicode(getter_Shares(sharedName));
AppendToString(sharedName, -1, aStr);
SerializeAttributes(content, name, aStr);
AppendToString(kGreaterThan, aStr);
if (LineBreakAfterOpen(name, hasDirtyAttr)) {
AppendToString(mLineBreak, aStr);
mColPos = 0;
}
if ((name.get() == nsHTMLAtoms::script) ||
(name.get() == nsHTMLAtoms::style) ||
(name.get() == nsHTMLAtoms::noscript)) {
mInCDATA = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLContentSerializer::AppendElementEnd(nsIDOMElement *aElement,
nsAWritableString& aStr)
{
NS_ENSURE_ARG(aElement);
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (!content) return NS_ERROR_FAILURE;
PRBool hasDirtyAttr = HasDirtyAttr(content);
nsCOMPtr<nsIAtom> name;
content->GetTag(*getter_AddRefs(name));
if ((name.get() == nsHTMLAtoms::pre) ||
(name.get() == nsHTMLAtoms::script) ||
(name.get() == nsHTMLAtoms::style)) {
mPreLevel--;
}
nsXPIDLString sharedName;
name->GetUnicode(getter_Shares(sharedName));
nsCOMPtr<nsIParserService> parserService;
GetParserService(getter_AddRefs(parserService));
if (parserService && (name.get() != nsHTMLAtoms::style)) {
nsAutoString nameStr(sharedName);
PRBool isContainer;
PRInt32 id;
parserService->HTMLStringTagToId(nameStr, &id);
parserService->IsContainer(id, isContainer);
if (!isContainer) return NS_OK;
}
if (LineBreakBeforeClose(name, hasDirtyAttr)) {
AppendToString(mLineBreak, aStr);
mColPos = 0;
}
EndIndentation(name, hasDirtyAttr, aStr);
AppendToString(kEndTag, aStr);
AppendToString(sharedName, -1, aStr);
AppendToString(kGreaterThan, aStr);
if (LineBreakAfterClose(name, hasDirtyAttr)) {
AppendToString(mLineBreak, aStr);
mColPos = 0;
}
mInCDATA = PR_FALSE;
return NS_OK;
}
void
nsHTMLContentSerializer::AppendToString(const PRUnichar* aStr,
PRInt32 aLength,
nsAWritableString& aOutputStr)
{
if (mBodyOnly && !mInBody) {
return;
}
PRInt32 length = (aLength == -1) ? nsCRT::strlen(aStr) : aLength;
mColPos += length;
aOutputStr.Append(aStr, length);
}
void
nsHTMLContentSerializer::AppendToString(const PRUnichar aChar,
nsAWritableString& aOutputStr)
{
if (mBodyOnly && !mInBody) {
return;
}
mColPos += 1;
aOutputStr.Append(aChar);
}
void
nsHTMLContentSerializer::AppendToStringWrapped(const nsAReadableString& aStr,
nsAWritableString& aOutputStr,
PRBool aTranslateEntities)
{
PRInt32 length = aStr.Length();
nsAutoString line;
PRBool done = PR_FALSE;
PRInt32 indx = 0;
PRInt32 strOffset = 0;
PRInt32 lineLength, oldLineEnd;
// Make sure we haven't gone too far already
if (mColPos > mMaxColumn) {
AppendToString(mLineBreak, aOutputStr);
mColPos = 0;
}
// Find the end of the first old line
oldLineEnd = aStr.FindChar(PRUnichar('\n'), 0);
while ((!done) && (strOffset < length)) {
// This is how much is needed to fill up the new line
PRInt32 leftInLine = mMaxColumn - mColPos;
// This is the last position in the current old line
PRInt32 oldLineLimit;
if (oldLineEnd == kNotFound) {
oldLineLimit = length;
}
else {
oldLineLimit = oldLineEnd;
}
PRBool addLineBreak = PR_FALSE;
// if we can fill up the new line with less than what's
// in the current old line...
if ((strOffset + leftInLine) < oldLineLimit) {
addLineBreak = PR_TRUE;
// Look for the next word end to break
indx = aStr.FindChar(PRUnichar(' '), strOffset + leftInLine);
// If it's after the end of the current line, then break at
// the current line
if ((indx == kNotFound) ||
((oldLineEnd != kNotFound) && (oldLineEnd < indx))) {
indx = oldLineEnd;
}
}
else {
indx = oldLineEnd;
}
// if there was no place to break, then just add the entire string
if (indx == kNotFound) {
if (strOffset == 0) {
AppendToString(aStr, aOutputStr, aTranslateEntities);
}
else {
lineLength = length - strOffset;
aStr.Right(line, lineLength);
AppendToString(line, aOutputStr, aTranslateEntities);
}
done = PR_TRUE;
}
else {
// Add the part of the current old line that's part of the
// new line
lineLength = indx - strOffset;
aStr.Mid(line, strOffset, lineLength);
AppendToString(line, aOutputStr, aTranslateEntities);
// if we've reached the end of an old line, don't add the
// old line break and find the end of the next old line.
if (indx == oldLineEnd) {
oldLineEnd = aStr.FindChar(PRUnichar('\n'), indx+1);
AppendToString(NS_LITERAL_STRING(" "), aOutputStr);
}
if (addLineBreak) {
AppendToString(mLineBreak, aOutputStr);
mColPos = 0;
}
strOffset = indx+1;
}
}
}
static PRUint16 kGTVal = 62;
static const char* kEntities[] = {
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "amp", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"lt", "", "gt"
};
static const char* kAttrEntities[] = {
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "quot", "", "", "", "amp", "apos",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"lt", "", "gt"
};
void
nsHTMLContentSerializer::AppendToString(const nsAReadableString& aStr,
nsAWritableString& aOutputStr,
PRBool aTranslateEntities,
PRBool aIncrColumn)
{
if (mBodyOnly && !mInBody) {
return;
}
if (aIncrColumn) {
mColPos += aStr.Length();
}
if (aTranslateEntities && !mInCDATA) {
if (mFlags & nsIDocumentEncoder::OutputEncodeEntities) {
nsCOMPtr<nsIParserService> parserService;
GetParserService(getter_AddRefs(parserService));
if (!parserService) {
NS_ERROR("Can't get parser service");
return;
}
nsReadingIterator<PRUnichar> done_reading;
aStr.EndReading(done_reading);
// for each chunk of |aString|...
PRUint32 advanceLength = 0;
nsReadingIterator<PRUnichar> iter;
const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
for (aStr.BeginReading(iter);
iter != done_reading;
iter.advance(PRInt32(advanceLength))) {
PRUint32 fragmentLength = iter.size_forward();
const PRUnichar* c = iter.get();
const PRUnichar* fragmentStart = c;
const PRUnichar* fragmentEnd = c + fragmentLength;
const char* entityText = nsnull;
nsCAutoString entityReplacement;
advanceLength = 0;
// for each character in this chunk, check if it
// needs to be replaced
for (; c < fragmentEnd; c++, advanceLength++) {
PRUnichar val = *c;
if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
entityText = entityTable[val];
break;
} else if (mIsLatin1 && val > 127 && val < 256) {
parserService->HTMLConvertUnicodeToEntity(val, entityReplacement);
if (entityReplacement.Length() > 0) {
entityText = entityReplacement.get();
break;
}
}
}
aOutputStr.Append(fragmentStart, advanceLength);
if (entityText) {
aOutputStr.Append(PRUnichar('&'));
aOutputStr.Append(NS_ConvertASCIItoUCS2(entityText));
aOutputStr.Append(PRUnichar(';'));
advanceLength++;
}
}
} else {
nsXMLContentSerializer::AppendToString(aStr, aOutputStr, aTranslateEntities, aIncrColumn);
}
return;
}
aOutputStr.Append(aStr);
}
PRBool
nsHTMLContentSerializer::HasDirtyAttr(nsIContent* aContent)
{
nsAutoString val;
if (NS_CONTENT_ATTR_NOT_THERE != aContent->GetAttribute(kNameSpaceID_None,
nsLayoutAtoms::mozdirty,
val)) {
return PR_TRUE;
}
else {
return PR_FALSE;
}
}
PRBool
nsHTMLContentSerializer::LineBreakBeforeOpen(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
if (aName == nsHTMLAtoms::title ||
aName == nsHTMLAtoms::meta ||
aName == nsHTMLAtoms::link ||
aName == nsHTMLAtoms::style ||
aName == nsHTMLAtoms::script ||
aName == nsHTMLAtoms::html) {
return PR_TRUE;
}
else {
nsCOMPtr<nsIParserService> parserService;
GetParserService(getter_AddRefs(parserService));
if (parserService) {
nsAutoString str;
aName->ToString(str);
PRBool res;
PRInt32 id;
parserService->HTMLStringTagToId(str, &id);
parserService->IsBlock(id, res);
return res;
}
}
return PR_FALSE;
}
PRBool
nsHTMLContentSerializer::LineBreakAfterOpen(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
if ((aName == nsHTMLAtoms::html) ||
(aName == nsHTMLAtoms::head) ||
(aName == nsHTMLAtoms::body) ||
(aName == nsHTMLAtoms::ul) ||
(aName == nsHTMLAtoms::ol) ||
(aName == nsHTMLAtoms::dl) ||
(aName == nsHTMLAtoms::table) ||
(aName == nsHTMLAtoms::tbody) ||
(aName == nsHTMLAtoms::tr) ||
(aName == nsHTMLAtoms::br) ||
(aName == nsHTMLAtoms::meta) ||
(aName == nsHTMLAtoms::link) ||
(aName == nsHTMLAtoms::script) ||
(aName == nsHTMLAtoms::style)) {
return PR_TRUE;
}
return PR_FALSE;
}
PRBool
nsHTMLContentSerializer::LineBreakBeforeClose(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
if ((aName == nsHTMLAtoms::html) ||
(aName == nsHTMLAtoms::head) ||
(aName == nsHTMLAtoms::body) ||
(aName == nsHTMLAtoms::ul) ||
(aName == nsHTMLAtoms::ol) ||
(aName == nsHTMLAtoms::dl) ||
(aName == nsHTMLAtoms::table) ||
(aName == nsHTMLAtoms::tbody)) {
return PR_TRUE;
}
return PR_FALSE;
}
PRBool
nsHTMLContentSerializer::LineBreakAfterClose(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
if ((aName == nsHTMLAtoms::html) ||
(aName == nsHTMLAtoms::head) ||
(aName == nsHTMLAtoms::body) ||
(aName == nsHTMLAtoms::tr) ||
(aName == nsHTMLAtoms::th) ||
(aName == nsHTMLAtoms::td) ||
(aName == nsHTMLAtoms::pre) ||
(aName == nsHTMLAtoms::title) ||
(aName == nsHTMLAtoms::li) ||
(aName == nsHTMLAtoms::dt) ||
(aName == nsHTMLAtoms::dd) ||
(aName == nsHTMLAtoms::blockquote) ||
(aName == nsHTMLAtoms::p) ||
(aName == nsHTMLAtoms::div)) {
return PR_TRUE;
}
else {
nsCOMPtr<nsIParserService> parserService;
GetParserService(getter_AddRefs(parserService));
if (parserService) {
nsAutoString str;
aName->ToString(str);
PRBool res;
PRInt32 id;
parserService->HTMLStringTagToId(str, &id);
parserService->IsBlock(id, res);
return res;
}
}
return PR_FALSE;
}
void
nsHTMLContentSerializer::StartIndentation(nsIAtom* aName,
PRBool aHasDirtyAttr,
nsAWritableString& aStr)
{
if ((mDoFormat || aHasDirtyAttr) && !mPreLevel && !mColPos) {
for (PRInt32 i = mIndent; --i >= 0; ) {
AppendToString(kIndentStr.get(), -1,
aStr);
}
}
if ((aName == nsHTMLAtoms::head) ||
(aName == nsHTMLAtoms::table) ||
(aName == nsHTMLAtoms::tr) ||
(aName == nsHTMLAtoms::ul) ||
(aName == nsHTMLAtoms::ol) ||
(aName == nsHTMLAtoms::tbody) ||
(aName == nsHTMLAtoms::form) ||
(aName == nsHTMLAtoms::frameset) ||
(aName == nsHTMLAtoms::blockquote) ||
(aName == nsHTMLAtoms::li) ||
(aName == nsHTMLAtoms::dt) ||
(aName == nsHTMLAtoms::dd)) {
mIndent++;
}
}
void
nsHTMLContentSerializer::EndIndentation(nsIAtom* aName,
PRBool aHasDirtyAttr,
nsAWritableString& aStr)
{
if ((aName == nsHTMLAtoms::head) ||
(aName == nsHTMLAtoms::table) ||
(aName == nsHTMLAtoms::tr) ||
(aName == nsHTMLAtoms::ul) ||
(aName == nsHTMLAtoms::ol) ||
(aName == nsHTMLAtoms::li) ||
(aName == nsHTMLAtoms::tbody) ||
(aName == nsHTMLAtoms::form) ||
(aName == nsHTMLAtoms::frameset)) {
mIndent--;
}
if ((mDoFormat || aHasDirtyAttr) && !mPreLevel && !mColPos) {
for (PRInt32 i = mIndent; --i >= 0; ) {
AppendToString(kIndentStr.get(), -1,
aStr);
}
}
}
// See if the string has any lines longer than longLineLen:
// if so, we presume formatting is wonky (e.g. the node has been edited)
// and we'd better rewrap the whole text node.
PRBool
nsHTMLContentSerializer::HasLongLines(const nsString& text, PRInt32& aLastNewlineOffset)
{
PRUint32 start=0;
PRUint32 theLen=text.Length();
PRBool rv = PR_FALSE;
aLastNewlineOffset = kNotFound;
for (start = 0; start < theLen; )
{
PRInt32 eol = text.FindChar('\n', PR_FALSE, start);
if (eol < 0) {
eol = text.Length();
}
else {
aLastNewlineOffset = eol;
}
if (PRInt32(eol - start) > kLongLineLen)
rv = PR_TRUE;
start = eol+1;
}
return rv;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,332 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* - David W. Hyatt (hyatt@netscape.com)
* - Mike Pinkerton (pinkerton@netscape.com)
* - Akkana Peck (akkana@netscape.com)
*/
#include "nsXBLWindowHandler.h"
#include "nsCOMPtr.h"
#include "nsPIWindowRoot.h"
#include "nsIDOMWindowInternal.h"
#include "nsIFocusController.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocShell.h"
#include "nsIPresShell.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventReceiver.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsIXBLPrototypeBinding.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMEvent.h"
#include "nsIContent.h"
#include "nsHTMLAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsIXBLDocumentInfo.h"
#include "nsIDocument.h"
#include "nsIXBLService.h"
#include "nsIServiceManager.h"
class nsXBLSpecialDocInfo
{
public:
nsCOMPtr<nsIXBLDocumentInfo> mHTMLBindings;
nsCOMPtr<nsIXBLDocumentInfo> mPlatformHTMLBindings;
nsCOMPtr<nsIXBLDocumentInfo> mUserHTMLBindings;
nsCString mHTMLBindingStr;
nsCString mPlatformHTMLBindingStr;
nsCString mUserHTMLBindingStr;
static char* sHTMLBindingStr;
static char* sPlatformHTMLBindingStr;
static char* sUserHTMLBindingStr;
PRBool mInitialized;
public:
void LoadDocInfo();
void GetAllHandlers(const char* aType,
nsIXBLPrototypeHandler** handler,
nsIXBLPrototypeHandler** platformHandler,
nsIXBLPrototypeHandler** userHandler);
void GetHandlers(nsIXBLDocumentInfo* aInfo,
const nsAReadableCString& aRef,
nsIXBLPrototypeHandler** aResult);
nsXBLSpecialDocInfo() : mInitialized(PR_FALSE) {};
};
char* nsXBLSpecialDocInfo::sHTMLBindingStr = "resource:///res/builtin/htmlBindings.xml";
char* nsXBLSpecialDocInfo::sPlatformHTMLBindingStr = "resource:///res/builtin/platformHTMLBindings.xml";
// Allow for a userHTMLBindings.xml.
// XXX Should be in the user profile directory, when we have a urlspec for that
char* nsXBLSpecialDocInfo::sUserHTMLBindingStr = "resource:///res/builtin/userHTMLBindings.xml";
void nsXBLSpecialDocInfo::LoadDocInfo()
{
if (mInitialized)
return;
mInitialized = PR_TRUE;
mHTMLBindingStr = sHTMLBindingStr;
mPlatformHTMLBindingStr = sPlatformHTMLBindingStr;
mUserHTMLBindingStr = sUserHTMLBindingStr;
if (mHTMLBindings && mPlatformHTMLBindings && mUserHTMLBindings)
return;
nsresult rv;
NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv);
if (NS_FAILED(rv) || !xblService)
return;
// Obtain the XP and platform doc infos
xblService->LoadBindingDocumentInfo(nsnull, nsnull,
mHTMLBindingStr,
nsCAutoString(""), PR_TRUE,
getter_AddRefs(mHTMLBindings));
xblService->LoadBindingDocumentInfo(nsnull, nsnull,
mPlatformHTMLBindingStr,
nsCAutoString(""), PR_TRUE,
getter_AddRefs(mPlatformHTMLBindings));
xblService->LoadBindingDocumentInfo(nsnull, nsnull,
mUserHTMLBindingStr,
nsCAutoString(""), PR_TRUE,
getter_AddRefs(mUserHTMLBindings));
}
//
// GetHandlers
//
//
void
nsXBLSpecialDocInfo::GetHandlers(nsIXBLDocumentInfo* aInfo,
const nsAReadableCString& aRef,
nsIXBLPrototypeHandler** aResult)
{
nsCOMPtr<nsIXBLPrototypeBinding> binding;
aInfo->GetPrototypeBinding(aRef, getter_AddRefs(binding));
if (!binding) {
nsCOMPtr<nsIDocument> doc;
aInfo->GetDocument(getter_AddRefs(doc));
nsCOMPtr<nsIContent> root = getter_AddRefs(doc->GetRootContent());
if (root) { // no root, no handlers. don't crash please.
PRInt32 childCount;
root->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
root->ChildAt(i, *getter_AddRefs(child));
nsAutoString id;
child->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id);
if (id.EqualsWithConversion(nsPromiseFlatCString(aRef).get())) {
NS_NewXBLPrototypeBinding(aRef, child, aInfo, getter_AddRefs(binding));
aInfo->SetPrototypeBinding(aRef, binding);
break;
}
}
}
}
if (binding) {
nsCOMPtr<nsIXBLPrototypeHandler> dummy;
binding->GetPrototypeHandlers(aResult, getter_AddRefs(dummy)); // Addref happens here.
}
} // GetHandlers
void
nsXBLSpecialDocInfo::GetAllHandlers(const char* aType,
nsIXBLPrototypeHandler** aHandler,
nsIXBLPrototypeHandler** aPlatformHandler,
nsIXBLPrototypeHandler** aUserHandler)
{
if (mUserHTMLBindings) {
nsCAutoString type(aType);
type.Append("User");
GetHandlers(mUserHTMLBindings, type, aUserHandler);
}
if (mPlatformHTMLBindings) {
nsCAutoString type(aType);
GetHandlers(mPlatformHTMLBindings, type, aPlatformHandler);
}
if (mHTMLBindings) {
nsCAutoString type(aType);
type.Append("Base");
GetHandlers(mHTMLBindings, type, aHandler);
}
}
// Init statics
nsXBLSpecialDocInfo* nsXBLWindowHandler::sXBLSpecialDocInfo = nsnull;
PRUint32 nsXBLWindowHandler::sRefCnt = 0;
//
// nsXBLWindowHandler ctor
//
// Increment the refcount
//
nsXBLWindowHandler :: nsXBLWindowHandler (nsIDOMElement* aElement, nsIDOMEventReceiver* aReceiver)
: mElement(aElement), mReceiver(aReceiver)
{
++sRefCnt;
}
//
// nsXBLWindowHandler dtor
//
// Decrement the refcount. If we get to zero, get rid of the static XBL doc
// info.
//
nsXBLWindowHandler :: ~nsXBLWindowHandler ( )
{
--sRefCnt;
if ( !sRefCnt ) {
delete sXBLSpecialDocInfo;
sXBLSpecialDocInfo = nsnull;
}
}
//
// IsEditor
//
// Determine if the document we're working with is Editor or Browser
//
PRBool
nsXBLWindowHandler :: IsEditor()
{
nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(mReceiver));
nsCOMPtr<nsIFocusController> focusController;
windowRoot->GetFocusController(getter_AddRefs(focusController));
if (!focusController) {
NS_WARNING("********* Something went wrong! No focus controller on the root!!!\n");
return PR_FALSE;
}
nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
if (!focusedWindow)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> obj(do_QueryInterface(focusedWindow));
nsCOMPtr<nsIDocShell> docShell;
obj->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIPresShell> presShell;
if (docShell)
docShell->GetPresShell(getter_AddRefs(presShell));
if (presShell) {
PRBool isEditor;
presShell->GetDisplayNonTextSelection(&isEditor);
return isEditor;
}
return PR_FALSE;
} // IsEditor
//
// WalkHandlersInternal
//
// Given a particular DOM event and a pointer to the first handler in the list,
// scan through the list to find something to handle the event and then make it
// so.
//
nsresult
nsXBLWindowHandler::WalkHandlersInternal(nsIDOMEvent* aEvent, nsIAtom* aEventType,
nsIXBLPrototypeHandler* aHandler)
{
nsresult rv;
nsCOMPtr<nsIXBLPrototypeHandler> currHandler = aHandler;
while (currHandler) {
PRBool stopped;
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
privateEvent->IsDispatchStopped(&stopped);
if (stopped)
return NS_OK;
// if the handler says it wants the event, execute it
if ( EventMatched(currHandler, aEventType, aEvent) ) {
// ...but don't exectute if it is disabled.
nsAutoString disabled;
nsCOMPtr<nsIContent> elt;
currHandler->GetHandlerElement(getter_AddRefs(elt));
elt->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, disabled);
if (!disabled.Equals(NS_LITERAL_STRING("true"))) {
nsCOMPtr<nsIDOMEventReceiver> rec = mReceiver;
if (mElement)
rec = do_QueryInterface(elt);
rv = currHandler->ExecuteHandler(rec, aEvent);
if (NS_SUCCEEDED(rv))
return NS_OK;
}
}
// the current handler didn't want it, try the next one.
nsCOMPtr<nsIXBLPrototypeHandler> nextHandler;
currHandler->GetNextHandler(getter_AddRefs(nextHandler));
currHandler = nextHandler;
}
return NS_OK;
} // WalkHandlersInternal
//
// EnsureHandlers
//
// Lazily load the XP and platform-specific bindings
//
nsresult
nsXBLWindowHandler::EnsureHandlers()
{
if (!sXBLSpecialDocInfo)
sXBLSpecialDocInfo = new nsXBLSpecialDocInfo();
if (!sXBLSpecialDocInfo)
return NS_ERROR_OUT_OF_MEMORY;
sXBLSpecialDocInfo->LoadDocInfo();
// Now determine which handlers we should be using.
if (IsEditor()) {
sXBLSpecialDocInfo->GetAllHandlers("editor",
getter_AddRefs(mHandler),
getter_AddRefs(mPlatformHandler),
getter_AddRefs(mUserHandler));
}
else {
sXBLSpecialDocInfo->GetAllHandlers("browser",
getter_AddRefs(mHandler),
getter_AddRefs(mPlatformHandler),
getter_AddRefs(mUserHandler));
}
return NS_OK;
} // EnsureHandlers

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,259 +0,0 @@
/* -*- Mode: C++ tab-width: 2 indent-tabs-mode: nil c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <stdio.h>
#include "nsIEditor.h"
#include "nsIHTMLEditor.h"
#include "TextEditorTest.h"
#include "nsISelection.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIEditProperty.h"
#include "nsString.h"
#ifdef NS_DEBUG
#define TEST_RESULT(r) { if (NS_FAILED(r)) {printf("FAILURE result=%X\n", r); return r; } }
#define TEST_POINTER(p) { if (!p) {printf("FAILURE null pointer\n"); return NS_ERROR_NULL_POINTER; } }
TextEditorTest::TextEditorTest()
{
printf("constructed a TextEditorTest\n");
}
TextEditorTest::~TextEditorTest()
{
printf("destroyed a TextEditorTest\n");
}
void TextEditorTest::Run(nsIEditor *aEditor, PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
{
if (!aEditor) return;
mTextEditor = do_QueryInterface(aEditor);
mEditor = do_QueryInterface(aEditor);
RunUnitTest(outNumTests, outNumTestsFailed);
}
nsresult TextEditorTest::RunUnitTest(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
{
nsresult result;
if (!outNumTests || !outNumTestsFailed)
return NS_ERROR_NULL_POINTER;
*outNumTests = 0;
*outNumTestsFailed = 0;
result = InitDoc();
TEST_RESULT(result);
// shouldn't we just bail on error here?
// insert some simple text
result = mTextEditor->InsertText(NS_LITERAL_STRING("1234567890abcdefghij1234567890").get());
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
// insert some more text
result = mTextEditor->InsertText(NS_LITERAL_STRING("Moreover, I am cognizant of the interrelatedness of all communities and states. I cannot sit idly by in Atlanta and not be concerned about what happens in Birmingham. Injustice anywhere is a threat to justice everywhere").get());
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
result = TestInsertBreak();
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
result = TestTextProperties();
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
// get us back to the original document
result = mEditor->Undo(12);
TEST_RESULT(result);
return result;
}
nsresult TextEditorTest::InitDoc()
{
nsresult result = mEditor->SelectAll();
TEST_RESULT(result);
result = mEditor->DeleteSelection(nsIEditor::eNext);
TEST_RESULT(result);
return result;
}
nsresult TextEditorTest::TestInsertBreak()
{
nsCOMPtr<nsISelection>selection;
nsresult result = mEditor->GetSelection(getter_AddRefs(selection));
TEST_RESULT(result);
TEST_POINTER(selection.get());
nsCOMPtr<nsIDOMNode>anchor;
result = selection->GetAnchorNode(getter_AddRefs(anchor));
TEST_RESULT(result);
TEST_POINTER(anchor.get());
selection->Collapse(anchor, 0);
// insert one break
printf("inserting a break\n");
result = mTextEditor->InsertLineBreak();
TEST_RESULT(result);
mEditor->DebugDumpContent();
// insert a second break adjacent to the first
printf("inserting a second break\n");
result = mTextEditor->InsertLineBreak();
TEST_RESULT(result);
mEditor->DebugDumpContent();
return result;
}
nsresult TextEditorTest::TestTextProperties()
{
nsCOMPtr<nsIDOMDocument>doc;
nsresult result = mEditor->GetDocument(getter_AddRefs(doc));
TEST_RESULT(result);
TEST_POINTER(doc.get());
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString textTag; textTag.AssignWithConversion("__moz_text");
result = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
TEST_RESULT(result);
TEST_POINTER(nodeList.get());
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(0!=count, "there are no text nodes in the document!");
nsCOMPtr<nsIDOMNode>textNode;
result = nodeList->Item(count-1, getter_AddRefs(textNode));
TEST_RESULT(result);
TEST_POINTER(textNode.get());
// set the whole text node to bold
printf("set the whole first text node to bold\n");
nsCOMPtr<nsISelection>selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
TEST_RESULT(result);
TEST_POINTER(selection.get());
nsCOMPtr<nsIDOMCharacterData>textData;
textData = do_QueryInterface(textNode);
PRUint32 length;
textData->GetLength(&length);
selection->Collapse(textNode, 0);
selection->Extend(textNode, length);
nsCOMPtr<nsIHTMLEditor> htmlEditor (do_QueryInterface(mTextEditor));
if (!htmlEditor)
return NS_ERROR_FAILURE;
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first=PR_FALSE;
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_FALSE==first, "first should be false");
NS_ASSERTION(PR_FALSE==any, "any should be false");
NS_ASSERTION(PR_FALSE==all, "all should be false");
result = htmlEditor->SetInlineProperty(nsIEditProperty::b, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
// remove the bold we just set
printf("set the whole first text node to not bold\n");
result = htmlEditor->RemoveInlineProperty(nsIEditProperty::b, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_FALSE==first, "first should be false");
NS_ASSERTION(PR_FALSE==any, "any should be false");
NS_ASSERTION(PR_FALSE==all, "all should be false");
mEditor->DebugDumpContent();
// set all but the first and last character to bold
printf("set the first text node (1, length-1) to bold and italic, and (2, length-1) to underline.\n");
selection->Collapse(textNode, 1);
selection->Extend(textNode, length-1);
result = htmlEditor->SetInlineProperty(nsIEditProperty::b, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
// make all that same text italic
result = htmlEditor->SetInlineProperty(nsIEditProperty::i, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::i, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
// make all the text underlined, except for the first 2 and last 2 characters
result = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
TEST_RESULT(result);
TEST_POINTER(nodeList.get());
nodeList->GetLength(&count);
NS_ASSERTION(0!=count, "there are no text nodes in the document!");
result = nodeList->Item(count-2, getter_AddRefs(textNode));
TEST_RESULT(result);
TEST_POINTER(textNode.get());
textData = do_QueryInterface(textNode);
textData->GetLength(&length);
NS_ASSERTION(length==915, "wrong text node");
selection->Collapse(textNode, 1);
selection->Extend(textNode, length-2);
result = htmlEditor->SetInlineProperty(nsIEditProperty::u, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::u, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
return result;
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,259 +0,0 @@
/* -*- Mode: C++ tab-width: 2 indent-tabs-mode: nil c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <stdio.h>
#include "nsIEditor.h"
#include "nsIHTMLEditor.h"
#include "TextEditorTest.h"
#include "nsISelection.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIEditProperty.h"
#include "nsString.h"
#ifdef NS_DEBUG
#define TEST_RESULT(r) { if (NS_FAILED(r)) {printf("FAILURE result=%X\n", r); return r; } }
#define TEST_POINTER(p) { if (!p) {printf("FAILURE null pointer\n"); return NS_ERROR_NULL_POINTER; } }
TextEditorTest::TextEditorTest()
{
printf("constructed a TextEditorTest\n");
}
TextEditorTest::~TextEditorTest()
{
printf("destroyed a TextEditorTest\n");
}
void TextEditorTest::Run(nsIEditor *aEditor, PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
{
if (!aEditor) return;
mTextEditor = do_QueryInterface(aEditor);
mEditor = do_QueryInterface(aEditor);
RunUnitTest(outNumTests, outNumTestsFailed);
}
nsresult TextEditorTest::RunUnitTest(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
{
nsresult result;
if (!outNumTests || !outNumTestsFailed)
return NS_ERROR_NULL_POINTER;
*outNumTests = 0;
*outNumTestsFailed = 0;
result = InitDoc();
TEST_RESULT(result);
// shouldn't we just bail on error here?
// insert some simple text
result = mTextEditor->InsertText(NS_LITERAL_STRING("1234567890abcdefghij1234567890").get());
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
// insert some more text
result = mTextEditor->InsertText(NS_LITERAL_STRING("Moreover, I am cognizant of the interrelatedness of all communities and states. I cannot sit idly by in Atlanta and not be concerned about what happens in Birmingham. Injustice anywhere is a threat to justice everywhere").get());
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
result = TestInsertBreak();
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
result = TestTextProperties();
TEST_RESULT(result);
(*outNumTests)++;
(*outNumTestsFailed) += (NS_FAILED(result) != NS_OK);
// get us back to the original document
result = mEditor->Undo(12);
TEST_RESULT(result);
return result;
}
nsresult TextEditorTest::InitDoc()
{
nsresult result = mEditor->SelectAll();
TEST_RESULT(result);
result = mEditor->DeleteSelection(nsIEditor::eNext);
TEST_RESULT(result);
return result;
}
nsresult TextEditorTest::TestInsertBreak()
{
nsCOMPtr<nsISelection>selection;
nsresult result = mEditor->GetSelection(getter_AddRefs(selection));
TEST_RESULT(result);
TEST_POINTER(selection.get());
nsCOMPtr<nsIDOMNode>anchor;
result = selection->GetAnchorNode(getter_AddRefs(anchor));
TEST_RESULT(result);
TEST_POINTER(anchor.get());
selection->Collapse(anchor, 0);
// insert one break
printf("inserting a break\n");
result = mTextEditor->InsertLineBreak();
TEST_RESULT(result);
mEditor->DebugDumpContent();
// insert a second break adjacent to the first
printf("inserting a second break\n");
result = mTextEditor->InsertLineBreak();
TEST_RESULT(result);
mEditor->DebugDumpContent();
return result;
}
nsresult TextEditorTest::TestTextProperties()
{
nsCOMPtr<nsIDOMDocument>doc;
nsresult result = mEditor->GetDocument(getter_AddRefs(doc));
TEST_RESULT(result);
TEST_POINTER(doc.get());
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString textTag; textTag.AssignWithConversion("__moz_text");
result = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
TEST_RESULT(result);
TEST_POINTER(nodeList.get());
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(0!=count, "there are no text nodes in the document!");
nsCOMPtr<nsIDOMNode>textNode;
result = nodeList->Item(count-1, getter_AddRefs(textNode));
TEST_RESULT(result);
TEST_POINTER(textNode.get());
// set the whole text node to bold
printf("set the whole first text node to bold\n");
nsCOMPtr<nsISelection>selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
TEST_RESULT(result);
TEST_POINTER(selection.get());
nsCOMPtr<nsIDOMCharacterData>textData;
textData = do_QueryInterface(textNode);
PRUint32 length;
textData->GetLength(&length);
selection->Collapse(textNode, 0);
selection->Extend(textNode, length);
nsCOMPtr<nsIHTMLEditor> htmlEditor (do_QueryInterface(mTextEditor));
if (!htmlEditor)
return NS_ERROR_FAILURE;
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first=PR_FALSE;
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_FALSE==first, "first should be false");
NS_ASSERTION(PR_FALSE==any, "any should be false");
NS_ASSERTION(PR_FALSE==all, "all should be false");
result = htmlEditor->SetInlineProperty(nsIEditProperty::b, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
// remove the bold we just set
printf("set the whole first text node to not bold\n");
result = htmlEditor->RemoveInlineProperty(nsIEditProperty::b, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_FALSE==first, "first should be false");
NS_ASSERTION(PR_FALSE==any, "any should be false");
NS_ASSERTION(PR_FALSE==all, "all should be false");
mEditor->DebugDumpContent();
// set all but the first and last character to bold
printf("set the first text node (1, length-1) to bold and italic, and (2, length-1) to underline.\n");
selection->Collapse(textNode, 1);
selection->Extend(textNode, length-1);
result = htmlEditor->SetInlineProperty(nsIEditProperty::b, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
// make all that same text italic
result = htmlEditor->SetInlineProperty(nsIEditProperty::i, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::i, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
result = htmlEditor->GetInlineProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
// make all the text underlined, except for the first 2 and last 2 characters
result = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
TEST_RESULT(result);
TEST_POINTER(nodeList.get());
nodeList->GetLength(&count);
NS_ASSERTION(0!=count, "there are no text nodes in the document!");
result = nodeList->Item(count-2, getter_AddRefs(textNode));
TEST_RESULT(result);
TEST_POINTER(textNode.get());
textData = do_QueryInterface(textNode);
textData->GetLength(&length);
NS_ASSERTION(length==915, "wrong text node");
selection->Collapse(textNode, 1);
selection->Extend(textNode, length-2);
result = htmlEditor->SetInlineProperty(nsIEditProperty::u, nsnull, nsnull);
TEST_RESULT(result);
result = htmlEditor->GetInlineProperty(nsIEditProperty::u, nsnull, nsnull, first, any, all);
TEST_RESULT(result);
NS_ASSERTION(PR_TRUE==first, "first should be true");
NS_ASSERTION(PR_TRUE==any, "any should be true");
NS_ASSERTION(PR_TRUE==all, "all should be true");
mEditor->DebugDumpContent();
return result;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,423 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Conrad Carlen <ccarlen@netscape.com>
*/
// PPBrowser
#include "CProfileManager.h"
#include "ApplIDs.h"
#include "UMacUnicode.h"
// PowerPlant
#include <LEditText.h>
#include <LTextTableView.h>
#include <LPushButton.h>
#include <LTableMonoGeometry.h>
#include <LTableArrayStorage.h>
#include <LTableSingleSelector.h>
#include <LCheckBox.h>
// Mozilla
#include "nsIProfile.h"
#include "nsIDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIObserverService.h"
#include "nsXPIDLString.h"
#include "nsIRegistry.h"
// Constants
const MessageT msg_OnNewProfile = 2000;
const MessageT msg_OnDeleteProfile = 2001;
const MessageT msg_OnRenameProfile = 2002;
#define kRegistryGlobalPrefsSubtreeString (NS_LITERAL_STRING("global-prefs"))
#define kRegistryShowProfilesAtStartup "start-show-dialog"
//*****************************************************************************
//*** CProfileManager
//*****************************************************************************
CProfileManager::CProfileManager() :
LAttachment(msg_AnyMessage,true)
{
}
CProfileManager::~CProfileManager()
{
}
void CProfileManager::StartUp()
{
nsresult rv;
NS_WITH_SERVICE(nsIProfile, profileService, NS_PROFILE_CONTRACTID, &rv);
ThrowIfNil_(profileService);
PRInt32 profileCount;
rv = profileService->GetProfileCount(&profileCount);
ThrowIfError_(rv);
if (profileCount == 0)
{
// Make a new default profile
NS_NAMED_LITERAL_STRING(newProfileName, "default");
rv = profileService->CreateNewProfile(newProfileName.get(), nsnull, nsnull, PR_FALSE);
ThrowIfError_(rv);
rv = profileService->SetCurrentProfile(newProfileName.get());
ThrowIfError_(rv);
}
else
{
// Use our flag here to check for whether to show profile mgr UI. If the flag
// says don't show it, just start with the last used profile.
PRBool showIt;
rv = GetShowDialogOnStart(&showIt);
if (NS_FAILED(rv) || (profileCount > 1 && showIt))
{
DoManageProfilesDialog();
}
else
{
// GetCurrentProfile returns the profile which was last used but is not nescesarily
// active. Call SetCurrentProfile to make it installed and active.
nsXPIDLString currProfileName;
rv = profileService->GetCurrentProfile(getter_Copies(currProfileName));
ThrowIfError_(rv);
rv = profileService->SetCurrentProfile(currProfileName);
ThrowIfError_(rv);
}
}
}
Boolean CProfileManager::DoNewProfileDialog(char *outName, UInt32 bufSize)
{
Boolean confirmed;
StDialogHandler theHandler(dlog_NewProfile, LCommander::GetTopCommander());
LWindow *theDialog = theHandler.GetDialog();
ThrowIfNil_(theDialog);
LEditText *responseText = dynamic_cast<LEditText*>(theDialog->FindPaneByID('Name'));
ThrowIfNil_(responseText);
theDialog->SetLatentSub(responseText);
theDialog->Show();
theDialog->Select();
while (true) // This is our modal dialog event loop
{
MessageT hitMessage = theHandler.DoDialog();
if (hitMessage == msg_OK)
{
Str255 pStr;
UInt32 outLen;
responseText->GetDescriptor(pStr);
outLen = pStr[0] >= bufSize ? bufSize - 1 : pStr[0];
memcpy(outName, &pStr[1], outLen);
outName[outLen] = '\0';
confirmed = PR_TRUE;
break;
}
else if (hitMessage == msg_Cancel)
{
confirmed = PR_FALSE;
break;
}
}
return confirmed;
}
void CProfileManager::DoManageProfilesDialog()
{
nsresult rv;
StDialogHandler theHandler(dlog_ManageProfiles, LCommander::GetTopCommander());
LWindow *theDialog = theHandler.GetDialog();
NS_WITH_SERVICE(nsIProfile, profileService, NS_PROFILE_CONTRACTID, &rv);
ThrowIfNil_(profileService);
// Set up the dialog by filling the list of current profiles
LTextTableView *table = (LTextTableView*) theDialog->FindPaneByID('List');
ThrowIfNil_(table);
LPushButton *deleteButton = (LPushButton *) theDialog->FindPaneByID('Dele');
ThrowIfNil_(deleteButton);
//Str255 pascalStr;
nsAutoString unicodeStr;
nsCAutoString cStr;
char dataBuf[256];
UInt32 dataSize;
// PowerPlant stuff to set up the list view
STableCell selectedCell(1, 1);
SDimension16 tableSize;
TableIndexT rows, cols;
table->GetFrameSize(tableSize);
table->SetTableGeometry(new LTableMonoGeometry(table, tableSize.width, 16));
table->SetTableStorage(new LTableArrayStorage(table, 0UL));
table->SetTableSelector(new LTableSingleSelector(table));
table->InsertCols(1, 0);
// Get the name of the current profile so we can select it
nsXPIDLString currProfileName;
profileService->GetCurrentProfile(getter_Copies(currProfileName));
// Get the list of profile names and add them to the list
PRUint32 listLen;
PRUnichar **profileList;
rv = profileService->GetProfileList(&listLen, &profileList);
ThrowIfError_(rv);
for (PRUint32 index = 0; index < listLen; index++)
{
CPlatformUCSConversion::GetInstance()->UCSToPlatform(nsLiteralString(profileList[index]), cStr);
table->InsertRows(1, LONG_MAX, cStr.get(), cStr.Length(), true);
if (nsCRT::strcmp(profileList[index], currProfileName.get()) == 0)
selectedCell.row = index + 1;
}
PRInt32 numProfiles;
rv = profileService->GetProfileCount(&numProfiles);
ThrowIfError_(rv);
(numProfiles > 1) ? deleteButton->Enable() : deleteButton->Disable();
table->SelectCell(selectedCell);
// Handle the "Ask At StartUp" checkbox
LCheckBox *showAtStartCheck = (LCheckBox*) theDialog->FindPaneByID('Show');
ThrowIfNil_(showAtStartCheck);
PRBool showIt;
rv = GetShowDialogOnStart(&showIt);
if (NS_FAILED(rv))
showIt = PR_TRUE;
showAtStartCheck->SetValue(showIt);
theDialog->Show();
theDialog->Select();
while (true) // This is our modal dialog event loop
{
MessageT hitMessage = theHandler.DoDialog();
if (hitMessage == msg_OK)
{
theDialog->Hide();
SetShowDialogOnStart(showAtStartCheck->GetValue());
selectedCell = table->GetFirstSelectedCell();
if (selectedCell.row > 0)
{
dataSize = sizeof(dataBuf) - 1;
table->GetCellData(selectedCell, dataBuf, dataSize);
dataBuf[dataSize] = '\0';
CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsLiteralCString(dataBuf), unicodeStr);
rv = profileService->SetCurrentProfile(unicodeStr.GetUnicode());
}
break;
}
else if (hitMessage == msg_Cancel)
{
break;
}
else if (hitMessage == msg_OnNewProfile)
{
if (DoNewProfileDialog(dataBuf, sizeof(dataBuf)))
{
CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsLiteralCString(dataBuf), unicodeStr);
rv = profileService->CreateNewProfile(unicodeStr.GetUnicode(), nsnull, nsnull, PR_FALSE);
if (NS_FAILED(rv))
break;
table->InsertRows(1, LONG_MAX, dataBuf, strlen(dataBuf), true);
table->GetTableSize(rows, cols);
table->SelectCell(STableCell(rows, cols));
rv = profileService->GetProfileCount(&numProfiles);
(NS_SUCCEEDED(rv) && numProfiles > 1) ? deleteButton->Enable() : deleteButton->Disable();
}
}
else if (hitMessage == msg_OnDeleteProfile)
{
selectedCell = table->GetFirstSelectedCell();
if (selectedCell.row > 0)
{
dataSize = sizeof(dataBuf) - 1;
table->GetCellData(selectedCell, dataBuf, dataSize);
dataBuf[dataSize] = '\0';
CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsLiteralCString(dataBuf), unicodeStr);
rv = profileService->DeleteProfile(unicodeStr.GetUnicode(), PR_TRUE);
if (NS_FAILED(rv))
break;
table->RemoveRows(1, selectedCell.row, true);
table->GetTableSize(rows, cols);
if (selectedCell.row >= rows)
selectedCell.row = rows - 1;
table->SelectCell(selectedCell);
rv = profileService->GetProfileCount(&numProfiles);
(NS_SUCCEEDED(rv) && numProfiles > 1) ? deleteButton->Enable() : deleteButton->Disable();
}
}
else if (hitMessage == msg_OnRenameProfile)
{
nsAutoString oldName;
selectedCell = table->GetFirstSelectedCell();
dataSize = sizeof(dataBuf) - 1;
table->GetCellData(selectedCell, dataBuf, dataSize);
dataBuf[dataSize] = '\0';
CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsLiteralCString(dataBuf), oldName);
if (DoNewProfileDialog(dataBuf, sizeof(dataBuf)))
{
CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsLiteralCString(dataBuf), unicodeStr);
profileService->RenameProfile(oldName.GetUnicode(), unicodeStr.GetUnicode());
table->SetCellData(selectedCell, dataBuf, strlen(dataBuf));
}
}
}
}
/*
The following three methods have nothing to do with profile management per se.
They use the registry to store a flag which allows the user to choose whether
to show the profile manager dialog at startup. After all, since we can switch
it at any time - why must we deal with the dialog every time we start the app?
*/
nsresult CProfileManager::GetShowDialogOnStart(PRBool* showIt)
{
nsresult rv = NS_OK;
*showIt = PR_TRUE;
nsCOMPtr<nsIRegistry> registry;
rv = OpenAppRegistry(getter_AddRefs(registry));
if (NS_FAILED(rv)) return rv;
nsRegistryKey profilesTreeKey;
rv = registry->GetKey(nsIRegistry::Common,
kRegistryGlobalPrefsSubtreeString.get(),
&profilesTreeKey);
if (NS_SUCCEEDED(rv))
{
PRInt32 flagValue;
rv = registry->GetInt(profilesTreeKey,
kRegistryShowProfilesAtStartup,
&flagValue);
if (NS_SUCCEEDED(rv))
*showIt = (flagValue != 0);
}
return rv;
}
nsresult CProfileManager::SetShowDialogOnStart(PRBool showIt)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIRegistry> registry;
rv = OpenAppRegistry(getter_AddRefs(registry));
if (NS_FAILED(rv)) return rv;
nsRegistryKey profilesTreeKey;
rv = registry->GetKey(nsIRegistry::Common,
kRegistryGlobalPrefsSubtreeString.get(),
&profilesTreeKey);
if (NS_FAILED(rv))
{
rv = registry->AddKey(nsIRegistry::Common,
kRegistryGlobalPrefsSubtreeString.get(),
&profilesTreeKey);
}
if (NS_SUCCEEDED(rv))
{
rv = registry->SetInt(profilesTreeKey,
kRegistryShowProfilesAtStartup,
showIt);
}
return rv;
}
nsresult CProfileManager::OpenAppRegistry(nsIRegistry **aRegistry)
{
NS_ENSURE_ARG_POINTER(aRegistry);
nsresult rv;
nsCOMPtr<nsIFile> regFile;
nsXPIDLCString regFilePath;
rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_FILE, getter_AddRefs(regFile));
if (NS_FAILED(rv)) return rv;
rv = regFile->GetPath(getter_Copies(regFilePath));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRegistry> registry(do_CreateInstance(NS_REGISTRY_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
rv = registry->Open(regFilePath);
if (NS_FAILED(rv)) return rv;
*aRegistry = registry;
NS_IF_ADDREF(*aRegistry);
return NS_OK;
}
//*****************************************************************************
//*** CProfileManager::LAttachment
//*****************************************************************************
void CProfileManager::ExecuteSelf(MessageT inMessage, void *ioParam)
{
mExecuteHost = true;
// update status
if (inMessage == msg_CommandStatus) {
SCommandStatus *status = (SCommandStatus *)ioParam;
if (status->command == cmd_ManageProfiles) {
*status->enabled = true;
*status->usesMark = false;
mExecuteHost = false; // we handled it
}
}
else if (inMessage == cmd_ManageProfiles) {
DoManageProfilesDialog();
mExecuteHost = false; // we handled it
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,789 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Notes:
* The logging sink is now both a sink and a proxy.
* If you want to dump the calls from the parser to the sink,
* create a content sink as usual and hand it to the parser.
*
* If you want to use a normal sink AND simultaneously have a
* parse-log generated, you can set an environment variable
* and a logging sink will be created. It will act as a proxy
* to the REAL sink you are using after it logs the call. This
* form of the loggingsink is constructed using the version
* that accepts an nsIHTMLContentSink*.
*
* Contributor(s):
*/
#include "nsLoggingSink.h"
#include "nsHTMLTags.h"
#include "nsString.h"
#include "prprf.h"
static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kILoggingSinkIID, NS_ILOGGING_SINK_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
// list of tags that have skipped content
static char gSkippedContentTags[] = {
eHTMLTag_style,
eHTMLTag_script,
eHTMLTag_server,
eHTMLTag_textarea,
eHTMLTag_title,
0
};
nsresult
NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
nsLoggingSink* it = new nsLoggingSink();
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(kIContentSinkIID, (void**) aInstancePtrResult);
}
nsLoggingSink::nsLoggingSink() {
NS_INIT_REFCNT();
mOutput = 0;
mLevel=-1;
mSink=0;
}
nsLoggingSink::~nsLoggingSink() {
mSink=0;
if(mOutput && mAutoDeleteOutput) {
delete mOutput;
}
mOutput=0;
}
NS_IMPL_ADDREF(nsLoggingSink)
NS_IMPL_RELEASE(nsLoggingSink)
nsresult
nsLoggingSink::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_PRECONDITION(nsnull != aInstancePtr, "null ptr");
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kISupportsIID)) {
nsISupports* tmp = this;
*aInstancePtr = (void*) tmp;
}
else if (aIID.Equals(kIContentSinkIID)) {
nsIContentSink* tmp = this;
*aInstancePtr = (void*) tmp;
}
else if (aIID.Equals(kIHTMLContentSinkIID)) {
nsIHTMLContentSink* tmp = this;
*aInstancePtr = (void*) tmp;
}
else if (aIID.Equals(kILoggingSinkIID)) {
nsILoggingSink* tmp = this;
*aInstancePtr = (void*) tmp;
}
else {
*aInstancePtr = nsnull;
return NS_NOINTERFACE;
}
NS_ADDREF(this);
return NS_OK;
}
NS_IMETHODIMP
nsLoggingSink::SetOutputStream(PRFileDesc *aStream,PRBool autoDeleteOutput) {
mOutput = aStream;
mAutoDeleteOutput=autoDeleteOutput;
return NS_OK;
}
static
void WriteTabs(PRFileDesc * out,int aTabCount) {
int tabs;
for(tabs=0;tabs<aTabCount;tabs++)
PR_fprintf(out, " ");
}
NS_IMETHODIMP
nsLoggingSink::WillBuildModel() {
WriteTabs(mOutput,++mLevel);
PR_fprintf(mOutput, "<begin>\n");
//proxy the call to the real sink if you have one.
if(mSink) {
mSink->WillBuildModel();
}
return NS_OK;
}
NS_IMETHODIMP
nsLoggingSink::DidBuildModel(PRInt32 aQualityLevel) {
WriteTabs(mOutput,--mLevel);
PR_fprintf(mOutput, "</begin>\n");
//proxy the call to the real sink if you have one.
nsresult theResult=NS_OK;
if(mSink) {
theResult=mSink->DidBuildModel(aQualityLevel);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::WillInterrupt() {
nsresult theResult=NS_OK;
//proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->WillInterrupt();
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::WillResume() {
nsresult theResult=NS_OK;
//proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->WillResume();
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::SetParser(nsIParser* aParser) {
nsresult theResult=NS_OK;
//proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->SetParser(aParser);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenContainer(const nsIParserNode& aNode) {
OpenNode("container", aNode); //do the real logging work...
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenContainer(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseContainer(const nsIParserNode& aNode) {
nsresult theResult=NS_OK;
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const char* tag = nsHTMLTags::GetStringValue(nodeType);
theResult=CloseNode(tag);
}
else theResult= CloseNode("???");
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseContainer(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::AddLeaf(const nsIParserNode& aNode) {
LeafNode(aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddLeaf(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::NotifyError(const nsParserError* aError) {
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->NotifyError(aError);
}
return theResult;
}
/**
* This gets called by the parser when you want to add
* a PI node to the current container in the content
* model.
*
* @updated gess 3/25/98
* @param
* @return
*/
NS_IMETHODIMP
nsLoggingSink::AddProcessingInstruction(const nsIParserNode& aNode){
#ifdef VERBOSE_DEBUG
DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
#endif
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddProcessingInstruction(aNode);
}
return theResult;
}
/**
* This gets called by the parser when it encounters
* a DOCTYPE declaration in the HTML document.
*/
NS_IMETHODIMP
nsLoggingSink::AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode) {
#ifdef VERBOSE_DEBUG
DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
#endif
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddDocTypeDecl(aNode,aMode);
}
return theResult;
}
/**
* This gets called by the parser when you want to add
* a comment node to the current container in the content
* model.
*
* @updated gess 3/25/98
* @param
* @return
*/
NS_IMETHODIMP
nsLoggingSink::AddComment(const nsIParserNode& aNode){
#ifdef VERBOSE_DEBUG
DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
#endif
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddComment(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::SetTitle(const nsString& aValue) {
char* tmp;
GetNewCString(aValue, &tmp);
WriteTabs(mOutput,++mLevel);
if(tmp) {
PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp);
nsMemory::Free(tmp);
}
--mLevel;
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->SetTitle(aValue);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenHTML(const nsIParserNode& aNode) {
OpenNode("html", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenHTML(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseHTML(const nsIParserNode& aNode) {
CloseNode("html");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseHTML(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenHead(const nsIParserNode& aNode) {
OpenNode("head", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenHead(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseHead(const nsIParserNode& aNode) {
CloseNode("head");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseHead(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenBody(const nsIParserNode& aNode) {
OpenNode("body", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenBody(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseBody(const nsIParserNode& aNode) {
CloseNode("body");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseBody(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenForm(const nsIParserNode& aNode) {
OpenNode("form", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenForm(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseForm(const nsIParserNode& aNode) {
CloseNode("form");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseForm(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenMap(const nsIParserNode& aNode) {
OpenNode("map", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenMap(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseMap(const nsIParserNode& aNode) {
CloseNode("map");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseMap(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenFrameset(const nsIParserNode& aNode) {
OpenNode("frameset", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenFrameset(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseFrameset(const nsIParserNode& aNode) {
CloseNode("frameset");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseFrameset(aNode);
}
return theResult;
}
nsresult
nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) {
WriteTabs(mOutput,++mLevel);
PR_fprintf(mOutput,"<open container=");
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const char* tag = nsHTMLTags::GetStringValue(nodeType);
PR_fprintf(mOutput, "\"%s\"", tag);
}
else {
char* text;
GetNewCString(aNode.GetText(), &text);
if(text) {
PR_fprintf(mOutput, "\"%s\"", text);
nsMemory::Free(text);
}
}
if (WillWriteAttributes(aNode)) {
PR_fprintf(mOutput, ">\n");
WriteAttributes(aNode);
PR_fprintf(mOutput, "</open>\n");
}
else {
PR_fprintf(mOutput, ">\n");
}
return NS_OK;
}
nsresult
nsLoggingSink::CloseNode(const char* aKind) {
WriteTabs(mOutput,mLevel--);
PR_fprintf(mOutput, "<close container=\"%s\">\n", aKind);
return NS_OK;
}
nsresult
nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) {
WriteTabs(mOutput,1+mLevel);
nsAutoString tmp;
PRInt32 ac = aNode.GetAttributeCount();
for (PRInt32 i = 0; i < ac; i++) {
char* key=nsnull;
char* value=nsnull;
const nsAReadableString& k = aNode.GetKeyAt(i);
const nsString& v = aNode.GetValueAt(i);
GetNewCString(k, &key);
if(key) {
PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", key);
nsMemory::Free(key);
}
tmp.Truncate();
tmp.Append(v);
if(tmp.Length() > 0) {
PRUnichar first = tmp.First();
if ((first == '"') || (first == '\'')) {
if (tmp.Last() == first) {
tmp.Cut(0, 1);
PRInt32 pos = tmp.Length() - 1;
if (pos >= 0) {
tmp.Cut(pos, 1);
}
} else {
// Mismatched quotes - leave them in
}
}
GetNewCString(tmp, &value);
if(value) {
PR_fprintf(mOutput, "%s\"/>\n", value);
WriteTabs(mOutput,1+mLevel);
nsMemory::Free(value);
}
}
}
if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
char* content;
GetNewCString(aNode.GetSkippedContent(), &content);
if(content) {
PR_fprintf(mOutput, " <content value=\"");
PR_fprintf(mOutput, "%s\"/>\n", content) ;
nsMemory::Free(content);
}
}
WriteTabs(mOutput,1+mLevel);
return NS_OK;
}
PRBool
nsLoggingSink::WillWriteAttributes(const nsIParserNode& aNode)
{
PRInt32 ac = aNode.GetAttributeCount();
if (0 != ac) {
return PR_TRUE;
}
if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
const nsString& content = aNode.GetSkippedContent();
if (content.Length() > 0) {
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsLoggingSink::LeafNode(const nsIParserNode& aNode)
{
WriteTabs(mOutput,1+mLevel);
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const char* tag = nsHTMLTags::GetStringValue(nodeType);
if(tag)
PR_fprintf(mOutput, "<leaf tag=\"%s\"", tag);
else PR_fprintf(mOutput, "<leaf tag=\"???\"");
if (WillWriteAttributes(aNode)) {
PR_fprintf(mOutput, ">\n");
WriteAttributes(aNode);
PR_fprintf(mOutput, "</leaf>\n");
}
else {
PR_fprintf(mOutput, "/>\n");
}
}
else {
PRInt32 pos;
nsAutoString tmp;
char* str;
switch (nodeType) {
case eHTMLTag_whitespace:
case eHTMLTag_text:
GetNewCString(aNode.GetText(), &str);
if(str) {
PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str);
nsMemory::Free(str);
}
break;
case eHTMLTag_newline:
PR_fprintf(mOutput, "<newline/>\n");
break;
case eHTMLTag_entity:
tmp.Append(aNode.GetText());
tmp.Cut(0, 1);
pos = tmp.Length() - 1;
if (pos >= 0) {
tmp.Cut(pos, 1);
}
PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", tmp.GetBuffer());
break;
default:
NS_NOTREACHED("unsupported leaf node type");
}//switch
}
return NS_OK;
}
nsresult
nsLoggingSink::QuoteText(const nsAReadableString& aValue, nsString& aResult) {
aResult.Truncate();
/*
if you're stepping through the string anyway, why not use iterators instead of forcing the string to copy?
*/
nsPromiseFlatString flat(aValue);
const PRUnichar* cp = flat.get();
const PRUnichar* end = cp + aValue.Length();
while (cp < end) {
PRUnichar ch = *cp++;
if (ch == '"') {
aResult.AppendWithConversion("&quot;");
}
else if (ch == '&') {
aResult.AppendWithConversion("&amp;");
}
else if ((ch < 32) || (ch >= 127)) {
aResult.AppendWithConversion("&#");
aResult.AppendInt(PRInt32(ch), 10);
aResult.AppendWithConversion(';');
}
else {
aResult.Append(ch);
}
}
return NS_OK;
}
/**
* Use this method to convert nsString to char*.
* REMEMBER: Match this call with nsMemory::Free(aResult);
*
* @update 04/04/99 harishd
* @param aValue - The string value
* @param aResult - String coverted to char*.
*/
nsresult
nsLoggingSink::GetNewCString(const nsAReadableString& aValue, char** aResult)
{
nsresult result=NS_OK;
nsAutoString temp;
result=QuoteText(aValue,temp);
if(NS_SUCCEEDED(result)) {
if(temp.Length()>0) {
*aResult=temp.ToNewCString();
}
}
return result;
}
NS_IMETHODIMP
nsLoggingSink::DoFragment(PRBool aFlag)
{
return NS_OK;
}
/**
* This gets called when handling illegal contents, especially
* in dealing with tables. This method creates a new context.
*
* @update 04/04/99 harishd
* @param aPosition - The position from where the new context begins.
*/
NS_IMETHODIMP
nsLoggingSink::BeginContext(PRInt32 aPosition)
{
return NS_OK;
}
/**
* This method terminates any new context that got created by
* BeginContext and switches back to the main context.
*
* @update 04/04/99 harishd
* @param aPosition - Validates the end of a context.
*/
NS_IMETHODIMP
nsLoggingSink::EndContext(PRInt32 aPosition)
{
return NS_OK;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,411 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#include "nsBoxObject.h"
#include "nsIBoxLayoutManager.h"
#include "nsIBoxPaintManager.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIStyleContext.h"
#include "nsIFrame.h"
#include "nsXPIDLString.h"
#include "nsILookAndFeel.h"
#include "nsWidgetsCID.h"
#include "nsIServiceManager.h"
// Static IIDs/CIDs. Try to minimize these.
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
// Implementation /////////////////////////////////////////////////////////////////
// Static member variable initialization
// Implement our nsISupports methods
NS_IMPL_ISUPPORTS3(nsBoxObject, nsIBoxObject, nsPIBoxObject, nsISecurityCheckedComponent)
// Constructors/Destructors
nsBoxObject::nsBoxObject(void)
:mContent(nsnull), mPresShell(nsnull)
{
NS_INIT_ISUPPORTS();
}
nsBoxObject::~nsBoxObject(void)
{
}
NS_IMETHODIMP
nsBoxObject::GetLayoutManager(nsIBoxLayoutManager** aResult)
{
*aResult = mLayoutManager;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::SetLayoutManager(nsIBoxLayoutManager* aLayoutManager)
{
mLayoutManager = aLayoutManager;
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::GetPaintManager(nsIBoxPaintManager** aResult)
{
*aResult = mPaintManager;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::SetPaintManager(nsIBoxPaintManager* aPaintManager)
{
mPaintManager = aPaintManager;
return NS_OK;
}
// nsPIBoxObject //////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsBoxObject::Init(nsIContent* aContent, nsIPresShell* aShell)
{
mContent = aContent;
mPresShell = aShell;
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::SetDocument(nsIDocument* aDocument)
{
mPresState = nsnull;
if (aDocument) {
nsCOMPtr<nsIPresShell> shell = getter_AddRefs(aDocument->GetShellAt(0));
mPresShell = shell;
}
else {
mPresShell = nsnull;
}
return NS_OK;
}
nsIFrame*
nsBoxObject::GetFrame()
{
nsIFrame* frame = nsnull;
if (mPresShell)
mPresShell->GetPrimaryFrameFor(mContent, &frame);
return frame;
}
nsresult
nsBoxObject::GetOffsetRect(nsRect& aRect)
{
nsresult res = NS_OK;
aRect.x = aRect.y = 0;
aRect.Empty();
nsCOMPtr<nsIDocument> doc;
mContent->GetDocument(*getter_AddRefs(doc));
if (doc) {
// Get Presentation shell 0
nsCOMPtr<nsIPresShell> presShell = getter_AddRefs(doc->GetShellAt(0));
if(presShell) {
// Flush all pending notifications so that our frames are uptodate
presShell->FlushPendingNotifications();
// Get the Frame for our content
nsIFrame* frame = nsnull;
presShell->GetPrimaryFrameFor(mContent, &frame);
if(frame != nsnull) {
// Get its origin
nsPoint origin;
frame->GetOrigin(origin);
// Get the union of all rectangles in this and continuation frames
nsRect rcFrame;
nsIFrame* next = frame;
do {
nsRect rect;
next->GetRect(rect);
rcFrame.UnionRect(rcFrame, rect);
next->GetNextInFlow(&next);
} while (nsnull != next);
// Find the frame parent whose content's tagName either matches
// the tagName passed in or is the document element.
nsCOMPtr<nsIContent> docElement = getter_AddRefs(doc->GetRootContent());
nsIFrame* parent = frame;
nsCOMPtr<nsIContent> parentContent;
frame->GetParent(&parent);
while (parent) {
parent->GetContent(getter_AddRefs(parentContent));
if (parentContent) {
// If we've hit the document element, break here
if (parentContent.get() == docElement.get()) {
break;
}
}
// Add the parent's origin to our own to get to the
// right coordinate system
nsPoint parentOrigin;
parent->GetOrigin(parentOrigin);
origin += parentOrigin;
parent->GetParent(&parent);
}
// For the origin, add in the border for the frame
const nsStyleBorder* border;
nsStyleCoord coord;
frame->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)border);
if (border) {
if (eStyleUnit_Coord == border->mBorder.GetLeftUnit()) {
origin.x += border->mBorder.GetLeft(coord).GetCoordValue();
}
if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) {
origin.y += border->mBorder.GetTop(coord).GetCoordValue();
}
}
// And subtract out the border for the parent
if (parent) {
const nsStyleBorder* parentBorder;
parent->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)parentBorder);
if (parentBorder) {
if (eStyleUnit_Coord == parentBorder->mBorder.GetLeftUnit()) {
origin.x -= parentBorder->mBorder.GetLeft(coord).GetCoordValue();
}
if (eStyleUnit_Coord == parentBorder->mBorder.GetTopUnit()) {
origin.y -= parentBorder->mBorder.GetTop(coord).GetCoordValue();
}
}
}
// Get the Presentation Context from the Shell
nsCOMPtr<nsIPresContext> context;
presShell->GetPresContext(getter_AddRefs(context));
if(context) {
// Get the scale from that Presentation Context
float scale;
context->GetTwipsToPixels(&scale);
// Convert to pixels using that scale
aRect.x = NSTwipsToIntPixels(origin.x, scale);
aRect.y = NSTwipsToIntPixels(origin.y, scale);
aRect.width = NSTwipsToIntPixels(rcFrame.width, scale);
aRect.height = NSTwipsToIntPixels(rcFrame.height, scale);
}
}
}
}
return res;
}
NS_IMETHODIMP
nsBoxObject::GetX(PRInt32* aResult)
{
nsRect rect;
GetOffsetRect(rect);
*aResult = rect.x;
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::GetY(PRInt32* aResult)
{
nsRect rect;
GetOffsetRect(rect);
*aResult = rect.y;
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::GetWidth(PRInt32* aResult)
{
nsRect rect;
GetOffsetRect(rect);
*aResult = rect.width;
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::GetHeight(PRInt32* aResult)
{
nsRect rect;
GetOffsetRect(rect);
*aResult = rect.height;
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::GetLookAndFeelMetric(const PRUnichar* aPropertyName,
PRUnichar** aResult)
{
nsCOMPtr<nsILookAndFeel> lookAndFeel(do_GetService(kLookAndFeelCID));
if (!lookAndFeel)
return NS_ERROR_FAILURE;
nsAutoString property(aPropertyName);
if (property.EqualsIgnoreCase("scrollbarStyle")) {
PRInt32 metricResult;
lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ScrollArrowStyle, metricResult);
switch (metricResult) {
case nsILookAndFeel::eMetric_ScrollArrowStyleBothAtBottom:
*aResult = nsXPIDLString::Copy(NS_LITERAL_STRING("doublebottom").get());
break;
case nsILookAndFeel::eMetric_ScrollArrowStyleBothAtEachEnd:
*aResult = nsXPIDLString::Copy(NS_LITERAL_STRING("double").get());
break;
case nsILookAndFeel::eMetric_ScrollArrowStyleBothAtTop:
*aResult = nsXPIDLString::Copy(NS_LITERAL_STRING("doubletop").get());
break;
default:
*aResult = nsXPIDLString::Copy(NS_LITERAL_STRING("single").get());
break;
}
}
else if (property.EqualsIgnoreCase("thumbStyle")) {
PRInt32 metricResult;
lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ScrollSliderStyle, metricResult);
if ( metricResult == nsILookAndFeel::eMetric_ScrollThumbStyleNormal )
*aResult = nsXPIDLString::Copy(NS_LITERAL_STRING("fixed").get());
else
*aResult = nsXPIDLString::Copy(NS_LITERAL_STRING("proportional").get());
}
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::GetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports** aResult)
{
if (!mPresState) {
*aResult = nsnull;
return NS_OK;
}
nsAutoString propertyName(aPropertyName);
return mPresState->GetStatePropertyAsSupports(propertyName, aResult); // Addref here.
}
NS_IMETHODIMP
nsBoxObject::SetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports* aValue)
{
if (!mPresState)
NS_NewPresState(getter_AddRefs(mPresState));
nsAutoString propertyName(aPropertyName);
return mPresState->SetStatePropertyAsSupports(propertyName, aValue);
}
NS_IMETHODIMP
nsBoxObject::GetProperty(const PRUnichar* aPropertyName, PRUnichar** aResult)
{
if (!mPresState) {
*aResult = nsnull;
return NS_OK;
}
nsAutoString propertyName(aPropertyName);
nsAutoString result;
nsresult rv = mPresState->GetStateProperty(propertyName, result);
if (NS_FAILED(rv))
return rv;
*aResult = nsXPIDLString::Copy(result.GetUnicode());
return NS_OK;
}
NS_IMETHODIMP
nsBoxObject::SetProperty(const PRUnichar* aPropertyName, const PRUnichar* aPropertyValue)
{
if (!mPresState)
NS_NewPresState(getter_AddRefs(mPresState));
nsAutoString propertyName(aPropertyName);
nsAutoString propertyValue(aPropertyValue);
return mPresState->SetStateProperty(propertyName, propertyValue);
}
NS_IMETHODIMP
nsBoxObject::RemoveProperty(const PRUnichar* aPropertyName)
{
if (!mPresState)
return NS_OK;
nsAutoString propertyName(aPropertyName);
return mPresState->RemoveStateProperty(propertyName);
}
/* string canCreateWrapper (in nsIIDPtr iid); */
NS_IMETHODIMP nsBoxObject::CanCreateWrapper(const nsIID * iid, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canCallMethod (in nsIIDPtr iid, in wstring methodName); */
NS_IMETHODIMP nsBoxObject::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canGetProperty (in nsIIDPtr iid, in wstring propertyName); */
NS_IMETHODIMP nsBoxObject::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
/* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
NS_IMETHODIMP nsBoxObject::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
{
nsCAutoString str("AllAccess");
*_retval = str.ToNewCString();
return NS_OK;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult
NS_NewBoxObject(nsIBoxObject** aResult)
{
*aResult = new nsBoxObject;
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,585 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nscore.h"
#include "nsIStringBundle.h"
#include "nsImportFieldMap.h"
#include "nsImportStringBundle.h"
#include "ImportDebug.h"
////////////////////////////////////////////////////////////////////////
NS_METHOD nsImportFieldMap::Create( nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
nsImportFieldMap *it = new nsImportFieldMap();
if (it == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF( it);
nsresult rv = it->QueryInterface( aIID, aResult);
NS_RELEASE( it);
return rv;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsImportFieldMap, nsIImportFieldMap)
nsImportFieldMap::nsImportFieldMap()
{
NS_INIT_ISUPPORTS();
m_numFields = 0;
m_pFields = nsnull;
m_pActive = nsnull;
m_allocated = 0;
// need to init the description array
m_mozFieldCount = 0;
nsIStringBundle *pBundle = nsImportStringBundle::GetStringBundleProxy();
nsString *pStr;
for (PRInt32 i = IMPORT_FIELD_DESC_START; i <= IMPORT_FIELD_DESC_END; i++, m_mozFieldCount++) {
pStr = new nsString();
if (pBundle) {
nsImportStringBundle::GetStringByID( i, *pStr, pBundle);
}
else
pStr->AppendInt( i);
m_descriptions.AppendElement( (void *)pStr);
}
NS_IF_RELEASE( pBundle);
}
nsImportFieldMap::~nsImportFieldMap()
{
if (m_pFields)
delete [] m_pFields;
if (m_pActive)
delete [] m_pActive;
nsString * pStr;
for (PRInt32 i = 0; i < m_mozFieldCount; i++) {
pStr = (nsString *) m_descriptions.ElementAt( i);
delete pStr;
}
m_descriptions.Clear();
}
NS_IMETHODIMP nsImportFieldMap::GetNumMozFields(PRInt32 *aNumFields)
{
NS_PRECONDITION(aNumFields != nsnull, "null ptr");
if (!aNumFields)
return NS_ERROR_NULL_POINTER;
*aNumFields = m_mozFieldCount;
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::GetMapSize(PRInt32 *aNumFields)
{
NS_PRECONDITION(aNumFields != nsnull, "null ptr");
if (!aNumFields)
return NS_ERROR_NULL_POINTER;
*aNumFields = m_numFields;
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::GetFieldDescription(PRInt32 index, PRUnichar **_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
*_retval = nsnull;
if ((index < 0) || (index >= m_descriptions.Count()))
return( NS_ERROR_FAILURE);
*_retval = ((nsString *)m_descriptions.ElementAt( index))->ToNewUnicode();
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::SetFieldMapSize(PRInt32 size)
{
nsresult rv = Allocate( size);
if (NS_FAILED( rv))
return( rv);
m_numFields = size;
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::DefaultFieldMap(PRInt32 size)
{
nsresult rv = SetFieldMapSize( size);
if (NS_FAILED( rv))
return( rv);
for (PRInt32 i = 0; i < size; i++) {
m_pFields[i] = i;
m_pActive[i] = PR_TRUE;
}
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::GetFieldMap(PRInt32 index, PRInt32 *_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return NS_ERROR_NULL_POINTER;
if ((index < 0) || (index >= m_numFields))
return( NS_ERROR_FAILURE);
*_retval = m_pFields[index];
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::SetFieldMap(PRInt32 index, PRInt32 fieldNum)
{
if (index == -1) {
nsresult rv = Allocate( m_numFields + 1);
if (NS_FAILED( rv))
return( rv);
index = m_numFields;
m_numFields++;
}
else {
if ((index < 0) || (index >= m_numFields))
return( NS_ERROR_FAILURE);
}
if ((fieldNum != -1) && ((fieldNum < 0) || (fieldNum >= m_mozFieldCount)))
return( NS_ERROR_FAILURE);
m_pFields[index] = fieldNum;
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::SetFieldMapByDescription(PRInt32 index, const PRUnichar *fieldDesc)
{
NS_PRECONDITION(fieldDesc != nsnull, "null ptr");
if (!fieldDesc)
return NS_ERROR_NULL_POINTER;
PRInt32 i = FindFieldNum( fieldDesc);
if (i == -1)
return( NS_ERROR_FAILURE);
return( SetFieldMap( index, i));
}
NS_IMETHODIMP nsImportFieldMap::GetFieldActive(PRInt32 index, PRBool *active)
{
NS_PRECONDITION(active != nsnull, "null ptr");
if (!active)
return NS_ERROR_NULL_POINTER;
if ((index < 0) || (index >= m_numFields))
return( NS_ERROR_FAILURE);
*active = m_pActive[index];
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::SetFieldActive(PRInt32 index, PRBool active)
{
if ((index < 0) || (index >= m_numFields))
return( NS_ERROR_FAILURE);
m_pActive[index] = active;
return( NS_OK);
}
NS_IMETHODIMP nsImportFieldMap::SetFieldValue(nsIAddrDatabase *database, nsIMdbRow *row, PRInt32 fieldNum, const PRUnichar *value)
{
NS_PRECONDITION(database != nsnull, "null ptr");
NS_PRECONDITION(row != nsnull, "null ptr");
NS_PRECONDITION(value != nsnull, "null ptr");
if (!database || !row || !value)
return NS_ERROR_NULL_POINTER;
// Allow the special value for a null field
if (fieldNum == -1)
return( NS_OK);
if ((fieldNum < 0) || (fieldNum >= m_mozFieldCount))
return( NS_ERROR_FAILURE);
// UGGG!!!!! lot's of typing here!
nsresult rv;
nsString str(value);
char *pVal = str.ToNewUTF8String();
switch( fieldNum) {
case 0:
rv = database->AddFirstName( row, pVal);
break;
case 1:
rv = database->AddLastName( row, pVal);
break;
case 2:
rv = database->AddDisplayName( row, pVal);
break;
case 3:
rv = database->AddNickName( row, pVal);
break;
case 4:
rv = database->AddPrimaryEmail( row, pVal);
break;
case 5:
rv = database->Add2ndEmail( row, pVal);
break;
case 6:
rv = database->AddWorkPhone( row, pVal);
break;
case 7:
rv = database->AddHomePhone( row, pVal);
break;
case 8:
rv = database->AddFaxNumber( row, pVal);
break;
case 9:
rv = database->AddPagerNumber( row, pVal);
break;
case 10:
rv = database->AddCellularNumber( row, pVal);
break;
case 11:
rv = database->AddHomeAddress( row, pVal);
break;
case 12:
rv = database->AddHomeAddress2( row, pVal);
break;
case 13:
rv = database->AddHomeCity( row, pVal);
break;
case 14:
rv = database->AddHomeState( row, pVal);
break;
case 15:
rv = database->AddHomeZipCode( row, pVal);
break;
case 16:
rv = database->AddHomeCountry( row, pVal);
break;
case 17:
rv = database->AddWorkAddress( row, pVal);
break;
case 18:
rv = database->AddWorkAddress2( row, pVal);
break;
case 19:
rv = database->AddWorkCity( row, pVal);
break;
case 20:
rv = database->AddWorkState( row, pVal);
break;
case 21:
rv = database->AddWorkZipCode( row, pVal);
break;
case 22:
rv = database->AddWorkCountry( row, pVal);
break;
case 23:
rv = database->AddJobTitle(row, pVal);
break;
case 24:
rv = database->AddDepartment(row, pVal);
break;
case 25:
rv = database->AddCompany(row, pVal);
break;
case 26:
rv = database->AddWebPage1(row, pVal);
break;
case 27:
rv = database->AddWebPage2(row, pVal);
break;
case 28:
rv = database->AddBirthYear(row, pVal);
break;
case 29:
rv = database->AddBirthMonth(row, pVal);
break;
case 30:
rv = database->AddBirthDay(row, pVal);
break;
case 31:
rv = database->AddCustom1(row, pVal);
break;
case 32:
rv = database->AddCustom2(row, pVal);
break;
case 33:
rv = database->AddCustom3(row, pVal);
break;
case 34:
rv = database->AddCustom4(row, pVal);
break;
case 35:
rv = database->AddNotes(row, pVal);
break;
default:
/* Get the field description, and add it as an anonymous attr? */
/* OR WHAT???? */
{
rv = NS_ERROR_FAILURE;
}
}
nsCRT::free( pVal);
return( rv);
}
NS_IMETHODIMP nsImportFieldMap::SetFieldValueByDescription(nsIAddrDatabase *database, nsIMdbRow *row, const PRUnichar *fieldDesc, const PRUnichar *value)
{
NS_PRECONDITION(fieldDesc != nsnull, "null ptr");
if (!fieldDesc)
return NS_ERROR_NULL_POINTER;
PRInt32 i = FindFieldNum( fieldDesc);
if (i == -1)
return( NS_ERROR_FAILURE);
return( SetFieldValue( database, row, i, value));
}
NS_IMETHODIMP nsImportFieldMap::GetFieldValue(nsIAbCard *card, PRInt32 fieldNum, PRUnichar **_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
NS_PRECONDITION(card != nsnull, "null ptr");
if (!_retval || !card)
return NS_ERROR_NULL_POINTER;
if (fieldNum == -1) {
PRUnichar c = 0;
*_retval = nsCRT::strdup( &c);
return( NS_OK);
}
if ((fieldNum < 0) || (fieldNum >= m_mozFieldCount))
return( NS_ERROR_FAILURE);
// ARRGGG!!! Lots of typing again
// get the field from the card
nsresult rv;
PRUnichar * pVal = nsnull;
switch (fieldNum) {
case 0:
rv = card->GetFirstName( &pVal);
break;
case 1:
rv = card->GetLastName( &pVal);
break;
case 2:
rv = card->GetDisplayName( &pVal);
break;
case 3:
rv = card->GetNickName( &pVal);
break;
case 4:
rv = card->GetPrimaryEmail( &pVal);
break;
case 5:
rv = card->GetSecondEmail( &pVal);
break;
case 6:
rv = card->GetWorkPhone( &pVal);
break;
case 7:
rv = card->GetHomePhone( &pVal);
break;
case 8:
rv = card->GetFaxNumber( &pVal);
break;
case 9:
rv = card->GetPagerNumber( &pVal);
break;
case 10:
rv = card->GetCellularNumber( &pVal);
break;
case 11:
rv = card->GetHomeAddress( &pVal);
break;
case 12:
rv = card->GetHomeAddress2( &pVal);
break;
case 13:
rv = card->GetHomeCity( &pVal);
break;
case 14:
rv = card->GetHomeState( &pVal);
break;
case 15:
rv = card->GetHomeZipCode( &pVal);
break;
case 16:
rv = card->GetHomeCountry( &pVal);
break;
case 17:
rv = card->GetWorkAddress( &pVal);
break;
case 18:
rv = card->GetWorkAddress2( &pVal);
break;
case 19:
rv = card->GetWorkCity( &pVal);
break;
case 20:
rv = card->GetWorkState( &pVal);
break;
case 21:
rv = card->GetWorkZipCode( &pVal);
break;
case 22:
rv = card->GetWorkCountry( &pVal);
break;
case 23:
rv = card->GetJobTitle( &pVal);
break;
case 24:
rv = card->GetDepartment( &pVal);
break;
case 25:
rv = card->GetCompany( &pVal);
break;
case 26:
rv = card->GetWebPage1( &pVal);
break;
case 27:
rv = card->GetWebPage2( &pVal);
break;
case 28:
rv = card->GetBirthYear( &pVal);
break;
case 29:
rv = card->GetBirthMonth( &pVal);
break;
case 30:
rv = card->GetBirthDay( &pVal);
break;
case 31:
rv = card->GetCustom1( &pVal);
break;
case 32:
rv = card->GetCustom2( &pVal);
break;
case 33:
rv = card->GetCustom3( &pVal);
break;
case 34:
rv = card->GetCustom4( &pVal);
break;
case 35:
rv = card->GetNotes( &pVal);
break;
default:
/* Get the field description, and add it as an anonymous attr? */
/* OR WHAT???? */
{
rv = NS_ERROR_FAILURE;
}
}
*_retval = pVal;
return( rv);
}
NS_IMETHODIMP nsImportFieldMap::GetFieldValueByDescription(nsIAbCard *card, const PRUnichar *fieldDesc, PRUnichar **_retval)
{
NS_PRECONDITION(fieldDesc != nsnull, "null ptr");
if (!fieldDesc)
return NS_ERROR_NULL_POINTER;
PRInt32 i = FindFieldNum( fieldDesc);
if (i == -1)
return( NS_ERROR_FAILURE);
return( GetFieldValue( card, i, _retval));
}
nsresult nsImportFieldMap::Allocate( PRInt32 newSize)
{
if (newSize <= m_allocated)
return( NS_OK);
PRInt32 sz = m_allocated;
while (sz < newSize)
sz += 30;
PRInt32 *pData = new PRInt32[ sz];
if (!pData)
return( NS_ERROR_FAILURE);
PRBool *pActive = new PRBool[sz];
if (!pActive)
return( NS_ERROR_FAILURE);
PRInt32 i;
for (i = 0; i < sz; i++) {
pData[i] = -1;
pActive[i] = PR_TRUE;
}
if (m_numFields) {
for (i = 0; i < m_numFields; i++) {
pData[i] = m_pFields[i];
pActive[i] = m_pActive[i];
}
delete [] m_pFields;
delete [] m_pActive;
}
m_allocated = sz;
m_pFields = pData;
m_pActive = pActive;
return( NS_OK);
}
PRInt32 nsImportFieldMap::FindFieldNum( const PRUnichar *pDesc)
{
nsString * pStr;
for (PRInt32 i = 0; i < m_mozFieldCount; i++) {
pStr = (nsString *)m_descriptions.ElementAt( i);
if (!Compare(*pStr, nsAutoString(pDesc)))
return( i);
}
return( -1);
}

View File

@@ -1,795 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
/*
Text import addressbook interfaces
*/
#include "nscore.h"
#include "nsCRT.h"
#include "nsString.h"
#include "nsIServiceManager.h"
#include "nsIImportService.h"
#include "nsIComponentManager.h"
#include "nsTextImport.h"
#include "nsIMemory.h"
#include "nsIImportGeneric.h"
#include "nsIImportAddressBooks.h"
#include "nsIImportABDescriptor.h"
#include "nsIImportFieldMap.h"
#include "nsIOutputStream.h"
#include "nsIAddrDatabase.h"
#include "nsTextFormatter.h"
#include "nsTextStringBundle.h"
#include "nsIStringBundle.h"
#include "nsTextAddress.h"
#include "nsIPref.h"
#include "nsXPIDLString.h"
#include "nsProxiedService.h"
#include "TextDebugLog.h"
static NS_DEFINE_CID(kImportServiceCID, NS_IMPORTSERVICE_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
class ImportAddressImpl : public nsIImportAddressBooks
{
public:
ImportAddressImpl();
virtual ~ImportAddressImpl();
static nsresult Create(nsIImportAddressBooks** aImport);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIImportAddressBooks interface
/* PRBool GetSupportsMultiple (); */
NS_IMETHOD GetSupportsMultiple(PRBool *_retval) { *_retval = PR_FALSE; return( NS_OK);}
/* PRBool GetAutoFind (out wstring description); */
NS_IMETHOD GetAutoFind(PRUnichar **description, PRBool *_retval);
/* PRBool GetNeedsFieldMap (nsIFileSpec *location); */
NS_IMETHOD GetNeedsFieldMap(nsIFileSpec *location, PRBool *_retval);
/* void GetDefaultLocation (out nsIFileSpec location, out boolean found, out boolean userVerify); */
NS_IMETHOD GetDefaultLocation(nsIFileSpec **location, PRBool *found, PRBool *userVerify);
/* nsISupportsArray FindAddressBooks (in nsIFileSpec location); */
NS_IMETHOD FindAddressBooks(nsIFileSpec *location, nsISupportsArray **_retval);
/* nsISupports InitFieldMap(nsIFileSpec location, nsIImportFieldMap fieldMap); */
NS_IMETHOD InitFieldMap(nsIFileSpec *location, nsIImportFieldMap *fieldMap);
/* void ImportAddressBook (in nsIImportABDescriptor source, in nsISupports destination, in nsISupports fieldMap, out boolean fatalError); */
NS_IMETHOD ImportAddressBook( nsIImportABDescriptor *source,
nsIAddrDatabase * destination,
nsIImportFieldMap * fieldMap,
PRUnichar ** errorLog,
PRUnichar ** successLog,
PRBool * fatalError);
/* unsigned long GetImportProgress (); */
NS_IMETHOD GetImportProgress(PRUint32 *_retval);
NS_IMETHOD GetSampleData( PRInt32 index, PRBool *pFound, PRUnichar **pStr);
NS_IMETHOD SetSampleLocation( nsIFileSpec *);
private:
void ClearSampleFile( void);
void SaveFieldMap( nsIImportFieldMap *pMap);
static void ReportSuccess( nsString& name, nsString *pStream);
static void SetLogs( nsString& success, nsString& error, PRUnichar **pError, PRUnichar **pSuccess);
static void ReportError( PRInt32 errorNum, nsString& name, nsString *pStream);
static void SanitizeSampleData( nsCString& val);
private:
nsTextAddress m_text;
PRBool m_haveDelim;
nsIFileSpec * m_fileLoc;
char m_delim;
PRUint32 m_bytesImported;
};
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
nsTextImport::nsTextImport()
{
NS_INIT_REFCNT();
IMPORT_LOG0( "nsTextImport Module Created\n");
nsTextStringBundle::GetStringBundle();
}
nsTextImport::~nsTextImport()
{
IMPORT_LOG0( "nsTextImport Module Deleted\n");
}
NS_IMPL_ISUPPORTS1(nsTextImport, nsIImportModule)
NS_IMETHODIMP nsTextImport::GetName( PRUnichar **name)
{
NS_PRECONDITION(name != nsnull, "null ptr");
if (! name)
return NS_ERROR_NULL_POINTER;
*name = nsTextStringBundle::GetStringByID( TEXTIMPORT_NAME);
return NS_OK;
}
NS_IMETHODIMP nsTextImport::GetDescription( PRUnichar **name)
{
NS_PRECONDITION(name != nsnull, "null ptr");
if (! name)
return NS_ERROR_NULL_POINTER;
*name = nsTextStringBundle::GetStringByID( TEXTIMPORT_DESCRIPTION);
return NS_OK;
}
NS_IMETHODIMP nsTextImport::GetSupports( char **supports)
{
NS_PRECONDITION(supports != nsnull, "null ptr");
if (! supports)
return NS_ERROR_NULL_POINTER;
*supports = nsCRT::strdup( kTextSupportsString);
return( NS_OK);
}
NS_IMETHODIMP nsTextImport::GetSupportsUpgrade( PRBool *pUpgrade)
{
NS_PRECONDITION(pUpgrade != nsnull, "null ptr");
if (! pUpgrade)
return NS_ERROR_NULL_POINTER;
*pUpgrade = PR_FALSE;
return( NS_OK);
}
NS_IMETHODIMP nsTextImport::GetImportInterface( const char *pImportType, nsISupports **ppInterface)
{
NS_PRECONDITION(pImportType != nsnull, "null ptr");
if (! pImportType)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(ppInterface != nsnull, "null ptr");
if (! ppInterface)
return NS_ERROR_NULL_POINTER;
*ppInterface = nsnull;
nsresult rv;
if (!nsCRT::strcmp( pImportType, "addressbook")) {
// create the nsIImportMail interface and return it!
nsIImportAddressBooks * pAddress = nsnull;
nsIImportGeneric * pGeneric = nsnull;
rv = ImportAddressImpl::Create( &pAddress);
if (NS_SUCCEEDED( rv)) {
NS_WITH_SERVICE( nsIImportService, impSvc, kImportServiceCID, &rv);
if (NS_SUCCEEDED( rv)) {
rv = impSvc->CreateNewGenericAddressBooks( &pGeneric);
if (NS_SUCCEEDED( rv)) {
pGeneric->SetData( "addressInterface", pAddress);
rv = pGeneric->QueryInterface( kISupportsIID, (void **)ppInterface);
}
}
}
NS_IF_RELEASE( pAddress);
NS_IF_RELEASE( pGeneric);
return( rv);
}
return( NS_ERROR_NOT_AVAILABLE);
}
/////////////////////////////////////////////////////////////////////////////////
nsresult ImportAddressImpl::Create(nsIImportAddressBooks** aImport)
{
NS_PRECONDITION(aImport != nsnull, "null ptr");
if (! aImport)
return NS_ERROR_NULL_POINTER;
*aImport = new ImportAddressImpl();
if (! *aImport)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aImport);
return NS_OK;
}
ImportAddressImpl::ImportAddressImpl()
{
NS_INIT_REFCNT();
m_fileLoc = nsnull;
m_haveDelim = PR_FALSE;
}
ImportAddressImpl::~ImportAddressImpl()
{
if (m_fileLoc) {
PRBool open = PR_FALSE;
m_fileLoc->IsStreamOpen( &open);
if (open)
m_fileLoc->CloseStream();
NS_RELEASE( m_fileLoc);
}
}
NS_IMPL_THREADSAFE_ISUPPORTS1(ImportAddressImpl, nsIImportAddressBooks)
NS_IMETHODIMP ImportAddressImpl::GetAutoFind(PRUnichar **addrDescription, PRBool *_retval)
{
NS_PRECONDITION(addrDescription != nsnull, "null ptr");
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (! addrDescription || !_retval)
return NS_ERROR_NULL_POINTER;
nsString str;
*_retval = PR_FALSE;
nsTextStringBundle::GetStringByID( TEXTIMPORT_ADDRESS_NAME, str);
*addrDescription = str.ToNewUnicode();
return( NS_OK);
}
NS_IMETHODIMP ImportAddressImpl::GetDefaultLocation(nsIFileSpec **ppLoc, PRBool *found, PRBool *userVerify)
{
NS_PRECONDITION(found != nsnull, "null ptr");
NS_PRECONDITION(ppLoc != nsnull, "null ptr");
NS_PRECONDITION(userVerify != nsnull, "null ptr");
if (! found || !userVerify || !ppLoc)
return NS_ERROR_NULL_POINTER;
*ppLoc = nsnull;
*found = PR_FALSE;
*userVerify = PR_TRUE;
return( NS_OK);
}
NS_IMETHODIMP ImportAddressImpl::FindAddressBooks(nsIFileSpec *pLoc, nsISupportsArray **ppArray)
{
NS_PRECONDITION(pLoc != nsnull, "null ptr");
NS_PRECONDITION(ppArray != nsnull, "null ptr");
if (!pLoc || !ppArray)
return NS_ERROR_NULL_POINTER;
ClearSampleFile();
*ppArray = nsnull;
PRBool exists = PR_FALSE;
nsresult rv = pLoc->Exists( &exists);
if (NS_FAILED( rv) || !exists)
return( NS_ERROR_FAILURE);
PRBool isFile = PR_FALSE;
rv = pLoc->IsFile( &isFile);
if (NS_FAILED( rv) || !isFile)
return( NS_ERROR_FAILURE);
rv = m_text.DetermineDelim( pLoc);
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Error determining delimitter\n");
return( rv);
}
m_haveDelim = PR_TRUE;
m_delim = m_text.GetDelim();
m_fileLoc = pLoc;
NS_ADDREF( m_fileLoc);
/* Build an address book descriptor based on the file passed in! */
nsCOMPtr<nsISupportsArray> array;
rv = NS_NewISupportsArray( getter_AddRefs( array));
if (NS_FAILED( rv)) {
IMPORT_LOG0( "FAILED to allocate the nsISupportsArray\n");
return( rv);
}
NS_WITH_SERVICE( nsIImportService, impSvc, kImportServiceCID, &rv);
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Failed to obtain the import service\n");
return( rv);
}
nsXPIDLCString pName;
rv = pLoc->GetLeafName(getter_Copies(pName));
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Failed getting leaf name of file\n");
return( rv);
}
// for get unicode leafname. If it uses nsILocalFile interface,
// these codes do not need due to nsILocalFile->GetUnicodeLeafName()
nsString name;
rv = impSvc->SystemStringToUnicode((const char*) pName, name);
if (NS_FAILED(rv))
name.AssignWithConversion((const char*) pName);
PRInt32 idx = name.RFindChar( '.');
if ((idx != -1) && (idx > 0) && ((name.Length() - idx - 1) < 5)) {
nsString t;
name.Left( t, idx);
name = t;
}
nsCOMPtr<nsIImportABDescriptor> desc;
nsISupports * pInterface;
rv = impSvc->CreateNewABDescriptor( getter_AddRefs( desc));
if (NS_SUCCEEDED( rv)) {
PRUint32 sz = 0;
pLoc->GetFileSize( &sz);
desc->SetPreferredName( name.GetUnicode());
desc->SetSize( sz);
nsIFileSpec *pSpec = nsnull;
desc->GetFileSpec( &pSpec);
if (pSpec) {
pSpec->FromFileSpec( pLoc);
NS_RELEASE( pSpec);
}
rv = desc->QueryInterface( kISupportsIID, (void **) &pInterface);
array->AppendElement( pInterface);
pInterface->Release();
}
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Error creating address book descriptor for text import\n");
}
else {
rv = array->QueryInterface( NS_GET_IID(nsISupportsArray), (void **) ppArray);
}
return( rv);
}
void ImportAddressImpl::ReportSuccess( nsString& name, nsString *pStream)
{
if (!pStream)
return;
// load the success string
nsIStringBundle *pBundle = nsTextStringBundle::GetStringBundleProxy();
PRUnichar *pFmt = nsTextStringBundle::GetStringByID( TEXTIMPORT_ADDRESS_SUCCESS, pBundle);
PRUnichar *pText = nsTextFormatter::smprintf( pFmt, name.GetUnicode());
pStream->Append( pText);
nsTextFormatter::smprintf_free( pText);
nsTextStringBundle::FreeString( pFmt);
pStream->AppendWithConversion( LF);
NS_IF_RELEASE( pBundle);
}
void ImportAddressImpl::ReportError( PRInt32 errorNum, nsString& name, nsString *pStream)
{
if (!pStream)
return;
// load the error string
nsIStringBundle *pBundle = nsTextStringBundle::GetStringBundleProxy();
PRUnichar *pFmt = nsTextStringBundle::GetStringByID( errorNum, pBundle);
PRUnichar *pText = nsTextFormatter::smprintf( pFmt, name.GetUnicode());
pStream->Append( pText);
nsTextFormatter::smprintf_free( pText);
nsTextStringBundle::FreeString( pFmt);
pStream->AppendWithConversion( LF);
NS_IF_RELEASE( pBundle);
}
void ImportAddressImpl::SetLogs( nsString& success, nsString& error, PRUnichar **pError, PRUnichar **pSuccess)
{
if (pError)
*pError = error.ToNewUnicode();
if (pSuccess)
*pSuccess = success.ToNewUnicode();
}
NS_IMETHODIMP ImportAddressImpl::ImportAddressBook( nsIImportABDescriptor *pSource,
nsIAddrDatabase * pDestination,
nsIImportFieldMap * fieldMap,
PRUnichar ** pErrorLog,
PRUnichar ** pSuccessLog,
PRBool * fatalError)
{
NS_PRECONDITION(pSource != nsnull, "null ptr");
NS_PRECONDITION(pDestination != nsnull, "null ptr");
NS_PRECONDITION(fatalError != nsnull, "null ptr");
nsCOMPtr<nsIStringBundle> bundle( dont_AddRef( nsTextStringBundle::GetStringBundleProxy()));
m_bytesImported = 0;
nsString success;
nsString error;
if (!pSource || !pDestination || !fatalError) {
IMPORT_LOG0( "*** Bad param passed to text address import\n");
nsTextStringBundle::GetStringByID( TEXTIMPORT_ADDRESS_BADPARAM, error, bundle);
if (fatalError)
*fatalError = PR_TRUE;
SetLogs( success, error, pErrorLog, pSuccessLog);
return( NS_ERROR_NULL_POINTER);
}
ClearSampleFile();
PRBool addrAbort = PR_FALSE;
nsString name;
PRUnichar * pName;
if (NS_SUCCEEDED( pSource->GetPreferredName( &pName))) {
name = pName;
nsCRT::free( pName);
}
PRUint32 addressSize = 0;
pSource->GetSize( &addressSize);
if (addressSize == 0) {
IMPORT_LOG0( "Address book size is 0, skipping import.\n");
ReportSuccess( name, &success);
SetLogs( success, error, pErrorLog, pSuccessLog);
return( NS_OK);
}
nsIFileSpec * inFile;
if (NS_FAILED( pSource->GetFileSpec( &inFile))) {
ReportError( TEXTIMPORT_ADDRESS_BADSOURCEFILE, name, &error);
SetLogs( success, error, pErrorLog, pSuccessLog);
return( NS_ERROR_FAILURE);
}
#ifdef IMPORT_DEBUG
char *pPath;
inFile->GetNativePath( &pPath);
IMPORT_LOG1( "Import address book: %s\n", pPath);
nsCRT::free( pPath);
#endif
nsresult rv = NS_OK;
PRBool isLDIF = PR_FALSE;
rv = nsTextAddress::IsLDIFFile( inFile, &isLDIF);
if (NS_FAILED( rv)) {
inFile->Release();
ReportError( TEXTIMPORT_ADDRESS_CONVERTERROR, name, &error);
SetLogs( success, error, pErrorLog, pSuccessLog);
return( rv);
}
if (isLDIF) {
// This get's tricky, the database really requires the thing
// to have an .ldi extension so if it doesn't we may need to
// copy the file to a temp file with the correct name, then
// import it!
rv = m_text.ImportLDIF( &addrAbort, name.GetUnicode(), inFile, pDestination, error);
}
else {
rv = m_text.ImportAddresses( &addrAbort, name.GetUnicode(), inFile, pDestination, fieldMap, error, &m_bytesImported);
SaveFieldMap( fieldMap);
}
inFile->Release();
if (NS_SUCCEEDED( rv) && error.IsEmpty()) {
ReportSuccess( name, &success);
}
else {
ReportError( TEXTIMPORT_ADDRESS_CONVERTERROR, name, &error);
}
SetLogs( success, error, pErrorLog, pSuccessLog);
IMPORT_LOG0( "*** Text address import done\n");
return( rv);
}
NS_IMETHODIMP ImportAddressImpl::GetImportProgress(PRUint32 *_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
if (!_retval)
return( NS_ERROR_NULL_POINTER);
*_retval = m_bytesImported;
return( NS_OK);
}
NS_IMETHODIMP ImportAddressImpl::GetNeedsFieldMap(nsIFileSpec *location, PRBool *_retval)
{
NS_PRECONDITION(_retval != nsnull, "null ptr");
NS_PRECONDITION(location != nsnull, "null ptr");
if (!location || !_retval)
return( NS_ERROR_NULL_POINTER);
*_retval = PR_TRUE;
PRBool exists = PR_FALSE;
PRBool isFile = PR_FALSE;
nsresult rv = location->Exists( &exists);
rv = location->IsFile( &isFile);
if (!exists || !isFile)
return( NS_ERROR_FAILURE);
PRBool isLDIF = PR_FALSE;
rv = nsTextAddress::IsLDIFFile( location, &isLDIF);
if (NS_FAILED( rv)) {
IMPORT_LOG0( "*** Error determining if file is of type LDIF\n");
return( rv);
}
if (isLDIF)
*_retval = PR_FALSE;
return( NS_OK);
}
void ImportAddressImpl::SanitizeSampleData( nsCString& val)
{
// remove any line-feeds...
val.ReplaceSubstring( "\x0D\x0A", ", ");
val.ReplaceChar( 13, ',');
val.ReplaceChar( 10, ',');
}
NS_IMETHODIMP ImportAddressImpl::GetSampleData( PRInt32 index, PRBool *pFound, PRUnichar **pStr)
{
NS_PRECONDITION(pFound != nsnull, "null ptr");
NS_PRECONDITION(pStr != nsnull, "null ptr");
if (!pFound || !pStr)
return( NS_ERROR_NULL_POINTER);
if (!m_fileLoc) {
IMPORT_LOG0( "*** Error, called GetSampleData before SetSampleLocation\n");
return( NS_ERROR_FAILURE);
}
nsresult rv;
*pStr = nsnull;
PRBool open = PR_FALSE;
PRUnichar term = 0;
if (!m_haveDelim) {
rv = m_fileLoc->IsStreamOpen( &open);
if (open) {
m_fileLoc->CloseStream();
open = PR_FALSE;
}
rv = m_text.DetermineDelim( m_fileLoc);
if (NS_FAILED( rv))
return( rv);
m_haveDelim = PR_TRUE;
m_delim = m_text.GetDelim();
}
else {
rv = m_fileLoc->IsStreamOpen( &open);
}
if (!open) {
rv = m_fileLoc->OpenStreamForReading();
if (NS_FAILED( rv)) {
*pFound = PR_FALSE;
*pStr = nsCRT::strdup( &term);
return( NS_OK);
}
}
PRInt32 lineLen;
PRInt32 bufSz = 10240;
char *pLine = new char[bufSz];
NS_WITH_SERVICE( nsIImportService, impSvc, kImportServiceCID, &rv);
rv = nsTextAddress::ReadRecordNumber( m_fileLoc, pLine, bufSz, m_delim, &lineLen, index);
if (NS_SUCCEEDED( rv)) {
nsString str;
nsCString field;
nsString uField;
PRInt32 fNum = 0;
while (nsTextAddress::GetField( pLine, lineLen, fNum, field, m_delim)) {
if (fNum)
str.AppendWithConversion( "\n");
SanitizeSampleData( field);
if (impSvc)
impSvc->SystemStringToUnicode( field, uField);
else
uField.AssignWithConversion( field);
str.Append( uField);
fNum++;
field.Truncate();
}
*pStr = nsCRT::strdup( str.GetUnicode());
*pFound = PR_TRUE;
/* IMPORT_LOG1( "Sample data: %S\n", str.GetUnicode()); */
}
else {
*pFound = PR_FALSE;
*pStr = nsCRT::strdup( &term);
}
delete [] pLine;
return( NS_OK);
}
NS_IMETHODIMP ImportAddressImpl::SetSampleLocation( nsIFileSpec *pLocation)
{
NS_IF_RELEASE( m_fileLoc);
m_haveDelim = PR_FALSE;
m_fileLoc = pLocation;
NS_IF_ADDREF( m_fileLoc);
return( NS_OK);
}
void ImportAddressImpl::ClearSampleFile( void)
{
if (m_fileLoc) {
PRBool open = PR_FALSE;
m_fileLoc->IsStreamOpen( &open);
if (open)
m_fileLoc->CloseStream();
NS_RELEASE( m_fileLoc);
m_fileLoc = nsnull;
m_haveDelim = PR_FALSE;
}
}
NS_IMETHODIMP ImportAddressImpl::InitFieldMap(nsIFileSpec *location, nsIImportFieldMap *fieldMap)
{
// Let's remember the last one the user used!
// This should be normal for someone importing multiple times, it's usually
// from the same file format.
nsresult rv;
NS_WITH_SERVICE( nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_SUCCEEDED( rv)) {
nsXPIDLCString prefStr;
rv = prefs->CopyCharPref( "mailnews.import.text.fieldmap", getter_Copies(prefStr));
if (NS_SUCCEEDED( rv)) {
const char *pStr = (const char *)prefStr;
if (pStr) {
fieldMap->SetFieldMapSize( 0);
long fNum;
PRBool active;
long fIndex = 0;
while (*pStr) {
while (*pStr && (*pStr != '+') && (*pStr != '-'))
pStr++;
if (*pStr == '+')
active = PR_TRUE;
else if (*pStr == '-')
active = PR_FALSE;
else
break;
fNum = 0;
while (*pStr && ((*pStr < '0') || (*pStr > '9')))
pStr++;
if (!(*pStr))
break;
while (*pStr && (*pStr >= '0') && (*pStr <= '9')) {
fNum *= 10;
fNum += (*pStr - '0');
pStr++;
}
while (*pStr && (*pStr != ','))
pStr++;
if (*pStr == ',')
pStr++;
fieldMap->SetFieldMap( -1, fNum);
fieldMap->SetFieldActive( fIndex, active);
fIndex++;
}
if (!fIndex) {
int num;
fieldMap->GetNumMozFields( &num);
fieldMap->DefaultFieldMap( num);
}
}
}
}
return( NS_OK);
}
void ImportAddressImpl::SaveFieldMap( nsIImportFieldMap *pMap)
{
if (!pMap)
return;
int size;
int index;
PRBool active;
nsCString str;
pMap->GetMapSize( &size);
for (long i = 0; i < size; i++) {
index = i;
active = PR_FALSE;
pMap->GetFieldMap( i, &index);
pMap->GetFieldActive( i, &active);
if (active)
str.Append( '+');
else
str.Append( '-');
str.AppendInt( index);
str.Append( ',');
}
PRBool done = PR_FALSE;
nsresult rv;
// NS_WITH_PROXIED_SERVICE( nsIPref, prefs, kPrefServiceCID, NS_UI_THREAD_EVENTQ, &rv);
NS_WITH_SERVICE( nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_SUCCEEDED( rv)) {
nsXPIDLCString prefStr;
rv = prefs->CopyCharPref( "mailnews.import.text.fieldmap", getter_Copies(prefStr));
if (NS_SUCCEEDED( rv)) {
if (!Compare(str, nsCAutoString((const char *)prefStr)))
done = PR_TRUE;
}
if (!done) {
rv = prefs->SetCharPref( "mailnews.import.text.fieldmap", str);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,501 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIOService.h"
#include "nsIProtocolHandler.h"
#include "nscore.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsIFileTransportService.h"
#include "nsIURI.h"
#include "nsIStreamListener.h"
#include "prprf.h"
#include "nsLoadGroup.h"
#include "nsInputStreamChannel.h"
#include "nsXPIDLString.h"
#include "nsIErrorService.h"
#include "netCore.h"
#include "nsIObserverService.h"
static NS_DEFINE_CID(kFileTransportService, NS_FILETRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
static NS_DEFINE_CID(kErrorServiceCID, NS_ERRORSERVICE_CID);
////////////////////////////////////////////////////////////////////////////////
nsIOService::nsIOService()
: mOffline(PR_FALSE)
{
NS_INIT_REFCNT();
}
nsresult
nsIOService::Init()
{
nsresult rv = NS_OK;
// Hold onto the eventQueue service. We do not want any eventqueues to go away
// when we shutdown until we process all remaining transports
if (NS_SUCCEEDED(rv))
mEventQueueService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
// We need to get references to these services so that we can shut them
// down later. If we wait until the nsIOService is being shut down,
// GetService will fail at that point.
rv = nsServiceManager::GetService(kSocketTransportServiceCID,
NS_GET_IID(nsISocketTransportService),
getter_AddRefs(mSocketTransportService));
if (NS_FAILED(rv)) return rv;
rv = nsServiceManager::GetService(kFileTransportService,
NS_GET_IID(nsIFileTransportService),
getter_AddRefs(mFileTransportService));
if (NS_FAILED(rv)) return rv;
rv = nsServiceManager::GetService(kDNSServiceCID,
NS_GET_IID(nsIDNSService),
getter_AddRefs(mDNSService));
// XXX hack until xpidl supports error info directly (http://bugzilla.mozilla.org/show_bug.cgi?id=13423)
nsCOMPtr<nsIErrorService> errorService = do_GetService(kErrorServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_NETWORK, NECKO_MSGS_URL);
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_READ_FROM, "ReadFrom");
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_WROTE_TO, "WroteTo");
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_RESOLVING_HOST, "ResolvingHost");
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_CONNECTED_TO, "ConnectedTo");
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_SENDING_TO, "SendingTo");
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_RECEIVING_FROM, "ReceivingFrom");
if (NS_FAILED(rv)) return rv;
rv = errorService->RegisterErrorStringBundleKey(NS_NET_STATUS_CONNECTING_TO, "ConnectingTo");
if (NS_FAILED(rv)) return rv;
}
return rv;
}
nsIOService::~nsIOService()
{
(void)SetOffline(PR_TRUE);
if (mFileTransportService)
(void)mFileTransportService->Shutdown();
}
NS_METHOD
nsIOService::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
static nsISupports *_rValue = nsnull;
nsresult rv;
NS_ENSURE_NO_AGGREGATION(aOuter);
if (_rValue)
{
NS_ADDREF (_rValue);
*aResult = _rValue;
return NS_OK;
}
nsIOService* _ios = new nsIOService();
if (_ios == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(_ios);
rv = _ios->Init();
if (NS_FAILED(rv))
{
delete _ios;
return rv;
}
rv = _ios->QueryInterface(aIID, aResult);
if (NS_FAILED(rv))
{
delete _ios;
return rv;
}
_rValue = NS_STATIC_CAST (nsISupports*, *aResult);
NS_RELEASE (_rValue);
_rValue = nsnull;
return rv;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsIOService, nsIIOService);
////////////////////////////////////////////////////////////////////////////////
#define MAX_SCHEME_LENGTH 64 // XXX big enough?
#define MAX_NET_CONTRACTID_LENGTH (MAX_SCHEME_LENGTH + NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX_LENGTH + 1)
NS_IMETHODIMP
nsIOService::CacheProtocolHandler(const char *scheme, nsIProtocolHandler *handler)
{
for (unsigned int i=0; i<NS_N(gScheme); i++)
{
if (!nsCRT::strcasecmp(scheme, gScheme[i]))
{
nsresult rv;
NS_ASSERTION(!mWeakHandler[i], "Protocol handler already cached");
// Make sure the handler supports weak references.
nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(handler, &rv);
if (!factoryPtr)
{
// Dont cache handlers that dont support weak reference as
// there is real danger of a circular reference.
#ifdef DEBUG_dp
printf("DEBUG: %s protcol handler doesn't support weak ref. Not cached.\n", scheme);
#endif /* DEBUG_dp */
return NS_ERROR_FAILURE;
}
mWeakHandler[i] = getter_AddRefs(NS_GetWeakReference(handler));
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsIOService::GetCachedProtocolHandler(const char *scheme, nsIProtocolHandler **result)
{
for (unsigned int i=0; i<NS_N(gScheme); i++)
{
if (!nsCRT::strcasecmp(scheme, gScheme[i]))
if (mWeakHandler[i])
{
nsCOMPtr<nsIProtocolHandler> temp = do_QueryReferent(mWeakHandler[i]);
if (temp)
{
*result = temp.get();
NS_ADDREF(*result);
return NS_OK;
}
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsIOService::GetProtocolHandler(const char* scheme, nsIProtocolHandler* *result)
{
nsresult rv;
NS_ASSERTION(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX_LENGTH
== nsCRT::strlen(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX),
"need to fix NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX_LENGTH");
NS_ENSURE_ARG_POINTER(scheme);
// XXX we may want to speed this up by introducing our own protocol
// scheme -> protocol handler mapping, avoiding the string manipulation
// and service manager stuff
rv = GetCachedProtocolHandler(scheme, result);
if (NS_SUCCEEDED(rv)) return NS_OK;
char buf[MAX_NET_CONTRACTID_LENGTH];
nsCAutoString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX);
contractID += scheme;
contractID.ToLowerCase();
contractID.ToCString(buf, MAX_NET_CONTRACTID_LENGTH);
rv = nsServiceManager::GetService(buf, NS_GET_IID(nsIProtocolHandler), (nsISupports **)result);
if (NS_FAILED(rv))
{
// okay we don't have a protocol handler to handle this url type, so use the default protocol handler.
// this will cause urls to get dispatched out to the OS ('cause we can't do anything with them) when
// we try to read from a channel created by the default protocol handler.
rv = nsServiceManager::GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", NS_GET_IID(nsIProtocolHandler), (nsISupports **)result);
if (NS_FAILED(rv)) return NS_ERROR_UNKNOWN_PROTOCOL;
}
CacheProtocolHandler(scheme, *result);
return NS_OK;
}
NS_IMETHODIMP
nsIOService::ExtractScheme(const char* inURI, PRUint32 *startPos,
PRUint32 *endPos, char* *scheme)
{
return ExtractURLScheme(inURI, startPos, endPos, scheme);
}
nsresult
nsIOService::NewURI(const char* aSpec, nsIURI* aBaseURI,
nsIURI* *result, nsIProtocolHandler* *hdlrResult)
{
nsresult rv;
nsIURI* base;
NS_ENSURE_ARG_POINTER(aSpec);
char* scheme;
rv = ExtractScheme(aSpec, nsnull, nsnull, &scheme);
if (NS_SUCCEEDED(rv)) {
// then aSpec is absolute
// ignore aBaseURI in this case
base = nsnull;
}
else {
// then aSpec is relative
if (aBaseURI == nsnull)
return NS_ERROR_MALFORMED_URI;
rv = aBaseURI->GetScheme(&scheme);
if (NS_FAILED(rv)) return rv;
base = aBaseURI;
}
nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
nsCRT::free(scheme);
if (NS_FAILED(rv)) return rv;
if (hdlrResult) {
*hdlrResult = handler;
NS_ADDREF(*hdlrResult);
}
return handler->NewURI(aSpec, base, result);
}
NS_IMETHODIMP
nsIOService::NewURI(const char* aSpec, nsIURI* aBaseURI,
nsIURI* *result)
{
return NewURI(aSpec, aBaseURI, result, nsnull);
}
NS_IMETHODIMP
nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(aURI);
nsXPIDLCString scheme;
rv = aURI->GetScheme(getter_Copies(scheme));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler((const char*)scheme, getter_AddRefs(handler));
if (NS_FAILED(rv)) return rv;
rv = handler->NewChannel(aURI, result);
return rv;
}
NS_IMETHODIMP
nsIOService::NewChannel(const char *aSpec, nsIURI *aBaseURI, nsIChannel **result)
{
nsresult rv;
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIProtocolHandler> handler;
rv = NewURI(aSpec, aBaseURI, getter_AddRefs(uri), getter_AddRefs(handler));
if (NS_FAILED(rv)) return rv;
rv = handler->NewChannel(uri, result);
return rv;
}
NS_IMETHODIMP
nsIOService::GetOffline(PRBool *offline)
{
*offline = mOffline;
return NS_OK;
}
NS_IMETHODIMP
nsIOService::SetOffline(PRBool offline)
{
nsCOMPtr<nsIObserverService>
observerService(do_GetService(NS_OBSERVERSERVICE_CONTRACTID));
nsresult rv1 = NS_OK;
nsresult rv2 = NS_OK;
if (offline) {
mOffline = PR_TRUE; // indicate we're trying to shutdown
// be sure to try and shutdown both (even if the first fails)
if (mDNSService)
rv1 = mDNSService->Shutdown(); // shutdown dns service first, because it has callbacks for socket transport
if (mSocketTransportService)
rv2 = mSocketTransportService->Shutdown();
if (NS_FAILED(rv1)) return rv1;
if (NS_FAILED(rv2)) return rv2;
// don't care if notification fails
if (observerService)
(void)observerService->Notify(this,
NS_LITERAL_STRING("network:offline-status-changed").get(),
NS_LITERAL_STRING("offline").get());
}
else if (!offline && mOffline) {
// go online
if (mDNSService)
rv1 = mDNSService->Init();
if (NS_FAILED(rv2)) return rv1;
if (mSocketTransportService)
rv2 = mSocketTransportService->Init(); //XXX should we shutdown the dns service?
if (NS_FAILED(rv2)) return rv1;
mOffline = PR_FALSE; // indicate success only AFTER we've
// brought up the services
// don't care if notification fails
if (observerService)
(void)observerService->Notify(this,
NS_LITERAL_STRING("network:offline-status-changed").get(),
NS_LITERAL_STRING("online").get());
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// URL parsing utilities
/* encode characters into % escaped hexcodes */
/* use the following masks to specify which
part of an URL you want to escape:
url_Scheme = 1
url_Username = 2
url_Password = 4
url_Host = 8
url_Directory = 16
url_FileBaseName = 32
url_FileExtension = 64
url_Param = 128
url_Query = 256
url_Ref = 512
*/
/* by default this function will not escape parts of a string
that already look escaped, which means it already includes
a valid hexcode. This is done to avoid multiple escapes of
a string. Use the following mask to force escaping of a
string:
url_Forced = 1024
*/
NS_IMETHODIMP
nsIOService::Escape(const char *str, PRInt16 mask, char** result)
{
nsCAutoString esc_str;
nsresult rv = nsURLEscape((char*)str,mask,esc_str);
CRTFREEIF(*result);
if (NS_FAILED(rv))
return rv;
*result = esc_str.ToNewCString();
if (!*result)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsIOService::Unescape(const char *str, char **result)
{
return nsURLUnescape((char*)str,result);
}
NS_IMETHODIMP
nsIOService::ExtractPort(const char *str, PRInt32 *result)
{
PRInt32 returnValue = -1;
*result = (0 < PR_sscanf(str, "%d", &returnValue)) ? returnValue : -1;
return NS_OK;
}
NS_IMETHODIMP
nsIOService::ResolveRelativePath(const char *relativePath, const char* basePath,
char **result)
{
nsCAutoString name;
nsCAutoString path(basePath);
PRBool needsDelim = PR_FALSE;
if ( !path.IsEmpty() ) {
PRUnichar last = path.Last();
needsDelim = !(last == '/' || last == '\\' );
}
PRBool end = PR_FALSE;
char c;
while (!end) {
c = *relativePath++;
switch (c) {
case '\0':
case '#':
case ';':
case '?':
end = PR_TRUE;
// fall through...
case '/':
case '\\':
// delimiter found
if (name.Equals("..")) {
// pop path
PRInt32 pos = path.RFind("/");
if (pos > 0) {
path.Truncate(pos + 1);
path += name;
}
else {
return NS_ERROR_MALFORMED_URI;
}
}
else if (name.Equals(".") || name.Equals("")) {
// do nothing
}
else {
// append name to path
if (needsDelim)
path += "/";
path += name;
needsDelim = PR_TRUE;
}
name = "";
break;
default:
// append char to name
name += c;
}
}
// append anything left on relativePath (e.g. #..., ;..., ?...)
if (c != '\0')
path += --relativePath;
*result = path.ToNewCString();
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,789 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Notes:
* The logging sink is now both a sink and a proxy.
* If you want to dump the calls from the parser to the sink,
* create a content sink as usual and hand it to the parser.
*
* If you want to use a normal sink AND simultaneously have a
* parse-log generated, you can set an environment variable
* and a logging sink will be created. It will act as a proxy
* to the REAL sink you are using after it logs the call. This
* form of the loggingsink is constructed using the version
* that accepts an nsIHTMLContentSink*.
*
* Contributor(s):
*/
#include "nsLoggingSink.h"
#include "nsHTMLTags.h"
#include "nsString.h"
#include "prprf.h"
static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kILoggingSinkIID, NS_ILOGGING_SINK_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
// list of tags that have skipped content
static char gSkippedContentTags[] = {
eHTMLTag_style,
eHTMLTag_script,
eHTMLTag_server,
eHTMLTag_textarea,
eHTMLTag_title,
0
};
nsresult
NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
nsLoggingSink* it = new nsLoggingSink();
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(kIContentSinkIID, (void**) aInstancePtrResult);
}
nsLoggingSink::nsLoggingSink() {
NS_INIT_REFCNT();
mOutput = 0;
mLevel=-1;
mSink=0;
}
nsLoggingSink::~nsLoggingSink() {
mSink=0;
if(mOutput && mAutoDeleteOutput) {
delete mOutput;
}
mOutput=0;
}
NS_IMPL_ADDREF(nsLoggingSink)
NS_IMPL_RELEASE(nsLoggingSink)
nsresult
nsLoggingSink::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_PRECONDITION(nsnull != aInstancePtr, "null ptr");
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kISupportsIID)) {
nsISupports* tmp = this;
*aInstancePtr = (void*) tmp;
}
else if (aIID.Equals(kIContentSinkIID)) {
nsIContentSink* tmp = this;
*aInstancePtr = (void*) tmp;
}
else if (aIID.Equals(kIHTMLContentSinkIID)) {
nsIHTMLContentSink* tmp = this;
*aInstancePtr = (void*) tmp;
}
else if (aIID.Equals(kILoggingSinkIID)) {
nsILoggingSink* tmp = this;
*aInstancePtr = (void*) tmp;
}
else {
*aInstancePtr = nsnull;
return NS_NOINTERFACE;
}
NS_ADDREF(this);
return NS_OK;
}
NS_IMETHODIMP
nsLoggingSink::SetOutputStream(PRFileDesc *aStream,PRBool autoDeleteOutput) {
mOutput = aStream;
mAutoDeleteOutput=autoDeleteOutput;
return NS_OK;
}
static
void WriteTabs(PRFileDesc * out,int aTabCount) {
int tabs;
for(tabs=0;tabs<aTabCount;tabs++)
PR_fprintf(out, " ");
}
NS_IMETHODIMP
nsLoggingSink::WillBuildModel() {
WriteTabs(mOutput,++mLevel);
PR_fprintf(mOutput, "<begin>\n");
//proxy the call to the real sink if you have one.
if(mSink) {
mSink->WillBuildModel();
}
return NS_OK;
}
NS_IMETHODIMP
nsLoggingSink::DidBuildModel(PRInt32 aQualityLevel) {
WriteTabs(mOutput,--mLevel);
PR_fprintf(mOutput, "</begin>\n");
//proxy the call to the real sink if you have one.
nsresult theResult=NS_OK;
if(mSink) {
theResult=mSink->DidBuildModel(aQualityLevel);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::WillInterrupt() {
nsresult theResult=NS_OK;
//proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->WillInterrupt();
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::WillResume() {
nsresult theResult=NS_OK;
//proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->WillResume();
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::SetParser(nsIParser* aParser) {
nsresult theResult=NS_OK;
//proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->SetParser(aParser);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenContainer(const nsIParserNode& aNode) {
OpenNode("container", aNode); //do the real logging work...
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenContainer(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseContainer(const nsIParserNode& aNode) {
nsresult theResult=NS_OK;
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const char* tag = nsHTMLTags::GetStringValue(nodeType);
theResult=CloseNode(tag);
}
else theResult= CloseNode("???");
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseContainer(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::AddLeaf(const nsIParserNode& aNode) {
LeafNode(aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddLeaf(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::NotifyError(const nsParserError* aError) {
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->NotifyError(aError);
}
return theResult;
}
/**
* This gets called by the parser when you want to add
* a PI node to the current container in the content
* model.
*
* @updated gess 3/25/98
* @param
* @return
*/
NS_IMETHODIMP
nsLoggingSink::AddProcessingInstruction(const nsIParserNode& aNode){
#ifdef VERBOSE_DEBUG
DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
#endif
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddProcessingInstruction(aNode);
}
return theResult;
}
/**
* This gets called by the parser when it encounters
* a DOCTYPE declaration in the HTML document.
*/
NS_IMETHODIMP
nsLoggingSink::AddDocTypeDecl(const nsIParserNode& aNode, PRInt32 aMode) {
#ifdef VERBOSE_DEBUG
DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
#endif
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddDocTypeDecl(aNode,aMode);
}
return theResult;
}
/**
* This gets called by the parser when you want to add
* a comment node to the current container in the content
* model.
*
* @updated gess 3/25/98
* @param
* @return
*/
NS_IMETHODIMP
nsLoggingSink::AddComment(const nsIParserNode& aNode){
#ifdef VERBOSE_DEBUG
DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
#endif
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddComment(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::SetTitle(const nsString& aValue) {
char* tmp;
GetNewCString(aValue, &tmp);
WriteTabs(mOutput,++mLevel);
if(tmp) {
PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp);
nsMemory::Free(tmp);
}
--mLevel;
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->SetTitle(aValue);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenHTML(const nsIParserNode& aNode) {
OpenNode("html", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenHTML(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseHTML(const nsIParserNode& aNode) {
CloseNode("html");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseHTML(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenHead(const nsIParserNode& aNode) {
OpenNode("head", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenHead(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseHead(const nsIParserNode& aNode) {
CloseNode("head");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseHead(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenBody(const nsIParserNode& aNode) {
OpenNode("body", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenBody(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseBody(const nsIParserNode& aNode) {
CloseNode("body");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseBody(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenForm(const nsIParserNode& aNode) {
OpenNode("form", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenForm(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseForm(const nsIParserNode& aNode) {
CloseNode("form");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseForm(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenMap(const nsIParserNode& aNode) {
OpenNode("map", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenMap(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseMap(const nsIParserNode& aNode) {
CloseNode("map");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseMap(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::OpenFrameset(const nsIParserNode& aNode) {
OpenNode("frameset", aNode);
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenFrameset(aNode);
}
return theResult;
}
NS_IMETHODIMP
nsLoggingSink::CloseFrameset(const nsIParserNode& aNode) {
CloseNode("frameset");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->CloseFrameset(aNode);
}
return theResult;
}
nsresult
nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) {
WriteTabs(mOutput,++mLevel);
PR_fprintf(mOutput,"<open container=");
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const char* tag = nsHTMLTags::GetStringValue(nodeType);
PR_fprintf(mOutput, "\"%s\"", tag);
}
else {
char* text;
GetNewCString(aNode.GetText(), &text);
if(text) {
PR_fprintf(mOutput, "\"%s\"", text);
nsMemory::Free(text);
}
}
if (WillWriteAttributes(aNode)) {
PR_fprintf(mOutput, ">\n");
WriteAttributes(aNode);
PR_fprintf(mOutput, "</open>\n");
}
else {
PR_fprintf(mOutput, ">\n");
}
return NS_OK;
}
nsresult
nsLoggingSink::CloseNode(const char* aKind) {
WriteTabs(mOutput,mLevel--);
PR_fprintf(mOutput, "<close container=\"%s\">\n", aKind);
return NS_OK;
}
nsresult
nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) {
WriteTabs(mOutput,1+mLevel);
nsAutoString tmp;
PRInt32 ac = aNode.GetAttributeCount();
for (PRInt32 i = 0; i < ac; i++) {
char* key=nsnull;
char* value=nsnull;
const nsAReadableString& k = aNode.GetKeyAt(i);
const nsString& v = aNode.GetValueAt(i);
GetNewCString(k, &key);
if(key) {
PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", key);
nsMemory::Free(key);
}
tmp.Truncate();
tmp.Append(v);
if(tmp.Length() > 0) {
PRUnichar first = tmp.First();
if ((first == '"') || (first == '\'')) {
if (tmp.Last() == first) {
tmp.Cut(0, 1);
PRInt32 pos = tmp.Length() - 1;
if (pos >= 0) {
tmp.Cut(pos, 1);
}
} else {
// Mismatched quotes - leave them in
}
}
GetNewCString(tmp, &value);
if(value) {
PR_fprintf(mOutput, "%s\"/>\n", value);
WriteTabs(mOutput,1+mLevel);
nsMemory::Free(value);
}
}
}
if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
char* content;
GetNewCString(aNode.GetSkippedContent(), &content);
if(content) {
PR_fprintf(mOutput, " <content value=\"");
PR_fprintf(mOutput, "%s\"/>\n", content) ;
nsMemory::Free(content);
}
}
WriteTabs(mOutput,1+mLevel);
return NS_OK;
}
PRBool
nsLoggingSink::WillWriteAttributes(const nsIParserNode& aNode)
{
PRInt32 ac = aNode.GetAttributeCount();
if (0 != ac) {
return PR_TRUE;
}
if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
const nsString& content = aNode.GetSkippedContent();
if (content.Length() > 0) {
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsLoggingSink::LeafNode(const nsIParserNode& aNode)
{
WriteTabs(mOutput,1+mLevel);
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const char* tag = nsHTMLTags::GetStringValue(nodeType);
if(tag)
PR_fprintf(mOutput, "<leaf tag=\"%s\"", tag);
else PR_fprintf(mOutput, "<leaf tag=\"???\"");
if (WillWriteAttributes(aNode)) {
PR_fprintf(mOutput, ">\n");
WriteAttributes(aNode);
PR_fprintf(mOutput, "</leaf>\n");
}
else {
PR_fprintf(mOutput, "/>\n");
}
}
else {
PRInt32 pos;
nsAutoString tmp;
char* str;
switch (nodeType) {
case eHTMLTag_whitespace:
case eHTMLTag_text:
GetNewCString(aNode.GetText(), &str);
if(str) {
PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str);
nsMemory::Free(str);
}
break;
case eHTMLTag_newline:
PR_fprintf(mOutput, "<newline/>\n");
break;
case eHTMLTag_entity:
tmp.Append(aNode.GetText());
tmp.Cut(0, 1);
pos = tmp.Length() - 1;
if (pos >= 0) {
tmp.Cut(pos, 1);
}
PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", tmp.GetBuffer());
break;
default:
NS_NOTREACHED("unsupported leaf node type");
}//switch
}
return NS_OK;
}
nsresult
nsLoggingSink::QuoteText(const nsAReadableString& aValue, nsString& aResult) {
aResult.Truncate();
/*
if you're stepping through the string anyway, why not use iterators instead of forcing the string to copy?
*/
nsPromiseFlatString flat(aValue);
const PRUnichar* cp = flat.get();
const PRUnichar* end = cp + aValue.Length();
while (cp < end) {
PRUnichar ch = *cp++;
if (ch == '"') {
aResult.AppendWithConversion("&quot;");
}
else if (ch == '&') {
aResult.AppendWithConversion("&amp;");
}
else if ((ch < 32) || (ch >= 127)) {
aResult.AppendWithConversion("&#");
aResult.AppendInt(PRInt32(ch), 10);
aResult.AppendWithConversion(';');
}
else {
aResult.Append(ch);
}
}
return NS_OK;
}
/**
* Use this method to convert nsString to char*.
* REMEMBER: Match this call with nsMemory::Free(aResult);
*
* @update 04/04/99 harishd
* @param aValue - The string value
* @param aResult - String coverted to char*.
*/
nsresult
nsLoggingSink::GetNewCString(const nsAReadableString& aValue, char** aResult)
{
nsresult result=NS_OK;
nsAutoString temp;
result=QuoteText(aValue,temp);
if(NS_SUCCEEDED(result)) {
if(temp.Length()>0) {
*aResult=temp.ToNewCString();
}
}
return result;
}
NS_IMETHODIMP
nsLoggingSink::DoFragment(PRBool aFlag)
{
return NS_OK;
}
/**
* This gets called when handling illegal contents, especially
* in dealing with tables. This method creates a new context.
*
* @update 04/04/99 harishd
* @param aPosition - The position from where the new context begins.
*/
NS_IMETHODIMP
nsLoggingSink::BeginContext(PRInt32 aPosition)
{
return NS_OK;
}
/**
* This method terminates any new context that got created by
* BeginContext and switches back to the main context.
*
* @update 04/04/99 harishd
* @param aPosition - Validates the end of a context.
*/
NS_IMETHODIMP
nsLoggingSink::EndContext(PRInt32 aPosition)
{
return NS_OK;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +0,0 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src obsolete
#ifdef ENABLE_TESTS
#DIRS += \
# tests
#endif
include $(topsrcdir)/config/rules.mk

View File

@@ -1,29 +0,0 @@
<html>
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is Mozilla.
-
- The Initial Developer of the Original Code is Netscape
- Communications. Portions created by Netscape Communications are
- Copyright (C) 2001 by Netscape Communications. All
- Rights Reserved.
-
- Contributor(s):
- Scott Collins <scc@mozilla.org> (original author)
-->
<body>
<h1><span class="LXRSHORTDESC">managing sequences of characters</span></h1>
<p>
<span class="LXRLONGDESC"></span>
</p>
</body>
</html>

View File

@@ -1,29 +0,0 @@
<html>
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is Mozilla.
-
- The Initial Developer of the Original Code is Netscape
- Communications. Portions created by Netscape Communications are
- Copyright (C) 2001 by Netscape Communications. All
- Rights Reserved.
-
- Contributor(s):
- Scott Collins <scc@mozilla.org> (original author)
-->
<body>
<h1><span class="LXRSHORTDESC">documentation aimed at programmers who are clients of the string library</span></h1>
<p>
<span class="LXRLONGDESC"></span>
</p>
</body>
</html>

View File

@@ -1,30 +0,0 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/*
* Mac build settings for the release string library
*/
#include "MacPrefix.h"
// while we're still a part of xpcom, make stuff get exported
#define _IMPL_NS_COM 1

View File

@@ -1,30 +0,0 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/*
* Mac build settings for the debug string library
*/
#include "MacPrefix_debug.h"
// while we're still a part of xpcom, make stuff get exported
#define _IMPL_NS_COM 1

Binary file not shown.

View File

@@ -1,34 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH=..
DIRS= public \
src \
obsolete \
#!if !defined(DISABLE_TESTS)
# tests \
#!endif
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,27 +0,0 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Scott Collins <scc@mozilla.org> (original author)
#
nsStr.h
nsString.h
nsString2.h
nsXPIDLString.h

View File

@@ -1,58 +0,0 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
LIBRARY_NAME = string_obsolete_s
REQUIRES = unicharutil xpcom
CPPSRCS = \
nsStr.cpp \
nsString.cpp \
nsString2.cpp \
nsXPIDLString.cpp \
$(NULL)
EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
nsXPIDLString.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_COM -D_IMPL_NS_BASE

View File

@@ -1,35 +0,0 @@
<html>
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is Mozilla.
-
- The Initial Developer of the Original Code is Netscape
- Communications. Portions created by Netscape Communications are
- Copyright (C) 2001 by Netscape Communications. All
- Rights Reserved.
-
- Contributor(s):
- Scott Collins <scc@mozilla.org> (original author)
-->
<body>
<h1><span class="LXRSHORTDESC">original string implementations soon to be replaced (the names you are using will still be good)</span></h1>
<p>
<span class="LXRLONGDESC">These are the original string implementations by rickg and others.
Most of the code here will be made obsolete by the new shared-buffer string (see bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=53065">#53065</a>).
For the most part, this change is intended to be transparent to clients.
The type names you are using for strings now, e.g., nsString, nsAutoString, nsXPIDLString, will still be good,
they will just refer to better, but compatible, implementations.
If you're interested in learning how strings work, you probably want to start with
<a href="http://lxr.mozilla.org/seamonkey/source/string/public/nsAReadableString.h">nsAReadableString</a>.</span>
</p>
</body>
</html>

View File

@@ -1,971 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
/* bufferRoutines.h --- rickg's original string manipulation underpinnings;
this code will be made obsolete by the new shared-buffer string (see bug #53065)
*/
#ifndef _BUFFERROUTINES_H
#define _BUFFERROUTINES_H
/******************************************************************************************
MODULE NOTES:
This file contains the workhorse copy and shift functions used in nsStrStruct.
Ultimately, I plan to make the function pointers in this system available for
use by external modules. They'll be able to install their own "handlers".
Not so, today though.
*******************************************************************************************/
#include "nsCRT.h"
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
#include "nsUnicharUtilCIID.h"
#include "nsIServiceManager.h"
#include "nsICaseConversion.h"
#endif
#endif /* XPCOM_STANDALONE */
#define KSHIFTLEFT (0)
#define KSHIFTRIGHT (1)
// uncomment the following line to caught nsString char* casting problem
//#define DEBUG_ILLEGAL_CAST_UP
//#define DEBUG_ILLEGAL_CAST_DOWN
#if defined(DEBUG_ILLEGAL_CAST_UP) || defined(DEBUG_ILLEGAL_CAST_DOWN)
static PRBool track_illegal = PR_TRUE;
static PRBool track_latin1 = PR_TRUE;
#ifdef XP_UNIX
#include "nsTraceRefcnt.h"
class CTraceFile {
public:
CTraceFile() {
mFile = fopen("nsStringTrace.txt" , "a+");
}
~CTraceFile() {
fflush(mFile);
fclose(mFile);
}
void ReportCastUp(const char* data, const char* msg)
{
if(mFile) {
fprintf(mFile, "ERRORTEXT= %s\n", msg);
fprintf(mFile, "BEGINDATA\n");
const char* s=data;
while(*s) {
if(*s & 0x80) {
fprintf(mFile, "[%2X]", (char)*s);
} else {
fprintf(mFile, "%c", *s);
}
s++;
}
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
}
}
void ReportCastDown(const PRUnichar* data, const char* msg)
{
if(mFile) {
fprintf(mFile, "ERRORTEXT=%s\n", msg);
fprintf(mFile, "BEGINDATA\n");
const PRUnichar* s=data;
while(*s) {
if(*s & 0xFF80) {
fprintf(mFile, "\\u%X", *s);
} else {
fprintf(mFile, "%c", *s);
}
s++;
}
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
}
}
private:
FILE* mFile;
};
static CTraceFile gTrace;
#define TRACE_ILLEGAL_CAST_UP(c, s, m) if(!(c)) gTrace.ReportCastUp(s,m);
#define TRACE_ILLEGAL_CAST_DOWN(c, s, m) if(!(c)) gTrace.ReportCastDown(s,m);
#else // XP_UNIX
#define TRACE_ILLEGAL_CAST_UP(c, s, m) NS_ASSERTION((c), (m))
#define TRACE_ILLEGAL_CAST_DOWN(c, s, m) NS_ASSERTION((c), (m))
#endif //XP_UNIX
#endif
inline PRUnichar GetUnicharAt(const char* aString,PRUint32 anIndex) {
return ((PRUnichar*)aString)[anIndex];
}
inline PRUnichar GetCharAt(const char* aString,PRUint32 anIndex) {
return (PRUnichar)aString[anIndex];
}
//----------------------------------------------------------------------------------------
//
// This set of methods is used to shift the contents of a char buffer.
// The functions are differentiated by shift direction and the underlying charsize.
//
/**
* This method shifts single byte characters left by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where left-shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "cut"
*/
void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
char* dst = aDest+anOffset;
char* src = aDest+anOffset+aCount;
memmove(dst,src,aLength-(aCount+anOffset));
}
/**
* This method shifts single byte characters right by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "inserted"
*/
void ShiftCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
char* src = aDest+anOffset;
char* dst = aDest+anOffset+aCount;
memmove(dst,src,aLength-anOffset);
}
/**
* This method shifts unicode characters by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "cut"
*/
void ShiftDoubleCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* root=(PRUnichar*)aDest;
PRUnichar* dst = root+anOffset;
PRUnichar* src = root+anOffset+aCount;
memmove(dst,src,(aLength-(aCount+anOffset))*sizeof(PRUnichar));
}
/**
* This method shifts unicode characters by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "inserted"
*/
void ShiftDoubleCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* root=(PRUnichar*)aDest;
PRUnichar* src = root+anOffset;
PRUnichar* dst = root+anOffset+aCount;
memmove(dst,src,sizeof(PRUnichar)*(aLength-anOffset));
}
typedef void (*ShiftChars)(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
ShiftChars gShiftChars[2][2]= {
{&ShiftCharsLeft,&ShiftCharsRight},
{&ShiftDoubleCharsLeft,&ShiftDoubleCharsRight}
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to copy one buffer onto another.
// The functions are differentiated by the size of source and dest character sizes.
// WARNING: Your destination buffer MUST be big enough to hold all the source bytes.
// We don't validate these ranges here (this should be done in higher level routines).
//
/**
* Going 1 to 1 is easy, since we assume ascii. No conversions are necessary.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars1To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
char* dst = aDest+anDestOffset;
char* src = (char*)aSource+anOffset;
memcpy(dst,src,aCount);
}
/**
* Going 1 to 2 requires a conversion from ascii to unicode. This can be expensive.
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars1To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* theDest=(PRUnichar*)aDest;
PRUnichar* to = theDest+anDestOffset;
const unsigned char* first= (const unsigned char*)aSource+anOffset;
const unsigned char* last = first+aCount;
#ifdef DEBUG_ILLEGAL_CAST_UP
PRBool illegal= PR_FALSE;
#endif
//now loop over characters, shifting them left...
while(first<last) {
*to=(PRUnichar)(*first);
#ifdef DEBUG_ILLEGAL_CAST_UP
if(track_illegal && track_latin1 && ((*to)& 0x80))
illegal= PR_TRUE;
#endif
to++;
first++;
}
#ifdef DEBUG_ILLEGAL_CAST_UP
TRACE_ILLEGAL_CAST_UP((!illegal), aSource, "illegal cast up in CopyChars1To2");
#endif
}
/**
* Going 2 to 1 requires a conversion from unicode down to ascii. This can be lossy.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars2To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
char* to = aDest+anDestOffset;
PRUnichar* theSource=(PRUnichar*)aSource;
const PRUnichar* first= theSource+anOffset;
const PRUnichar* last = first+aCount;
#ifdef DEBUG_ILLEGAL_CAST_DOWN
PRBool illegal= PR_FALSE;
#endif
//now loop over characters, shifting them left...
while(first<last) {
if(*first<256)
*to=(char)*first;
else {
*to='.';
NS_ASSERTION( (*first < 256), "data in U+0100-U+FFFF will be lost");
}
#ifdef DEBUG_ILLEGAL_CAST_DOWN
if(track_illegal) {
if(track_latin1) {
if(*first & 0xFF80)
illegal = PR_TRUE;
} else {
if(*first & 0xFF00)
illegal = PR_TRUE;
} // track_latin1
} // track_illegal
#endif
to++;
first++;
}
#ifdef DEBUG_ILLEGAL_CAST_DOWN
TRACE_ILLEGAL_CAST_DOWN((!illegal), theSource, "illegal cast down in CopyChars2To1");
#endif
}
/**
* Going 2 to 2 is fast and efficient.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars2To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* theDest=(PRUnichar*)aDest;
PRUnichar* to = theDest+anDestOffset;
PRUnichar* theSource=(PRUnichar*)aSource;
PRUnichar* from= theSource+anOffset;
memcpy((void*)to,(void*)from,aCount*sizeof(PRUnichar));
}
//--------------------------------------------------------------------------------------
typedef void (*CopyChars)(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
CopyChars gCopyChars[2][2]={
{&CopyChars1To1,&CopyChars1To2},
{&CopyChars2To1,&CopyChars2To2}
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to search a buffer looking for a char.
//
/**
* This methods cans the given buffer for the given char
*
* @update gess 02/17/00
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=0;
if(aCount<0)
aCount = (PRInt32)aDestLength;
if((aChar<256) && (0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
//We'll only search if the given aChar is within the normal ascii a range,
//(Since this string is definitely within the ascii range).
if(0<aCount) {
const char* left= aDest+anOffset;
const char* last= left+aCount;
const char* max = aDest+aDestLength;
const char* end = (last<max) ? last : max;
if(aIgnoreCase) {
char theChar=(char)nsCRT::ToUpper(aChar);
while(left<end){
if(nsCRT::ToUpper(*left)==theChar)
return left-aDest;
++left;
}
}
else {
PRInt32 theMax = end-left;
if(0<theMax) {
unsigned char theChar = (unsigned char) aChar;
const char* result=(const char*)memchr(left, (int)theChar, theMax);
if(result) {
return result-aDest;
}
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer for the given char
*
* @update gess 3/25/98
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 FindChar2(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=0;
if(aCount<0)
aCount = (PRInt32)aDestLength;
if((0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
if(0<aCount) {
const PRUnichar* root = (PRUnichar*)aDest;
const PRUnichar* left = root+anOffset;
const PRUnichar* last = left+aCount;
const PRUnichar* max = root+aDestLength;
const PRUnichar* end = (last<max) ? last : max;
if(aIgnoreCase) {
PRUnichar theChar=nsCRT::ToUpper(aChar);
while(left<end){
if(nsCRT::ToUpper(*left)==theChar)
return left-root;
++left;
}
}
else {
while(left<end){
if(*left==aChar)
return (left-root);
++left;
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer (in reverse) for the given char
*
* @update gess 02/17/00
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDestLength-1;
if(aCount<0)
aCount = aDestLength;
if((aChar<256) && (0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
//We'll only search if the given aChar is within the normal ascii a range,
//(Since this string is definitely within the ascii range).
if(0<aCount) {
const char* rightmost = aDest+anOffset;
const char* min = rightmost-aCount+1;
const char* leftmost = (min<aDest) ? aDest: min;
if(aIgnoreCase) {
char theChar=(char)nsCRT::ToUpper(aChar);
while(leftmost<rightmost){
if(nsCRT::ToUpper(*rightmost)==theChar)
return rightmost-aDest;
--rightmost;
}
}
else {
char theChar=(char)aChar;
while(leftmost<=rightmost){
if((*rightmost)==theChar)
return rightmost-aDest;
--rightmost;
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer for the given char
*
* @update gess 3/25/98
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 RFindChar2(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDestLength-1;
if(aCount<0)
aCount = aDestLength;
if((0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
if(0<aCount) {
const PRUnichar* root = (PRUnichar*)aDest;
const PRUnichar* rightmost = root+anOffset;
const PRUnichar* min = rightmost-aCount+1;
const PRUnichar* leftmost = (min<root) ? root: min;
if(aIgnoreCase) {
PRUnichar theChar=nsCRT::ToUpper(aChar);
while(leftmost<rightmost){
if(nsCRT::ToUpper(*rightmost)==theChar)
return rightmost-root;
--rightmost;
}
}
else {
while(leftmost<=rightmost){
if((*rightmost)==aChar)
return rightmost-root;
--rightmost;
}
}
}
}
return kNotFound;
}
typedef PRInt32 (*FindChars)(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount);
FindChars gFindChars[]={&FindChar1,&FindChar2};
FindChars gRFindChars[]={&RFindChar1,&RFindChar2};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to compare one buffer onto another.
// The functions are differentiated by the size of source and dest character sizes.
// WARNING: Your destination buffer MUST be big enough to hold all the source bytes.
// We don't validate these ranges here (this should be done in higher level routines).
//
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result=0;
if(aIgnoreCase)
result=nsCRT::strncasecmp(aStr1,aStr2,aCount);
else result=memcmp(aStr1,aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result=0;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount);
else result=nsCRT::strncmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr1,aStr2,aCount);
else result=nsCRT::strncmp((PRUnichar*)aStr1,aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
else result=nsCRT::strncmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
return result;
}
typedef PRInt32 (*CompareChars)(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
CompareChars gCompare[2][2]={
{&Compare1To1,&Compare1To2},
{&Compare2To1,&Compare2To2},
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to convert the case of strings...
//
/**
* This method performs a case conversion the data in the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be case shifted
* @param aCount is the number of chars to compare
* @param aToUpper tells us whether to convert to upper or lower
* @return 0
*/
PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper){
PRInt32 result=0;
typedef char chartype;
chartype* cp = (chartype*)aString;
chartype* end = cp + aCount-1;
while (cp <= end) {
chartype ch = *cp;
if(aToUpper) {
if ((ch >= 'a') && (ch <= 'z')) {
*cp = 'A' + (ch - 'a');
}
}
else {
if ((ch >= 'A') && (ch <= 'Z')) {
*cp = 'a' + (ch - 'A');
}
}
cp++;
}
return result;
}
//----------------------------------------------------------------------------------------
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
class HandleCaseConversionShutdown3 : public nsIShutdownListener {
public :
NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service);
HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); }
virtual ~HandleCaseConversionShutdown3(void) {}
NS_DECL_ISUPPORTS
};
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
static nsICaseConversion * gCaseConv = 0;
NS_IMPL_ISUPPORTS1(HandleCaseConversionShutdown3, nsIShutdownListener);
nsresult HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) {
if (cid.Equals(kUnicharUtilCID)) {
NS_ASSERTION(service == gCaseConv, "wrong service!");
if(gCaseConv){
gCaseConv->Release();
gCaseConv = 0;
}
}
return NS_OK;
}
class CCaseConversionServiceInitializer {
public:
CCaseConversionServiceInitializer(){
HandleCaseConversionShutdown3* listener =
new HandleCaseConversionShutdown3();
if(listener){
nsServiceManager::GetService(kUnicharUtilCID, NS_GET_IID(nsICaseConversion),(nsISupports**) &gCaseConv, listener);
}
}
};
#endif
#endif /* XPCOM_STANDALONE */
//----------------------------------------------------------------------------------------
/**
* This method performs a case conversion the data in the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be case shifted
* @param aCount is the number of chars to compare
* @param aToUpper tells us whether to convert to upper or lower
* @return 0
*/
PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper){
PRUnichar* cp = (PRUnichar*)aString;
PRUnichar* end = cp + aCount-1;
PRInt32 result=0;
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
static CCaseConversionServiceInitializer gCaseConversionServiceInitializer;
// I18N code begin
if(gCaseConv) {
nsresult err=(aToUpper) ? gCaseConv->ToUpper(cp, cp, aCount) : gCaseConv->ToLower(cp, cp, aCount);
if(NS_SUCCEEDED(err))
return 0;
}
// I18N code end
#endif
#endif /* XPCOM_STANDALONE */
while (cp <= end) {
PRUnichar ch = *cp;
if(aToUpper) {
if ((ch >= 'a') && (ch <= 'z')) {
*cp = 'A' + (ch - 'a');
}
}
else {
if ((ch >= 'A') && (ch <= 'Z')) {
*cp = 'a' + (ch - 'A');
}
}
cp++;
}
return result;
}
typedef PRInt32 (*CaseConverters)(char*,PRUint32,PRBool);
CaseConverters gCaseConverters[]={&ConvertCase1,&ConvertCase2};
//----------------------------------------------------------------------------------------
//
// This set of methods is used compress char sequences in a buffer...
//
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update rickg 03.23.2000
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
char* from = aString;
char* end = aString + aLength;
char* to = from;
//this code converts /n, /t, /r into normal space ' ';
//it also compresses runs of whitespace down to a single char...
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (from < end) {
char theChar = *from++;
*to++=theChar; //always copy this char...
if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
while (from < end) {
theChar = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
break;
}
} //while
} //if
} //if
*to = 0;
}
return to - aString;
}
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update rickg 03.23.2000
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet){
PRUnichar* from = (PRUnichar*)aString;
PRUnichar* end = from + aLength;
PRUnichar* to = from;
//this code converts /n, /t, /r into normal space ' ';
//it also compresses runs of whitespace down to a single char...
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (from < end) {
PRUnichar theChar = *from++;
*to++=theChar; //always copy this char...
if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
while (from < end) {
theChar = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
break;
}
} //while
} //if
} //if
*to = 0;
}
return to - (PRUnichar*)aString;
}
typedef PRInt32 (*CompressChars)(char* aString,PRUint32 aCount,const char* aSet);
CompressChars gCompressChars[]={&CompressChars1,&CompressChars2};
/**
* This method strips chars in a given set from the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 StripChars1(char* aString,PRUint32 aLength,const char* aSet){
char* to = aString;
char* from = aString-1;
char* end = aString + aLength;
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (++from < end) {
char theChar = *from;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
}
}
*to = 0;
}
return to - (char*)aString;
}
/**
* This method strips chars in a given set from the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 StripChars2(char* aString,PRUint32 aLength,const char* aSet){
PRUnichar* to = (PRUnichar*)aString;
PRUnichar* from = (PRUnichar*)aString-1;
PRUnichar* end = to + aLength;
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (++from < end) {
PRUnichar theChar = *from;
//Note the test for ascii range below. If you have a real unicode char,
//and you're searching for chars in the (given) ascii string, there's no
//point in doing the real search since it's out of the ascii range.
if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
*to++ = theChar;
}
}
*to = 0;
}
return to - (PRUnichar*)aString;
}
typedef PRInt32 (*StripChars)(char* aString,PRUint32 aCount,const char* aSet);
StripChars gStripChars[]={&StripChars1,&StripChars2};
#endif

View File

@@ -1,50 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH=..\..
EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
nsXPIDLString.h \
$(NULL)
LIBRARY_NAME=string_obsolete_s
LCFLAGS = -D_IMPL_NS_COM -D_IMPL_NS_BASE -DWIN32_LEAN_AND_MEAN
CPP_OBJS = \
.\$(OBJDIR)\nsStr.obj \
.\$(OBJDIR)\nsString.obj \
.\$(OBJDIR)\nsString2.obj \
.\$(OBJDIR)\nsXPIDLString.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,921 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
#include "nsStr.h"
#include "bufferRoutines.h"
#include <stdio.h> //only used for printf
#include "nsCRT.h"
#include "nsDeque.h"
/******************************************************************************************
MODULE NOTES:
This file contains the nsStr data structure.
This general purpose buffer management class is used as the basis for our strings.
It's benefits include:
1. An efficient set of library style functions for manipulating nsStrs
2. Support for 1 and 2 byte character strings (which can easily be increased to n)
3. Unicode awareness and interoperability.
*******************************************************************************************/
//static const char* kCallFindChar = "For better performance, call FindChar() for targets whose length==1.";
//static const char* kCallRFindChar = "For better performance, call RFindChar() for targets whose length==1.";
static const PRUnichar gCommonEmptyBuffer[1] = {0};
static PRBool gStringAcquiredMemory = PR_TRUE;
/**
* This method initializes all the members of the nsStr structure
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
aDest.mStr=(char*)gCommonEmptyBuffer;
aDest.mLength=0;
aDest.mCapacity=0;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=0;
}
/**
* This method initializes all the members of the nsStr structure
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
aDest.mStr=(aCString) ? aCString : (char*)gCommonEmptyBuffer;
aDest.mLength=aLength;
aDest.mCapacity=aCapacity;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=aOwnsBuffer;
}
/**
* This member destroys the memory buffer owned by an nsStr object (if it actually owns it)
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Destroy(nsStr& aDest) {
if((aDest.mStr) && (aDest.mStr!=(char*)gCommonEmptyBuffer)) {
Free(aDest);
}
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents are not preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aString.mCapacity) {
result=Realloc(aString,aNewLength);
if(aString.mStr)
AddNullTerminator(aString);
}
return result;
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents ARE preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
#ifndef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
// the new strategy is, allocate exact size, double on grows
if ( aDest.mCapacity ) {
PRUint32 newCapacity = aDest.mCapacity;
while ( newCapacity < aNewLength )
newCapacity <<= 1;
aNewLength = newCapacity;
}
#endif
result=EnsureCapacity(theTempStr,aNewLength);
if(result) {
if(aDest.mLength) {
StrAppend(theTempStr,aDest,0,aDest.mLength);
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mLength=theTempStr.mLength;
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
return result;
}
/**
* Replaces the contents of aDest with aSource, up to aCount of chars.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed.
* @param aSource is where chars are copied from
* @param aCount is the number of chars copied from aSource
*/
void nsStr::StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(&aDest!=&aSource){
StrTruncate(aDest,0);
StrAppend(aDest,aSource,anOffset,aCount);
}
}
/**
* This method appends the given nsStr to this one. Note that we have to
* pay attention to the underlying char-size of both structs.
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aSource is where char are copied from
* @aCount is the number of bytes to be copied
*/
void nsStr::StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(anOffset<aSource.mLength){
PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRUint32 theLength=(anOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-anOffset);
if(0<theLength){
PRBool isBigEnough=PR_TRUE;
if(aDest.mLength+theLength > aDest.mCapacity) {
isBigEnough=GrowCapacity(aDest,aDest.mLength+theLength);
}
if(isBigEnough) {
//now append new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
}
}
/**
* This method inserts up to "aCount" chars from a source nsStr into a dest nsStr.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed
* @param aDestOffset is where in aDest the insertion is to occur
* @param aSource is where chars are copied from
* @param aSrcOffset is where in aSource chars are copied from
* @param aCount is the number of chars from aSource to be inserted into aDest
*/
void nsStr::StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
// 3. You're inserting onto the 1..n-1 pos of a string (the hard case).
if(0<aSource.mLength){
if(aDest.mLength){
if(aDestOffset<aDest.mLength){
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
if(aSrcOffset<aSource.mLength) {
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
PRBool isBigEnough=EnsureCapacity(theTempStr,aDest.mLength+theLength); //grow the temp buffer to the right size
if(isBigEnough) {
if(aDestOffset) {
StrAppend(theTempStr,aDest,0,aDestOffset); //first copy leftmost data...
}
StrAppend(theTempStr,aSource,0,aSource.mLength); //next copy inserted (new) data
PRUint32 theRemains=aDest.mLength-aDestOffset;
if(theRemains) {
StrAppend(theTempStr,aDest,aDestOffset,theRemains); //next copy rightmost data
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
else {
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
}
//finally, make sure to update the string length...
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}//if
//else nothing to do!
}
else StrAppend(aDest,aSource,0,aCount);
}
else StrAppend(aDest,aSource,0,aCount);
}
}
/**
* This method deletes up to aCount chars from aDest
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aDestOffset is where in aDest deletion is to occur
* @param aCount is the number of chars to be deleted in aDest
*/
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
if(aDestOffset<aDest.mLength){
PRUint32 theDelta=aDest.mLength-aDestOffset;
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
if(aDestOffset+theLength<aDest.mLength) {
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
else StrTruncate(aDest,aDestOffset);
}//if
}
/**
* This method truncates the given nsStr at given offset
* @update gess10/30/98
* @param aDest is the nsStr to be truncated
* @param aDestOffset is where in aDest truncation is to occur
*/
void nsStr::StrTruncate(nsStr& aDest,PRUint32 aDestOffset){
if(aDest.mCapacity && aDestOffset<=aDest.mCapacity){
aDest.mLength=aDestOffset;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
/**
* This method forces the given string to upper or lowercase
* @update gess1/7/99
* @param aDest is the string you're going to change
* @param aToUpper: if TRUE, then we go uppercase, otherwise we go lowercase
* @return
*/
void nsStr::ChangeCase(nsStr& aDest,PRBool aToUpper) {
// somehow UnicharUtil return failed, fallback to the old ascii only code
gCaseConverters[aDest.mCharSize](aDest.mStr,aDest.mLength,aToUpper);
}
/**
* This method removes characters from the given set from this string.
* NOTE: aSet is a char*, and it's length is computed using strlen, which assumes null termination.
*
* @update gess 11/7/99
* @param aDest
* @param aSet
* @param aEliminateLeading
* @param aEliminateTrailing
* @return nothing
*/
void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
if((aDest.mLength>0) && aSet){
PRInt32 theIndex=-1;
PRInt32 theMax=aDest.mLength;
PRInt32 theSetLen=nsCRT::strlen(aSet);
if(aEliminateLeading) {
while(++theIndex<=theMax) {
PRUnichar theChar=GetCharAt(aDest,theIndex);
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound==thePos)
break;
}
if(0<theIndex) {
if(theIndex<theMax) {
Delete(aDest,0,theIndex);
}
else StrTruncate(aDest,0);
}
}
if(aEliminateTrailing) {
theIndex=aDest.mLength;
PRInt32 theNewLen=theIndex;
while(--theIndex>=0) {
PRUnichar theChar=GetCharAt(aDest,theIndex); //read at end now...
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound<thePos)
theNewLen=theIndex;
else break;
}
if(theNewLen<theMax) {
StrTruncate(aDest,theNewLen);
}
}
}
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
Trim(aDest,aSet,aEliminateLeading,aEliminateTrailing);
PRUint32 aNewLen=gCompressChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::StripChars(nsStr& aDest,const char* aSet){
if((0<aDest.mLength) && (aSet)) {
PRUint32 aNewLen=gStripChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
}
/**************************************************************
Searching methods...
**************************************************************/
/**
* This searches aDest for a given substring
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tells us how many iterations to make from offset; -1 means the full length of the string
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
if(0<=theMaxPos) {
if(anOffset<0)
anOffset=0;
if((0<aDest.mLength) && (anOffset<=theMaxPos) && (aTarget.mLength)) {
if(aCount<0)
aCount = MaxInt(theMaxPos,1);
if(0<aCount) {
PRInt32 aDelta= (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* left = root+(anOffset*aDelta);
const char* last = left+((aCount)*aDelta);
const char* max = root+(theMaxPos*aDelta);
const char* right = (last<max) ? last : max;
while(left<=right){
PRInt32 cmp=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(left,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==cmp) {
return (left-root)/aDelta;
}
left+=aDelta;
} //while
} //if
}
} //if
return kNotFound;
}
/**
* This searches aDest for a given character
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tell us how many chars to search from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallFindChar);
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
PRInt32 thePos;
//Note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if((0<aDest.mLength) && (0<aSet.mLength)){
while(++index<(PRInt32)aDest.mLength) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**************************************************************
Reverse Searching methods...
**************************************************************/
/**
* This searches aDest (in reverse) for a given substring
*
* @update gess 2/18/00
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search (counting from left)
* @param aCount tell us how many iterations to perform from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
if(aCount<0)
aCount = aDest.mLength;
if((0<aDest.mLength) && ((PRUint32)anOffset<aDest.mLength) && (aTarget.mLength)) {
if(0<aCount) {
PRInt32 aDelta = (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* destLast = root+(aDest.mLength*aDelta); //pts to last char in aDest (likely null)
const char* rightmost = root+(anOffset*aDelta);
const char* min = rightmost-((aCount-1)*aDelta);
const char* leftmost = (min<root) ? root: min;
while(leftmost<=rightmost) {
//don't forget to divide by delta in next text (bug found by rhp)...
if(aTarget.mLength<=PRUint32((destLast-rightmost)/aDelta)) {
PRInt32 result=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(rightmost,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==result) {
return (rightmost-root)/aDelta;
}
} //if
rightmost-=aDelta;
} //while
}
}
return kNotFound;
}
/**
* This searches aDest (in reverse) for a given character
*
* @update gess 2/04/00
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search; -1 means start at very end (mLength)
* @param aCount tell us how many iterations to perform from offset; -1 means use full length.
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest (in reverese) for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallRFindChar);
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
PRInt32 thePos;
//note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if(0<aDest.mLength) {
while(--index>=0) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**
* Compare source and dest strings, up to an (optional max) number of chars
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aCount -- if (-1), then we use length of longer string; if (0<aCount) then it gives the max # of chars to compare
* @param aIgnorecase tells us whether to search with case sensitivity
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
*/
PRInt32 nsStr::StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
PRInt32 result=0;
if(aCount) {
PRInt32 minlen=(aSource.mLength<aDest.mLength) ? aSource.mLength : aDest.mLength;
if(0==minlen) {
if ((aDest.mLength == 0) && (aSource.mLength == 0))
return 0;
if (aDest.mLength == 0)
return -1;
return 1;
}
PRInt32 theCount = (aCount<0) ? minlen: MinInt(aCount,minlen);
result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,theCount,aIgnoreCase);
if (0==result) {
if(-1==aCount) {
//Since the caller didn't give us a length to test, and minlen characters matched,
//we have to assume that the longer string is greater.
if (aDest.mLength != aSource.mLength) {
//we think they match, but we've only compared minlen characters.
//if the string lengths are different, then they don't really match.
result = (aDest.mLength<aSource.mLength) ? -1 : 1;
}
} //if
}
}
return result;
}
/**
* Overwrites the contents of dest at offset with contents of aSource
*
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aDestOffset is the offset within aDest where source should be copied
* @return error code
*/
void nsStr::Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 aDestOffset) {
if(aDest.mLength && aSource.mLength) {
if((aDest.mLength-aDestOffset)>=aSource.mLength) {
//if you're here, then both dest and source have valid lengths
//and there's enough room in dest (at offset) to contain source.
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
}
}
}
//----------------------------------------------------------------------------------------
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
static int mAllocCount=0;
mAllocCount++;
#ifdef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
//we're given the acount value in charunits; now scale up to next multiple.
PRUint32 theNewCapacity=kDefaultStringSize;
while(theNewCapacity<aCount){
theNewCapacity<<=1;
}
aDest.mCapacity=theNewCapacity++;
PRUint32 theSize=(theNewCapacity<<aDest.mCharSize);
aDest.mStr = (char*)nsMemory::Alloc(theSize);
#else
// the new strategy is, allocate exact size, double on grows
aDest.mCapacity = aCount;
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.mCharSize);
#endif
if(aDest.mStr) {
aDest.mOwnsBuffer=1;
gStringAcquiredMemory=PR_TRUE;
}
else gStringAcquiredMemory=PR_FALSE;
return gStringAcquiredMemory;
}
PRBool nsStr::Free(nsStr& aDest){
if(aDest.mStr){
if(aDest.mOwnsBuffer){
nsMemory::Free(aDest.mStr);
}
aDest.mStr=0;
aDest.mOwnsBuffer=0;
return PR_TRUE;
}
return PR_FALSE;
}
PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
nsStr temp;
memcpy(&temp,&aDest,sizeof(aDest));
PRBool result=Alloc(temp,aCount);
if(result) {
Free(aDest);
aDest.mStr=temp.mStr;
aDest.mCapacity=temp.mCapacity;
aDest.mOwnsBuffer=temp.mOwnsBuffer;
}
return result;
}
/**
* Retrieve last memory error
*
* @update gess 10/11/99
* @return memory error (usually returns PR_TRUE)
*/
PRBool nsStr::DidAcquireMemory(void) {
return gStringAcquiredMemory;
}
//----------------------------------------------------------------------------------------
CBufDescriptor::CBufDescriptor(char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_FALSE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_TRUE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_FALSE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_TRUE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
//----------------------------------------------------------------------------------------
PRUint32
nsStr::HashCode(const nsStr& aDest)
{
if (aDest.mCharSize == eTwoByte)
return nsCRT::HashCode(aDest.mUStr);
else
return nsCRT::HashCode(aDest.mStr);
}
#ifdef NS_STR_STATS
#include <ctype.h>
#ifdef XP_MAC
#define isascii(c) ((unsigned)(c) < 0x80)
#endif
void
nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate)
{
PRInt32 printLen = (PRInt32)aDest.mLength;
if (aDest.mCharSize == eOneByte) {
const char* chars = aDest.mStr;
while (printLen-- && (!truncate || *chars != '\n')) {
fputc(*chars++, out);
}
}
else {
const PRUnichar* chars = aDest.mUStr;
while (printLen-- && (!truncate || *chars != '\n')) {
if (isascii(*chars))
fputc((char)(*chars++), out);
else
fputc('-', out);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// String Usage Statistics Routines
static PLHashTable* gStringInfo = nsnull;
PRLock* gStringInfoLock = nsnull;
PRBool gNoStringInfo = PR_FALSE;
nsStringInfo::nsStringInfo(nsStr& str)
: mCount(0)
{
nsStr::Initialize(mStr, str.mCharSize);
nsStr::StrAssign(mStr, str, 0, -1);
// nsStr::Print(mStr, stdout);
// fputc('\n', stdout);
}
PR_EXTERN(PRHashNumber)
nsStr_Hash(const void* key)
{
nsStr* str = (nsStr*)key;
return nsStr::HashCode(*str);
}
PR_EXTERN(PRIntn)
nsStr_Compare(const void *v1, const void *v2)
{
nsStr* str1 = (nsStr*)v1;
nsStr* str2 = (nsStr*)v2;
return nsStr::StrCompare(*str1, *str2, -1, PR_FALSE) == 0;
}
nsStringInfo*
nsStringInfo::GetInfo(nsStr& str)
{
if (gStringInfo == nsnull) {
gStringInfo = PL_NewHashTable(1024,
nsStr_Hash,
nsStr_Compare,
PL_CompareValues,
NULL, NULL);
gStringInfoLock = PR_NewLock();
}
PR_Lock(gStringInfoLock);
nsStringInfo* info =
(nsStringInfo*)PL_HashTableLookup(gStringInfo, &str);
if (info == NULL) {
gNoStringInfo = PR_TRUE;
info = new nsStringInfo(str);
if (info) {
PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info);
if (e == NULL) {
delete info;
info = NULL;
}
}
gNoStringInfo = PR_FALSE;
}
PR_Unlock(gStringInfoLock);
return info;
}
void
nsStringInfo::Seen(nsStr& str)
{
if (!gNoStringInfo) {
nsStringInfo* info = GetInfo(str);
info->mCount++;
}
}
void
nsStringInfo::Report(FILE* out)
{
if (gStringInfo) {
fprintf(out, "\n== String Stats\n");
PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out);
}
}
PRIntn
nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg)
{
nsStringInfo* entry = (nsStringInfo*)he->value;
FILE* out = (FILE*)arg;
fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength);
nsStr::Print(entry->mStr, out, PR_TRUE);
fputc('\n', out);
return HT_ENUMERATE_NEXT;
}
#endif // NS_STR_STATS
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,527 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsStr.h --- the underlying buffer for rickg's original string implementations;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsStr
#define _nsStr
/***********************************************************************
MODULE NOTES:
1. There are two philosophies to building string classes:
A. Hide the underlying buffer & offer API's allow indirect iteration
B. Reveal underlying buffer, risk corruption, but gain performance
We chose the option B for performance reasons.
2 Our internal buffer always holds capacity+1 bytes.
The nsStr struct is a simple structure (no methods) that contains
the necessary info to be described as a string. This simple struct
is manipulated by the static methods provided in this class.
(Which effectively makes this a library that works on structs).
There are also object-based versions called nsString and nsAutoString
which use nsStr but makes it look at feel like an object.
***********************************************************************/
/***********************************************************************
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated. However,
since it maintains a length byte, you can store NULL's inside
the string. Just be careful passing such buffers to 3rd party
API's that assume that NULL always terminate the buffer.
2. nsCStrings can be upsampled into nsString without data loss
3. Char searching is faster than string searching. Use char interfaces
if your needs will allow it.
4. It's easy to use the stack for nsAutostring buffer storage (fast too!).
See the CBufDescriptor class in this file.
5. If you don't provide the optional count argument to Append() and Insert(),
the method will assume that the given buffer is terminated by the first
NULL it encounters.
6. Downsampling from nsString to nsCString can be lossy -- avoid it if possible!
7. Calls to ToNewCString() and ToNewUnicode() should be matched with calls to nsMemory::Free().
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsMemory
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenuously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
--- FAQ ---
Q. When should I use nsCString instead of nsString?
A. You should really try to stick with nsString, so that we stay as unicode
compliant as possible. But there are cases where an interface you use requires
a char*. In such cases, it's fair to use nsCString.
Q. I know that my string is going to be a certain size. Can I pre-size my nsString?
A. Yup, here's how:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
Q. Should nsAutoString or nsCAutoString ever live on the heap?
A. That would be counterproductive. The point of nsAutoStrings is to preallocate your
buffers, and to auto-destroy the string when it goes out of scope.
Q. I already have a char*. Can I use the nsString functionality on that buffer?
A. Yes you can -- by using an intermediate class called CBufDescriptor.
The CBufDescriptor class is used to tell nsString about an external buffer (heap or stack) to use
instead of it's own internal buffers. Here's an example:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString/nsCString interfaces. Cool, huh?
Note however that just like any other nsStringXXX use, if you write more data
than will fit in the buffer, a visit to the heap manager will be in order.
Q. What is the simplest way to get from a char* to PRUnichar*?
A. The simplest way is by construction (or assignment):
{
char* theBuf = "hello there";
nsAutoString foo(theBuf);
}
If you don't want the char* to be copied into the nsAutoString, the use a
CBufDescriptor instead.
**********************************************************************************/
#include "nscore.h"
#include "nsMemory.h"
#include <string.h>
#include <stdio.h>
#include "plhash.h"
//----------------------------------------------------------------------------------------
enum eCharSize {eOneByte=0,eTwoByte=1};
#define kDefaultCharSize eTwoByte
#define kRadix10 (10)
#define kRadix16 (16)
#define kAutoDetect (100)
#define kRadixUnknown (kAutoDetect+1)
#define IGNORE_CASE (PR_TRUE)
const PRInt32 kDefaultStringSize = 64;
const PRInt32 kNotFound = -1;
//----------------------------------------------------------------------------------------
class NS_COM CBufDescriptor {
public:
CBufDescriptor(char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(PRUnichar* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
char* mBuffer;
eCharSize mCharSize;
PRUint32 mCapacity;
PRInt32 mLength;
PRBool mStackBased;
PRBool mIsConst;
};
//----------------------------------------------------------------------------------------
struct NS_COM nsStr {
nsStr() {
MOZ_COUNT_CTOR(nsStr);
}
~nsStr() {
MOZ_COUNT_DTOR(nsStr);
}
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,eCharSize aCharSize);
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
/**
* This method destroys the given nsStr, and *MAY*
* deallocate it's memory depending on the setting
* of the internal mOwnsBUffer flag.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used to the nsStr
*/
static void Destroy(nsStr& aDest);
/**
* These methods are where memory allocation/reallocation occur.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used on the nsStr
* @return
*/
static PRBool EnsureCapacity(nsStr& aString,PRUint32 aNewLength);
static PRBool GrowCapacity(nsStr& aString,PRUint32 aNewLength);
/**
* These methods are used to append content to the given nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to assign contents of a source string to dest string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to insert content from source string to the dest nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to insert
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
/**
* This method deletes chars from the given str.
* The given allocator may choose to resize the str as well.
*
* @update gess 01/04/99
* @param aDest is the nsStr to be deleted from
* @param aDestOffset tells us where in dest to start deleting
* @param aCount tells us the (max) # of chars to delete
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
/**
* This method is used to truncate the given string.
* The given allocator may choose to resize the str as well (but it's not likely).
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrTruncate(nsStr& aDest,PRUint32 aDestOffset);
/**
* This method is used to perform a case conversion on the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be case shifted
* @param toUpper tells us to go upper vs. lower
*/
static void ChangeCase(nsStr& aDest,PRBool aToUpper);
/**
* This method trims chars (given in aSet) from the edges of given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to remove from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method removes all occurances of chars in given set from aDest
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void StripChars(nsStr& aDest,const char* aSet);
/**
* This method compares the data bewteen two nsStr's
*
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
static PRInt32 StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase);
/**
* These methods scan the given string for 1 or more chars in a given direction
*
* @update gess 01/04/99
* @param aDest is the nsStr to be searched to
* @param aSource (or aChar) is the substr we're looking to find
* @param aIgnoreCase tells us whether to search in a case-sensitive manner
* @param anOffset tells us where in the dest string to start searching
* @return the index of the source (substr) in dest, or -1 (kNotFound) if not found.
*/
static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static void Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 anOffset);
static PRBool DidAcquireMemory(void);
/**
* Returns a hash code for the string for use in a PLHashTable.
*/
static PRUint32 HashCode(const nsStr& aDest);
#ifdef NS_STR_STATS
/**
* Prints an nsStr. If truncate is true, the string is only printed up to
* the first newline. (Note: The current implementation doesn't handle
* non-ascii unicode characters.)
*/
static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE);
#endif
PRUint32 mLength;
PRUint32 mCapacity;
eCharSize mCharSize;
PRBool mOwnsBuffer;
union {
char* mStr;
PRUnichar* mUStr;
};
private:
static PRBool Alloc(nsStr& aString,PRUint32 aCount);
static PRBool Realloc(nsStr& aString,PRUint32 aCount);
static PRBool Free(nsStr& aString);
};
/**************************************************************
A couple of tiny helper methods used in the string classes.
**************************************************************/
inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt1 : anInt2;
}
inline PRInt32 MaxInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt2 : anInt1;
}
inline void AddNullTerminator(nsStr& aDest) {
if(eTwoByte==aDest.mCharSize)
aDest.mUStr[aDest.mLength]=0;
else aDest.mStr[aDest.mLength]=0;
}
/**
* Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
*
* Return the given buffer to the heap manager. Calls allocator::Free()
* @return string length
*/
inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
/**
* This method is used to access a given char in the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param anIndex tells us where in dest to get the char from
* @return the given char, or 0 if anIndex is out of range
*/
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
if(anIndex<aDest.mLength) {
return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
}//if
return 0;
}
#ifdef NS_STR_STATS
class nsStringInfo {
public:
nsStringInfo(nsStr& str);
~nsStringInfo() {}
static nsStringInfo* GetInfo(nsStr& str);
static void Seen(nsStr& str);
static void Report(FILE* out = stdout);
static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg);
protected:
nsStr mStr;
PRUint32 mCount;
};
#define NSSTR_SEEN(str) nsStringInfo::Seen(str)
#else // !NS_STR_STATS
#define NSSTR_SEEN(str) /* nothing */
#endif // !NS_STR_STATS
#endif // _nsStr

File diff suppressed because it is too large Load Diff

View File

@@ -1,583 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsString.h --- rickg's original strings of 1-byte chars, |nsCString| and |nsCAutoString|;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsCString_
#define _nsCString_
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#include "nsString2.h"
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsStr.h"
#include "nsIAtom.h"
#include "nsAString.h"
/* this file will one day be _only_ a compatibility header for clients using the names
|ns[C]String| et al ... which we probably want to support forever.
In the mean time, people are used to getting the names |nsAReadable[C]String| and friends
from here as well; so we must continue to include the other compatibility headers
even though we don't use them ourself.
*/
#include "nsAWritableString.h"
// for compatibility
class NS_COM nsSubsumeCStr;
class NS_COM nsCString :
public nsAFlatCString,
public nsStr {
protected:
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const;
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
public:
virtual const char* get() const { return mStr; }
public:
/**
* Default constructor.
*/
nsCString();
/**
* This is our copy constructor
* @param reference to another nsCString
*/
nsCString(const nsCString& aString);
explicit nsCString( const nsACString& );
explicit nsCString(const char*);
nsCString(const char*, PRInt32);
/**
* This constructor takes a subsumestr
* @param reference to subsumestr
*/
explicit nsCString(nsSubsumeCStr& aSubsumeStr);
/**
* Destructor
*
*/
virtual ~nsCString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string capacity
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**********************************************************************
Accessor methods...
*********************************************************************/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsCString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsCString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars(const char* aSet);
void StripChar(PRUnichar aChar,PRInt32 anOffset=0);
void StripChar(char aChar,PRInt32 anOffset=0) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar(PRUnichar aOldChar,PRUnichar aNewChar);
void ReplaceChar(const char* aSet,PRUnichar aNewChar);
void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue);
void ReplaceSubstring(const char* aTarget,const char* aNewValue);
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
//#ifndef STANDALONE_STRING_TESTS
operator const char*() const {return (const char*)mStr;}
//#endif
/**
* This method constructs a new nsCString that is a clone
* of this string.
*
*/
nsCString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return this
*/
nsCString& operator=( const nsCString& aString ) { Assign(aString); return *this; }
nsCString& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
//nsCString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCString& operator=( char aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(const PRUnichar*,PRInt32=-1);
void AssignWithConversion( const nsString& aString );
void AssignWithConversion( const nsAString& aString );
void AssignWithConversion(PRUnichar);
/*
* Appends n characters from given string to this,
*
* @param aString is the source to be appended to this
* @param aCount -- number of chars to copy; -1 tells us to compute the strlen for you
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return number of chars copied
*/
void AppendWithConversion(const nsString&, PRInt32=-1);
void AppendWithConversion(PRUnichar aChar);
void AppendWithConversion( const nsAString& aString );
void AppendWithConversion(const PRUnichar*, PRInt32=-1);
// Why no |AppendWithConversion(const PRUnichar*, PRInt32)|? --- now I know, because implicit construction hid the need for this routine
void AppendInt(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
void AppendFloat( double aFloat );
void InsertWithConversion(PRUnichar aChar,PRUint32 anOffset);
// Why no |InsertWithConversion(PRUnichar*)|?
#if 0
virtual void do_AppendFromReadable( const nsACString& );
virtual void do_InsertFromReadable( const nsACString&, PRUint32 );
#endif
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
void DebugDump(void) const;
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( PRUnichar );
void AssignWithConversion( char );
void AssignWithConversion( const char*, PRInt32=-1 );
void AppendWithConversion( char );
void InsertWithConversion( char, PRUint32 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsCString, char)
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCString, char)
extern NS_COM int fputs(const nsCString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsCString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsCAutoString : public nsCString {
public:
virtual ~nsCAutoString();
nsCAutoString();
explicit nsCAutoString(const nsCString& );
explicit nsCAutoString(const nsACString& aString);
explicit nsCAutoString(const char* aString);
nsCAutoString(const char* aString,PRInt32 aLength);
explicit nsCAutoString(const CBufDescriptor& aBuffer);
#if defined(AIX) || defined(XP_OS2_VACPP)
explicit nsCAutoString(const nsSubsumeCStr& aSubsumeStr); // AIX and VAC++ require a const
#else
explicit nsCAutoString(nsSubsumeCStr& aSubsumeStr);
#endif // AIX || XP_OS2_VACPP
nsCAutoString& operator=( const nsCAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
public:
nsCAutoString& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
// nsCAutoString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCAutoString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCAutoString& operator=( char aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize];
};
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCAutoString, char)
/**
* A helper class that converts a UCS2 string to UTF8
*/
class NS_COM NS_ConvertUCS2toUTF8
: public nsCAutoString
/*
...
*/
{
public:
explicit
NS_ConvertUCS2toUTF8( const PRUnichar* aString )
{
Append( aString, ~PRUint32(0) /* MAXINT */);
}
NS_ConvertUCS2toUTF8( const PRUnichar* aString, PRUint32 aLength )
{
Append( aString, aLength );
}
explicit
NS_ConvertUCS2toUTF8( PRUnichar aChar )
{
Append( &aChar, 1 );
}
explicit NS_ConvertUCS2toUTF8( const nsAString& aString );
protected:
void Append( const PRUnichar* aString, PRUint32 aLength );
private:
// NOT TO BE IMPLEMENTED
NS_ConvertUCS2toUTF8( char );
operator const char*() const; // use |get()|
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
copy semantics when another string is assign to this.
Instead, it "steals" the contents of the source string.
This is very handy for returning nsString classes as part of
an operator+(...) for example, in that it cuts down the number
of copy operations that must occur.
You should probably not use this class unless you really know
what you're doing.
***************************************************************/
class NS_COM nsSubsumeCStr : public nsCString {
public:
explicit nsSubsumeCStr(nsStr& aString);
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr& operator=( const nsSubsumeCStr& aString ) { Assign(aString); return *this; }
nsSubsumeCStr& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
//nsSubsumeCStr& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeCStr& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsSubsumeCStr& operator=( char aChar ) { Assign(aChar); return *this; }
private:
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,666 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsString2.h --- rickg's original strings of 2-byte chars, |nsString| and |nsAutoString|;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsString_
#define _nsString_
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsString.h"
#include "nsIAtom.h"
#include "nsStr.h"
#include "nsCRT.h"
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
#ifdef STANDALONE_MI_STRING_TESTS
class nsAFlatString { public: virtual ~nsAString() { } };
#endif
class nsISizeOfHandler;
#define nsString2 nsString
#define nsAutoString2 nsAutoString
class NS_COM nsSubsumeStr;
class NS_COM nsString :
public nsAFlatString,
public nsStr {
protected:
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const;
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
virtual const PRUnichar* get() const { return GetUnicode(); }
public:
/**
* Default constructor.
*/
nsString();
/**
* This is our copy constructor
* @param reference to another nsString
*/
nsString(const nsString& aString);
explicit nsString(const nsAString&);
explicit nsString(const PRUnichar*);
nsString(const PRUnichar*, PRInt32);
/**
* This constructor takes a subsumestr
* @param reference to subsumestr
*/
#if defined(AIX) || defined(XP_OS2_VACPP)
explicit nsString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ require a const here
#else
explicit nsString(nsSubsumeStr& aSubsumeStr);
#endif
/**
* Destructor
*
*/
virtual ~nsString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string length
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**
* Determine whether or not the characters in this
* string are in store as 1 or 2 byte (unicode) strings.
*
* @return TRUE if ordered.
*/
PRBool IsUnicode(void) const {
PRBool result=PRBool(mCharSize==eTwoByte);
return result;
}
/**********************************************************************
Getters/Setters...
*********************************************************************/
/**
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
*/
const char* GetBuffer(void) const;
const PRUnichar* GetUnicode(void) const;
/**
* Set nth character.
*/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars( const char* aSet );
void StripChar( PRUnichar aChar, PRInt32 anOffset=0 );
void StripChar( char aChar, PRInt32 anOffset=0 ) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
void StripChar( PRInt32 anInt, PRInt32 anOffset=0 ) { StripChar((PRUnichar)anInt,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar( PRUnichar anOldChar, PRUnichar aNewChar );
void ReplaceChar( const char* aSet, PRUnichar aNewChar );
void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue );
void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue );
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
/**
* This method constructs a new nsString is a clone of this string.
*
*/
nsString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates an UTF8 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new null-terminated UTF8 string
*/
char* ToNewUTF8String() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
* @return this
*/
nsString& operator=( const nsString& aString ) { Assign(aString); return *this; }
nsString& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
//nsString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(char);
void AssignWithConversion(const char*);
void AssignWithConversion(const char*, PRInt32);
/*
* Appends n characters from given string to this,
* This version computes the length of your given string
*
* @param aString is the source to be appended to this
* @return number of chars copied
*/
void AppendInt(PRInt32, PRInt32=10); //radix=8,10 or 16
void AppendFloat(double);
void AppendWithConversion(const char*, PRInt32=-1);
void AppendWithConversion(char);
virtual void do_AppendFromElement( PRUnichar );
//void InsertWithConversion(char);
void InsertWithConversion(const char*, PRUint32, PRInt32=-1);
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where in this strig to start searching (counting from left)
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsAtom(/*FIX: const */nsIAtom* anAtom,PRBool aIgnoreCase) const;
PRBool EqualsIgnoreCase(const nsString& aString) const;
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(/*FIX: const */nsIAtom *aAtom) const;
/**
* Determine if given buffer is plain ascii
*
* @param aBuffer -- if null, then we test *this, otherwise we test given buffer
* @return TRUE if is all ascii chars or if strlen==0
*/
PRBool IsASCII(const PRUnichar* aBuffer=0);
void DebugDump(void) const;
/**
* Determine if given char is a valid space character
*
* @param aChar is character to be tested
* @return TRUE if is valid space char
*/
static PRBool IsSpace(PRUnichar ch);
/**
* Determine if given char in valid alpha range
*
* @param aChar is character to be tested
* @return TRUE if in alpha range
*/
static PRBool IsAlpha(PRUnichar ch);
/**
* Determine if given char is valid digit
*
* @param aChar is character to be tested
* @return TRUE if char is a valid digit
*/
static PRBool IsDigit(PRUnichar ch);
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( char );
void AssignWithConversion( PRUnichar );
void AssignWithConversion( const PRUnichar*, PRInt32=-1 );
void AppendWithConversion( PRUnichar );
void AppendWithConversion( const PRUnichar*, PRInt32=-1 );
void InsertWithConversion( const PRUnichar*, PRUint32, PRInt32=-1 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsString, PRUnichar)
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsString, PRUnichar)
extern NS_COM int fputs(const nsString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsAutoString : public nsString {
public:
virtual ~nsAutoString();
nsAutoString();
nsAutoString(const nsAutoString& aString);
explicit nsAutoString(const nsAString& aString);
explicit nsAutoString(const nsString& aString);
explicit nsAutoString(const PRUnichar* aString);
nsAutoString(const PRUnichar* aString,PRInt32 aLength);
explicit nsAutoString(PRUnichar aChar);
explicit nsAutoString(const CBufDescriptor& aBuffer);
#if defined(AIX) || defined(XP_OS2_VACPP)
explicit nsAutoString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ requires a const
#else
explicit nsAutoString(nsSubsumeStr& aSubsumeStr);
#endif // AIX || XP_OS2_VACPP
nsAutoString& operator=( const nsAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( char ); // NOT TO BE IMPLEMENTED
public:
nsAutoString& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
// nsAutoString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsAutoString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsAutoString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize<<eTwoByte];
};
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsAutoString, PRUnichar)
class NS_COM NS_ConvertASCIItoUCS2
: public nsAutoString
/*
...
*/
{
public:
explicit NS_ConvertASCIItoUCS2( const char* );
NS_ConvertASCIItoUCS2( const char*, PRUint32 );
explicit NS_ConvertASCIItoUCS2( char );
#if 0
operator const nsLocalString() const
{
return nsLocalString(mUStr, mLength);
}
#endif
private:
// NOT TO BE IMPLEMENTED
NS_ConvertASCIItoUCS2( PRUnichar );
};
class NS_COM NS_ConvertUTF8toUCS2
: public nsAutoString
{
public:
explicit
NS_ConvertUTF8toUCS2( const char* aCString )
{
Init( aCString, ~PRUint32(0) /* MAXINT */ );
}
NS_ConvertUTF8toUCS2( const char* aCString, PRUint32 aLength )
{
Init( aCString, aLength );
}
explicit
NS_ConvertUTF8toUCS2( char aChar )
{
Init( &aChar, 1 );
}
protected:
void Init( const char* aCString, PRUint32 aLength );
private:
NS_ConvertUTF8toUCS2( PRUnichar );
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
copy semantics when another string is assign to this.
Instead, it "steals" the contents of the source string.
This is very handy for returning nsString classes as part of
an operator+(...) for example, in that it cuts down the number
of copy operations that must occur.
You should probably not use this class unless you really know
what you're doing.
***************************************************************/
class NS_COM nsSubsumeStr : public nsString {
public:
nsSubsumeStr();
explicit nsSubsumeStr(nsStr& aString);
nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
int Subsume(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeStr& operator=( const nsSubsumeStr& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeStr& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
//nsSubsumeStr& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeStr& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsSubsumeStr& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
private:
void operator=( char ); // NOT TO BE IMPLEMENTED
};
#endif

View File

@@ -1,163 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDebug.h"
#include "nsMemory.h"
#include "nsXPIDLString.h"
#include "plstr.h"
// If the allocator changes, fix it here.
#define XPIDL_STRING_ALLOC(__len) ((PRUnichar*) nsMemory::Alloc((__len) * sizeof(PRUnichar)))
#define XPIDL_CSTRING_ALLOC(__len) ((char*) nsMemory::Alloc((__len) * sizeof(char)))
#define XPIDL_FREE(__ptr) (nsMemory::Free(__ptr))
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
nsXPIDLString::~nsXPIDLString()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
}
PRUnichar*
nsXPIDLString::Copy(const PRUnichar* aString)
{
NS_ASSERTION(aString, "null ptr");
if (! aString)
return 0;
PRInt32 len = 0;
{
const PRUnichar* p = aString;
while (*p++)
len++;
}
PRUnichar* result = XPIDL_STRING_ALLOC(len + 1);
if (result) {
PRUnichar* q = result;
while (*aString) {
*q = *aString;
q++;
aString++;
}
*q = '\0';
}
return result;
}
PRUnichar**
nsXPIDLString::StartAssignmentByValue()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_TRUE;
return &mBuf;
}
const PRUnichar**
nsXPIDLString::StartAssignmentByReference()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_FALSE;
return (const PRUnichar**) &mBuf;
}
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
nsXPIDLCString::~nsXPIDLCString()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
}
nsXPIDLCString& nsXPIDLCString::operator =(const char* aCString)
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
if (aCString) {
mBuf = Copy(aCString);
mBufOwner = PR_TRUE;
}
else {
mBuf = 0;
mBufOwner = PR_FALSE;
}
return *this;
}
char*
nsXPIDLCString::Copy(const char* aCString)
{
NS_ASSERTION(aCString, "null ptr");
if (! aCString)
return 0;
PRInt32 len = PL_strlen(aCString);
char* result = XPIDL_CSTRING_ALLOC(len + 1);
if (result)
PL_strcpy(result, aCString);
return result;
}
char**
nsXPIDLCString::StartAssignmentByValue()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_TRUE;
return &mBuf;
}
const char**
nsXPIDLCString::StartAssignmentByReference()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_FALSE;
return (const char**) &mBuf;
}

View File

@@ -1,389 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsXPIDLString.h --- an `|auto_ptr|' for character buffers, this functionality will be replaced
by the new shared-buffer string (see bug #53065)
*/
#ifndef nsXPIDLString_h__
#define nsXPIDLString_h__
/*
A set of string wrapper classes that ease transition to use of XPIDL
interfaces. nsXPIDLString and nsXPIDLCString are to XPIDL `wstring'
and `string' out params as nsCOMPtr is to generic XPCOM interface
pointers. They help you deal with object ownership.
Consider the following interface:
interface nsIFoo {
attribute string Bar;
};
This will generate the following C++ header file:
class nsIFoo {
NS_IMETHOD SetBar(const PRUnichar* aValue);
NS_IMETHOD GetBar(PRUnichar* *aValue);
};
The GetBar() method will allocate a copy of the nsIFoo object's
"bar" attribute, and leave you to deal with freeing it:
nsIFoo* aFoo; // assume we get this somehow
PRUnichar* bar;
aFoo->GetFoo(&bar);
// Use bar here...
printf("bar is %s!\n", bar);
nsMemory::Free(bar);
This makes your life harder, because you need to convolute your code
to ensure that you don't leak `bar'.
Enter nsXPIDLString, which manages the ownership of the allocated
string, and automatically destroys it when the nsXPIDLString goes
out of scope:
nsIFoo* aFoo;
nsXPIDLString bar;
aFoo->GetFoo( getter_Copies(bar) );
// Use bar here...
printf("bar is %s!\n", (const char*) bar);
// no need to remember to nsMemory::Free().
Like nsCOMPtr, nsXPIDLString uses some syntactic sugar to make it
painfully clear exactly what the code expects. You need to wrap an
nsXPIDLString object with either `getter_Copies()' or
`getter_Shares()' before passing it to a getter: these tell the
nsXPIDLString how ownership is being handled.
In the case of `getter_Copies()', the callee is allocating a copy
(which is usually the case). In the case of `getter_Shares()', the
callee is returning a const reference to `the real deal' (this can
be done using the [shared] attribute in XPIDL).
*/
#include "nscore.h"
#include "nsCom.h"
#include "prtypes.h"
#ifndef __PRUNICHAR__
#define __PRUNICHAR__
typedef PRUint16 PRUnichar;
#endif /* __PRUNICHAR__ */
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
//
// A wrapper for Unicode strings. With the |getter_Copies()| and
// |getter_Shares()| helper functions, this can be used instead of
// the "naked" |PRUnichar*| interface for |wstring| parameters in
// XPIDL interfaces.
//
class NS_COM nsXPIDLString {
private:
PRUnichar* mBuf;
PRBool mBufOwner;
PRUnichar** StartAssignmentByValue();
const PRUnichar** StartAssignmentByReference();
public:
/**
* Construct a new, uninitialized wrapper for a Unicode string.
*/
nsXPIDLString() : mBuf(0), mBufOwner(PR_FALSE) {}
virtual ~nsXPIDLString();
/**
* Return a reference to the immutable Unicode string.
*/
operator const PRUnichar*() const { return get(); }
/**
* Return a reference to the immutable Unicode string.
*/
const PRUnichar* get() const { return mBuf; }
/**
* Make a copy of the Unicode string. Use this function in the
* callee to ensure that the correct memory allocator is used.
*/
static PRUnichar* Copy(const PRUnichar* aString);
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLString& mXPIDLString;
public:
GetterCopies(nsXPIDLString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator PRUnichar**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLString& aXPIDLString);
};
friend class GetterCopies;
// A helper class for assignment-by-reference. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterShares {
private:
nsXPIDLString& mXPIDLString;
public:
GetterShares(nsXPIDLString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator const PRUnichar**() {
return mXPIDLString.StartAssignmentByReference();
}
friend GetterShares getter_Shares(nsXPIDLString& aXPIDLString);
};
friend class GetterShares;
private:
// not to be implemented
nsXPIDLString(nsXPIDLString& /* aXPIDLString */) {}
void operator=(nsXPIDLString& /* aXPIDLString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLString object that is to
* receive an |out| value.
*/
inline nsXPIDLString::GetterCopies
getter_Copies(nsXPIDLString& aXPIDLString)
{
return nsXPIDLString::GetterCopies(aXPIDLString);
}
/**
* Use this function to "wrap" the nsXPIDLString object that is to
* receive a |[shared] out| value.
*/
inline nsXPIDLString::GetterShares
getter_Shares(nsXPIDLString& aXPIDLString)
{
return nsXPIDLString::GetterShares(aXPIDLString);
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const PRUnichar* lhs, const nsXPIDLString& rhs)
{
return lhs == NS_STATIC_CAST(const PRUnichar*, rhs);
}
inline
PRBool
operator==(const nsXPIDLString& lhs, const PRUnichar* rhs)
{
return NS_STATIC_CAST(const PRUnichar*, lhs) == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLString& rhs)
{
return NS_REINTERPRET_CAST(PRUnichar*, lhs) == NS_STATIC_CAST(const PRUnichar*, rhs);
}
inline
PRBool
operator==(const nsXPIDLString& lhs, int rhs)
{
return NS_STATIC_CAST(const PRUnichar*, lhs) == NS_REINTERPRET_CAST(PRUnichar*, rhs);
}
#endif
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
//
// A wrapper for Unicode strings. With the |getter_Copies()| and
// |getter_Shares()| helper functions, this can be used instead of
// the "naked" |char*| interface for |string| parameters in XPIDL
// interfaces.
//
class NS_COM nsXPIDLCString {
private:
char* mBuf;
PRBool mBufOwner;
char** StartAssignmentByValue();
const char** StartAssignmentByReference();
public:
/**
* Construct a new, uninitialized wrapper for a single-byte string.
*/
nsXPIDLCString() : mBuf(0), mBufOwner(PR_FALSE) {}
virtual ~nsXPIDLCString();
/**
* Assign a single-byte string to this wrapper. Copies
* and owns the result.
*/
nsXPIDLCString& operator=(const char* aString);
/**
* Return a reference to the immutable single-byte string.
*/
operator const char*() const { return get(); }
/**
* Return a reference to the immutable single-byte string.
*/
const char* get() const { return mBuf; }
/**
* Make a copy of the single-byte string. Use this function in the
* callee to ensure that the correct memory allocator is used.
*/
static char* Copy(const char* aString);
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLCString& mXPIDLString;
public:
GetterCopies(nsXPIDLCString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator char**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLCString& aXPIDLString);
};
friend class GetterCopies;
// A helper class for assignment-by-reference. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterShares {
private:
nsXPIDLCString& mXPIDLString;
public:
GetterShares(nsXPIDLCString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator const char**() {
return mXPIDLString.StartAssignmentByReference();
}
friend GetterShares getter_Shares(nsXPIDLCString& aXPIDLString);
};
friend class GetterShares;
private:
// not to be implemented
nsXPIDLCString(nsXPIDLCString& /* aXPIDLString */) {}
void operator=(nsXPIDLCString& /* aXPIDLCString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLCString object that is to
* receive an |out| value.
*/
inline nsXPIDLCString::GetterCopies
getter_Copies(nsXPIDLCString& aXPIDLString)
{
return nsXPIDLCString::GetterCopies(aXPIDLString);
}
/**
* Use this function to "wrap" the nsXPIDLCString object that is to
* receive a |[shared] out| value.
*/
inline nsXPIDLCString::GetterShares
getter_Shares(nsXPIDLCString& aXPIDLString)
{
return nsXPIDLCString::GetterShares(aXPIDLString);
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const char* lhs, const nsXPIDLCString& rhs)
{
return lhs == NS_STATIC_CAST(const char*, rhs);
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, const char* rhs)
{
return NS_STATIC_CAST(const char*, lhs) == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLCString& rhs)
{
return NS_REINTERPRET_CAST(char*, lhs) == NS_STATIC_CAST(const char*, rhs);
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, int rhs)
{
return NS_STATIC_CAST(const char*, lhs) == NS_REINTERPRET_CAST(char*, rhs);
}
#endif
#endif // nsXPIDLString_h__

View File

@@ -1,49 +0,0 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Scott Collins <scc@mozilla.org> (original author)
#
nsAFlatString.h
nsAlgorithm.h
nsAPromiseString.h
nsAReadableString.h
nsAString.h
nsAWritableString.h
nsBufferHandle.h
nsBufferHandleUtils.h
nsCharTraits.h
nsCommonString.h
nsFragmentedString.h
nsLiteralString.h
nsLocalString.h
nsPrintfCString.h
nsPrivateSharableString.h
nsPromiseConcatenation.h
nsPromiseFlatString.h
nsPromiseSubstring.h
nsReadableUtils.h
nsSharedBufferList.h
nsSlidingString.h
nsStringFragment.h
nsStringFwd.h
nsStringIterator.h
nsStringIteratorUtils.h
nsStringTraits.h

View File

@@ -1,64 +0,0 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
EXPORTS = \
nsAFlatString.h \
nsAlgorithm.h \
nsAPromiseString.h \
nsAReadableString.h \
nsAString.h \
nsAWritableString.h \
nsBufferHandle.h \
nsBufferHandleUtils.h \
nsCharTraits.h \
nsCommonString.h \
nsFragmentedString.h \
nsLiteralString.h \
nsLocalString.h \
nsPrintfCString.h \
nsPrivateSharableString.h \
nsPromiseConcatenation.h \
nsPromiseFlatString.h \
nsPromiseSubstring.h \
nsReadableUtils.h \
nsSharedBufferList.h \
nsSlidingString.h \
nsStringFragment.h \
nsStringFwd.h \
nsStringIterator.h \
nsStringIteratorUtils.h \
nsStringTraits.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -1,56 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH=..\..
EXPORTS = \
nsAFlatString.h \
nsAlgorithm.h \
nsAPromiseString.h \
nsAReadableString.h \
nsAString.h \
nsAWritableString.h \
nsBufferHandle.h \
nsBufferHandleUtils.h \
nsCharTraits.h \
nsCommonString.h \
nsFragmentedString.h \
nsLiteralString.h \
nsLocalString.h \
nsPrintfCString.h \
nsPrivateSharableString.h \
nsPromiseConcatenation.h \
nsPromiseFlatString.h \
nsPromiseSubstring.h \
nsReadableUtils.h \
nsSharedBufferList.h \
nsSlidingString.h \
nsStringFragment.h \
nsStringFwd.h \
nsStringIterator.h \
nsStringIteratorUtils.h \
nsStringTraits.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,83 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsAFlatString.h --- */
#ifndef nsAFlatString_h___
#define nsAFlatString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
class NS_COM nsAFlatString
: public nsAString
{
public:
// don't really want this to be virtual, and won't after |obsolete_nsString| is really dead
virtual const PRUnichar* get() const { return GetBufferHandle()->DataStart(); }
PRUnichar operator[]( PRUint32 i ) const { return get()[ i ]; }
PRUnichar CharAt( PRUint32 ) const;
virtual PRUint32 Length() const { return PRUint32(GetBufferHandle()->DataLength()); }
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
};
class NS_COM nsAFlatCString
: public nsACString
{
public:
// don't really want this to be virtual, and won't after |obsolete_nsCString| is really dead
virtual const char* get() const { return GetBufferHandle()->DataStart(); }
char operator[]( PRUint32 i ) const { return get()[ i ]; }
char CharAt( PRUint32 ) const;
virtual PRUint32 Length() const { return PRUint32(GetBufferHandle()->DataLength()); }
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
};
inline
PRUnichar
nsAFlatString::CharAt( PRUint32 i ) const
{
NS_ASSERTION(i<Length(), "|CharAt| out-of-range");
return operator[](i);
}
inline
char
nsAFlatCString::CharAt( PRUint32 i ) const
{
NS_ASSERTION(i<Length(), "|CharAt| out-of-range");
return operator[](i);
}
#endif /* !defined(nsAFlatString_h___) */

View File

@@ -1,38 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsAPromiseString.h --- abstract base class for strings don't actually own their own characters, but proxy data from other strings */
#ifndef nsAPromiseString_h___
#define nsAPromiseString_h___
/**
* Don't |#include| this file yourself. You will get it automatically if you need it.
*
* Why is it a separate file? To make it easier to find the classes in your local tree.
*/
class NS_COM nsAPromiseString : public nsAString { };
class NS_COM nsAPromiseCString : public nsACString { };
#endif /* !defined(nsAPromiseString_h___) */

View File

@@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsAReadableString.h --- a compatibility header for clients still using the names |nsAReadable[C]String| et al */
#ifndef nsAReadableString_h___
#define nsAReadableString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
typedef const nsAString nsAReadableString;
typedef const nsACString nsAReadableCString;
#ifndef nsLiteralString_h___
#include "nsLiteralString.h"
#endif
#ifndef nsPromiseSubstring_h___
#include "nsPromiseSubstring.h"
#endif
#ifndef nsPromiseFlatString_h___
#include "nsPromiseFlatString.h"
#endif
#ifdef NEED_CPP_TEMPLATE_CAST_TO_BASE
#define NS_READABLE_CAST(CharT, expr) (NS_STATIC_CAST(const nsStringTraits<CharT>::abstract_string_type&, (expr)))
#else
#define NS_READABLE_CAST(CharT, expr) (expr)
#endif
#endif // !defined(nsAReadableString_h___)

View File

@@ -1,772 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsAString_h___
#define nsAString_h___
#ifndef nsStringFwd_h___
#include "nsStringFwd.h"
#endif
#ifndef nsPrivateSharableString_h___
#include "nsPrivateSharableString.h"
#endif
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
#endif
#ifndef nsStringIterator_h___
#include "nsStringIterator.h"
#endif
/**
*
*/
class NS_COM nsAString
: public nsPrivateSharableString
{
public:
typedef nsAString self_type;
typedef nsAPromiseString promise_type;
typedef PRUnichar char_type;
typedef char incompatible_char_type;
typedef nsReadingIterator<char_type> const_iterator;
typedef nsWritingIterator<char_type> iterator;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
// nsAString(); // auto-generated default constructor OK (we're abstract anyway)
// nsAString( const self_type& ); // auto-generated copy-constructor OK (again, only because we're abstract)
virtual ~nsAString() { } // ...yes, I expect to be sub-classed
inline const_iterator& BeginReading( const_iterator& ) const;
inline const_iterator& EndReading( const_iterator& ) const;
inline iterator& BeginWriting( iterator& );
inline iterator& EndWriting( iterator& );
virtual size_type Length() const = 0;
PRBool IsEmpty() const { return Length() == 0; }
inline PRBool Equals( const self_type& ) const;
PRBool Equals( const char_type* ) const;
/**
* |CharAt|, |operator[]|, |First()|, and |Last()| are not guaranteed to be constant-time operations.
* These signatures should be pushed down into interfaces that guarantee flat allocation.
* Clients at _this_ level should always use iterators.
*/
char_type First() const;
char_type Last() const;
size_type CountChar( char_type ) const;
/*
|Left|, |Mid|, and |Right| are annoying signatures that seem better almost
any _other_ way than they are now. Consider these alternatives
aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
Left(aReadable, 17, aWritable); // ...a global function that does the assignment
as opposed to the current signature
aReadable.Left(aWritable, 17); // ...a member function that does the assignment
or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
aWritable = Substring(aReadable, 0, 17);
*/
size_type Left( self_type&, size_type ) const;
size_type Mid( self_type&, PRUint32, PRUint32 ) const;
size_type Right( self_type&, size_type ) const;
// Find( ... ) const;
PRInt32 FindChar( char_type, index_type aOffset = 0 ) const;
// FindCharInSet( ... ) const;
// RFind( ... ) const;
// RFindChar( ... ) const;
// RFindCharInSet( ... ) const;
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( size_type ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( size_type ) { }
void
Truncate( size_type aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const char_type* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const self_type& aReadable ) { AssignFromReadable(aReadable); }
inline void Assign( const promise_type& aReadable );
void Assign( const char_type* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const char_type* aPtr, size_type aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( char_type aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
self_type& operator=( const self_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const promise_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const char_type* aPtr ) { Assign(aPtr); return *this; }
self_type& operator=( char_type aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const self_type& aReadable ) { AppendFromReadable(aReadable); }
inline void Append( const promise_type& aReadable );
void Append( const char_type* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const char_type* aPtr, size_type aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( char_type aChar ) { do_AppendFromElement(aChar); }
self_type& operator+=( const self_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const promise_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const char_type* aPtr ) { Append(aPtr); return *this; }
self_type& operator+=( char_type aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const self_type& aReadable, index_type atPosition ) { InsertFromReadable(aReadable, atPosition); }
inline void Insert( const promise_type& aReadable, index_type atPosition );
void Insert( const char_type* aPtr, index_type atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const char_type* aPtr, index_type atPosition, size_type aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( char_type aChar, index_type atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( index_type cutStart, size_type cutLength );
void Replace( index_type cutStart, size_type cutLength, const self_type& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
// void Replace( index_type cutStart, size_type cutLength, const promise_type& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
// NOT TO BE IMPLEMENTED
index_type CountChar( incompatible_char_type ) const;
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, index_type );
protected:
void AssignFromReadable( const self_type& );
void AssignFromPromise( const self_type& );
virtual void do_AssignFromReadable( const self_type& );
virtual void do_AssignFromElementPtr( const char_type* );
virtual void do_AssignFromElementPtrLength( const char_type*, size_type );
virtual void do_AssignFromElement( char_type );
void AppendFromReadable( const self_type& );
void AppendFromPromise( const self_type& );
virtual void do_AppendFromReadable( const self_type& );
virtual void do_AppendFromElementPtr( const char_type* );
virtual void do_AppendFromElementPtrLength( const char_type*, size_type );
virtual void do_AppendFromElement( char_type );
void InsertFromReadable( const self_type&, index_type );
void InsertFromPromise( const self_type&, index_type );
virtual void do_InsertFromReadable( const self_type&, index_type );
virtual void do_InsertFromElementPtr( const char_type*, index_type );
virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type );
virtual void do_InsertFromElement( char_type, index_type );
void ReplaceFromReadable( index_type, size_type, const self_type& );
void ReplaceFromPromise( index_type, size_type, const self_type& );
virtual void do_ReplaceFromReadable( index_type, size_type, const self_type& );
// protected:
public:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
virtual PRBool Promises( const self_type& aString ) const { return &aString == this; }
};
class NS_COM nsACString
: public nsPrivateSharableCString
{
public:
typedef nsACString self_type;
typedef nsAPromiseCString promise_type;
typedef char char_type;
typedef PRUnichar incompatible_char_type;
typedef nsReadingIterator<char_type> const_iterator;
typedef nsWritingIterator<char_type> iterator;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
// nsACString(); // auto-generated default constructor OK (we're abstract anyway)
// nsACString( const self_type& ); // auto-generated copy-constructor OK (again, only because we're abstract)
virtual ~nsACString() { } // ...yes, I expect to be sub-classed
inline const_iterator& BeginReading( const_iterator& ) const;
inline const_iterator& EndReading( const_iterator& ) const;
inline iterator& BeginWriting( iterator& );
inline iterator& EndWriting( iterator& );
virtual size_type Length() const = 0;
PRBool IsEmpty() const { return Length() == 0; }
inline PRBool Equals( const self_type& ) const;
PRBool Equals( const char_type* ) const;
/**
* |CharAt|, |operator[]|, |First()|, and |Last()| are not guaranteed to be constant-time operations.
* These signatures should be pushed down into interfaces that guarantee flat allocation.
* Clients at _this_ level should always use iterators.
*/
char_type First() const;
char_type Last() const;
size_type CountChar( char_type ) const;
/*
|Left|, |Mid|, and |Right| are annoying signatures that seem better almost
any _other_ way than they are now. Consider these alternatives
aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
Left(aReadable, 17, aWritable); // ...a global function that does the assignment
as opposed to the current signature
aReadable.Left(aWritable, 17); // ...a member function that does the assignment
or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
aWritable = Substring(aReadable, 0, 17);
*/
size_type Left( self_type&, size_type ) const;
size_type Mid( self_type&, PRUint32, PRUint32 ) const;
size_type Right( self_type&, size_type ) const;
// Find( ... ) const;
PRInt32 FindChar( char_type, PRUint32 aOffset = 0 ) const;
// FindCharInSet( ... ) const;
// RFind( ... ) const;
// RFindChar( ... ) const;
// RFindCharInSet( ... ) const;
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( size_type ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( size_type ) { }
void
Truncate( size_type aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const char_type* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const self_type& aReadable ) { AssignFromReadable(aReadable); }
inline void Assign( const promise_type& aReadable );
void Assign( const char_type* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const char_type* aPtr, size_type aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( char_type aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
self_type& operator=( const self_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const promise_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const char_type* aPtr ) { Assign(aPtr); return *this; }
self_type& operator=( char_type aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const self_type& aReadable ) { AppendFromReadable(aReadable); }
inline void Append( const promise_type& aReadable );
void Append( const char_type* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const char_type* aPtr, size_type aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( char_type aChar ) { do_AppendFromElement(aChar); }
self_type& operator+=( const self_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const promise_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const char_type* aPtr ) { Append(aPtr); return *this; }
self_type& operator+=( char_type aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const self_type& aReadable, index_type atPosition ) { InsertFromReadable(aReadable, atPosition); }
inline void Insert( const promise_type& aReadable, index_type atPosition );
void Insert( const char_type* aPtr, index_type atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const char_type* aPtr, index_type atPosition, size_type aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( char_type aChar, index_type atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( index_type cutStart, size_type cutLength );
void Replace( index_type cutStart, size_type cutLength, const self_type& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
// void Replace( index_type cutStart, size_type cutLength, const promise_type& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
// NOT TO BE IMPLEMENTED
index_type CountChar( incompatible_char_type ) const;
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, index_type );
protected:
void AssignFromReadable( const self_type& );
void AssignFromPromise( const self_type& );
virtual void do_AssignFromReadable( const self_type& );
virtual void do_AssignFromElementPtr( const char_type* );
virtual void do_AssignFromElementPtrLength( const char_type*, size_type );
virtual void do_AssignFromElement( char_type );
void AppendFromReadable( const self_type& );
void AppendFromPromise( const self_type& );
virtual void do_AppendFromReadable( const self_type& );
virtual void do_AppendFromElementPtr( const char_type* );
virtual void do_AppendFromElementPtrLength( const char_type*, size_type );
virtual void do_AppendFromElement( char_type );
void InsertFromReadable( const self_type&, index_type );
void InsertFromPromise( const self_type&, index_type );
virtual void do_InsertFromReadable( const self_type&, index_type );
virtual void do_InsertFromElementPtr( const char_type*, index_type );
virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type );
virtual void do_InsertFromElement( char_type, index_type );
void ReplaceFromReadable( index_type, size_type, const self_type& );
void ReplaceFromPromise( index_type, size_type, const self_type& );
virtual void do_ReplaceFromReadable( index_type, size_type, const self_type& );
// protected:
public:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
virtual PRBool Promises( const self_type& aString ) const { return &aString == this; }
};
#include "nsAPromiseString.h"
inline
void
nsAString::Assign( const nsAPromiseString& aReadable )
{
AssignFromPromise(aReadable);
}
inline
void
nsAString::Append( const nsAPromiseString& aReadable )
{
AppendFromPromise(aReadable);
}
inline
void
nsAString::Insert( const nsAPromiseString& aReadable, index_type atPosition )
{
InsertFromPromise(aReadable, atPosition);
}
inline
void
nsACString::Assign( const nsAPromiseCString& aReadable )
{
AssignFromPromise(aReadable);
}
inline
void
nsACString::Append( const nsAPromiseCString& aReadable )
{
AppendFromPromise(aReadable);
}
inline
void
nsACString::Insert( const nsAPromiseCString& aReadable, index_type atPosition )
{
InsertFromPromise(aReadable, atPosition);
}
/**
* Note: measure -- should the |Begin...| and |End...| be |inline|?
*/
inline
nsAString::const_iterator&
nsAString::BeginReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsAString::const_iterator&
nsAString::EndReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
inline
nsAString::iterator&
nsAString::BeginWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsAString::iterator&
nsAString::EndWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
NS_COM int Compare( const nsAString& lhs, const nsAString& rhs );
inline
PRBool
nsAString::Equals( const self_type& rhs ) const
{
return Length()==rhs.Length() && Compare(*this, rhs)==0;
}
inline
PRBool
operator!=( const nsAString& lhs, const nsAString& rhs )
{
return !lhs.Equals(rhs);
}
inline
PRBool
operator< ( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)< 0;
}
inline
PRBool
operator<=( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)<=0;
}
inline
PRBool
operator==( const nsAString& lhs, const nsAString& rhs )
{
return lhs.Equals(rhs);
}
inline
PRBool
operator>=( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)>=0;
}
inline
PRBool
operator> ( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)> 0;
}
inline
nsAString::size_type
nsAString::Left( nsAString& aResult, size_type aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
/**
*
*/
inline
nsACString::const_iterator&
nsACString::BeginReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsACString::const_iterator&
nsACString::EndReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
inline
nsACString::iterator&
nsACString::BeginWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsACString::iterator&
nsACString::EndWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
NS_COM int Compare( const nsACString& lhs, const nsACString& rhs );
inline
PRBool
nsACString::Equals( const self_type& rhs ) const
{
return Length()==rhs.Length() && Compare(*this, rhs)==0;
}
inline
PRBool
operator!=( const nsACString& lhs, const nsACString& rhs )
{
return !lhs.Equals(rhs);
}
inline
PRBool
operator< ( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)< 0;
}
inline
PRBool
operator<=( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)<=0;
}
inline
PRBool
operator==( const nsACString& lhs, const nsACString& rhs )
{
return lhs.Equals(rhs);
}
inline
PRBool
operator>=( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)>=0;
}
inline
PRBool
operator> ( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)> 0;
}
inline
nsACString::size_type
nsACString::Left( nsACString& aResult, size_type aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
// Once you've got strings, you shouldn't need to do anything else to have concatenation
#ifndef nsPromiseConcatenation_h___
#include "nsPromiseConcatenation.h"
#endif
#endif // !defined(nsAString_h___)

View File

@@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsAWritableString.h --- a compatibility header for clients still using the names |nsAWritable[C]String| */
#ifndef nsAWritableString_h___
#define nsAWritableString_h___
#ifndef nsAReadableString_h___
#include "nsAReadableString.h"
#endif
typedef nsAString nsAWritableString;
typedef nsACString nsAWritableCString;
#endif // !defined(nsAWritableString_h___)

View File

@@ -1,112 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsAlgorithm_h___
#define nsAlgorithm_h___
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
// for |nsCharSourceTraits|, |nsCharSinkTraits|
#endif
#ifndef prtypes_h___
#include "prtypes.h"
// for |PRUint32|...
#endif
template <class T>
inline
const T&
NS_MIN( const T& a, const T& b )
{
return b < a ? b : a;
}
template <class T>
inline
const T&
NS_MAX( const T& a, const T& b )
{
return a > b ? a : b;
}
template <class InputIterator, class T>
inline
PRUint32
NS_COUNT( InputIterator& first, const InputIterator& last, const T& value )
{
PRUint32 result = 0;
for ( ; first != last; ++first )
if ( *first == value )
++result;
return result;
}
template <class InputIterator, class OutputIterator>
inline
OutputIterator&
copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result )
{
typedef nsCharSourceTraits<InputIterator> source_traits;
typedef nsCharSinkTraits<OutputIterator> sink_traits;
while ( first != last )
{
PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last)));
NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate");
source_traits::advance(first, count_copied);
}
return result;
}
template <class InputIterator, class OutputIterator>
OutputIterator&
copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result )
{
while ( first != last )
{
last.normalize_backward();
result.normalize_backward();
PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) );
if ( first.fragment().mStart == last.fragment().mStart )
lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get()));
NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate");
#ifdef _MSC_VER
// XXX Visual C++ can't stomach 'typename' where it rightfully should
nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
#else
nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
#endif
last.advance( -PRInt32(lengthToCopy) );
result.advance( -PRInt32(lengthToCopy) );
}
return result;
}
#endif // !defined(nsAlgorithm_h___)

View File

@@ -1,350 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
/* nsBufferHandle.h --- the collection of classes that describe the atomic hunks of strings */
#ifndef nsBufferHandle_h___
#define nsBufferHandle_h___
#include <stddef.h>
// for |ptrdiff_t|
#include "prtypes.h"
// for |PRBool|
#include "nsDebug.h"
// for |NS_ASSERTION|
#include "nscore.h"
// for |PRUnichar|, |NS_REINTERPRET_CAST|
/**
The classes in this file are collectively called `buffer handles'.
All buffer handles begin with a pointer-tuple that delimits the useful content of a
hunk of string. A buffer handle that points to a sharable hunk of string data
additionally has a field which multiplexes some flags and a reference count.
ns[Const]BufferHandle nsSharedBufferHandle mFlexBufferHandle
+-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+
| mDataStart | | mDataStart | | mDataStart |
+-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+
| mDataEnd | | mDataEnd | | mDataEnd |
+-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+
| mFlags | | mFlags |
+-----+-----+-----+-----+ +-----+-----+-----+-----+
. mAllocator . | mStorageStart |
......................... +-----+-----+-----+-----+
| mStorageEnd |
+-----+-----+-----+-----+
. mAllocator .
.........................
Given only a |ns[Const]BufferHandle|, there is no legal way to tell if it is sharable.
In all cases, the data might immediately follow the handle in the same allocated block.
From the |mFlags| field, you can tell exactly what configuration of a handle you
actually have.
*/
/**
*
*/
template <class CharT>
class nsBufferHandle
{
public:
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
CharT* DataStart() { return mDataStart; }
const CharT* DataStart() const { return mDataStart; }
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
CharT* DataEnd() { return mDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
CharT* mDataStart;
CharT* mDataEnd;
};
template <class CharT>
class nsConstBufferHandle
{
public:
nsConstBufferHandle( const CharT* aDataStart, const CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
const CharT* DataStart() const { return mDataStart; }
const CharT* DataEnd() const { return mDataEnd; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
const CharT* mDataStart;
const CharT* mDataEnd;
};
/**
* string allocator stuff needs to move to its own file
* also see http://bugzilla.mozilla.org/show_bug.cgi?id=70087
*/
template <class CharT>
class nsStringAllocator
{
public:
// more later
virtual void Deallocate( CharT* ) const = 0;
};
/**
* the following two routines must be provided by the client embedding strings
*/
NS_COM nsStringAllocator<char>& StringAllocator_char();
NS_COM nsStringAllocator<PRUnichar>& StringAllocator_wchar_t();
/**
* this traits class lets templated clients pick the appropriate non-template global allocator
*/
template <class T>
struct nsStringAllocatorTraits
{
};
NS_SPECIALIZE_TEMPLATE
struct nsStringAllocatorTraits<char>
{
static nsStringAllocator<char>& global_string_allocator() { return StringAllocator_char(); }
};
NS_SPECIALIZE_TEMPLATE
struct nsStringAllocatorTraits<PRUnichar>
{
static nsStringAllocator<PRUnichar>& global_string_allocator() { return StringAllocator_wchar_t(); }
};
// end of string allocator stuff that needs to move
/**
*
*/
template <class CharT>
class nsSharedBufferHandle
: public nsBufferHandle<CharT>
{
protected:
enum
{
kIsShared = 0x8000000,
kIsSingleAllocationWithBuffer = 0x4000000, // handle and buffer are one piece, no separate deallocation is possible for the buffer
kIsStorageDefinedSeparately = 0x2000000, // i.e., we're using the ``flex'' structure defined below
kIsUserAllocator = 0x1000000, // can't |delete|, call a hook instead
kImplementationFlagsMask = 0x0F00000,
kFlagsMask = 0xFF00000,
kRefCountMask = 0x00FFFFF
};
public:
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
{
mFlags = kIsShared;
}
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT*, CharT*, PRBool isSingleAllocation )
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
{
mFlags = kIsShared;
if ( isSingleAllocation )
mFlags |= kIsSingleAllocationWithBuffer;
}
~nsSharedBufferHandle();
void
AcquireReference() const
{
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
mutable_this->set_refcount( get_refcount()+1 );
}
void
ReleaseReference() const
{
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
if ( !mutable_this->set_refcount( get_refcount()-1 ) )
delete mutable_this;
// hmm, what if |kIsUserAllocator| and |kIsSingleAllocationWithBuffer|?
}
PRBool
IsReferenced() const
{
return get_refcount() != 0;
}
PRUint32
GetImplementationFlags() const
{
return mFlags & kImplementationFlagsMask;
}
void
SetImplementationFlags( PRUint32 aNewFlags )
{
mFlags = (mFlags & ~kImplementationFlagsMask) | (aNewFlags & kImplementationFlagsMask);
}
protected:
PRUint32 mFlags;
PRUint32
get_refcount() const
{
return mFlags & kRefCountMask;
}
PRUint32
set_refcount( PRUint32 aNewRefCount )
{
NS_ASSERTION(aNewRefCount <= kRefCountMask, "aNewRefCount <= kRefCountMask");
mFlags = (mFlags & kFlagsMask) | aNewRefCount;
return aNewRefCount;
}
nsStringAllocator<CharT>& get_allocator() const;
};
template <class CharT>
class nsFlexBufferHandle
: public nsSharedBufferHandle<CharT>
{
public:
nsFlexBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
: nsSharedBufferHandle<CharT>(aDataStart, aDataEnd),
mStorageStart(aStorageStart),
mStorageEnd(aStorageEnd)
{
this->mFlags |= this->kIsStorageDefinedSeparately;
}
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
CharT* StorageStart() { return mStorageStart; }
const CharT* StorageStart() const { return mStorageStart; }
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
CharT* StorageEnd() { return mStorageEnd; }
const CharT* StorageEnd() const { return mStorageEnd; }
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
protected:
CharT* mStorageStart;
CharT* mStorageEnd;
};
template <class CharT>
class nsSharedBufferHandleWithAllocator
: public nsSharedBufferHandle<CharT>
{
public:
nsSharedBufferHandleWithAllocator( CharT* aDataStart, CharT* aDataEnd, nsStringAllocator<CharT>& aAllocator )
: nsSharedBufferHandle<CharT>(aDataStart, aDataEnd),
mAllocator(aAllocator)
{
this->mFlags |= this->kIsUserAllocator;
}
nsStringAllocator<CharT>& get_allocator() const { return mAllocator; }
protected:
nsStringAllocator<CharT>& mAllocator;
};
template <class CharT>
class nsFlexBufferHandleWithAllocator
: public nsFlexBufferHandle<CharT>
{
public:
nsFlexBufferHandleWithAllocator( CharT* aDataStart, CharT* aDataEnd,
CharT* aStorageStart, CharT* aStorageEnd,
nsStringAllocator<CharT>& aAllocator )
: nsFlexBufferHandle<CharT>(aDataStart, aDataEnd, aStorageStart, aStorageEnd),
mAllocator(aAllocator)
{
this->mFlags |= this->kIsUserAllocator;
}
nsStringAllocator<CharT>& get_allocator() const { return mAllocator; }
protected:
nsStringAllocator<CharT>& mAllocator;
};
template <class CharT>
nsStringAllocator<CharT>&
nsSharedBufferHandle<CharT>::get_allocator() const
// really don't want this to be |inline|
{
if ( mFlags & kIsUserAllocator )
{
if ( mFlags & kIsStorageDefinedSeparately )
return NS_REINTERPRET_CAST(const nsFlexBufferHandleWithAllocator<CharT>*, this)->get_allocator();
else
return NS_REINTERPRET_CAST(const nsSharedBufferHandleWithAllocator<CharT>*, this)->get_allocator();
}
return nsStringAllocatorTraits<CharT>::global_string_allocator();
}
template <class CharT>
nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
// really don't want this to be |inline|
{
NS_ASSERTION(!IsReferenced(), "!IsReferenced()");
if ( !(mFlags & kIsSingleAllocationWithBuffer) )
{
CharT* string_storage = this->mDataStart;
if ( mFlags & kIsStorageDefinedSeparately )
string_storage = NS_REINTERPRET_CAST(nsFlexBufferHandle<CharT>*, this)->StorageStart();
get_allocator().Deallocate(string_storage);
}
}
#endif // !defined(nsBufferHandle_h___)

View File

@@ -1,174 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsBufferHandleUtils_h___
#define nsBufferHandleUtils_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
#include <new.h>
// for placement |new|
template <class CharT>
class nsAutoBufferHandle
{
public:
nsAutoBufferHandle() : mHandle(0) { }
nsAutoBufferHandle( const nsAutoBufferHandle<CharT>& aOther )
: mHandle(aOther.get())
{
if ( mHandle)
mHandle->AcquireReference();
}
explicit
nsAutoBufferHandle( const nsSharedBufferHandle<CharT>* aHandle )
: mHandle(aHandle)
{
if ( mHandle)
mHandle->AcquireReference();
}
~nsAutoBufferHandle()
{
if ( mHandle )
mHandle->ReleaseReference();
}
nsAutoBufferHandle<CharT>&
operator=( const nsSharedBufferHandle<CharT>* rhs )
{
nsSharedBufferHandle<CharT>* old_handle = mHandle;
if ( (mHandle = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, rhs)) )
mHandle->AcquireReference();
if ( old_handle )
old_handle->ReleaseReference();
return *this;
}
nsAutoBufferHandle<CharT>&
operator=( const nsAutoBufferHandle<CharT>& rhs )
{
return operator=(rhs.get());
}
nsSharedBufferHandle<CharT>*
get() const
{
return mHandle;
}
operator nsSharedBufferHandle<CharT>*() const
{
return get();
}
nsSharedBufferHandle<CharT>*
operator->() const
{
return get();
}
private:
nsSharedBufferHandle<CharT>* mHandle;
};
template <class HandleT, class CharT>
inline
size_t
NS_AlignedHandleSize( const HandleT*, const CharT* )
{
// figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part
return ((sizeof(HandleT) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
}
template <class HandleT, class CharT>
inline
const CharT*
NS_DataAfterHandle( const HandleT* aHandlePtr, const CharT* aDummyCharTPtr )
{
typedef const CharT* CharT_ptr;
return CharT_ptr(NS_STATIC_CAST(const unsigned char*, aHandlePtr) + NS_AlignedHandleSize(aHandlePtr, aDummyCharTPtr));
}
template <class HandleT, class CharT>
inline
CharT*
NS_DataAfterHandle( HandleT* aHandlePtr, const CharT* aDummyCharTPtr )
{
typedef CharT* CharT_ptr;
return CharT_ptr(NS_STATIC_CAST(unsigned char*, aHandlePtr) + NS_AlignedHandleSize(aHandlePtr, aDummyCharTPtr));
}
template <class HandleT, class StringT>
HandleT*
NS_AllocateContiguousHandleWithData( const HandleT* aDummyHandlePtr, const StringT& aDataSource, PRUint32 aAdditionalCapacity )
{
typedef typename StringT::char_type char_type;
typedef char_type* char_ptr;
// figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part
size_t handle_size = NS_AlignedHandleSize(aDummyHandlePtr, char_ptr(0));
// figure out how many |char_type|s wee need to fit in the data part
size_t data_length = aDataSource.Length();
size_t buffer_length = data_length + aAdditionalCapacity;
// how many bytes is that (including a zero-terminator so we can claim to be flat)?
size_t buffer_size = buffer_length * sizeof(char_type);
HandleT* result = 0;
void* handle_ptr = ::operator new(handle_size + buffer_size);
if ( handle_ptr )
{
char_ptr data_start_ptr = char_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size);
char_ptr data_end_ptr = data_start_ptr + data_length;
char_ptr buffer_end_ptr = data_start_ptr + buffer_length;
typename StringT::const_iterator fromBegin, fromEnd;
char_ptr toBegin = data_start_ptr;
copy_string(aDataSource.BeginReading(fromBegin), aDataSource.EndReading(fromEnd), toBegin);
// and if the caller bothered asking for a buffer bigger than their string, we'll zero-terminate
if ( aAdditionalCapacity > 0 )
*toBegin = char_type(0);
result = new (handle_ptr) HandleT(data_start_ptr, data_end_ptr, data_start_ptr, buffer_end_ptr, PR_TRUE);
}
return result;
}
#endif // !defined(nsBufferHandleUtils_h___)

View File

@@ -1,705 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsCharTraits_h___
#define nsCharTraits_h___
#include <ctype.h>
// for |EOF|, |WEOF|
#include <string.h>
// for |memcpy|, et al
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
#ifndef nsStringIteratorUtils_h___
#include "nsStringIteratorUtils.h"
#endif
#ifdef HAVE_CPP_BOOL
typedef bool nsCharTraits_bool;
#else
typedef PRBool nsCharTraits_bool;
#endif
template <class CharT>
struct nsCharTraits
{
typedef CharT char_type;
typedef char incompatible_char_type;
static
void
assign( char_type& lhs, const char_type& rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef int int_type;
static
char_type
to_char_type( const int_type& c )
{
return char_type(c);
}
static
int_type
to_int_type( const char_type& c )
{
return int_type(c);
}
static
nsCharTraits_bool
eq_int_type( const int_type& lhs, const int_type& rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( const char_type& lhs, const char_type& rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( const char_type& lhs, const char_type& rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
char_type*
copy( char_type* s1, const char_type* s2, size_t n )
{
char_type* result = s1;
while ( n-- )
assign(*s1++, *s2++);
return result;
}
static
char_type*
move( char_type* s1, const char_type* s2, size_t n )
{
char_type* result = s1;
if ( n )
{
if ( s2 > s1 )
copy(s1, s2, n);
else
{
s1 += n;
s2 += n;
while ( n-- )
assign(*--s1, *--s2);
}
}
return result;
}
static
char_type*
assign( char_type* s, size_t n, const char_type& c )
{
char_type* result = s;
while ( n-- )
assign(*s++, c);
return result;
}
static
int
compare( const char_type* s1, const char_type* s2, size_t n )
{
for ( ; n--; ++s1, ++s2 )
{
if ( lt(*s1, *s2) )
return -1;
if ( lt(*s2, *s1) )
return 1;
}
return 0;
}
static
size_t
length( const char_type* s )
{
size_t result = 0;
while ( !eq(*s++, CharT(0)) )
++result;
return result;
}
static
const char_type*
find( const char_type* s, size_t n, const char_type& c )
{
while ( n-- )
{
if ( eq(*s, c) )
return s;
++s;
}
return 0;
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return EOF;
}
static
int_type
not_eof( const int_type& c )
{
return eq_int_type(c, eof()) ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
NS_SPECIALIZE_TEMPLATE
struct nsCharTraits<char>
{
typedef char char_type;
typedef PRUnichar incompatible_char_type;
static
void
assign( char& lhs, char rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef int int_type;
static
char
to_char_type( int c )
{
return char(c);
}
static
int
to_int_type( char c )
{
return int( NS_STATIC_CAST(unsigned char, c) );
}
static
nsCharTraits_bool
eq_int_type( int lhs, int rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( char lhs, char rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( char lhs, char rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
char*
move( char* s1, const char* s2, size_t n )
{
return NS_STATIC_CAST(char*, memmove(s1, s2, n));
}
static
char*
copy( char* s1, const char* s2, size_t n )
{
return NS_STATIC_CAST(char*, memcpy(s1, s2, n));
}
static
char*
assign( char* s, size_t n, char c )
{
return NS_STATIC_CAST(char*, memset(s, to_int_type(c), n));
}
static
int
compare( const char* s1, const char* s2, size_t n )
{
return memcmp(s1, s2, n);
}
static
size_t
length( const char* s )
{
return strlen(s);
}
static
const char*
find( const char* s, size_t n, char c )
{
return NS_REINTERPRET_CAST(const char*, memchr(s, to_int_type(c), n));
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return EOF;
}
static
int
not_eof( int c )
{
return c==eof() ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
#if 0
NS_SPECIALIZE_TEMPLATE
struct nsCharTraits<wchar_t>
{
typedef wchar_t char_type;
static
void
assign( wchar_t& lhs, wchar_t rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef wint_t int_type;
static
wchar_t
to_char_type( int_type c )
{
return wchar_t(c);
}
static
int_type
to_int_type( wchar_t c )
{
return int_type(c);
}
static
nsCharTraits_bool
eq_int_type( int_type lhs, int_type rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( wchar_t lhs, wchar_t rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( wchar_t lhs, wchar_t rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
wchar_t*
move( wchar_t* s1, const wchar_t* s2, size_t n )
{
return NS_STATIC_CAST(wchar_t*, wmemmove(s1, s2, n));
}
static
wchar_t*
copy( wchar_t* s1, const wchar_t* s2, size_t n )
{
return NS_STATIC_CAST(wchar_t*, wmemcpy(s1, s2, n));
}
static
wchar_t*
assign( wchar_t* s, size_t n, wchar_t c )
{
return NS_STATIC_CAST(wchar_t*, wmemset(s, to_int_type(c), n));
}
static
int
compare( const wchar_t* s1, const wchar_t* s2, size_t n )
{
return wmemcmp(s1, s2, n);
}
static
size_t
length( const wchar_t* s )
{
return wcslen(s);
}
static
const wchar_t*
find( const wchar_t* s, size_t n, wchar_t c )
{
return NS_REINTERPRET_CAST(const wchar_t*, wmemchr(s, to_int_type(c), n));
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return WEOF;
}
static
int_type
not_eof( int_type c )
{
return c==eof() ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
#endif
template <class InputIterator>
struct nsCharSourceTraits
{
typedef typename InputIterator::difference_type difference_type;
#if 0
static
PRUint32
distance( const InputIterator& first, const InputIterator& last )
{
// ...
}
#endif
static
PRUint32
readable_distance( const InputIterator& iter )
{
return iter.size_forward();
}
static
PRUint32
readable_distance( const InputIterator& first, const InputIterator& last )
{
return PRUint32(SameFragment(first, last) ? last.get()-first.get() : first.size_forward());
}
static
const typename InputIterator::value_type*
read( const InputIterator& iter )
{
return iter.get();
}
static
void
advance( InputIterator& s, difference_type n )
{
s.advance(n);
}
};
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
template <class CharT>
struct nsCharSourceTraits<CharT*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( CharT* first, CharT* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( CharT* s )
{
return PRUint32(nsCharTraits<CharT>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( CharT* first, CharT* last )
{
return PRUint32(last-first);
}
static
const CharT*
read( CharT* s )
{
return s;
}
static
void
advance( CharT*& s, difference_type n )
{
s += n;
}
};
#else
NS_SPECIALIZE_TEMPLATE
struct nsCharSourceTraits<const char*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( const char* first, const char* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( const char* s )
{
return PRUint32(nsCharTraits<char>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( const char* first, const char* last )
{
return PRUint32(last-first);
}
static
const char*
read( const char* s )
{
return s;
}
static
void
advance( const char*& s, difference_type n )
{
s += n;
}
};
NS_SPECIALIZE_TEMPLATE
struct nsCharSourceTraits<const PRUnichar*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( const PRUnichar* first, const PRUnichar* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( const PRUnichar* s )
{
return PRUint32(nsCharTraits<PRUnichar>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( const PRUnichar* first, const PRUnichar* last )
{
return PRUint32(last-first);
}
static
const PRUnichar*
read( const PRUnichar* s )
{
return s;
}
static
void
advance( const PRUnichar*& s, difference_type n )
{
s += n;
}
};
#endif
template <class OutputIterator>
struct nsCharSinkTraits
{
static
PRUint32
write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
{
return iter.write(s, n);
}
};
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
template <class CharT>
struct nsCharSinkTraits<CharT*>
{
static
PRUint32
write( CharT*& iter, const CharT* s, PRUint32 n )
{
nsCharTraits<CharT>::move(iter, s, n);
iter += n;
return n;
}
};
#else
NS_SPECIALIZE_TEMPLATE
struct nsCharSinkTraits<char*>
{
static
PRUint32
write( char*& iter, const char* s, PRUint32 n )
{
nsCharTraits<char>::move(iter, s, n);
iter += n;
return n;
}
};
NS_SPECIALIZE_TEMPLATE
struct nsCharSinkTraits<PRUnichar*>
{
static
PRUint32
write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
{
nsCharTraits<PRUnichar>::move(iter, s, n);
iter += n;
return n;
}
};
#endif
#endif // !defined(nsCharTraits_h___)

View File

@@ -1,102 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsCommonString.h --- a string implementation that shares its underlying storage */
#ifndef nsCommonString_h___
#define nsCommonString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
#ifndef nsBufferHandleUtils_h___
#include "nsBufferHandleUtils.h"
#endif
//-------1---------2---------3---------4---------5---------6---------7---------8
/**
* Not yet ready for non-|const| access
*/
class NS_COM nsCommonString
: public nsAFlatString
{
public:
typedef nsCommonString self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
public:
nsCommonString() { }
nsCommonString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { }
nsCommonString( const string_type& aReadable ) { assign(aReadable); }
self_type&
operator=( const string_type& aReadable )
{
assign(aReadable);
return *this;
}
protected:
void assign( const string_type& );
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
private:
nsAutoBufferHandle<char_type> mBuffer;
};
class NS_COM nsCommonCString
: public nsAFlatCString
{
public:
typedef nsCommonCString self_type;
typedef char char_type;
typedef nsACString string_type;
public:
nsCommonCString() { }
nsCommonCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { }
nsCommonCString( const string_type& aReadable ) { assign(aReadable); }
self_type&
operator=( const string_type& aReadable )
{
assign(aReadable);
return *this;
}
protected:
void assign( const string_type& );
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
private:
nsAutoBufferHandle<char_type> mBuffer;
};
#endif /* !defined(nsCommonString_h___) */

View File

@@ -1,269 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsPromiseConcatenation.h --- string concatenation machinery lives here, but don't include this file
directly, always get it by including either "nsAString.h" or one of the compatibility headers */
#ifndef nsPromiseConcatenation_h___
#define nsPromiseConcatenation_h___
/**
NOT FOR USE BY HUMANS
Instances of this class only exist as anonymous temporary results from |operator+()|.
This is the machinery that makes string concatenation efficient. No allocations or
character copies are required unless and until a final assignment is made. It works
its magic by overriding and forwarding calls to |GetReadableFragment()|.
Note: |nsPromiseConcatenation| imposes some limits on string concatenation with |operator+()|.
- no more than 33 strings, e.g., |s1 + s2 + s3 + ... s32 + s33|
- left to right evaluation is required ... do not use parentheses to override this
In practice, neither of these is onerous. Parentheses do not change the semantics of the
concatenation, only the order in which the result is assembled ... so there's no reason
for a user to need to control it. Too many strings summed together can easily be worked
around with an intermediate assignment. I wouldn't have the parentheses limitation if I
assigned the identifier mask starting at the top, the first time anybody called
|GetReadableFragment()|.
*/
class NS_COM nsPromiseConcatenation
: public nsAPromiseString
{
public:
typedef nsPromiseConcatenation self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) | mFragmentIdentifierMask);
return kRightString;
}
public:
nsPromiseConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsPromiseConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsPromiseConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsPromiseConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
class NS_COM nsPromiseCConcatenation
: public nsAPromiseCString
{
public:
typedef nsPromiseCConcatenation self_type;
typedef char char_type;
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) | mFragmentIdentifierMask);
return kRightString;
}
public:
nsPromiseCConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsPromiseCConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsPromiseCConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsPromiseCConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
/*
How shall we provide |operator+()|?
What would it return? It has to return a stack based object, because the client will
not be given an opportunity to handle memory management in an expression like
myWritableString = stringA + stringB + stringC;
...so the `obvious' answer of returning a new |nsSharedString| is no good. We could
return an |nsString|, if that name were in scope here, though there's no telling what the client
will really want to do with the result. What might be better, though,
is to return a `promise' to concatenate some strings...
By making |nsPromiseConcatenation| inherit from readable strings, we automatically handle
assignment and other interesting uses within writable strings, plus we drastically reduce
the number of cases we have to write |operator+()| for. The cost is extra temporary concat strings
in the evaluation of strings of '+'s, e.g., |A + B + C + D|, and that we have to do some work
to implement the virtual functions of readables.
*/
inline
const nsPromiseConcatenation
operator+( const nsPromiseConcatenation& lhs, const nsAString& rhs )
{
return nsPromiseConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsPromiseCConcatenation
operator+( const nsPromiseCConcatenation& lhs, const nsACString& rhs )
{
return nsPromiseCConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsPromiseConcatenation
operator+( const nsAString& lhs, const nsAString& rhs )
{
return nsPromiseConcatenation(lhs, rhs);
}
inline
const nsPromiseCConcatenation
operator+( const nsACString& lhs, const nsACString& rhs )
{
return nsPromiseCConcatenation(lhs, rhs);
}
#if 0
inline
const nsPromiseConcatenation
nsPromiseConcatenation::operator+( const string_type& rhs ) const
{
return nsPromiseConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
inline
const nsPromiseCConcatenation
nsPromiseCConcatenation::operator+( const string_type& rhs ) const
{
return nsPromiseCConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
#endif
#endif /* !defined(nsPromiseConcatenation_h___) */

View File

@@ -1,127 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsLocalString_h___
#define nsLocalString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
/*
...this class wraps a constant literal string and lets it act like an |nsAReadable...|.
Use it like this:
SomeFunctionTakingACString( nsLiteralCString("Hello, World!") );
With some tweaking, I think I can make this work as well...
SomeStringFunc( nsLiteralString( L"Hello, World!" ) );
This class just holds a pointer. If you don't supply the length, it must calculate it.
No copying or allocations are performed.
|const nsLocalString&| appears frequently in interfaces because it
allows the automatic conversion of a |PRUnichar*|.
*/
class NS_COM nsLocalString
: public nsAFlatString
{
public:
explicit
nsLocalString( const PRUnichar* aLiteral )
: mHandle(NS_CONST_CAST(PRUnichar*, aLiteral), aLiteral ? (NS_CONST_CAST(PRUnichar*, aLiteral)+nsCharTraits<PRUnichar>::length(aLiteral)) : NS_CONST_CAST(PRUnichar*, aLiteral))
{
// nothing else to do here
}
nsLocalString( const PRUnichar* aLiteral, PRUint32 aLength )
: mHandle(NS_CONST_CAST(PRUnichar*, aLiteral), NS_CONST_CAST(PRUnichar*, aLiteral)+aLength)
{
// This is an annoying hack. Callers should be fixed to use the other
// constructor if they don't really know the length.
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller constructing a string doesn't know the real length. Please use the other constructor.");
mHandle.DataEnd(aLiteral ? (NS_CONST_CAST(PRUnichar*, aLiteral)+nsCharTraits<PRUnichar>::length(aLiteral)) : NS_CONST_CAST(PRUnichar*, aLiteral));
}
}
// nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK
// ~nsLocalString(); // auto-generated destructor OK
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const { return &mHandle; }
virtual const nsBufferHandle<PRUnichar>* GetBufferHandle() const { return &mHandle; }
private:
nsBufferHandle<PRUnichar> mHandle;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsLocalString& ); // we're immutable
};
class NS_COM nsLocalCString
: public nsAFlatCString
{
public:
explicit
nsLocalCString( const char* aLiteral )
: mHandle(NS_CONST_CAST(char*, aLiteral), aLiteral ? (NS_CONST_CAST(char*, aLiteral)+nsCharTraits<char>::length(aLiteral)) : NS_CONST_CAST(char*, aLiteral))
{
// nothing else to do here
}
nsLocalCString( const char* aLiteral, PRUint32 aLength )
: mHandle(NS_CONST_CAST(char*, aLiteral), NS_CONST_CAST(char*, aLiteral)+aLength)
{
// This is an annoying hack. Callers should be fixed to use the other
// constructor if they don't really know the length.
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller constructing a string doesn't know the real length. Please use the other constructor.");
mHandle.DataEnd(aLiteral ? (NS_CONST_CAST(char*, aLiteral)+nsCharTraits<char>::length(aLiteral)) : NS_CONST_CAST(char*, aLiteral));
}
}
// nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK
// ~nsLocalCString(); // auto-generated destructor OK
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const { return &mHandle; }
virtual const nsBufferHandle<char>* GetBufferHandle() const { return &mHandle; }
private:
nsBufferHandle<char> mHandle;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsLocalCString& ); // we're immutable
};
#endif /* !defined(nsLocalString_h___) */

View File

@@ -1,182 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsPromiseSubstring_h___
#define nsPromiseSubstring_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
//
// nsPromiseSubstring
//
class NS_COM nsPromiseSubstring
: public nsAPromiseString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsPromiseConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsPromiseConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsPromiseSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsPromiseSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsPromiseSubstring( const nsPromiseSubstring& ); // auto-generated copy-constructor should be OK
// ~nsPromiseSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& aString ) const { return mString.Promises(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
class NS_COM nsPromiseCSubstring
: public nsAPromiseCString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsPromiseConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsPromiseConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsPromiseCSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsPromiseCSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsPromiseCSubstring( const nsPromiseCSubstring& ); // auto-generated copy-constructor should be OK
// ~nsPromiseCSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseCSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& aString ) const { return mString.Promises(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
inline
const nsPromiseCSubstring
Substring( const nsACString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsPromiseCSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsPromiseSubstring
Substring( const nsAString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsPromiseSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsPromiseCSubstring
Substring( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
{
return nsPromiseCSubstring(aStart, aEnd);
}
inline
const nsPromiseSubstring
Substring( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
return nsPromiseSubstring(aStart, aEnd);
}
#endif /* !defined(nsPromiseSubstring_h___) */

View File

@@ -1,69 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla XPCOM.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsFragmentedString_h___
#define nsFragmentedString_h___
// WORK IN PROGRESS
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsSharedBufferList_h___
#include "nsSharedBufferList.h"
#endif
class nsFragmentedString
: public nsAString
/*
...
*/
{
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
nsFragmentedString() { }
virtual PRUint32 Length() const;
virtual void SetLength( PRUint32 aNewLength );
// virtual void SetCapacity( PRUint32 aNewCapacity );
// virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
protected:
// virtual void do_AssignFromReadable( const nsAString& );
// virtual void do_AppendFromReadable( const nsAString& );
// virtual void do_InsertFromReadable( const nsAString&, PRUint32 );
// virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const nsAString& );
private:
nsSharedBufferList mBufferList;
};
#endif // !defined(nsFragmentedString_h___)

View File

@@ -1,84 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsLiteralString_h___
#define nsLiteralString_h___
#ifndef nscore_h___
#include "nscore.h"
#endif
#ifndef nsLocalString_h___
#include "nsLocalString.h"
#endif
typedef const nsLocalString nsLiteralString;
typedef const nsLocalCString nsLiteralCString;
#if 0
inline
const nsLocalString
literal_string( const PRUnichar* aPtr )
{
return nsLocalString(aPtr);
}
inline
const nsLocalString
literal_string( const PRUnichar* aPtr, PRUint32 aLength )
{
return nsLocalString(aPtr, aLength);
}
inline
const nsLocalCString
literal_string( const char* aPtr )
{
return nsLocalCString(aPtr);
}
inline
const nsLocalCString
literal_string( const char* aPtr, PRUint32 aLength )
{
return nsLocalCString(aPtr, aLength);
}
#endif
#ifdef HAVE_CPP_2BYTE_WCHAR_T
#define NS_L(s) L##s
#define NS_MULTILINE_LITERAL_STRING(s) nsLiteralString(s, (sizeof(s)/sizeof(wchar_t))-1)
#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) nsLiteralString n(s, (sizeof(s)/sizeof(wchar_t))-1)
#else
#define NS_L(s) s
#define NS_MULTILINE_LITERAL_STRING(s) NS_ConvertASCIItoUCS2(s, sizeof(s)-1)
#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) NS_ConvertASCIItoUCS2 n(s, sizeof(s)-1)
#endif
#define NS_LITERAL_STRING(s) NS_MULTILINE_LITERAL_STRING(NS_L(s))
#define NS_NAMED_LITERAL_STRING(n,s) NS_NAMED_MULTILINE_LITERAL_STRING(n,NS_L(s))
#define NS_LITERAL_CSTRING(s) nsLiteralCString(s, sizeof(s)-1)
#define NS_NAMED_LITERAL_CSTRING(n,s) nsLiteralCString n(s, sizeof(s)-1)
#endif /* !defined(nsLiteralString_h___) */

View File

@@ -1,127 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsLocalString_h___
#define nsLocalString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
/*
...this class wraps a constant literal string and lets it act like an |nsAReadable...|.
Use it like this:
SomeFunctionTakingACString( nsLiteralCString("Hello, World!") );
With some tweaking, I think I can make this work as well...
SomeStringFunc( nsLiteralString( L"Hello, World!" ) );
This class just holds a pointer. If you don't supply the length, it must calculate it.
No copying or allocations are performed.
|const nsLocalString&| appears frequently in interfaces because it
allows the automatic conversion of a |PRUnichar*|.
*/
class NS_COM nsLocalString
: public nsAFlatString
{
public:
explicit
nsLocalString( const PRUnichar* aLiteral )
: mHandle(NS_CONST_CAST(PRUnichar*, aLiteral), aLiteral ? (NS_CONST_CAST(PRUnichar*, aLiteral)+nsCharTraits<PRUnichar>::length(aLiteral)) : NS_CONST_CAST(PRUnichar*, aLiteral))
{
// nothing else to do here
}
nsLocalString( const PRUnichar* aLiteral, PRUint32 aLength )
: mHandle(NS_CONST_CAST(PRUnichar*, aLiteral), NS_CONST_CAST(PRUnichar*, aLiteral)+aLength)
{
// This is an annoying hack. Callers should be fixed to use the other
// constructor if they don't really know the length.
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller constructing a string doesn't know the real length. Please use the other constructor.");
mHandle.DataEnd(aLiteral ? (NS_CONST_CAST(PRUnichar*, aLiteral)+nsCharTraits<PRUnichar>::length(aLiteral)) : NS_CONST_CAST(PRUnichar*, aLiteral));
}
}
// nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK
// ~nsLocalString(); // auto-generated destructor OK
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const { return &mHandle; }
virtual const nsBufferHandle<PRUnichar>* GetBufferHandle() const { return &mHandle; }
private:
nsBufferHandle<PRUnichar> mHandle;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsLocalString& ); // we're immutable
};
class NS_COM nsLocalCString
: public nsAFlatCString
{
public:
explicit
nsLocalCString( const char* aLiteral )
: mHandle(NS_CONST_CAST(char*, aLiteral), aLiteral ? (NS_CONST_CAST(char*, aLiteral)+nsCharTraits<char>::length(aLiteral)) : NS_CONST_CAST(char*, aLiteral))
{
// nothing else to do here
}
nsLocalCString( const char* aLiteral, PRUint32 aLength )
: mHandle(NS_CONST_CAST(char*, aLiteral), NS_CONST_CAST(char*, aLiteral)+aLength)
{
// This is an annoying hack. Callers should be fixed to use the other
// constructor if they don't really know the length.
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller constructing a string doesn't know the real length. Please use the other constructor.");
mHandle.DataEnd(aLiteral ? (NS_CONST_CAST(char*, aLiteral)+nsCharTraits<char>::length(aLiteral)) : NS_CONST_CAST(char*, aLiteral));
}
}
// nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK
// ~nsLocalCString(); // auto-generated destructor OK
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const { return &mHandle; }
virtual const nsBufferHandle<char>* GetBufferHandle() const { return &mHandle; }
private:
nsBufferHandle<char> mHandle;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsLocalCString& ); // we're immutable
};
#endif /* !defined(nsLocalString_h___) */

View File

@@ -1,96 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef nsPrintfCString_h___
#define nsPrintfCString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
/**
* |nsPrintfCString| lets you use a formated |printf| string as an |nsAReadableCString|.
*
* myCStr += nsPrintfCString("%f", 13.917);
* // ...a general purpose substitute for |AppendFloat|
*
* For longer patterns, you'll want to use the constructor that takes a length
*
* nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1);
*
* Exceding the default size (which you must specify in the constructor, it is not determined)
* causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is
* cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs).
* This class is intended to be useful for numbers and short
* strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no
* wide version of this class, since wide |printf| is not generally available. That means
* to get a wide version of your formatted data, you must, e.g.,
*
* CopyASCIItoUCS2(nsPrintfCString("%f", 13.917"), myStr);
*
* That's another good reason to avoid this class for anything but numbers ... as strings can be
* much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|.
*/
class nsPrintfCString
: public nsACString
{
enum { kLocalBufferSize=15 };
// ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask)
// pinkerton suggests 7. We should measure and decide what's appropriate
public:
explicit nsPrintfCString( const char* format, ... );
nsPrintfCString( size_t n, const char* format, ...);
~nsPrintfCString();
virtual PRUint32 Length() const;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 ) { return 0; }
// virtual PRBool GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const;
private:
char* mStart;
PRUint32 mLength;
char mLocalBuffer[ kLocalBufferSize + 1 ];
};
#endif // !defined(nsPrintfCString_h___)

View File

@@ -1,82 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsPrivateSharableString_h___
#define nsPrivateSharableString_h___
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
#endif
/**
* This class is part of the machinery that makes
* most string implementations in this family share their underlying buffers
* when convenient. It is _not_ part of the abstract string interface,
* though other machinery interested in sharing buffers will know about it.
*
* Normal string clients must _never_ call routines from this interface.
*/
class NS_COM nsPrivateSharableString
{
public:
typedef PRUnichar char_type;
public:
virtual ~nsPrivateSharableString() {}
virtual PRUint32 GetImplementationFlags() const;
virtual const nsBufferHandle<char_type>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char_type>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
/**
* |GetBufferHandle()| will return either |0|, or a reasonable pointer.
* The meaning of |0| is that the string points to a non-contiguous or else empty representation.
* Otherwise |GetBufferHandle()| returns a handle that points to the single contiguous hunk of characters
* that make up this string.
*/
};
class NS_COM nsPrivateSharableCString
{
public:
typedef char char_type;
public:
virtual ~nsPrivateSharableCString() {}
virtual PRUint32 GetImplementationFlags() const;
virtual const nsBufferHandle<char_type>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char_type>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
/**
* |GetBufferHandle()| will return either |0|, or a reasonable pointer.
* The meaning of |0| is that the string points to a non-contiguous or else empty representation.
* Otherwise |GetBufferHandle()| returns a handle that points to the single contiguous hunk of characters
* that make up this string.
*/
};
#endif // !defined(nsPrivateSharableString_h___)

View File

@@ -1,269 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsPromiseConcatenation.h --- string concatenation machinery lives here, but don't include this file
directly, always get it by including either "nsAString.h" or one of the compatibility headers */
#ifndef nsPromiseConcatenation_h___
#define nsPromiseConcatenation_h___
/**
NOT FOR USE BY HUMANS
Instances of this class only exist as anonymous temporary results from |operator+()|.
This is the machinery that makes string concatenation efficient. No allocations or
character copies are required unless and until a final assignment is made. It works
its magic by overriding and forwarding calls to |GetReadableFragment()|.
Note: |nsPromiseConcatenation| imposes some limits on string concatenation with |operator+()|.
- no more than 33 strings, e.g., |s1 + s2 + s3 + ... s32 + s33|
- left to right evaluation is required ... do not use parentheses to override this
In practice, neither of these is onerous. Parentheses do not change the semantics of the
concatenation, only the order in which the result is assembled ... so there's no reason
for a user to need to control it. Too many strings summed together can easily be worked
around with an intermediate assignment. I wouldn't have the parentheses limitation if I
assigned the identifier mask starting at the top, the first time anybody called
|GetReadableFragment()|.
*/
class NS_COM nsPromiseConcatenation
: public nsAPromiseString
{
public:
typedef nsPromiseConcatenation self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) | mFragmentIdentifierMask);
return kRightString;
}
public:
nsPromiseConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsPromiseConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsPromiseConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsPromiseConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
class NS_COM nsPromiseCConcatenation
: public nsAPromiseCString
{
public:
typedef nsPromiseCConcatenation self_type;
typedef char char_type;
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) | mFragmentIdentifierMask);
return kRightString;
}
public:
nsPromiseCConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsPromiseCConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsPromiseCConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsPromiseCConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
/*
How shall we provide |operator+()|?
What would it return? It has to return a stack based object, because the client will
not be given an opportunity to handle memory management in an expression like
myWritableString = stringA + stringB + stringC;
...so the `obvious' answer of returning a new |nsSharedString| is no good. We could
return an |nsString|, if that name were in scope here, though there's no telling what the client
will really want to do with the result. What might be better, though,
is to return a `promise' to concatenate some strings...
By making |nsPromiseConcatenation| inherit from readable strings, we automatically handle
assignment and other interesting uses within writable strings, plus we drastically reduce
the number of cases we have to write |operator+()| for. The cost is extra temporary concat strings
in the evaluation of strings of '+'s, e.g., |A + B + C + D|, and that we have to do some work
to implement the virtual functions of readables.
*/
inline
const nsPromiseConcatenation
operator+( const nsPromiseConcatenation& lhs, const nsAString& rhs )
{
return nsPromiseConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsPromiseCConcatenation
operator+( const nsPromiseCConcatenation& lhs, const nsACString& rhs )
{
return nsPromiseCConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsPromiseConcatenation
operator+( const nsAString& lhs, const nsAString& rhs )
{
return nsPromiseConcatenation(lhs, rhs);
}
inline
const nsPromiseCConcatenation
operator+( const nsACString& lhs, const nsACString& rhs )
{
return nsPromiseCConcatenation(lhs, rhs);
}
#if 0
inline
const nsPromiseConcatenation
nsPromiseConcatenation::operator+( const string_type& rhs ) const
{
return nsPromiseConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
inline
const nsPromiseCConcatenation
nsPromiseCConcatenation::operator+( const string_type& rhs ) const
{
return nsPromiseCConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
#endif
#endif /* !defined(nsPromiseConcatenation_h___) */

View File

@@ -1,150 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsPromiseFlatString_h___
#define nsPromiseFlatString_h___
#ifndef nsCommonString_h___
#include "nsCommonString.h"
#endif
/**
* WARNING:
*
* Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last resort,
* and this may be necessary when dealing with legacy or OS calls, but in general,
* requiring a zero-terminated contiguous hunk of characters kills many of the performance
* wins the string classes offer. Write your own code to use |nsA[C]String&|s for parameters.
* Write your string proccessing algorithms to exploit iterators. If you do this, you
* will benefit from being able to chain operations without copying or allocating and your
* code will be significantly more efficient. Remember, a function that takes an
* |const nsA[C]String&| can always be passed a raw character pointer by wrapping it (for free)
* in a |nsLocal[C]String|. But a function that takes a character pointer always has the
* potential to force allocation and copying.
*
*
* How to use it:
*
* Like all `promises', a |nsPromiseFlat[C]String| doesn't own the characters it promises.
* You must never use it to promise characters out of a string with a shorter lifespan.
* The typical use will be something like this
*
* SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD
*
* Here's a BAD use:
*
* const char* buffer = PromiseFlatCString(aCString).get();
* SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer
*
* A |nsPromiseFlat[C]String| doesn't support non-|const| access (you can't use it to make
* changes back into the original string). To help you avoid that, the only way to make
* one is with the function |PromiseFlat[C]String|, which produce a |const| instance.
* ``What if I need to keep a promise around for a little while?'' you might ask.
* In that case, you can keep a reference, like so
*
* const nsPromiseFlatString& flat = PromiseFlatString(aString);
* // this reference holds the anonymous temporary alive, but remember, it must _still_
* // have a lifetime shorter than that of |aString|
*
* SomeOSFunction(flat.get());
* SomeOtherOSFunction(flat.get());
*
*
* How does it work?
*
* A |nsPromiseFlat[C]String| is just a wrapper for another string. If you apply it to
* a string that happens to be flat, your promise is just a reference to that other string
* and all calls are forwarded through to it. If you apply it to a non-flat string,
* then a temporary flat string is created for you, by allocating and copying. In the unlikely
* event that you end up assigning the result into a sharing string (e.g., |nsCommon[C]String|),
* the right thing happens.
*/
class NS_COM nsPromiseFlatString
: public nsAFlatString /* , public nsAPromiseString */
{
friend const nsPromiseFlatString PromiseFlatString( const nsAString& );
public:
nsPromiseFlatString( const nsPromiseFlatString& );
virtual const PRUnichar* get() const; // this will be gone after we fix obsolete/nsString
protected:
nsPromiseFlatString() : mPromisedString(&mFlattenedString) { }
explicit nsPromiseFlatString( const nsAString& aString );
virtual const nsBufferHandle<char_type>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char_type>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseFlatString& );
private:
nsCommonString mFlattenedString;
const nsAFlatString* mPromisedString;
};
class NS_COM nsPromiseFlatCString
: public nsAFlatCString /* , public nsAPromiseCString */
{
friend const nsPromiseFlatCString PromiseFlatCString( const nsACString& );
public:
nsPromiseFlatCString( const nsPromiseFlatCString& );
virtual const char* get() const; // this will be gone after we fix obsolete/nsString
protected:
nsPromiseFlatCString() : mPromisedString(&mFlattenedString) { }
explicit nsPromiseFlatCString( const nsACString& aString );
virtual const nsBufferHandle<char_type>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char_type>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseFlatCString& );
private:
nsCommonCString mFlattenedString;
const nsAFlatCString* mPromisedString;
};
inline
const nsPromiseFlatString
PromiseFlatString( const nsAString& aString )
{
return nsPromiseFlatString(aString);
}
inline
const nsPromiseFlatCString
PromiseFlatCString( const nsACString& aString )
{
return nsPromiseFlatCString(aString);
}
#endif /* !defined(nsPromiseFlatString_h___) */

View File

@@ -1,182 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsPromiseSubstring_h___
#define nsPromiseSubstring_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
//
// nsPromiseSubstring
//
class NS_COM nsPromiseSubstring
: public nsAPromiseString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsPromiseConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsPromiseConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsPromiseSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsPromiseSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsPromiseSubstring( const nsPromiseSubstring& ); // auto-generated copy-constructor should be OK
// ~nsPromiseSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& aString ) const { return mString.Promises(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
class NS_COM nsPromiseCSubstring
: public nsAPromiseCString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsPromiseConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsPromiseConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsPromiseCSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsPromiseCSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsPromiseCSubstring( const nsPromiseCSubstring& ); // auto-generated copy-constructor should be OK
// ~nsPromiseCSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseCSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& aString ) const { return mString.Promises(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
inline
const nsPromiseCSubstring
Substring( const nsACString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsPromiseCSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsPromiseSubstring
Substring( const nsAString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsPromiseSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsPromiseCSubstring
Substring( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
{
return nsPromiseCSubstring(aStart, aEnd);
}
inline
const nsPromiseSubstring
Substring( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
return nsPromiseSubstring(aStart, aEnd);
}
#endif /* !defined(nsPromiseSubstring_h___) */

View File

@@ -1,217 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
* Johnny Stenbeck <jst@netscape.com>
*
*/
#ifndef nsReadableUtils_h___
#define nsReadableUtils_h___
/**
* I guess all the routines in this file are all mis-named.
* According to our conventions, they should be |NS_xxx|.
*/
#ifndef nsAString_h___
#include "nsAString.h"
#endif
NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& );
NS_COM void CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest );
NS_COM void CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewCString( const nsAString& aSource );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource an 8-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewCString( const nsACString& aSource );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs a encoding conversion by converting 16-bit wide characters down to UTF8 encoded 8-bits wide string copying |aSource| to your new buffer.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewUTF8String( const nsAString& aSource );
/**
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
*/
NS_COM PRUnichar* ToNewUnicode( const nsAString& aSource );
/**
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource an 8-bit wide string
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
*/
NS_COM PRUnichar* ToNewUnicode( const nsACString& aSource );
/**
* Copies |aLength| 16-bit characters from the start of |aSource| to the
* |PRUnichar| buffer |aDest|.
*
* After this operation |aDest| is not null terminated.
*
* @param aSource a 16-bit wide string
* @param aSrcOffset start offset in the source string
* @param aDest a |PRUnichar| buffer
* @param aLength the number of 16-bit characters to copy
* @return pointer to destination buffer - identical to |aDest|
*/
NS_COM PRUnichar* CopyUnicodeTo( const nsAString& aSource,
PRUint32 aSrcOffset,
PRUnichar* aDest,
PRUint32 aLength );
/**
* Copies 16-bit characters between iterators |aSrcStart| and
* |aSrcEnd| to the writable string |aDest|. Similar to the
* |nsString::Mid| method.
*
* After this operation |aDest| is not null terminated.
*
* @param aSrcStart start source iterator
* @param aSrcEnd end source iterator
* @param aDest destination for the copy
*/
NS_COM void CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAString& aDest );
/**
* Appends 16-bit characters between iterators |aSrcStart| and
* |aSrcEnd| to the writable string |aDest|.
*
* After this operation |aDest| is not null terminated.
*
* @param aSrcStart start source iterator
* @param aSrcEnd end source iterator
* @param aDest destination for the copy
*/
NS_COM void AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAString& aDest );
/**
* Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
*
* @param aString a 16-bit wide string to scan
*/
NS_COM PRBool IsASCII( const nsAString& aString );
/**
* Converts case in place in the argument string.
*/
NS_COM void ToUpperCase( nsAString& );
NS_COM void ToUpperCase( nsACString& );
NS_COM void ToLowerCase( nsAString& );
NS_COM void ToLowerCase( nsACString& );
/**
* Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|.
*
* Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
* point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
*
* Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
* If we need something faster; we can implement that later.
*/
NS_COM PRBool FindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
NS_COM PRBool FindInReadable( const nsACString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& );
/**
* Finds the rightmost occurance of |aPattern|
* Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
* point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
*
* Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
* If we need something faster; we can implement that later.
*/
NS_COM PRBool RFindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
NS_COM PRBool RFindInReadable( const nsACString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& );
/**
* Finds the leftmost occurance of |aChar|, if any in the range
* |aSearchStart|..|aSearchEnd|.
*
* Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to
* point to the match. If no match was found, returns |PR_FALSE| and
* makes |aSearchStart == aSearchEnd|.
*/
NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, const nsReadingIterator<PRUnichar>& aSearchEnd );
NS_COM PRBool FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, const nsReadingIterator<char>& aSearchEnd );
/**
* Finds the number of occurences of |aChar| in the string |aStr|
*/
NS_COM PRUint32 CountCharInReadable( const nsAString& aStr,
PRUnichar aChar );
NS_COM PRUint32 CountCharInReadable( const nsACString& aStr,
char aChar );
#endif // !defined(nsReadableUtils_h___)

View File

@@ -1,102 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsCommonString.h --- a string implementation that shares its underlying storage */
#ifndef nsCommonString_h___
#define nsCommonString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
#ifndef nsBufferHandleUtils_h___
#include "nsBufferHandleUtils.h"
#endif
//-------1---------2---------3---------4---------5---------6---------7---------8
/**
* Not yet ready for non-|const| access
*/
class NS_COM nsCommonString
: public nsAFlatString
{
public:
typedef nsCommonString self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
public:
nsCommonString() { }
nsCommonString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { }
nsCommonString( const string_type& aReadable ) { assign(aReadable); }
self_type&
operator=( const string_type& aReadable )
{
assign(aReadable);
return *this;
}
protected:
void assign( const string_type& );
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
private:
nsAutoBufferHandle<char_type> mBuffer;
};
class NS_COM nsCommonCString
: public nsAFlatCString
{
public:
typedef nsCommonCString self_type;
typedef char char_type;
typedef nsACString string_type;
public:
nsCommonCString() { }
nsCommonCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { }
nsCommonCString( const string_type& aReadable ) { assign(aReadable); }
self_type&
operator=( const string_type& aReadable )
{
assign(aReadable);
return *this;
}
protected:
void assign( const string_type& );
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
private:
nsAutoBufferHandle<char_type> mBuffer;
};
#endif /* !defined(nsCommonString_h___) */

View File

@@ -1,224 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsSharedBufferList_h___
#define nsSharedBufferList_h___
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
// for |nsSharedBufferHandle|
#endif
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsLocalString_h___
#include "nsLocalString.h"
#endif
#ifndef nsBufferHandleUtils_h___
#include "nsBufferHandleUtils.h"
// for |NS_AllocateContiguousHandleWithData|
#endif
/**
* This class forms the basis for several multi-fragment string classes, in
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
*
* This class is not templated. It is provided only for |PRUnichar|-based strings.
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
* or else duplicate this class.
*/
class NS_COM nsSharedBufferList
{
public:
class Buffer
: public nsFlexBufferHandle<PRUnichar>
{
public:
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd, PRBool aIsSingleAllocation=PR_FALSE )
: nsFlexBufferHandle<PRUnichar>(aDataStart, aDataEnd, aStorageStart, aStorageEnd)
{
if ( aIsSingleAllocation )
this->mFlags |= this->kIsSingleAllocationWithBuffer;
}
/**
* These buffers will be `owned' by the list, and only the
* the list itself will be allowed to delete member |Buffer|s,
* therefore, we cannot use the inherited |AcquireReference|
* and |ReleaseReference|, as they use the model that the
* buffer manages its own lifetime.
*/
void
AcquireNonOwningReference() const
{
Buffer* mutable_this = NS_CONST_CAST(Buffer*, this);
mutable_this->set_refcount( get_refcount()+1 );
}
void
ReleaseNonOwningReference() const
{
Buffer* mutable_this = NS_CONST_CAST(Buffer*, this);
mutable_this->set_refcount( get_refcount()-1 );
}
Buffer* mPrev;
Buffer* mNext;
private:
// pass-by-value is explicitly denied
Buffer( const Buffer& ); // NOT TO BE IMPLEMENTED
void operator=( const Buffer& ); // NOT TO BE IMPLEMENTED
};
struct Position
{
Buffer* mBuffer;
PRUnichar* mPosInBuffer;
Position() { }
Position( Buffer* aBuffer, PRUnichar* aPosInBuffer ) : mBuffer(aBuffer), mPosInBuffer(aPosInBuffer) { }
// Position( const Position& ); -- auto-generated copy-constructor OK
// Position& operator=( const Position& ); -- auto-generated copy-assignment OK
// ~Position(); -- auto-generated destructor OK
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
explicit
Position( const nsReadingIterator<PRUnichar>& aIter )
: mBuffer( NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier)) ),
mPosInBuffer( NS_CONST_CAST(PRUnichar*, aIter.get()) )
{
// nothing else to do here
}
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
Position&
operator=( const nsReadingIterator<PRUnichar>& aIter )
{
mBuffer = NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier));
mPosInBuffer = NS_CONST_CAST(PRUnichar*, aIter.get());
return *this;
}
void PointTo( Buffer* aBuffer, PRUnichar* aPosInBuffer ) { mBuffer=aBuffer; mPosInBuffer=aPosInBuffer; }
void PointBefore( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataStart()); }
void PointAfter( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataEnd()); }
// Position( const Position& ); -- automatically generated copy-constructor is OK
// Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK
// don't want to provide this as |operator-|, since that might imply O(1)
static ptrdiff_t Distance( const Position&, const Position& );
};
public:
nsSharedBufferList( Buffer* aBuffer = 0 )
: mFirstBuffer(aBuffer),
mLastBuffer(aBuffer),
mTotalDataLength(0)
{
if ( aBuffer )
{
aBuffer->mPrev = aBuffer->mNext = 0;
mTotalDataLength = aBuffer->DataLength();
}
}
virtual ~nsSharedBufferList();
private:
// pass-by-value is explicitly denied
nsSharedBufferList( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
void operator=( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
public:
void LinkBuffer( Buffer*, Buffer*, Buffer* );
Buffer* UnlinkBuffer( Buffer* );
enum SplitDisposition // when splitting a buffer in two...
{
kSplitCopyRightData, // copy the data right of the split point to a new buffer
kSplitCopyLeastData, // copy the smaller amount of data to the new buffer
kSplitCopyLeftData // copy the data left of the split point to a new buffer
};
void SplitBuffer( const Position&, SplitDisposition = kSplitCopyLeastData );
static
Buffer*
NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalCapacity = 1 )
{
typedef Buffer* Buffer_ptr;
return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), nsLocalString(aData, aDataLength), aAdditionalCapacity);
}
static
Buffer*
NewSingleAllocationBuffer( const nsAString& aReadable, PRUint32 aAdditionalCapacity = 1 )
{
typedef Buffer* Buffer_ptr;
return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), aReadable, aAdditionalCapacity);
}
static
Buffer*
NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
{
return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd);
}
void DiscardSuffix( PRUint32 );
// need other discards: prefix, and by iterator or pointer or something
Buffer* GetFirstBuffer() { return mFirstBuffer; }
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
Buffer* GetLastBuffer() { return mLastBuffer; }
const Buffer* GetLastBuffer() const { return mLastBuffer; }
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
protected:
void DestroyBuffers();
protected:
Buffer* mFirstBuffer;
Buffer* mLastBuffer;
ptrdiff_t mTotalDataLength;
};
#endif // !defined(nsSharedBufferList_h___)

View File

@@ -1,203 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsSlidingString_h___
#define nsSlidingString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsSharedBufferList_h___
#include "nsSharedBufferList.h"
#endif
/**
* Maintains the sequence from the prev-most referenced buffer to the last buffer.
* As prev-most buffers become un-referenced, they are unlinked from the list
* and destroyed.
*
* One or more |nsSlidingSubstring|s may reference into the list. Each |nsSlidingSubstring|
* holds a reference into the prev-most buffer intersecting the
* substring it describes. The destructor of a |nsSlidingSubstring| releases this
* reference, allowing the buffer list to destroy the contiguous prefix of
* unreferenced buffers.
*
* A single instance of |nsSlidingString| may reference this list.
* Through that interface, new data can be appended onto the next-most end
* of the list. |nsSlidingString| also the client to advance its starting point.
*
*/
class NS_COM nsSlidingSharedBufferList
: public nsSharedBufferList
{
public:
nsSlidingSharedBufferList( Buffer* aBuffer ) : nsSharedBufferList(aBuffer), mRefCount(0) { }
void AcquireReference() { ++mRefCount; }
void ReleaseReference() { if ( !--mRefCount ) delete this; }
void DiscardUnreferencedPrefix( Buffer* );
private:
PRUint32 mRefCount;
};
class nsSlidingString;
/**
* a substring over a buffer list, this
*/
class NS_COM nsSlidingSubstring
: virtual public nsAPromiseString
{
friend class nsSlidingString;
public:
typedef nsSlidingSharedBufferList::Buffer Buffer;
typedef nsSlidingSharedBufferList::Position Position;
nsSlidingSubstring()
: mStart(0,0),
mEnd(0,0),
mBufferList(0),
mLength(0)
{
// nothing else to do here
}
nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor
nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd );
nsSlidingSubstring( const nsSlidingString& );
nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd );
explicit nsSlidingSubstring( const nsAString& );
// copy the supplied string into a new buffer ... there will be no modifying instance over this buffer list
void Rebind( const nsSlidingSubstring& );
void Rebind( const nsSlidingSubstring&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
void Rebind( const nsSlidingString& );
void Rebind( const nsSlidingString&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
void Rebind( const nsAString& );
~nsSlidingSubstring();
virtual PRUint32 Length() const { return mLength; }
protected:
nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList );
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
private:
// can't assign into me, I'm a read-only reference
void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED
void
init_range_from_buffer_list()
// used only from constructors
{
mStart.PointBefore(mBufferList->GetFirstBuffer());
mEnd.PointAfter(mBufferList->GetLastBuffer());
mLength = PRUint32(Position::Distance(mStart, mEnd));
}
void
acquire_ownership_of_buffer_list() const
// used only from constructors and |Rebind|, requires |mStart| already be initialized
{
mBufferList->AcquireReference();
mStart.mBuffer->AcquireNonOwningReference();
}
void
release_ownership_of_buffer_list()
{
if ( mBufferList )
{
mStart.mBuffer->ReleaseNonOwningReference();
mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer);
mBufferList->ReleaseReference();
}
}
protected:
Position mStart;
Position mEnd;
nsSlidingSharedBufferList* mBufferList;
PRUint32 mLength;
};
/**
* An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class.
*
*/
class NS_COM nsSlidingString
: virtual public nsAPromiseString,
private nsSlidingSubstring
{
friend class nsSlidingSubstring;
public:
nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
// ...created by consuming ownership of a buffer ... |aStorageStart| must point to something
// that it will be OK for the slidking string to call |nsMemory::Free| on
virtual PRUint32 Length() const { return mLength; }
// you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done
void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
// void Append( ... ); do you want some |Append|s that copy the supplied data?
void DiscardPrefix( const nsReadingIterator<PRUnichar>& );
// any other way you want to do this?
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
void InsertReadable( const nsAString&, const nsReadingIterator<PRUnichar>& ); // ...to implement |nsScannerString::UngetReadable|
private:
void
acquire_ownership_of_buffer_list() const
// used only from constructors and |Rebind|, requires |mStart| already be initialized
{
mBufferList->AcquireReference();
mStart.mBuffer->AcquireNonOwningReference();
}
nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
};
#endif // !defined(nsSlidingString_h___)

View File

@@ -1,94 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsStringFragment.h --- machinery that makes string iterators work */
#ifndef nsStringFragment_h___
#define nsStringFragment_h___
/**
* An |nsFragmentRequest| is used to tell |GetReadableFragment| and
* |GetWritableFragment| what to do.
*
* @see GetReadableFragment
*/
enum nsFragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt };
/**
* A |nsReadableFragment| provides |const| access to a contiguous hunk of
* string of homogenous units, e.g., bytes (|char|). This doesn't mean it
* represents a flat hunk. It could be a variable length encoding, for
* instance UTF-8. And the fragment itself need not be zero-terminated.
*
* An |nsReadableFragment| is the underlying machinery that lets
* |nsReadingIterator|s work.
*
* @see nsReadingIterator
*/
template <class CharT>
struct nsReadableFragment
{
const CharT* mStart;
const CharT* mEnd;
const void* mFragmentIdentifier;
nsReadableFragment()
: mStart(0), mEnd(0), mFragmentIdentifier(0)
{
// nothing else to do here
}
};
/**
* A |nsWritableFragment| provides non-|const| access to a contiguous hunk of
* string of homogenous units, e.g., bytes (|char|). This doesn't mean it
* represents a flat hunk. It could be a variable length encoding, for
* instance UTF-8. And the fragment itself need not be zero-terminated.
*
* An |nsWritableFragment| is the underlying machinery that lets
* |nsWritingIterator|s work.
*
* @see nsWritingIterator
*/
template <class CharT>
struct nsWritableFragment
{
CharT* mStart;
CharT* mEnd;
void* mFragmentIdentifier;
nsWritableFragment()
: mStart(0), mEnd(0), mFragmentIdentifier(0)
{
// nothing else to do here
}
};
#endif /* !defined(nsStringFragment_h___) */

View File

@@ -1,61 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsStringFwd.h --- forward declarations for string classes */
#ifndef nsStringFwd_h___
#define nsStringFwd_h___
/**
* @see nsAString.h
*/
class nsAString;
class nsACString;
/**
* @see nsAPromiseString.h
*/
class nsAPromiseString;
class nsAPromiseCString;
/**
* @see nsAFlatString.h
*/
class nsAFlatString;
class nsAFlatCString;
/**
* @see nsLocalString.h
*/
class nsLocalString;
class nsLocalCString;
#endif /* !defined(nsStringFwd_h___) */

View File

@@ -1,436 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsStringIterator_h___
#define nsStringIterator_h___
#ifndef nsStringFragment_h___
#include "nsStringFragment.h"
#endif
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
#ifndef nsAlgorithm_h___
#include "nsAlgorithm.h"
// for |NS_MIN|, |NS_MAX|, and |NS_COUNT|...
#endif
/**
*
* @see nsReadableFragment
* @see nsAString
*/
template <class CharT>
class nsReadingIterator
// : public bidirectional_iterator_tag
{
public:
typedef ptrdiff_t difference_type;
typedef CharT value_type;
typedef const CharT* pointer;
typedef const CharT& reference;
// typedef bidirectional_iterator_tag iterator_category;
private:
friend class nsAString;
friend class nsACString;
typedef typename nsStringTraits<CharT>::abstract_string_type string_type;
nsReadableFragment<CharT> mFragment;
const CharT* mPosition;
const string_type* mOwningString;
public:
nsReadingIterator() { }
// nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
// nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK
inline void normalize_forward();
inline void normalize_backward();
pointer
get() const
{
return mPosition;
}
CharT
operator*() const
{
return *get();
}
#if 0
// An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
// don't like this when |CharT| is a type without members.
pointer
operator->() const
{
return get();
}
#endif
nsReadingIterator<CharT>&
operator++()
{
++mPosition;
normalize_forward();
return *this;
}
nsReadingIterator<CharT>
operator++( int )
{
nsReadingIterator<CharT> result(*this);
++mPosition;
normalize_forward();
return result;
}
nsReadingIterator<CharT>&
operator--()
{
normalize_backward();
--mPosition;
return *this;
}
nsReadingIterator<CharT>
operator--( int )
{
nsReadingIterator<CharT> result(*this);
normalize_backward();
--mPosition;
return result;
}
const nsReadableFragment<CharT>&
fragment() const
{
return mFragment;
}
const string_type&
string() const
{
NS_ASSERTION(mOwningString, "iterator not attached to a string (|mOwningString| == 0)");
return *mOwningString;
}
difference_type
size_forward() const
{
return mFragment.mEnd - mPosition;
}
difference_type
size_backward() const
{
return mPosition - mFragment.mStart;
}
nsReadingIterator<CharT>&
advance( difference_type n )
{
while ( n > 0 )
{
difference_type one_hop = NS_MIN(n, size_forward());
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a reading iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
normalize_forward();
n -= one_hop;
}
while ( n < 0 )
{
normalize_backward();
difference_type one_hop = NS_MAX(n, -size_backward());
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a reading iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
n -= one_hop;
}
return *this;
}
};
template <class CharT>
class nsWritingIterator
// : public nsReadingIterator<CharT>
{
public:
typedef ptrdiff_t difference_type;
typedef CharT value_type;
typedef CharT* pointer;
typedef CharT& reference;
// typedef bidirectional_iterator_tag iterator_category;
private:
friend class nsAString;
friend class nsACString;
typedef typename nsStringTraits<CharT>::abstract_string_type string_type;
nsWritableFragment<CharT> mFragment;
CharT* mPosition;
string_type* mOwningString;
public:
nsWritingIterator() { }
// nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
// nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
inline void normalize_forward();
inline void normalize_backward();
pointer
get() const
{
return mPosition;
}
reference
operator*() const
{
return *get();
}
#if 0
// An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
// don't like this when |CharT| is a type without members.
pointer
operator->() const
{
return get();
}
#endif
nsWritingIterator<CharT>&
operator++()
{
++mPosition;
normalize_forward();
return *this;
}
nsWritingIterator<CharT>
operator++( int )
{
nsWritingIterator<CharT> result(*this);
++mPosition;
normalize_forward();
return result;
}
nsWritingIterator<CharT>&
operator--()
{
normalize_backward();
--mPosition;
return *this;
}
nsWritingIterator<CharT>
operator--( int )
{
nsWritingIterator<CharT> result(*this);
normalize_backward();
--mPosition;
return result;
}
const nsWritableFragment<CharT>&
fragment() const
{
return mFragment;
}
nsWritableFragment<CharT>&
fragment()
{
return mFragment;
}
const string_type&
string() const
{
NS_ASSERTION(mOwningString, "iterator not attached to a string (|mOwningString| == 0)");
return *mOwningString;
}
string_type&
string()
{
NS_ASSERTION(mOwningString, "iterator not attached to a string (|mOwningString| == 0)");
return *mOwningString;
}
difference_type
size_forward() const
{
return mFragment.mEnd - mPosition;
}
difference_type
size_backward() const
{
return mPosition - mFragment.mStart;
}
nsWritingIterator<CharT>&
advance( difference_type n )
{
while ( n > 0 )
{
difference_type one_hop = NS_MIN(n, size_forward());
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
normalize_forward();
n -= one_hop;
}
while ( n < 0 )
{
normalize_backward();
difference_type one_hop = NS_MAX(n, -size_backward());
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
n -= one_hop;
}
return *this;
}
PRUint32
write( const value_type* s, PRUint32 n )
{
NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
n = NS_MIN(n, PRUint32(size_forward()));
nsCharTraits<value_type>::move(mPosition, s, n);
advance( difference_type(n) );
return n;
}
};
template <class CharT>
inline
void
nsReadingIterator<CharT>::normalize_forward()
{
while ( mPosition == mFragment.mEnd
&& mOwningString->GetReadableFragment(mFragment, kNextFragment) )
mPosition = mFragment.mStart;
}
template <class CharT>
inline
void
nsReadingIterator<CharT>::normalize_backward()
{
while ( mPosition == mFragment.mStart
&& mOwningString->GetReadableFragment(mFragment, kPrevFragment) )
mPosition = mFragment.mEnd;
}
template <class CharT>
inline
PRBool
operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
{
return lhs.get() == rhs.get();
}
template <class CharT>
inline
PRBool
operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
{
return lhs.get() != rhs.get();
}
//
// |nsWritingIterator|s
//
template <class CharT>
inline
void
nsWritingIterator<CharT>::normalize_forward()
{
while ( mPosition == mFragment.mEnd
&& mOwningString->GetWritableFragment(mFragment, kNextFragment) )
mPosition = mFragment.mStart;
}
template <class CharT>
inline
void
nsWritingIterator<CharT>::normalize_backward()
{
while ( mPosition == mFragment.mStart
&& mOwningString->GetWritableFragment(mFragment, kPrevFragment) )
mPosition = mFragment.mEnd;
}
template <class CharT>
inline
PRBool
operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
{
return lhs.get() == rhs.get();
}
template <class CharT>
inline
PRBool
operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
{
return lhs.get() != rhs.get();
}
#endif /* !defined(nsStringIterator_h___) */

View File

@@ -1,44 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsStringIteratorUtils_h___
#define nsStringIteratorUtils_h___
template <class Iterator>
inline
PRBool
SameFragment( const Iterator& lhs, const Iterator& rhs )
{
return lhs.fragment().mStart == rhs.fragment().mStart;
}
template <class CharT> class nsReadingIterator;
// NOTE: need to break iterators out into their own file (as with many classes here), need
// these routines, but can't currently |#include "nsReadableUtils.h"|, this hack is bad
// but we need it to get OS2 building again. Fix by splitting things into different files.
NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& );
#endif /* !defined(nsStringIteratorUtils_h___) */

View File

@@ -1,76 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsStringTraits.h --- declares specialized ``traits'' classes which allow templatized functions and classes to select appropriate non-template types */
#ifndef nsStringTraits_h___
#define nsStringTraits_h___
#ifndef nsStringFwd_h___
#include "nsStringFwd.h"
#endif
#ifndef nscore_h___
#include "nscore.h"
#endif
/**
*
*/
template <class CharT>
struct nsStringTraits
{
typedef nsAString abstract_string_type;
typedef nsAPromiseString abstract_promise_type;
typedef nsAFlatString abstract_flat_type;
typedef const nsLocalString literal_string_type;
};
#if 0
// for lame compilers, put these declarations into the general case
// so we only need to specialize for |char|
NS_SPECIALIZE_TEMPLATE
struct nsStringTraits<PRUnichar>
{
typedef nsAString abstract_string_type;
typedef nsAPromiseString abstract_promise_type;
typedef nsAFlatString abstract_flat_type;
typedef const nsLocalString literal_string_type;
};
#endif
NS_SPECIALIZE_TEMPLATE
struct nsStringTraits<char>
{
typedef nsACString abstract_string_type;
typedef nsAPromiseCString abstract_promise_type;
typedef nsAFlatCString abstract_flat_type;
typedef const nsLocalCString literal_string_type;
};
#endif /* !defined(nsStringTraits_h___) */

View File

@@ -1,61 +0,0 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
LIBRARY_NAME = string_s
REQUIRES = xpcom
CPPSRCS = \
nsAFlatString.cpp \
nsAString.cpp \
nsCommonString.cpp \
nsFragmentedString.cpp \
nsLocalString.cpp \
nsPrintfCString.cpp \
nsPrivateSharableString.cpp \
nsPromiseConcatenation.cpp \
nsPromiseFlatString.cpp \
nsPromiseSubstring.cpp \
nsReadableUtils.cpp \
nsSharedBufferList.cpp \
nsSlidingString.cpp \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_COM -D_IMPL_NS_BASE

View File

@@ -1,53 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is Netscape
# Communications. Portions created by Netscape Communications are
# Copyright (C) 2001 by Netscape Communications. All
# Rights Reserved.
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH=..\..
LIBRARY_NAME=string_s
LCFLAGS = -D_IMPL_NS_COM -D_IMPL_NS_BASE -DWIN32_LEAN_AND_MEAN
CPP_OBJS = \
.\$(OBJDIR)\nsAFlatString.obj \
.\$(OBJDIR)\nsAString.obj \
.\$(OBJDIR)\nsCommonString.obj \
.\$(OBJDIR)\nsFragmentedString.obj \
.\$(OBJDIR)\nsLocalString.obj \
.\$(OBJDIR)\nsPrintfCString.obj \
.\$(OBJDIR)\nsPrivateSharableString.obj \
.\$(OBJDIR)\nsPromiseConcatenation.obj \
.\$(OBJDIR)\nsPromiseFlatString.obj \
.\$(OBJDIR)\nsPromiseSubstring.obj \
.\$(OBJDIR)\nsReadableUtils.obj \
.\$(OBJDIR)\nsSharedBufferList.obj \
.\$(OBJDIR)\nsSlidingString.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,116 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#include "nsAFlatString.h"
const PRUnichar*
nsAFlatString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
const nsBufferHandle<PRUnichar>* buffer = GetBufferHandle();
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
PRUnichar*
nsAFlatString::GetWritableFragment( nsWritableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
nsBufferHandle<PRUnichar>* buffer = NS_CONST_CAST(nsBufferHandle<PRUnichar>*, GetBufferHandle());
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
const char*
nsAFlatCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
const nsBufferHandle<char>* buffer = GetBufferHandle();
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
char*
nsAFlatCString::GetWritableFragment( nsWritableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
nsBufferHandle<char>* buffer = NS_CONST_CAST(nsBufferHandle<char>*, GetBufferHandle());
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}

View File

@@ -1,921 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#include "nsAString.h"
#include "nsPromiseSubstring.h"
#include "nsLocalString.h"
NS_COM
int
Compare( const nsAString& lhs, const nsAString& rhs )
{
typedef nsAString::size_type size_type;
if ( &lhs == &rhs )
return 0;
size_type lLength = lhs.Length();
size_type rLength = rhs.Length();
size_type lengthToCompare = NS_MIN(lLength, rLength);
nsAString::const_iterator leftIter, rightIter;
lhs.BeginReading(leftIter);
rhs.BeginReading(rightIter);
int result;
for (;;)
{
size_type lengthAvailable = size_type( NS_MIN(leftIter.size_forward(), rightIter.size_forward()) );
if ( lengthAvailable > lengthToCompare )
lengthAvailable = lengthToCompare;
// Note: |result| should be declared in this |if| expression, but some compilers don't like that
if ( (result = nsCharTraits<PRUnichar>::compare(leftIter.get(), rightIter.get(), lengthAvailable)) != 0 )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter.advance( PRInt32(lengthAvailable) );
rightIter.advance( PRInt32(lengthAvailable) );
}
if ( lLength < rLength )
return -1;
else if ( rLength < lLength )
return 1;
else
return 0;
}
PRBool
nsAString::Equals( const char_type* rhs ) const
{
return Equals(nsLocalString(rhs));
}
nsAString::char_type
nsAString::First() const
{
NS_ASSERTION(Length()>0, "|First()| on an empty string");
const_iterator iter;
return *BeginReading(iter);
}
nsAString::char_type
nsAString::Last() const
{
NS_ASSERTION(Length()>0, "|Last()| on an empty string");
const_iterator iter;
if ( !IsEmpty() )
{
EndReading(iter);
iter.advance(-1);
}
return *iter; // Note: this has undefined results if |IsEmpty()|
}
nsAString::size_type
nsAString::CountChar( char_type c ) const
{
/*
re-write this to use a counting sink
*/
size_type result = 0;
size_type lengthToExamine = Length();
const_iterator iter;
for ( BeginReading(iter); ; )
{
PRInt32 lengthToExamineInThisFragment = iter.size_forward();
const char_type* fromBegin = iter.get();
result += size_type(NS_COUNT(fromBegin, fromBegin+lengthToExamineInThisFragment, c));
if ( !(lengthToExamine -= lengthToExamineInThisFragment) )
return result;
iter.advance(lengthToExamineInThisFragment);
}
// never reached; quiets warnings
return 0;
}
nsAString::size_type
nsAString::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
{
// If we're just assigning our entire self, give |aResult| the opportunity to share
if ( aStartPos == 0 && aLengthToCopy >= Length() )
aResult = *this;
else
aResult = Substring(*this, aStartPos, aLengthToCopy);
return aResult.Length();
}
nsAString::size_type
nsAString::Right( self_type& aResult, size_type aLengthToCopy ) const
{
size_type myLength = Length();
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
}
PRInt32
nsAString::FindChar( char_type aChar, PRUint32 aOffset ) const
{
const_iterator iter, done_searching;
BeginReading(iter).advance( PRInt32(aOffset) );
EndReading(done_searching);
size_type lengthSearched = 0;
while ( iter != done_searching )
{
PRInt32 fragmentLength = iter.size_forward();
const char_type* charFoundAt = nsCharTraits<char_type>::find(iter.get(), fragmentLength, aChar);
if ( charFoundAt )
return lengthSearched + (charFoundAt-iter.get()) + aOffset;
lengthSearched += fragmentLength;
iter.advance(fragmentLength);
}
return -1;
}
//
// |Assign()|
//
void
nsAString::AssignFromReadable( const self_type& rhs )
{
if ( this != &rhs )
do_AssignFromReadable(rhs);
// else, self-assign is a no-op
}
void
nsAString::AssignFromPromise( const self_type& aReadable )
/*
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
E.g.,
... writable& w ...
... readable& r ...
w = r + w;
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
of |r| before being retrieved to be appended.
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
in the case above, |Insert| could have special behavior with significantly better performance. Since
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
entire promise. If we measure and this turns out to show up on performance radar, we then have the
option to fix either the callers or this mechanism.
*/
{
if ( !aReadable.Promises(*this) )
do_AssignFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
// Note: not exception safe. We need something to manage temporary buffers like this
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AssignFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsAString::do_AssignFromReadable( const self_type& aReadable )
{
SetLength(0);
SetLength(aReadable.Length());
// first setting the length to |0| avoids copying characters only to be overwritten later
// in the case where the implementation decides to re-allocate
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
}
void
nsAString::do_AssignFromElementPtr( const char_type* aPtr )
{
do_AssignFromReadable(nsLocalString(aPtr));
}
void
nsAString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AssignFromReadable(nsLocalString(aPtr, aLength));
}
void
nsAString::do_AssignFromElement( char_type aChar )
{
do_AssignFromReadable(nsLocalString(&aChar, 1));
}
//
// |Append()|
//
void
nsAString::AppendFromReadable( const self_type& aReadable )
{
if ( this != &aReadable )
do_AppendFromReadable(aReadable);
else
AppendFromPromise(aReadable);
}
void
nsAString::AppendFromPromise( const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_AppendFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AppendFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsAString::do_AppendFromReadable( const self_type& aReadable )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
}
void
nsAString::do_AppendFromElementPtr( const char_type* aChar )
{
do_AppendFromReadable(nsLocalString(aChar));
}
void
nsAString::do_AppendFromElementPtrLength( const char_type* aChar, size_type aLength )
{
do_AppendFromReadable(nsLocalString(aChar, aLength));
}
void
nsAString::do_AppendFromElement( char_type aChar )
{
do_AppendFromReadable(nsLocalString(&aChar, 1));
}
//
// |Insert()|
//
void
nsAString::InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
if ( this != &aReadable )
do_InsertFromReadable(aReadable, atPosition);
else
InsertFromPromise(aReadable, atPosition);
}
void
nsAString::InsertFromPromise( const self_type& aReadable, index_type atPosition )
{
if ( !aReadable.Promises(*this) )
do_InsertFromReadable(aReadable, atPosition);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_InsertFromElementPtrLength(buffer, atPosition, length);
delete buffer;
}
// else assert
}
}
void
nsAString::do_InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( atPosition < oldLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(atPosition)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), EndWriting(toBegin));
else
atPosition = oldLength;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(atPosition)));
}
void
nsAString::do_InsertFromElementPtr( const char_type* aPtr, index_type atPosition )
{
do_InsertFromReadable(nsLocalString(aPtr), atPosition);
}
void
nsAString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
{
do_InsertFromReadable(nsLocalString(aPtr, aLength), atPosition);
}
void
nsAString::do_InsertFromElement( char_type aChar, index_type atPosition )
{
do_InsertFromReadable(nsLocalString(&aChar, 1), atPosition);
}
//
// |Cut()|
//
void
nsAString::Cut( index_type cutStart, size_type cutLength )
{
size_type myLength = this->Length();
cutLength = NS_MIN(cutLength, myLength-cutStart);
index_type cutEnd = cutStart + cutLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutEnd < myLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
SetLength(myLength-cutLength);
}
//
// |Replace()|
//
void
nsAString::ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
if ( this != &aReplacement )
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
else
ReplaceFromPromise(cutStart, cutLength, aReplacement);
}
void
nsAString::ReplaceFromPromise( index_type cutStart, size_type cutLength, const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_ReplaceFromReadable(cutStart, cutLength, nsLocalString(buffer, length));
delete buffer;
}
// else assert?
}
}
void
nsAString::do_ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
size_type oldLength = this->Length();
cutStart = NS_MIN(cutStart, oldLength);
cutLength = NS_MIN(cutLength, oldLength-cutStart);
index_type cutEnd = cutStart + cutLength;
size_type replacementLength = aReplacement.Length();
index_type replacementEnd = cutStart + replacementLength;
size_type newLength = oldLength - cutLength + replacementLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutLength > replacementLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
SetLength(newLength);
if ( cutLength < replacementLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
}
NS_COM
int
Compare( const nsACString& lhs, const nsACString& rhs )
{
typedef nsACString::size_type size_type;
if ( &lhs == &rhs )
return 0;
size_type lLength = lhs.Length();
size_type rLength = rhs.Length();
size_type lengthToCompare = NS_MIN(lLength, rLength);
nsACString::const_iterator leftIter, rightIter;
lhs.BeginReading(leftIter);
rhs.BeginReading(rightIter);
int result;
for (;;)
{
size_type lengthAvailable = size_type( NS_MIN(leftIter.size_forward(), rightIter.size_forward()) );
if ( lengthAvailable > lengthToCompare )
lengthAvailable = lengthToCompare;
// Note: |result| should be declared in this |if| expression, but some compilers don't like that
if ( (result = nsCharTraits<char>::compare(leftIter.get(), rightIter.get(), lengthAvailable)) != 0 )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter.advance( PRInt32(lengthAvailable) );
rightIter.advance( PRInt32(lengthAvailable) );
}
if ( lLength < rLength )
return -1;
else if ( rLength < lLength )
return 1;
else
return 0;
}
PRBool
nsACString::Equals( const char_type* rhs ) const
{
return Equals(nsLocalCString(rhs));
}
nsACString::char_type
nsACString::First() const
{
NS_ASSERTION(Length()>0, "|First()| on an empty string");
const_iterator iter;
return *BeginReading(iter);
}
nsACString::char_type
nsACString::Last() const
{
NS_ASSERTION(Length()>0, "|Last()| on an empty string");
const_iterator iter;
if ( !IsEmpty() )
{
EndReading(iter);
iter.advance(-1);
}
return *iter; // Note: this has undefined results if |IsEmpty()|
}
nsACString::size_type
nsACString::CountChar( char_type c ) const
{
/*
re-write this to use a counting sink
*/
size_type result = 0;
size_type lengthToExamine = Length();
const_iterator iter;
for ( BeginReading(iter); ; )
{
PRInt32 lengthToExamineInThisFragment = iter.size_forward();
const char_type* fromBegin = iter.get();
result += size_type(NS_COUNT(fromBegin, fromBegin+lengthToExamineInThisFragment, c));
if ( !(lengthToExamine -= lengthToExamineInThisFragment) )
return result;
iter.advance(lengthToExamineInThisFragment);
}
// never reached; quiets warnings
return 0;
}
nsACString::size_type
nsACString::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
{
// If we're just assigning our entire self, give |aResult| the opportunity to share
if ( aStartPos == 0 && aLengthToCopy >= Length() )
aResult = *this;
else
aResult = Substring(*this, aStartPos, aLengthToCopy);
return aResult.Length();
}
nsACString::size_type
nsACString::Right( self_type& aResult, size_type aLengthToCopy ) const
{
size_type myLength = Length();
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
}
PRInt32
nsACString::FindChar( char_type aChar, PRUint32 aOffset ) const
{
const_iterator iter, done_searching;
BeginReading(iter).advance( PRInt32(aOffset) );
EndReading(done_searching);
size_type lengthSearched = 0;
while ( iter != done_searching )
{
PRInt32 fragmentLength = iter.size_forward();
const char_type* charFoundAt = nsCharTraits<char_type>::find(iter.get(), fragmentLength, aChar);
if ( charFoundAt )
return lengthSearched + (charFoundAt-iter.get()) + aOffset;
lengthSearched += fragmentLength;
iter.advance(fragmentLength);
}
return -1;
}
//
// |Assign()|
//
void
nsACString::AssignFromReadable( const self_type& rhs )
{
if ( this != &rhs )
do_AssignFromReadable(rhs);
// else, self-assign is a no-op
}
void
nsACString::AssignFromPromise( const self_type& aReadable )
/*
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
E.g.,
... writable& w ...
... readable& r ...
w = r + w;
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
of |r| before being retrieved to be appended.
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
in the case above, |Insert| could have special behavior with significantly better performance. Since
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
entire promise. If we measure and this turns out to show up on performance radar, we then have the
option to fix either the callers or this mechanism.
*/
{
if ( !aReadable.Promises(*this) )
do_AssignFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
// Note: not exception safe. We need something to manage temporary buffers like this
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AssignFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsACString::do_AssignFromReadable( const self_type& aReadable )
{
SetLength(0);
SetLength(aReadable.Length());
// first setting the length to |0| avoids copying characters only to be overwritten later
// in the case where the implementation decides to re-allocate
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
}
void
nsACString::do_AssignFromElementPtr( const char_type* aPtr )
{
do_AssignFromReadable(nsLocalCString(aPtr));
}
void
nsACString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AssignFromReadable(nsLocalCString(aPtr, aLength));
}
void
nsACString::do_AssignFromElement( char_type aChar )
{
do_AssignFromReadable(nsLocalCString(&aChar, 1));
}
//
// |Append()|
//
void
nsACString::AppendFromReadable( const self_type& aReadable )
{
if ( this != &aReadable )
do_AppendFromReadable(aReadable);
else
AppendFromPromise(aReadable);
}
void
nsACString::AppendFromPromise( const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_AppendFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AppendFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsACString::do_AppendFromReadable( const self_type& aReadable )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
}
void
nsACString::do_AppendFromElementPtr( const char_type* aChar )
{
do_AppendFromReadable(nsLocalCString(aChar));
}
void
nsACString::do_AppendFromElementPtrLength( const char_type* aChar, size_type aLength )
{
do_AppendFromReadable(nsLocalCString(aChar, aLength));
}
void
nsACString::do_AppendFromElement( char_type aChar )
{
do_AppendFromReadable(nsLocalCString(&aChar, 1));
}
//
// |Insert()|
//
void
nsACString::InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
if ( this != &aReadable )
do_InsertFromReadable(aReadable, atPosition);
else
InsertFromPromise(aReadable, atPosition);
}
void
nsACString::InsertFromPromise( const self_type& aReadable, index_type atPosition )
{
if ( !aReadable.Promises(*this) )
do_InsertFromReadable(aReadable, atPosition);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_InsertFromElementPtrLength(buffer, atPosition, length);
delete buffer;
}
// else assert
}
}
void
nsACString::do_InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( atPosition < oldLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(atPosition)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), EndWriting(toBegin));
else
atPosition = oldLength;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(atPosition)));
}
void
nsACString::do_InsertFromElementPtr( const char_type* aPtr, index_type atPosition )
{
do_InsertFromReadable(nsLocalCString(aPtr), atPosition);
}
void
nsACString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
{
do_InsertFromReadable(nsLocalCString(aPtr, aLength), atPosition);
}
void
nsACString::do_InsertFromElement( char_type aChar, index_type atPosition )
{
do_InsertFromReadable(nsLocalCString(&aChar, 1), atPosition);
}
//
// |Cut()|
//
void
nsACString::Cut( index_type cutStart, size_type cutLength )
{
size_type myLength = this->Length();
cutLength = NS_MIN(cutLength, myLength-cutStart);
index_type cutEnd = cutStart + cutLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutEnd < myLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
SetLength(myLength-cutLength);
}
//
// |Replace()|
//
void
nsACString::ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
if ( this != &aReplacement )
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
else
ReplaceFromPromise(cutStart, cutLength, aReplacement);
}
void
nsACString::ReplaceFromPromise( index_type cutStart, size_type cutLength, const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_ReplaceFromReadable(cutStart, cutLength, nsLocalCString(buffer, length));
delete buffer;
}
// else assert?
}
}
void
nsACString::do_ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
size_type oldLength = this->Length();
cutStart = NS_MIN(cutStart, oldLength);
cutLength = NS_MIN(cutLength, oldLength-cutStart);
index_type cutEnd = cutStart + cutLength;
size_type replacementLength = aReplacement.Length();
index_type replacementEnd = cutStart + replacementLength;
size_type newLength = oldLength - cutLength + replacementLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutLength > replacementLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
SetLength(newLength);
if ( cutLength < replacementLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
}

View File

@@ -1,58 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsCommonString.h"
// #include "nsBufferHandleUtils.h"
void
nsCommonString::assign( const string_type& aReadable )
{
const nsSharedBufferHandle<char_type>* handle = aReadable.GetSharedBufferHandle();
if ( !handle )
handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1);
mBuffer = handle;
}
const nsSharedBufferHandle<PRUnichar>*
nsCommonString::GetSharedBufferHandle() const
{
return mBuffer.get();
}
void
nsCommonCString::assign( const string_type& aReadable )
{
const nsSharedBufferHandle<char_type>* handle = aReadable.GetSharedBufferHandle();
if ( !handle )
handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1);
mBuffer = handle;
}
const nsSharedBufferHandle<char>*
nsCommonCString::GetSharedBufferHandle() const
{
return mBuffer.get();
}

View File

@@ -1,197 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsAString.h"
// remember, no one should include "nsPromiseConcatenation.h" themselves
// one always gets it through "nsAString.h"
PRUint32
nsPromiseConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsPromiseConcatenation::Promises( const string_type& aString ) const
{
return mStrings[0]->Promises(aString) || mStrings[1]->Promises(aString);
}
#if 0
PRBool
nsPromiseConcatenation::PromisesExactly( const string_type& aString ) const
{
// Not really like this, test for the empty string, etc
return mStrings[0] == &aString && !mStrings[1] || !mStrings[0] && mStrings[1] == &aString;
}
#endif
const PRUnichar*
nsPromiseConcatenation::GetReadableFragment( nsReadableFragment<char_type>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
int whichString;
// based on the request, pick which string we will forward the |GetReadableFragment()| call into
switch ( aRequest )
{
case kPrevFragment:
case kNextFragment:
whichString = GetCurrentStringFromFragment(aFragment);
break;
case kFirstFragment:
whichString = SetLeftStringInFragment(aFragment);
break;
case kLastFragment:
whichString = SetRightStringInFragment(aFragment);
break;
case kFragmentAt:
PRUint32 leftLength = mStrings[kLeftString]->Length();
if ( aPosition < leftLength )
whichString = SetLeftStringInFragment(aFragment);
else
{
whichString = SetRightStringInFragment(aFragment);
aPosition -= leftLength;
}
break;
}
const char_type* result;
PRBool done;
do
{
done = PR_TRUE;
result = mStrings[whichString]->GetReadableFragment(aFragment, aRequest, aPosition);
if ( !result )
{
done = PR_FALSE;
if ( aRequest == kNextFragment && whichString == kLeftString )
{
aRequest = kFirstFragment;
whichString = SetRightStringInFragment(aFragment);
}
else if ( aRequest == kPrevFragment && whichString == kRightString )
{
aRequest = kLastFragment;
whichString = SetLeftStringInFragment(aFragment);
}
else
done = PR_TRUE;
}
}
while ( !done );
return result;
}
PRUint32
nsPromiseCConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsPromiseCConcatenation::Promises( const string_type& aString ) const
{
return mStrings[0]->Promises(aString) || mStrings[1]->Promises(aString);
}
#if 0
PRBool
nsPromiseCConcatenation::PromisesExactly( const string_type& aString ) const
{
// Not really like this, test for the empty string, etc
return mStrings[0] == &aString && !mStrings[1] || !mStrings[0] && mStrings[1] == &aString;
}
#endif
const char*
nsPromiseCConcatenation::GetReadableFragment( nsReadableFragment<char_type>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
int whichString;
// based on the request, pick which string we will forward the |GetReadableFragment()| call into
switch ( aRequest )
{
case kPrevFragment:
case kNextFragment:
whichString = GetCurrentStringFromFragment(aFragment);
break;
case kFirstFragment:
whichString = SetLeftStringInFragment(aFragment);
break;
case kLastFragment:
whichString = SetRightStringInFragment(aFragment);
break;
case kFragmentAt:
PRUint32 leftLength = mStrings[kLeftString]->Length();
if ( aPosition < leftLength )
whichString = SetLeftStringInFragment(aFragment);
else
{
whichString = SetRightStringInFragment(aFragment);
aPosition -= leftLength;
}
break;
}
const char_type* result;
PRBool done;
do
{
done = PR_TRUE;
result = mStrings[whichString]->GetReadableFragment(aFragment, aRequest, aPosition);
if ( !result )
{
done = PR_FALSE;
if ( aRequest == kNextFragment && whichString == kLeftString )
{
aRequest = kFirstFragment;
whichString = SetRightStringInFragment(aFragment);
}
else if ( aRequest == kPrevFragment && whichString == kRightString )
{
aRequest = kLastFragment;
whichString = SetLeftStringInFragment(aFragment);
}
else
done = PR_TRUE;
}
}
while ( !done );
return result;
}

View File

@@ -1,25 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#include "nsLocalString.h"

View File

@@ -1,123 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#include "nsPromiseSubstring.h"
PRUint32
nsPromiseSubstring::Length() const
{
return mLength;
}
const PRUnichar*
nsPromiseSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
// Offset any request for a specific position (First, Last, At) by our
// substrings startpos within the owning string
if ( aRequest == kFirstFragment )
{
aPosition = mStartPos;
aRequest = kFragmentAt;
}
else if ( aRequest == kLastFragment )
{
aPosition = mStartPos + mLength;
aRequest = kFragmentAt;
}
else if ( aRequest == kFragmentAt )
aPosition += mStartPos;
// requests for |kNextFragment| or |kPrevFragment| are just relayed down into the string we're slicing
const PRUnichar* position_ptr = mString.GetReadableFragment(aFragment, aRequest, aPosition);
// If |GetReadableFragment| returns |0|, then we are off the string, the contents of the
// fragment are garbage.
// Therefore, only need to fix up the fragment boundaries when |position_ptr| is not null
if ( position_ptr )
{
// if there's more physical data in the returned fragment than I logically have left...
size_t logical_size_backward = aPosition - mStartPos;
if ( size_t(position_ptr - aFragment.mStart) > logical_size_backward )
aFragment.mStart = position_ptr - logical_size_backward;
size_t logical_size_forward = mLength - logical_size_backward;
if ( size_t(aFragment.mEnd - position_ptr) > logical_size_forward )
aFragment.mEnd = position_ptr + logical_size_forward;
}
return position_ptr;
}
PRUint32
nsPromiseCSubstring::Length() const
{
return mLength;
}
const char*
nsPromiseCSubstring::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
// Offset any request for a specific position (First, Last, At) by our
// substrings startpos within the owning string
if ( aRequest == kFirstFragment )
{
aPosition = mStartPos;
aRequest = kFragmentAt;
}
else if ( aRequest == kLastFragment )
{
aPosition = mStartPos + mLength;
aRequest = kFragmentAt;
}
else if ( aRequest == kFragmentAt )
aPosition += mStartPos;
// requests for |kNextFragment| or |kPrevFragment| are just relayed down into the string we're slicing
const char* position_ptr = mString.GetReadableFragment(aFragment, aRequest, aPosition);
// If |GetReadableFragment| returns |0|, then we are off the string, the contents of the
// fragment are garbage.
// Therefore, only need to fix up the fragment boundaries when |position_ptr| is not null
if ( position_ptr )
{
// if there's more physical data in the returned fragment than I logically have left...
size_t logical_size_backward = aPosition - mStartPos;
if ( size_t(position_ptr - aFragment.mStart) > logical_size_backward )
aFragment.mStart = position_ptr - logical_size_backward;
size_t logical_size_forward = mLength - logical_size_backward;
if ( size_t(aFragment.mEnd - position_ptr) > logical_size_forward )
aFragment.mEnd = position_ptr + logical_size_forward;
}
return position_ptr;
}

Some files were not shown because too many files have changed in this diff Show More