Compare commits
1 Commits
CVS
...
tags/STABL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e47a46b213 |
@@ -1,617 +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.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) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsAVLTree.h"
|
||||
|
||||
|
||||
enum eLean {eLeft,eNeutral,eRight};
|
||||
|
||||
struct NS_COM nsAVLNode {
|
||||
public:
|
||||
|
||||
nsAVLNode(void* aValue) {
|
||||
mLeft=0;
|
||||
mRight=0;
|
||||
mSkew=eNeutral;
|
||||
mValue=aValue;
|
||||
}
|
||||
|
||||
nsAVLNode* mLeft;
|
||||
nsAVLNode* mRight;
|
||||
eLean mSkew;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************
|
||||
Now begin the tree class. Don't forget that the comparison
|
||||
between nodes must occur via the comparitor function,
|
||||
otherwise all you're testing is pointer addresses.
|
||||
************************************************************/
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
|
||||
nsAVLNodeFunctor* aDeallocator) :
|
||||
mComparitor(aComparitor), mDeallocator(aDeallocator) {
|
||||
mRoot=0;
|
||||
mCount=0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
avlDeleteTree(nsAVLNode* aNode){
|
||||
if (aNode) {
|
||||
avlDeleteTree(aNode->mLeft);
|
||||
avlDeleteTree(aNode->mRight);
|
||||
delete aNode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsAVLTree::~nsAVLTree(){
|
||||
if (mDeallocator) {
|
||||
ForEachDepthFirst(*mDeallocator);
|
||||
}
|
||||
avlDeleteTree(mRoot);
|
||||
}
|
||||
|
||||
|
||||
class CDoesntExist: public nsAVLNodeFunctor {
|
||||
public:
|
||||
CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
|
||||
}
|
||||
virtual void* operator()(void* anItem) {
|
||||
void* result=mOtherTree.FindItem(anItem);
|
||||
if(result)
|
||||
return nsnull;
|
||||
return anItem;
|
||||
}
|
||||
protected:
|
||||
const nsAVLTree& mOtherTree;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method compares two trees (members by identity).
|
||||
* @update gess12/27/98
|
||||
* @param tree to compare against
|
||||
* @return true if they are identical (contain same stuff).
|
||||
*/
|
||||
PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
|
||||
CDoesntExist functor(aCopy);
|
||||
void* theItem=FirstThat(functor);
|
||||
PRBool result=PRBool(!theItem);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlRotateRight(nsAVLNode*& aRootNode){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
|
||||
ptr2=aRootNode->mRight;
|
||||
if(ptr2->mSkew==eRight) {
|
||||
aRootNode->mRight=ptr2->mLeft;
|
||||
ptr2->mLeft=aRootNode;
|
||||
aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else {
|
||||
ptr3=ptr2->mLeft;
|
||||
ptr2->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=ptr2;
|
||||
aRootNode->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=aRootNode;
|
||||
if(ptr3->mSkew==eLeft)
|
||||
ptr2->mSkew=eRight;
|
||||
else ptr2->mSkew=eNeutral;
|
||||
if(ptr3->mSkew==eRight)
|
||||
aRootNode->mSkew=eLeft;
|
||||
else aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr3;
|
||||
}
|
||||
aRootNode->mSkew=eNeutral;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlRotateLeft(nsAVLNode*& aRootNode){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
|
||||
ptr2=aRootNode->mLeft;
|
||||
if(ptr2->mSkew==eLeft) {
|
||||
aRootNode->mLeft=ptr2->mRight;
|
||||
ptr2->mRight=aRootNode;
|
||||
aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else {
|
||||
ptr3=ptr2->mRight;
|
||||
ptr2->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=ptr2;
|
||||
aRootNode->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=aRootNode;
|
||||
if(ptr3->mSkew==eRight)
|
||||
ptr2->mSkew=eLeft;
|
||||
else ptr2->mSkew=eNeutral;
|
||||
if(ptr3->mSkew==eLeft)
|
||||
aRootNode->mSkew=eRight;
|
||||
else aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr3;
|
||||
}
|
||||
aRootNode->mSkew=eNeutral;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
|
||||
nsAVLNodeComparitor& aComparitor) {
|
||||
eAVLStatus result=eAVL_unknown;
|
||||
|
||||
if(!aRootNode) {
|
||||
aRootNode = aNewNode;
|
||||
return eAVL_ok;
|
||||
}
|
||||
|
||||
if(aNewNode==aRootNode->mValue) {
|
||||
return eAVL_duplicate;
|
||||
}
|
||||
|
||||
PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
|
||||
if(0 < theCompareResult) { //if(anItem<aRootNode->mValue)
|
||||
result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
|
||||
if(eAVL_ok==result) {
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
avlRotateLeft(aRootNode);
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eRight:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eLeft;
|
||||
break;
|
||||
} //switch
|
||||
}//if
|
||||
} //if
|
||||
else {
|
||||
result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
|
||||
if(eAVL_ok==result) {
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eRight:
|
||||
avlRotateRight(aRootNode);
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eRight;
|
||||
break;
|
||||
} //switch
|
||||
}
|
||||
} //if
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static void
|
||||
avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
eLean balnc2;
|
||||
eLean balnc3;
|
||||
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
ptr2=aRootNode->mLeft;
|
||||
balnc2=ptr2->mSkew;
|
||||
if(balnc2!=eRight) {
|
||||
aRootNode->mLeft=ptr2->mRight;
|
||||
ptr2->mRight=aRootNode;
|
||||
if(balnc2==eNeutral){
|
||||
aRootNode->mSkew=eLeft;
|
||||
ptr2->mSkew=eRight;
|
||||
delOk=PR_FALSE;
|
||||
}
|
||||
else{
|
||||
aRootNode->mSkew=eNeutral;
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else{
|
||||
ptr3=ptr2->mRight;
|
||||
balnc3=ptr3->mSkew;
|
||||
ptr2->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=ptr2;
|
||||
aRootNode->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=aRootNode;
|
||||
if(balnc3==eRight) {
|
||||
ptr2->mSkew=eLeft;
|
||||
}
|
||||
else {
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
if(balnc3==eLeft) {
|
||||
aRootNode->mSkew=eRight;
|
||||
}
|
||||
else {
|
||||
aRootNode->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr3;
|
||||
ptr3->mSkew=eNeutral;
|
||||
}
|
||||
break;
|
||||
|
||||
case eRight:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
break;
|
||||
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eLeft;
|
||||
delOk=PR_FALSE;
|
||||
break;
|
||||
}//switch
|
||||
return;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static void
|
||||
avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
eLean balnc2;
|
||||
eLean balnc3;
|
||||
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
break;
|
||||
|
||||
case eRight:
|
||||
ptr2=aRootNode->mRight;
|
||||
balnc2=ptr2->mSkew;
|
||||
if(balnc2!=eLeft) {
|
||||
aRootNode->mRight=ptr2->mLeft;
|
||||
ptr2->mLeft=aRootNode;
|
||||
if(balnc2==eNeutral){
|
||||
aRootNode->mSkew=eRight;
|
||||
ptr2->mSkew=eLeft;
|
||||
delOk=PR_FALSE;
|
||||
}
|
||||
else{
|
||||
aRootNode->mSkew=eNeutral;
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else{
|
||||
ptr3=ptr2->mLeft;
|
||||
balnc3=ptr3->mSkew;
|
||||
ptr2->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=ptr2;
|
||||
aRootNode->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=aRootNode;
|
||||
if(balnc3==eLeft) {
|
||||
ptr2->mSkew=eRight;
|
||||
}
|
||||
else {
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
if(balnc3==eRight) {
|
||||
aRootNode->mSkew=eLeft;
|
||||
}
|
||||
else {
|
||||
aRootNode->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr3;
|
||||
ptr3->mSkew=eNeutral;
|
||||
}
|
||||
break;
|
||||
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eRight;
|
||||
delOk=PR_FALSE;
|
||||
break;
|
||||
}//switch
|
||||
return;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
if(!anotherNode->mRight){
|
||||
aRootNode->mValue=anotherNode->mValue; //swap
|
||||
anotherNode=anotherNode->mLeft;
|
||||
delOk=PR_TRUE;
|
||||
}
|
||||
else{
|
||||
avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
|
||||
if(delOk)
|
||||
avlBalanceLeft(anotherNode,delOk);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
|
||||
nsAVLNodeComparitor& aComparitor){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
if(!aRootNode)
|
||||
delOk=PR_FALSE;
|
||||
else {
|
||||
PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
|
||||
if(cmp<0){
|
||||
avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
|
||||
if(delOk)
|
||||
avlBalanceRight(aRootNode,delOk);
|
||||
}
|
||||
else if(cmp>0){
|
||||
avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
|
||||
if(delOk)
|
||||
avlBalanceLeft(aRootNode,delOk);
|
||||
}
|
||||
else{ //they match...
|
||||
nsAVLNode* temp=aRootNode;
|
||||
if(!aRootNode->mRight) {
|
||||
aRootNode=aRootNode->mLeft;
|
||||
delOk=PR_TRUE;
|
||||
delete temp;
|
||||
}
|
||||
else if(!aRootNode->mLeft) {
|
||||
aRootNode=aRootNode->mRight;
|
||||
delOk=PR_TRUE;
|
||||
delete temp;
|
||||
}
|
||||
else {
|
||||
avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
|
||||
if(delOk)
|
||||
avlBalanceRight(aRootNode,delOk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
eAVLStatus
|
||||
nsAVLTree::AddItem(void* anItem){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
nsAVLNode* theNewNode=new nsAVLNode(anItem);
|
||||
result=avlInsert(mRoot,theNewNode,mComparitor);
|
||||
if(eAVL_duplicate!=result)
|
||||
mCount++;
|
||||
else {
|
||||
delete theNewNode;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
void* nsAVLTree::FindItem(void* aValue) const{
|
||||
nsAVLNode* result=mRoot;
|
||||
PRInt32 count=0;
|
||||
while(result) {
|
||||
count++;
|
||||
PRInt32 cmp=mComparitor(aValue,result->mValue);
|
||||
if(0==cmp) {
|
||||
//we matched...
|
||||
break;
|
||||
}
|
||||
else if(0>cmp){
|
||||
//theNode was greater...
|
||||
result=result->mLeft;
|
||||
}
|
||||
else {
|
||||
//aValue is greater...
|
||||
result=result->mRight;
|
||||
}
|
||||
}
|
||||
if(result) {
|
||||
return result->mValue;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/30/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
eAVLStatus
|
||||
nsAVLTree::RemoveItem(void* aValue){
|
||||
PRBool delOk=PR_TRUE;
|
||||
eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
|
||||
if(eAVL_ok==result)
|
||||
mCount--;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
|
||||
if(aNode) {
|
||||
avlForEachDepthFirst(aNode->mLeft,aFunctor);
|
||||
avlForEachDepthFirst(aNode->mRight,aFunctor);
|
||||
aFunctor(aNode->mValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void
|
||||
nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
|
||||
::avlForEachDepthFirst(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
|
||||
if(aNode) {
|
||||
avlForEach(aNode->mLeft,aFunctor);
|
||||
aFunctor(aNode->mValue);
|
||||
avlForEach(aNode->mRight,aFunctor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void
|
||||
nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
|
||||
::avlForEach(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void*
|
||||
avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
|
||||
void* result=nsnull;
|
||||
if(aNode) {
|
||||
result = avlFirstThat(aNode->mLeft,aFunctor);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = aFunctor(aNode->mValue);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = avlFirstThat(aNode->mRight,aFunctor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void*
|
||||
nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
|
||||
return ::avlFirstThat(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
@@ -1,74 +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.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) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsAVLTree_h___
|
||||
#define nsAVLTree_h___
|
||||
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
|
||||
enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
|
||||
|
||||
|
||||
struct nsAVLNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/26/98
|
||||
* @param anObject1 is the first object to be compared
|
||||
* @param anObject2 is the second object to be compared
|
||||
* @return -1,0,1 if object1 is less, equal, greater than object2
|
||||
*/
|
||||
class NS_COM nsAVLNodeComparitor {
|
||||
public:
|
||||
virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
|
||||
};
|
||||
|
||||
class NS_COM nsAVLNodeFunctor {
|
||||
public:
|
||||
virtual void* operator()(void* anItem)=0;
|
||||
};
|
||||
|
||||
class NS_COM nsAVLTree {
|
||||
public:
|
||||
nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
|
||||
~nsAVLTree(void);
|
||||
|
||||
PRBool operator==(const nsAVLTree& aOther) const;
|
||||
PRInt32 GetCount(void) const {return mCount;}
|
||||
|
||||
//main functions...
|
||||
eAVLStatus AddItem(void* anItem);
|
||||
eAVLStatus RemoveItem(void* anItem);
|
||||
void* FindItem(void* anItem) const;
|
||||
void ForEach(nsAVLNodeFunctor& aFunctor) const;
|
||||
void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
|
||||
void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
|
||||
|
||||
protected:
|
||||
|
||||
nsAVLNode* mRoot;
|
||||
PRInt32 mCount;
|
||||
nsAVLNodeComparitor& mComparitor;
|
||||
nsAVLNodeFunctor* mDeallocator;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsAVLTree_h___ */
|
||||
|
||||
@@ -1,617 +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.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) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsAVLTree.h"
|
||||
|
||||
|
||||
enum eLean {eLeft,eNeutral,eRight};
|
||||
|
||||
struct NS_COM nsAVLNode {
|
||||
public:
|
||||
|
||||
nsAVLNode(void* aValue) {
|
||||
mLeft=0;
|
||||
mRight=0;
|
||||
mSkew=eNeutral;
|
||||
mValue=aValue;
|
||||
}
|
||||
|
||||
nsAVLNode* mLeft;
|
||||
nsAVLNode* mRight;
|
||||
eLean mSkew;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************
|
||||
Now begin the tree class. Don't forget that the comparison
|
||||
between nodes must occur via the comparitor function,
|
||||
otherwise all you're testing is pointer addresses.
|
||||
************************************************************/
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
|
||||
nsAVLNodeFunctor* aDeallocator) :
|
||||
mComparitor(aComparitor), mDeallocator(aDeallocator) {
|
||||
mRoot=0;
|
||||
mCount=0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
avlDeleteTree(nsAVLNode* aNode){
|
||||
if (aNode) {
|
||||
avlDeleteTree(aNode->mLeft);
|
||||
avlDeleteTree(aNode->mRight);
|
||||
delete aNode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsAVLTree::~nsAVLTree(){
|
||||
if (mDeallocator) {
|
||||
ForEachDepthFirst(*mDeallocator);
|
||||
}
|
||||
avlDeleteTree(mRoot);
|
||||
}
|
||||
|
||||
|
||||
class CDoesntExist: public nsAVLNodeFunctor {
|
||||
public:
|
||||
CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
|
||||
}
|
||||
virtual void* operator()(void* anItem) {
|
||||
void* result=mOtherTree.FindItem(anItem);
|
||||
if(result)
|
||||
return nsnull;
|
||||
return anItem;
|
||||
}
|
||||
protected:
|
||||
const nsAVLTree& mOtherTree;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method compares two trees (members by identity).
|
||||
* @update gess12/27/98
|
||||
* @param tree to compare against
|
||||
* @return true if they are identical (contain same stuff).
|
||||
*/
|
||||
PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
|
||||
CDoesntExist functor(aCopy);
|
||||
void* theItem=FirstThat(functor);
|
||||
PRBool result=PRBool(!theItem);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlRotateRight(nsAVLNode*& aRootNode){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
|
||||
ptr2=aRootNode->mRight;
|
||||
if(ptr2->mSkew==eRight) {
|
||||
aRootNode->mRight=ptr2->mLeft;
|
||||
ptr2->mLeft=aRootNode;
|
||||
aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else {
|
||||
ptr3=ptr2->mLeft;
|
||||
ptr2->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=ptr2;
|
||||
aRootNode->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=aRootNode;
|
||||
if(ptr3->mSkew==eLeft)
|
||||
ptr2->mSkew=eRight;
|
||||
else ptr2->mSkew=eNeutral;
|
||||
if(ptr3->mSkew==eRight)
|
||||
aRootNode->mSkew=eLeft;
|
||||
else aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr3;
|
||||
}
|
||||
aRootNode->mSkew=eNeutral;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlRotateLeft(nsAVLNode*& aRootNode){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
|
||||
ptr2=aRootNode->mLeft;
|
||||
if(ptr2->mSkew==eLeft) {
|
||||
aRootNode->mLeft=ptr2->mRight;
|
||||
ptr2->mRight=aRootNode;
|
||||
aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else {
|
||||
ptr3=ptr2->mRight;
|
||||
ptr2->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=ptr2;
|
||||
aRootNode->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=aRootNode;
|
||||
if(ptr3->mSkew==eRight)
|
||||
ptr2->mSkew=eLeft;
|
||||
else ptr2->mSkew=eNeutral;
|
||||
if(ptr3->mSkew==eLeft)
|
||||
aRootNode->mSkew=eRight;
|
||||
else aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr3;
|
||||
}
|
||||
aRootNode->mSkew=eNeutral;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
|
||||
nsAVLNodeComparitor& aComparitor) {
|
||||
eAVLStatus result=eAVL_unknown;
|
||||
|
||||
if(!aRootNode) {
|
||||
aRootNode = aNewNode;
|
||||
return eAVL_ok;
|
||||
}
|
||||
|
||||
if(aNewNode==aRootNode->mValue) {
|
||||
return eAVL_duplicate;
|
||||
}
|
||||
|
||||
PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
|
||||
if(0 < theCompareResult) { //if(anItem<aRootNode->mValue)
|
||||
result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
|
||||
if(eAVL_ok==result) {
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
avlRotateLeft(aRootNode);
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eRight:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eLeft;
|
||||
break;
|
||||
} //switch
|
||||
}//if
|
||||
} //if
|
||||
else {
|
||||
result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
|
||||
if(eAVL_ok==result) {
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eRight:
|
||||
avlRotateRight(aRootNode);
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eRight;
|
||||
break;
|
||||
} //switch
|
||||
}
|
||||
} //if
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static void
|
||||
avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
eLean balnc2;
|
||||
eLean balnc3;
|
||||
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
ptr2=aRootNode->mLeft;
|
||||
balnc2=ptr2->mSkew;
|
||||
if(balnc2!=eRight) {
|
||||
aRootNode->mLeft=ptr2->mRight;
|
||||
ptr2->mRight=aRootNode;
|
||||
if(balnc2==eNeutral){
|
||||
aRootNode->mSkew=eLeft;
|
||||
ptr2->mSkew=eRight;
|
||||
delOk=PR_FALSE;
|
||||
}
|
||||
else{
|
||||
aRootNode->mSkew=eNeutral;
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else{
|
||||
ptr3=ptr2->mRight;
|
||||
balnc3=ptr3->mSkew;
|
||||
ptr2->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=ptr2;
|
||||
aRootNode->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=aRootNode;
|
||||
if(balnc3==eRight) {
|
||||
ptr2->mSkew=eLeft;
|
||||
}
|
||||
else {
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
if(balnc3==eLeft) {
|
||||
aRootNode->mSkew=eRight;
|
||||
}
|
||||
else {
|
||||
aRootNode->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr3;
|
||||
ptr3->mSkew=eNeutral;
|
||||
}
|
||||
break;
|
||||
|
||||
case eRight:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
break;
|
||||
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eLeft;
|
||||
delOk=PR_FALSE;
|
||||
break;
|
||||
}//switch
|
||||
return;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static void
|
||||
avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
eLean balnc2;
|
||||
eLean balnc3;
|
||||
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
break;
|
||||
|
||||
case eRight:
|
||||
ptr2=aRootNode->mRight;
|
||||
balnc2=ptr2->mSkew;
|
||||
if(balnc2!=eLeft) {
|
||||
aRootNode->mRight=ptr2->mLeft;
|
||||
ptr2->mLeft=aRootNode;
|
||||
if(balnc2==eNeutral){
|
||||
aRootNode->mSkew=eRight;
|
||||
ptr2->mSkew=eLeft;
|
||||
delOk=PR_FALSE;
|
||||
}
|
||||
else{
|
||||
aRootNode->mSkew=eNeutral;
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else{
|
||||
ptr3=ptr2->mLeft;
|
||||
balnc3=ptr3->mSkew;
|
||||
ptr2->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=ptr2;
|
||||
aRootNode->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=aRootNode;
|
||||
if(balnc3==eLeft) {
|
||||
ptr2->mSkew=eRight;
|
||||
}
|
||||
else {
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
if(balnc3==eRight) {
|
||||
aRootNode->mSkew=eLeft;
|
||||
}
|
||||
else {
|
||||
aRootNode->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr3;
|
||||
ptr3->mSkew=eNeutral;
|
||||
}
|
||||
break;
|
||||
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eRight;
|
||||
delOk=PR_FALSE;
|
||||
break;
|
||||
}//switch
|
||||
return;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
if(!anotherNode->mRight){
|
||||
aRootNode->mValue=anotherNode->mValue; //swap
|
||||
anotherNode=anotherNode->mLeft;
|
||||
delOk=PR_TRUE;
|
||||
}
|
||||
else{
|
||||
avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
|
||||
if(delOk)
|
||||
avlBalanceLeft(anotherNode,delOk);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
|
||||
nsAVLNodeComparitor& aComparitor){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
if(!aRootNode)
|
||||
delOk=PR_FALSE;
|
||||
else {
|
||||
PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
|
||||
if(cmp<0){
|
||||
avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
|
||||
if(delOk)
|
||||
avlBalanceRight(aRootNode,delOk);
|
||||
}
|
||||
else if(cmp>0){
|
||||
avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
|
||||
if(delOk)
|
||||
avlBalanceLeft(aRootNode,delOk);
|
||||
}
|
||||
else{ //they match...
|
||||
nsAVLNode* temp=aRootNode;
|
||||
if(!aRootNode->mRight) {
|
||||
aRootNode=aRootNode->mLeft;
|
||||
delOk=PR_TRUE;
|
||||
delete temp;
|
||||
}
|
||||
else if(!aRootNode->mLeft) {
|
||||
aRootNode=aRootNode->mRight;
|
||||
delOk=PR_TRUE;
|
||||
delete temp;
|
||||
}
|
||||
else {
|
||||
avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
|
||||
if(delOk)
|
||||
avlBalanceRight(aRootNode,delOk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
eAVLStatus
|
||||
nsAVLTree::AddItem(void* anItem){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
nsAVLNode* theNewNode=new nsAVLNode(anItem);
|
||||
result=avlInsert(mRoot,theNewNode,mComparitor);
|
||||
if(eAVL_duplicate!=result)
|
||||
mCount++;
|
||||
else {
|
||||
delete theNewNode;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
void* nsAVLTree::FindItem(void* aValue) const{
|
||||
nsAVLNode* result=mRoot;
|
||||
PRInt32 count=0;
|
||||
while(result) {
|
||||
count++;
|
||||
PRInt32 cmp=mComparitor(aValue,result->mValue);
|
||||
if(0==cmp) {
|
||||
//we matched...
|
||||
break;
|
||||
}
|
||||
else if(0>cmp){
|
||||
//theNode was greater...
|
||||
result=result->mLeft;
|
||||
}
|
||||
else {
|
||||
//aValue is greater...
|
||||
result=result->mRight;
|
||||
}
|
||||
}
|
||||
if(result) {
|
||||
return result->mValue;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/30/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
eAVLStatus
|
||||
nsAVLTree::RemoveItem(void* aValue){
|
||||
PRBool delOk=PR_TRUE;
|
||||
eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
|
||||
if(eAVL_ok==result)
|
||||
mCount--;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
|
||||
if(aNode) {
|
||||
avlForEachDepthFirst(aNode->mLeft,aFunctor);
|
||||
avlForEachDepthFirst(aNode->mRight,aFunctor);
|
||||
aFunctor(aNode->mValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void
|
||||
nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
|
||||
::avlForEachDepthFirst(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
|
||||
if(aNode) {
|
||||
avlForEach(aNode->mLeft,aFunctor);
|
||||
aFunctor(aNode->mValue);
|
||||
avlForEach(aNode->mRight,aFunctor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void
|
||||
nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
|
||||
::avlForEach(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void*
|
||||
avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
|
||||
void* result=nsnull;
|
||||
if(aNode) {
|
||||
result = avlFirstThat(aNode->mLeft,aFunctor);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = aFunctor(aNode->mValue);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = avlFirstThat(aNode->mRight,aFunctor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void*
|
||||
nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
|
||||
return ::avlFirstThat(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
@@ -1,74 +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.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) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsAVLTree_h___
|
||||
#define nsAVLTree_h___
|
||||
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
|
||||
enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
|
||||
|
||||
|
||||
struct nsAVLNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/26/98
|
||||
* @param anObject1 is the first object to be compared
|
||||
* @param anObject2 is the second object to be compared
|
||||
* @return -1,0,1 if object1 is less, equal, greater than object2
|
||||
*/
|
||||
class NS_COM nsAVLNodeComparitor {
|
||||
public:
|
||||
virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
|
||||
};
|
||||
|
||||
class NS_COM nsAVLNodeFunctor {
|
||||
public:
|
||||
virtual void* operator()(void* anItem)=0;
|
||||
};
|
||||
|
||||
class NS_COM nsAVLTree {
|
||||
public:
|
||||
nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
|
||||
~nsAVLTree(void);
|
||||
|
||||
PRBool operator==(const nsAVLTree& aOther) const;
|
||||
PRInt32 GetCount(void) const {return mCount;}
|
||||
|
||||
//main functions...
|
||||
eAVLStatus AddItem(void* anItem);
|
||||
eAVLStatus RemoveItem(void* anItem);
|
||||
void* FindItem(void* anItem) const;
|
||||
void ForEach(nsAVLNodeFunctor& aFunctor) const;
|
||||
void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
|
||||
void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
|
||||
|
||||
protected:
|
||||
|
||||
nsAVLNode* mRoot;
|
||||
PRInt32 mCount;
|
||||
nsAVLNodeComparitor& mComparitor;
|
||||
nsAVLNodeFunctor* mDeallocator;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsAVLTree_h___ */
|
||||
|
||||
@@ -1,717 +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.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.
|
||||
*/
|
||||
|
||||
/******************************************************************************************
|
||||
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.
|
||||
|
||||
*******************************************************************************************/
|
||||
|
||||
#include "nsStr.h"
|
||||
#include "bufferRoutines.h"
|
||||
#include "stdio.h" //only used for printf
|
||||
#include "nsCRT.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
|
||||
//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};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
result=EnsureCapacity(theTempStr,aNewLength);
|
||||
if(result) {
|
||||
if(aDest.mLength) {
|
||||
Append(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::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
|
||||
if(&aDest!=&aSource){
|
||||
Truncate(aDest,0);
|
||||
Append(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::Append(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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::Insert( 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) {
|
||||
Append(theTempStr,aDest,0,aDestOffset); //first copy leftmost data...
|
||||
}
|
||||
|
||||
Append(theTempStr,aSource,0,aSource.mLength); //next copy inserted (new) data
|
||||
|
||||
PRUint32 theRemains=aDest.mLength-aDestOffset;
|
||||
if(theRemains) {
|
||||
Append(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);
|
||||
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}
|
||||
else Append(aDest,aSource,0,aCount);
|
||||
}
|
||||
else Append(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);
|
||||
}
|
||||
else Truncate(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::Truncate(nsStr& aDest,PRUint32 aDestOffset){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
aDest.mLength=aDestOffset;
|
||||
AddNullTerminator(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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess1/7/99
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
if(kNotFound==thePos)
|
||||
break;
|
||||
}
|
||||
if(0<theIndex) {
|
||||
if(theIndex<theMax) {
|
||||
Delete(aDest,0,theIndex);
|
||||
}
|
||||
else Truncate(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);
|
||||
if(kNotFound<thePos)
|
||||
theNewLen=theIndex;
|
||||
else break;
|
||||
}
|
||||
if(theNewLen<theMax) {
|
||||
Truncate(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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Searching methods...
|
||||
**************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest for a given substring
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @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
|
||||
* @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) {
|
||||
// NS_PRECONDITION(aTarget.mLength!=1,kCallFindChar);
|
||||
|
||||
PRInt32 result=kNotFound;
|
||||
|
||||
if((0<aDest.mLength) && (anOffset<(PRInt32)aDest.mLength)) {
|
||||
PRInt32 theMax=aDest.mLength-aTarget.mLength;
|
||||
PRInt32 index=(0<=anOffset) ? anOffset : 0;
|
||||
|
||||
if((aDest.mLength>=aTarget.mLength) && (aTarget.mLength>0) && (index>=0)){
|
||||
PRInt32 theTargetMax=aTarget.mLength;
|
||||
while(index<=theMax) {
|
||||
PRInt32 theSubIndex=-1;
|
||||
PRBool matches=PR_TRUE;
|
||||
while((++theSubIndex<theTargetMax) && (matches)){
|
||||
PRUnichar theChar=(aIgnoreCase) ? nsCRT::ToLower(GetCharAt(aDest,index+theSubIndex)) : GetCharAt(aDest,index+theSubIndex);
|
||||
PRUnichar theTargetChar=(aIgnoreCase) ? nsCRT::ToLower(GetCharAt(aTarget,theSubIndex)) : GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
}
|
||||
if(matches) {
|
||||
result=index;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
} //while
|
||||
}//if
|
||||
}//if
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest for a given character
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @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
|
||||
* @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 result=kNotFound;
|
||||
if((0<aDest.mLength) && (anOffset<(PRInt32)aDest.mLength)) {
|
||||
PRUint32 index=(0<=anOffset) ? (PRUint32)anOffset : 0;
|
||||
result=gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,index,aChar,aIgnoreCase);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if(kNotFound!=thePos)
|
||||
return index;
|
||||
} //while
|
||||
}
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Reverse Searching methods...
|
||||
**************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest (in reverse) for a given substring
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @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)
|
||||
* @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) {
|
||||
//NS_PRECONDITION(aTarget.mLength!=1,kCallRFindChar);
|
||||
|
||||
PRInt32 result=kNotFound;
|
||||
|
||||
if((0<aDest.mLength) && (anOffset<(PRInt32)aDest.mLength)) {
|
||||
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength-1;
|
||||
|
||||
if((aDest.mLength>=aTarget.mLength) && (aTarget.mLength>0) && (index>=0)){
|
||||
|
||||
nsStr theCopy;
|
||||
nsStr::Initialize(theCopy,eOneByte);
|
||||
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength);
|
||||
if(aIgnoreCase){
|
||||
nsStr::ChangeCase(theCopy,PR_FALSE); //force to lowercase
|
||||
}
|
||||
|
||||
PRInt32 theTargetMax=theCopy.mLength;
|
||||
while(index>=0) {
|
||||
PRInt32 theSubIndex=-1;
|
||||
PRBool matches=PR_FALSE;
|
||||
if(index+theCopy.mLength<=aDest.mLength) {
|
||||
matches=PR_TRUE;
|
||||
while((++theSubIndex<theTargetMax) && (matches)){
|
||||
PRUnichar theDestChar=(aIgnoreCase) ? nsCRT::ToLower(GetCharAt(aDest,index+theSubIndex)) : GetCharAt(aDest,index+theSubIndex);
|
||||
PRUnichar theTargetChar=GetCharAt(theCopy,theSubIndex);
|
||||
matches=PRBool(theDestChar==theTargetChar);
|
||||
} //while
|
||||
} //if
|
||||
if(matches) {
|
||||
result=index;
|
||||
break;
|
||||
}
|
||||
index--;
|
||||
} //while
|
||||
nsStr::Destroy(theCopy);
|
||||
}//if
|
||||
}//if
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest (in reverse) for a given character
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @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
|
||||
* @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 result=kNotFound;
|
||||
if((0<aDest.mLength) && (anOffset<(PRInt32)aDest.mLength)) {
|
||||
PRUint32 index=(0<=anOffset) ? anOffset : aDest.mLength-1;
|
||||
result=gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,index,aChar,aIgnoreCase);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
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::Compare(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 maxlen=(aSource.mLength<aDest.mLength) ? aDest.mLength : aSource.mLength;
|
||||
aCount = (aCount<0) ? maxlen : MinInt(aCount,maxlen);
|
||||
result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,aCount,aIgnoreCase);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
|
||||
|
||||
static int mAllocCount=0;
|
||||
mAllocCount++;
|
||||
|
||||
//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*)nsAllocator::Alloc(theSize);
|
||||
|
||||
PRBool result=PR_FALSE;
|
||||
if(aDest.mStr) {
|
||||
aDest.mOwnsBuffer=1;
|
||||
result=PR_TRUE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool nsStr::Free(nsStr& aDest){
|
||||
if(aDest.mStr){
|
||||
if(aDest.mOwnsBuffer){
|
||||
nsAllocator::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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,450 +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.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.
|
||||
*/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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.
|
||||
2. If you try to set a null char (via SetChar()) a new length is set
|
||||
3. nsCStrings can be upsampled into nsString without data loss
|
||||
4. Char searching is faster than string searching. Use char interfaces
|
||||
if your needs will allow it.
|
||||
5. It's easy to use the stack for nsAutostring buffer storage (fast too!).
|
||||
See the CBufDescriptor class in this file.
|
||||
6. It's ONLY ok to provide non-null-terminated buffers to Append() and Insert()
|
||||
provided you specify a 0<n value for the optional count argument.
|
||||
7. Downsampling from nsString to nsCString is lossy -- avoid it if possible!
|
||||
8. Calls to ToNewCString() and ToNewUnicode() should be matched with calls to Recycle().
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
|
||||
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 nsAllocator
|
||||
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.
|
||||
|
||||
|
||||
PERFORMANCE CONSIDERATIONS:
|
||||
|
||||
Here are a few tricks to know in order to get better string performance:
|
||||
|
||||
1) Try to limit conversions between ascii and unicode; By sticking with nsString
|
||||
wherever possible your code will be i18n-compliant.
|
||||
|
||||
|
||||
2) Preallocating your string buffer cuts down trips to the allocator. So if you
|
||||
have need for an arbitrarily large buffer, pre-size it like this:
|
||||
|
||||
{
|
||||
nsString mBuffer;
|
||||
mBuffer.SetCapacity(aReasonableSize);
|
||||
}
|
||||
|
||||
3) Allocating nsAutoString or nsCAutoString on the heap is memory inefficient
|
||||
(after all, the whole point is to avoid a heap allocation of the buffer).
|
||||
|
||||
|
||||
4) Consider using an autoString to write into your arbitrarily-sized stack buffers, rather
|
||||
than it's own buffers.
|
||||
|
||||
For example, let's say you're going to call printf() to emit pretty-printed debug output
|
||||
of your object. You know from experience that the pretty-printed version of your object
|
||||
exceeds the capacity of an autostring. Ignoring memory considerations, you could simply
|
||||
use nsCString, appending the stringized version of each of your class's data members.
|
||||
This will probably result in calls to the heap manager.
|
||||
|
||||
But there's a way to do this without necessarily having to call the heap manager.
|
||||
All you do is declare a stack based buffer and instruct nsCString to use that instead
|
||||
of it's own internal buffer by using the CBufDescriptor class:
|
||||
|
||||
{
|
||||
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.
|
||||
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include <string.h>
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
enum eCharSize {eOneByte=0,eTwoByte=1};
|
||||
#define kDefaultCharSize eTwoByte
|
||||
#define kRadix10 (10)
|
||||
#define kRadix16 (16)
|
||||
#define kAutoDetect (100)
|
||||
#define kRadixUnknown (kAutoDetect+1)
|
||||
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 Append(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 Assign(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 Insert( 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 Truncate(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 Compare(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);
|
||||
static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset);
|
||||
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);
|
||||
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset);
|
||||
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given buffer to the heap manager. Calls allocator::Free()
|
||||
* @return string length
|
||||
*/
|
||||
inline void Recycle( char* aBuffer) { nsAllocator::Free(aBuffer); }
|
||||
inline void Recycle( PRUnichar* aBuffer) { nsAllocator::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] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,747 +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.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.
|
||||
*/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef _nsCString_
|
||||
#define _nsCString_
|
||||
|
||||
#include "nsString2.h"
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
#include <stdio.h>
|
||||
#include "nsStr.h"
|
||||
#include "nsIAtom.h"
|
||||
|
||||
|
||||
class NS_COM nsSubsumeCStr;
|
||||
|
||||
class NS_COM nsCString : public nsStr {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
nsCString();
|
||||
|
||||
/**
|
||||
* This constructor accepts an isolatin string
|
||||
* @param aCString is a ptr to a 1-byte cstr
|
||||
*/
|
||||
nsCString(const char* aCString,PRInt32 aLength=-1);
|
||||
|
||||
/**
|
||||
* This constructor accepts a unichar string
|
||||
* @param aCString is a ptr to a 2-byte cstr
|
||||
*/
|
||||
nsCString(const PRUnichar* aString,PRInt32 aLength=-1);
|
||||
|
||||
/**
|
||||
* This is a copy constructor that accepts an nsStr
|
||||
* @param reference to another nsCString
|
||||
*/
|
||||
nsCString(const nsStr&);
|
||||
|
||||
/**
|
||||
* This is our copy constructor
|
||||
* @param reference to another nsCString
|
||||
*/
|
||||
nsCString(const nsCString& aString);
|
||||
|
||||
/**
|
||||
* This constructor takes a subsumestr
|
||||
* @param reference to subsumestr
|
||||
*/
|
||||
nsCString(nsSubsumeCStr& aSubsumeStr);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
virtual ~nsCString();
|
||||
|
||||
/**
|
||||
* Retrieve the length of this string
|
||||
* @return string length
|
||||
*/
|
||||
inline PRInt32 Length() const { return (PRInt32)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) {
|
||||
Truncate(aLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new length of the string.
|
||||
* @param aLength is new string length.
|
||||
* @return nada
|
||||
*/
|
||||
void SetCapacity(PRUint32 aLength);
|
||||
/**
|
||||
* This method truncates this string to given length.
|
||||
*
|
||||
* @param anIndex -- new length of string
|
||||
* @return nada
|
||||
*/
|
||||
void Truncate(PRInt32 anIndex=0);
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not the characters in this
|
||||
* string are in sorted order.
|
||||
*
|
||||
* @return TRUE if ordered.
|
||||
*/
|
||||
PRBool IsOrdered(void) const;
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not this string has a length of 0
|
||||
*
|
||||
* @return TRUE if empty.
|
||||
*/
|
||||
PRBool IsEmpty(void) const {
|
||||
return PRBool(0==mLength);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Accessor methods...
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
|
||||
*/
|
||||
const char* GetBuffer(void) const;
|
||||
|
||||
|
||||
/**
|
||||
* Get nth character.
|
||||
*/
|
||||
PRUnichar operator[](PRUint32 anIndex) const;
|
||||
PRUnichar CharAt(PRUint32 anIndex) const;
|
||||
PRUnichar First(void) const;
|
||||
PRUnichar Last(void) const;
|
||||
|
||||
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
String creation methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Create a new string by appending given string to this
|
||||
* @param aString -- 2nd string to be appended
|
||||
* @return new string
|
||||
*/
|
||||
nsSubsumeCStr operator+(const nsCString& aString);
|
||||
|
||||
/**
|
||||
* create a new string by adding this to the given char*.
|
||||
* @param aCString is a ptr to cstring to be added to this
|
||||
* @return newly created string
|
||||
*/
|
||||
nsSubsumeCStr operator+(const char* aCString);
|
||||
|
||||
|
||||
/**
|
||||
* create a new string by adding this to the given char.
|
||||
* @param aChar is a char to be added to this
|
||||
* @return newly created string
|
||||
*/
|
||||
nsSubsumeCStr operator+(PRUnichar aChar);
|
||||
nsSubsumeCStr operator+(char aChar);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
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
|
||||
*/
|
||||
nsCString& StripChars(const char* aSet);
|
||||
nsCString& StripChar(char aChar);
|
||||
|
||||
/**
|
||||
* This method strips whitespace throughout the string
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
nsCString& StripWhitespace();
|
||||
|
||||
/**
|
||||
* swaps occurence of 1 string for another
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
nsCString& ReplaceChar(PRUnichar aOldChar,PRUnichar aNewChar);
|
||||
nsCString& ReplaceChar(const char* aSet,PRUnichar aNewChar);
|
||||
|
||||
PRInt32 CountChar(PRUnichar aChar);
|
||||
|
||||
/**
|
||||
* This method trims characters found in aTrimSet from
|
||||
* either end of the underlying string.
|
||||
*
|
||||
* @param aTrimSet -- contains chars to be trimmed from
|
||||
* both ends
|
||||
* @return this
|
||||
*/
|
||||
nsCString& Trim(const char* aSet,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
|
||||
*/
|
||||
nsCString& 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
|
||||
*/
|
||||
nsCString& CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
|
||||
|
||||
/**********************************************************************
|
||||
string conversion methods...
|
||||
*********************************************************************/
|
||||
|
||||
operator char*() {return mStr;}
|
||||
operator const char*() const {return (const char*)mStr;}
|
||||
|
||||
/**
|
||||
* 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 Recycle().
|
||||
* @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 Recycle().
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Try to derive the radix from the value contained in this string
|
||||
* @return kRadix10, kRadix16 or kAutoDetect (meaning unknown)
|
||||
*/
|
||||
PRUint32 DetermineRadix(void);
|
||||
|
||||
/**
|
||||
* Perform string to int conversion.
|
||||
* @param aErrorCode will contain error if one occurs
|
||||
* @return int rep of string value
|
||||
*/
|
||||
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
String manipulation methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Functionally equivalent to assign or operator=
|
||||
*
|
||||
*/
|
||||
nsCString& SetString(const char* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);}
|
||||
nsCString& SetString(const nsStr& aString,PRInt32 aLength=-1) {return Assign(aString,aLength);}
|
||||
|
||||
/**
|
||||
* assign given string to this string
|
||||
* @param aStr: buffer to be assigned to this
|
||||
* @param alength is the length of the given str (or -1)
|
||||
if you want me to determine its length
|
||||
* @return this
|
||||
*/
|
||||
nsCString& Assign(const nsStr& aString,PRInt32 aCount=-1);
|
||||
nsCString& Assign(const char* aString,PRInt32 aCount=-1);
|
||||
nsCString& Assign(const PRUnichar* aString,PRInt32 aCount=-1);
|
||||
nsCString& Assign(PRUnichar aChar);
|
||||
nsCString& Assign(char aChar);
|
||||
|
||||
/**
|
||||
* here come a bunch of assignment operators...
|
||||
* @param aString: string to be added to this
|
||||
* @return this
|
||||
*/
|
||||
nsCString& operator=(const nsCString& aString) {return Assign(aString);}
|
||||
nsCString& operator=(const nsStr& aString) {return Assign(aString);}
|
||||
nsCString& operator=(PRUnichar aChar) {return Assign(aChar);}
|
||||
nsCString& operator=(char aChar) {return Assign(aChar);}
|
||||
nsCString& operator=(const char* aCString) {return Assign(aCString);}
|
||||
nsCString& operator=(const PRUnichar* aString) {return Assign(aString);}
|
||||
#ifdef AIX
|
||||
nsCString& operator=(const nsSubsumeCStr& aSubsumeString); // AIX requires a const here
|
||||
#else
|
||||
nsCString& operator=(nsSubsumeCStr& aSubsumeString);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Here's a bunch of methods that append varying types...
|
||||
* @param various...
|
||||
* @return this
|
||||
*/
|
||||
nsCString& operator+=(const nsCString& aString){return Append(aString,aString.mLength);}
|
||||
nsCString& operator+=(const char* aCString) {return Append(aCString);}
|
||||
nsCString& operator+=(PRUnichar aChar){return Append(aChar);}
|
||||
nsCString& operator+=(char aChar){return Append(aChar);}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
nsCString& Append(const nsCString& aString) {return Append(aString,aString.mLength);}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
* @return number of chars copied
|
||||
*/
|
||||
nsCString& Append(const nsCString& aString,PRInt32 aCount);
|
||||
nsCString& Append(const nsStr& aString,PRInt32 aCount=-1);
|
||||
nsCString& Append(const char* aString,PRInt32 aCount=-1);
|
||||
nsCString& Append(PRUnichar aChar);
|
||||
nsCString& Append(char aChar);
|
||||
nsCString& Append(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
|
||||
nsCString& Append(float aFloat);
|
||||
|
||||
/*
|
||||
* Copies n characters from this string to given string,
|
||||
* starting at the leftmost offset.
|
||||
*
|
||||
*
|
||||
* @param aCopy -- Receiving string
|
||||
* @param aCount -- number of chars to copy
|
||||
* @return number of chars copied
|
||||
*/
|
||||
PRUint32 Left(nsCString& aCopy,PRInt32 aCount) const;
|
||||
|
||||
/*
|
||||
* Copies n characters from this string to given string,
|
||||
* starting at the given offset.
|
||||
*
|
||||
*
|
||||
* @param aCopy -- Receiving string
|
||||
* @param aCount -- number of chars to copy
|
||||
* @param anOffset -- position where copying begins
|
||||
* @return number of chars copied
|
||||
*/
|
||||
PRUint32 Mid(nsCString& aCopy,PRUint32 anOffset,PRInt32 aCount) const;
|
||||
|
||||
/*
|
||||
* Copies n characters from this string to given string,
|
||||
* starting at rightmost char.
|
||||
*
|
||||
*
|
||||
* @param aCopy -- Receiving string
|
||||
* @param aCount -- number of chars to copy
|
||||
* @return number of chars copied
|
||||
*/
|
||||
PRUint32 Right(nsCString& aCopy,PRInt32 aCount) const;
|
||||
|
||||
/*
|
||||
* This method inserts n chars from given string into this
|
||||
* string at str[anOffset].
|
||||
*
|
||||
* @param aCopy -- String to be inserted into this
|
||||
* @param anOffset -- insertion position within this str
|
||||
* @param aCount -- number of chars to be copied from aCopy
|
||||
* @return number of chars inserted into this.
|
||||
*/
|
||||
nsCString& Insert(const nsCString& aCopy,PRUint32 anOffset,PRInt32 aCount=-1);
|
||||
|
||||
/**
|
||||
* Insert a given string into this string at
|
||||
* a specified offset.
|
||||
*
|
||||
* @param aString* to be inserted into this string
|
||||
* @param anOffset is insert pos in str
|
||||
* @return the number of chars inserted into this string
|
||||
*/
|
||||
nsCString& Insert(const char* aChar,PRUint32 anOffset,PRInt32 aCount=-1);
|
||||
|
||||
/**
|
||||
* Insert a single char into this string at
|
||||
* a specified offset.
|
||||
*
|
||||
* @param character to be inserted into this string
|
||||
* @param anOffset is insert pos in str
|
||||
* @return the number of chars inserted into this string
|
||||
*/
|
||||
nsCString& Insert(PRUnichar aChar,PRUint32 anOffset);
|
||||
nsCString& Insert(char aChar,PRUint32 anOffset);
|
||||
|
||||
/*
|
||||
* This method is used to cut characters in this string
|
||||
* starting at anOffset, continuing for aCount chars.
|
||||
*
|
||||
* @param anOffset -- start pos for cut operation
|
||||
* @param aCount -- number of chars to be cut
|
||||
* @return *this
|
||||
*/
|
||||
nsCString& Cut(PRUint32 anOffset,PRInt32 aCount);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Searching methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Search for given character within this string.
|
||||
* This method does so by using a binary search,
|
||||
* so your string HAD BETTER BE ORDERED!
|
||||
*
|
||||
* @param aChar is the unicode char to be found
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 BinarySearch(PRUnichar aChar) const;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-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 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-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=-1) const;
|
||||
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
|
||||
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) 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
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-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) 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
|
||||
*/
|
||||
virtual PRInt32 Compare(const nsStr &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
virtual PRInt32 Compare(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
virtual PRInt32 Compare(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* These methods compare a given string type to this one
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator==(const nsStr &aString) const;
|
||||
PRBool operator==(const char* aString) const;
|
||||
PRBool operator==(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods perform a !compare of a given string type to this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE
|
||||
*/
|
||||
PRBool operator!=(const nsStr &aString) const;
|
||||
PRBool operator!=(const char* aString) const;
|
||||
PRBool operator!=(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is < than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator<(const nsStr &aString) const;
|
||||
PRBool operator<(const char* aString) const;
|
||||
PRBool operator<(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is > than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator>(const nsStr &S) const;
|
||||
PRBool operator>(const char* aString) const;
|
||||
PRBool operator>(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is <= than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator<=(const nsStr &S) const;
|
||||
PRBool operator<=(const char* aString) const;
|
||||
PRBool operator<=(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is >= than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator>=(const nsStr &S) const;
|
||||
PRBool operator>=(const char* aString) const;
|
||||
PRBool operator>=(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* Compare this to given string; note that we compare full strings here.
|
||||
* The optional length argument just lets us know how long the given string is.
|
||||
* If you provide a length, it is compared to length of this string as an
|
||||
* optimization.
|
||||
*
|
||||
* @param aString -- the string to compare to this
|
||||
* @param aCount -- number of chars in given string you want to compare
|
||||
* @return TRUE if equal
|
||||
*/
|
||||
PRBool Equals(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
|
||||
PRBool EqualsIgnoreCase(const nsStr& aString) const;
|
||||
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
|
||||
|
||||
|
||||
static void Recycle(nsCString* aString);
|
||||
static nsCString* CreateString(void);
|
||||
|
||||
};
|
||||
|
||||
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:
|
||||
|
||||
nsCAutoString();
|
||||
nsCAutoString(const char* aString,PRInt32 aLength=-1);
|
||||
nsCAutoString(const CBufDescriptor& aBuffer);
|
||||
nsCAutoString(const PRUnichar* aString,PRInt32 aLength=-1);
|
||||
nsCAutoString(const nsStr& aString);
|
||||
nsCAutoString(const nsCAutoString& aString);
|
||||
|
||||
#ifdef AIX
|
||||
nsCAutoString(const nsSubsumeCStr& aSubsumeStr); // AIX requires a const
|
||||
#else
|
||||
nsCAutoString(nsSubsumeCStr& aSubsumeStr);
|
||||
#endif // AIX
|
||||
nsCAutoString(PRUnichar aChar);
|
||||
virtual ~nsCAutoString();
|
||||
|
||||
nsCAutoString& operator=(const nsCString& aString) {nsCString::Assign(aString); return *this;}
|
||||
nsCAutoString& operator=(const char* aCString) {nsCString::Assign(aCString); return *this;}
|
||||
nsCAutoString& operator=(PRUnichar aChar) {nsCString::Assign(aChar); return *this;}
|
||||
nsCAutoString& operator=(char aChar) {nsCString::Assign(aChar); return *this;}
|
||||
|
||||
/**
|
||||
* Retrieve the size of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
|
||||
|
||||
char mBuffer[kDefaultStringSize];
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************
|
||||
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:
|
||||
nsSubsumeCStr(nsStr& aString);
|
||||
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,840 +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.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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef _nsString_
|
||||
#define _nsString_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
#include <stdio.h>
|
||||
#include "nsString.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsStr.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
class nsISizeOfHandler;
|
||||
|
||||
|
||||
#define nsString2 nsString
|
||||
#define nsAutoString2 nsAutoString
|
||||
|
||||
|
||||
class NS_COM nsSubsumeStr;
|
||||
class NS_COM nsString : public nsStr {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
nsString();
|
||||
|
||||
|
||||
/**
|
||||
* This constructor accepts an isolatin string
|
||||
* @param aCString is a ptr to a 1-byte cstr
|
||||
*/
|
||||
nsString(const char* aCString);
|
||||
|
||||
/**
|
||||
* This constructor accepts a unichar string
|
||||
* @param aCString is a ptr to a 2-byte cstr
|
||||
*/
|
||||
nsString(const PRUnichar* aString);
|
||||
|
||||
/**
|
||||
* This is a copy constructor that accepts an nsStr
|
||||
* @param reference to another nsString
|
||||
*/
|
||||
nsString(const nsStr&);
|
||||
|
||||
/**
|
||||
* This is our copy constructor
|
||||
* @param reference to another nsString
|
||||
*/
|
||||
nsString(const nsString& aString);
|
||||
|
||||
/**
|
||||
* This constructor takes a subsumestr
|
||||
* @param reference to subsumestr
|
||||
*/
|
||||
nsString(nsSubsumeStr& aSubsumeStr);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
virtual ~nsString();
|
||||
|
||||
/**
|
||||
* Retrieve the length of this string
|
||||
* @return string length
|
||||
*/
|
||||
inline PRInt32 Length() const { return (PRInt32)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) {
|
||||
Truncate(aLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new length of the string.
|
||||
* @param aLength is new string length.
|
||||
* @return nada
|
||||
*/
|
||||
void SetCapacity(PRUint32 aLength);
|
||||
|
||||
/**
|
||||
* This method truncates this string to given length.
|
||||
*
|
||||
* @param anIndex -- new length of string
|
||||
* @return nada
|
||||
*/
|
||||
void Truncate(PRInt32 anIndex=0);
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not the characters in this
|
||||
* string are in sorted order.
|
||||
*
|
||||
* @return TRUE if ordered.
|
||||
*/
|
||||
PRBool IsOrdered(void) const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not this string has a length of 0
|
||||
*
|
||||
* @return TRUE if empty.
|
||||
*/
|
||||
PRBool IsEmpty(void) const {
|
||||
return PRBool(0==mLength);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Getters/Setters...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
|
||||
*/
|
||||
const char* GetBuffer(void) const;
|
||||
const PRUnichar* GetUnicode(void) const;
|
||||
|
||||
|
||||
/**
|
||||
* Get nth character.
|
||||
*/
|
||||
PRUnichar operator[](PRUint32 anIndex) const;
|
||||
PRUnichar CharAt(PRUint32 anIndex) const;
|
||||
PRUnichar First(void) const;
|
||||
PRUnichar Last(void) const;
|
||||
|
||||
/**
|
||||
* Set nth character.
|
||||
*/
|
||||
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
String concatenation methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Create a new string by appending given string to this
|
||||
* @param aString -- 2nd string to be appended
|
||||
* @return new subsumable string
|
||||
*/
|
||||
nsSubsumeStr operator+(const nsStr& aString);
|
||||
nsSubsumeStr operator+(const nsString& aString);
|
||||
|
||||
/**
|
||||
* create a new string by adding this to the given cstring
|
||||
* @param aCString is a ptr to cstring to be added to this
|
||||
* @return newly created string
|
||||
*/
|
||||
nsSubsumeStr operator+(const char* aCString);
|
||||
|
||||
/**
|
||||
* create a new string by adding this to the given prunichar*.
|
||||
* @param aString is a ptr to UC-string to be added to this
|
||||
* @return newly created string
|
||||
*/
|
||||
nsSubsumeStr operator+(const PRUnichar* aString);
|
||||
|
||||
/**
|
||||
* create a new string by adding this to the given char.
|
||||
* @param aChar is a char to be added to this
|
||||
* @return newly created string
|
||||
*/
|
||||
nsSubsumeStr operator+(char aChar);
|
||||
|
||||
/**
|
||||
* create a new string by adding this to the given char.
|
||||
* @param aChar is a unichar to be added to this
|
||||
* @return newly created string
|
||||
*/
|
||||
nsSubsumeStr operator+(PRUnichar aChar);
|
||||
|
||||
/**********************************************************************
|
||||
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
|
||||
*/
|
||||
nsString& StripChars(const char* aSet);
|
||||
nsString& StripChar(char aChar);
|
||||
|
||||
/**
|
||||
* This method strips whitespace throughout the string
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
nsString& StripWhitespace();
|
||||
|
||||
/**
|
||||
* swaps occurence of 1 string for another
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
nsString& ReplaceChar(PRUnichar anOldChar,PRUnichar aNewChar);
|
||||
nsString& ReplaceChar(const char* aSet,PRUnichar aNewChar);
|
||||
|
||||
PRInt32 CountChar(PRUnichar aChar);
|
||||
|
||||
/**
|
||||
* This method trims characters found in aTrimSet from
|
||||
* either end of the underlying string.
|
||||
*
|
||||
* @param aTrimSet -- contains chars to be trimmed from
|
||||
* both ends
|
||||
* @return this
|
||||
*/
|
||||
nsString& Trim(const char* aSet,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
|
||||
*/
|
||||
nsString& 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
|
||||
*/
|
||||
nsString& 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 Recycle().
|
||||
* @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 Recycle().
|
||||
* @return ptr to new isolatin1 string
|
||||
*/
|
||||
char* ToNewUTF8String() const;
|
||||
|
||||
/**
|
||||
* Creates a unicode clone of this string
|
||||
* Note that calls to this method should be matched with calls to Recycle().
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Try to derive the radix from the value contained in this string
|
||||
* @return kRadix10, kRadix16 or kAutoDetect (meaning unknown)
|
||||
*/
|
||||
PRUint32 DetermineRadix(void);
|
||||
|
||||
/**
|
||||
* Perform string to int conversion.
|
||||
* @param aErrorCode will contain error if one occurs
|
||||
* @return int rep of string value
|
||||
*/
|
||||
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
String manipulation methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Functionally equivalent to assign or operator=
|
||||
*
|
||||
*/
|
||||
nsString& SetString(const char* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);}
|
||||
nsString& SetString(const PRUnichar* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);}
|
||||
nsString& SetString(const nsString& aString,PRInt32 aLength=-1) {return Assign(aString,aLength);}
|
||||
|
||||
/**
|
||||
* assign given string to this string
|
||||
* @param aStr: buffer to be assigned to this
|
||||
* @param alength is the length of the given str (or -1)
|
||||
if you want me to determine its length
|
||||
* @return this
|
||||
*/
|
||||
nsString& Assign(const nsStr& aString,PRInt32 aCount=-1);
|
||||
nsString& Assign(const char* aString,PRInt32 aCount=-1);
|
||||
nsString& Assign(const PRUnichar* aString,PRInt32 aCount=-1);
|
||||
nsString& Assign(char aChar);
|
||||
nsString& Assign(PRUnichar aChar);
|
||||
|
||||
/**
|
||||
* here come a bunch of assignment operators...
|
||||
* @param aString: string to be added to this
|
||||
* @return this
|
||||
*/
|
||||
nsString& operator=(const nsString& aString) {return Assign(aString);}
|
||||
nsString& operator=(const nsStr& aString) {return Assign(aString);}
|
||||
nsString& operator=(char aChar) {return Assign(aChar);}
|
||||
nsString& operator=(PRUnichar aChar) {return Assign(aChar);}
|
||||
nsString& operator=(const char* aCString) {return Assign(aCString);}
|
||||
nsString& operator=(const PRUnichar* aString) {return Assign(aString);}
|
||||
#ifdef AIX
|
||||
nsString& operator=(const nsSubsumeStr& aSubsumeString); // AIX requires a const here
|
||||
#else
|
||||
nsString& operator=(nsSubsumeStr& aSubsumeString);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Here's a bunch of methods that append varying types...
|
||||
* @param various...
|
||||
* @return this
|
||||
*/
|
||||
nsString& operator+=(const nsStr& aString){return Append(aString,aString.mLength);}
|
||||
nsString& operator+=(const nsString& aString){return Append(aString,aString.mLength);}
|
||||
nsString& operator+=(const char* aCString) {return Append(aCString);}
|
||||
//nsString& operator+=(char aChar){return Append(aChar);}
|
||||
nsString& operator+=(const PRUnichar* aUCString) {return Append(aUCString);}
|
||||
nsString& operator+=(PRUnichar aChar){return Append(aChar);}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
nsString& Append(const nsStr& aString) {return Append(aString,aString.mLength);}
|
||||
nsString& Append(const nsString& aString) {return Append(aString,aString.mLength);}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
* @return number of chars copied
|
||||
*/
|
||||
nsString& Append(const nsStr& aString,PRInt32 aCount);
|
||||
nsString& Append(const nsString& aString,PRInt32 aCount);
|
||||
nsString& Append(const char* aString,PRInt32 aCount=-1);
|
||||
nsString& Append(const PRUnichar* aString,PRInt32 aCount=-1);
|
||||
nsString& Append(char aChar);
|
||||
nsString& Append(PRUnichar aChar);
|
||||
nsString& Append(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
|
||||
nsString& Append(float aFloat);
|
||||
|
||||
/*
|
||||
* Copies n characters from this string to given string,
|
||||
* starting at the leftmost offset.
|
||||
*
|
||||
*
|
||||
* @param aCopy -- Receiving string
|
||||
* @param aCount -- number of chars to copy
|
||||
* @return number of chars copied
|
||||
*/
|
||||
PRUint32 Left(nsString& aCopy,PRInt32 aCount) const;
|
||||
|
||||
/*
|
||||
* Copies n characters from this string to given string,
|
||||
* starting at the given offset.
|
||||
*
|
||||
*
|
||||
* @param aCopy -- Receiving string
|
||||
* @param aCount -- number of chars to copy
|
||||
* @param anOffset -- position where copying begins
|
||||
* @return number of chars copied
|
||||
*/
|
||||
PRUint32 Mid(nsString& aCopy,PRUint32 anOffset,PRInt32 aCount) const;
|
||||
|
||||
/*
|
||||
* Copies n characters from this string to given string,
|
||||
* starting at rightmost char.
|
||||
*
|
||||
*
|
||||
* @param aCopy -- Receiving string
|
||||
* @param aCount -- number of chars to copy
|
||||
* @return number of chars copied
|
||||
*/
|
||||
PRUint32 Right(nsString& aCopy,PRInt32 aCount) const;
|
||||
|
||||
/*
|
||||
* This method inserts n chars from given string into this
|
||||
* string at str[anOffset].
|
||||
*
|
||||
* @param aCopy -- String to be inserted into this
|
||||
* @param anOffset -- insertion position within this str
|
||||
* @param aCount -- number of chars to be copied from aCopy
|
||||
* @return number of chars inserted into this.
|
||||
*/
|
||||
nsString& Insert(const nsString& aCopy,PRUint32 anOffset,PRInt32 aCount=-1);
|
||||
|
||||
/**
|
||||
* Insert a given string into this string at
|
||||
* a specified offset.
|
||||
*
|
||||
* @param aString* to be inserted into this string
|
||||
* @param anOffset is insert pos in str
|
||||
* @return the number of chars inserted into this string
|
||||
*/
|
||||
nsString& Insert(const char* aChar,PRUint32 anOffset,PRInt32 aCount=-1);
|
||||
nsString& Insert(const PRUnichar* aChar,PRUint32 anOffset,PRInt32 aCount=-1);
|
||||
|
||||
/**
|
||||
* Insert a single char into this string at
|
||||
* a specified offset.
|
||||
*
|
||||
* @param character to be inserted into this string
|
||||
* @param anOffset is insert pos in str
|
||||
* @return the number of chars inserted into this string
|
||||
*/
|
||||
//nsString& Insert(char aChar,PRUint32 anOffset);
|
||||
nsString& Insert(PRUnichar aChar,PRUint32 anOffset);
|
||||
|
||||
/*
|
||||
* This method is used to cut characters in this string
|
||||
* starting at anOffset, continuing for aCount chars.
|
||||
*
|
||||
* @param anOffset -- start pos for cut operation
|
||||
* @param aCount -- number of chars to be cut
|
||||
* @return *this
|
||||
*/
|
||||
nsString& Cut(PRUint32 anOffset,PRInt32 aCount);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Searching methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Search for given character within this string.
|
||||
* This method does so by using a binary search,
|
||||
* so your string HAD BETTER BE ORDERED!
|
||||
*
|
||||
* @param aChar is the unicode char to be found
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 BinarySearch(PRUnichar aChar) const;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 Find(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-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 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
|
||||
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-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=-1) const;
|
||||
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
|
||||
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) 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)
|
||||
*/
|
||||
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFind(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-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
|
||||
* @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) 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
|
||||
*/
|
||||
virtual PRInt32 Compare(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
virtual PRInt32 Compare(const nsStr &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
virtual PRInt32 Compare(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
virtual PRInt32 Compare(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* These methods compare a given string type to this one
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator==(const nsString &aString) const;
|
||||
PRBool operator==(const nsStr &aString) const;
|
||||
PRBool operator==(const char *aString) const;
|
||||
PRBool operator==(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods perform a !compare of a given string type to this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE
|
||||
*/
|
||||
PRBool operator!=(const nsString &aString) const;
|
||||
PRBool operator!=(const nsStr &aString) const;
|
||||
PRBool operator!=(const char* aString) const;
|
||||
PRBool operator!=(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is < than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator<(const nsString &aString) const;
|
||||
PRBool operator<(const nsStr &aString) const;
|
||||
PRBool operator<(const char* aString) const;
|
||||
PRBool operator<(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is > than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator>(const nsString &aString) const;
|
||||
PRBool operator>(const nsStr &S) const;
|
||||
PRBool operator>(const char* aString) const;
|
||||
PRBool operator>(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is <= than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator<=(const nsString &aString) const;
|
||||
PRBool operator<=(const nsStr &S) const;
|
||||
PRBool operator<=(const char* aString) const;
|
||||
PRBool operator<=(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* These methods test if a given string is >= than this
|
||||
* @param aString is the string to be compared to this
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
PRBool operator>=(const nsString &aString) const;
|
||||
PRBool operator>=(const nsStr &S) const;
|
||||
PRBool operator>=(const char* aString) const;
|
||||
PRBool operator>=(const PRUnichar* aString) const;
|
||||
|
||||
/**
|
||||
* Compare this to given string; note that we compare full strings here.
|
||||
* The optional length argument just lets us know how long the given string is.
|
||||
* If you provide a length, it is compared to length of this string as an
|
||||
* optimization.
|
||||
*
|
||||
* @param aString -- the string to compare to this
|
||||
* @param aCount -- number of chars to be compared.
|
||||
* @return TRUE if equal
|
||||
*/
|
||||
PRBool Equals(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool Equals(/*FIX: const */nsIAtom* anAtom,PRBool aIgnoreCase) const;
|
||||
PRBool Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase=PR_FALSE) const;
|
||||
|
||||
PRBool EqualsIgnoreCase(const nsString& aString) const;
|
||||
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsIgnoreCase(/*FIX: const */nsIAtom *aAtom) const;
|
||||
PRBool EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) 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);
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
static void Recycle(nsString* aString);
|
||||
static nsString* CreateString(void);
|
||||
|
||||
};
|
||||
|
||||
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:
|
||||
|
||||
nsAutoString();
|
||||
nsAutoString(const char* aCString,PRInt32 aLength=-1);
|
||||
nsAutoString(const PRUnichar* aString,PRInt32 aLength=-1);
|
||||
|
||||
nsAutoString(const CBufDescriptor& aBuffer);
|
||||
nsAutoString(const nsStr& aString);
|
||||
nsAutoString(const nsAutoString& aString);
|
||||
#ifdef AIX
|
||||
nsAutoString(const nsSubsumeStr& aSubsumeStr); // AIX requires a const
|
||||
#else
|
||||
nsAutoString(nsSubsumeStr& aSubsumeStr);
|
||||
#endif // AIX
|
||||
nsAutoString(PRUnichar aChar);
|
||||
virtual ~nsAutoString();
|
||||
|
||||
nsAutoString& operator=(const nsStr& aString) {nsString::Assign(aString); return *this;}
|
||||
nsAutoString& operator=(const nsAutoString& aString) {nsString::Assign(aString); return *this;}
|
||||
nsAutoString& operator=(const char* aCString) {nsString::Assign(aCString); return *this;}
|
||||
nsAutoString& operator=(char aChar) {nsString::Assign(aChar); return *this;}
|
||||
nsAutoString& operator=(const PRUnichar* aBuffer) {nsString::Assign(aBuffer); return *this;}
|
||||
nsAutoString& operator=(PRUnichar aChar) {nsString::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];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************
|
||||
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(nsStr& aString);
|
||||
nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,179 +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.
|
||||
*/
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "plstr.h"
|
||||
|
||||
// If the allocator changes, fix it here.
|
||||
#define XPIDL_STRING_ALLOC(__len) ((PRUnichar*) nsAllocator::Alloc((__len) * sizeof(PRUnichar)))
|
||||
#define XPIDL_CSTRING_ALLOC(__len) ((char*) nsAllocator::Alloc((__len) * sizeof(char)))
|
||||
#define XPIDL_FREE(__ptr) (nsAllocator::Free(__ptr))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsXPIDLString
|
||||
|
||||
nsXPIDLString::nsXPIDLString()
|
||||
: mBuf(0),
|
||||
mBufOwner(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLString::~nsXPIDLString()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLString::operator const PRUnichar*()
|
||||
{
|
||||
return 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()
|
||||
: mBuf(0),
|
||||
mBufOwner(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLCString::~nsXPIDLCString()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLCString& nsXPIDLCString::operator =(const char* aCString)
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = Copy(aCString);
|
||||
mBufOwner = PR_TRUE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLCString::operator const char*()
|
||||
{
|
||||
return mBuf;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,302 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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);
|
||||
nsAllocator::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 nsAllocator::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).
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsXPIDLString_h__
|
||||
#define nsXPIDLString_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();
|
||||
|
||||
virtual ~nsXPIDLString();
|
||||
|
||||
/**
|
||||
* Return a reference to the immutable Unicode string.
|
||||
*/
|
||||
operator const PRUnichar*();
|
||||
|
||||
/**
|
||||
* 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 */) {}
|
||||
nsXPIDLString& operator =(nsXPIDLString& /* aXPIDLString */) { return *this; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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();
|
||||
|
||||
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*();
|
||||
|
||||
/**
|
||||
* 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 */) {}
|
||||
nsXPIDLCString& operator =(nsXPIDLCString& /* aXPIDLCString */) { return *this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // nsXPIDLString_h__
|
||||
BIN
mozilla/webtools/tinderbox/1afi003r.gif
Normal file
BIN
mozilla/webtools/tinderbox/1afi003r.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
216
mozilla/webtools/tinderbox/Backwards.pm
Normal file
216
mozilla/webtools/tinderbox/Backwards.pm
Normal file
@@ -0,0 +1,216 @@
|
||||
# Backwards.pm
|
||||
|
||||
# Copyright (C) 1999 Uri Guttman. All rights reserved.
|
||||
# mail bugs, comments and feedback to uri@sysarch.com
|
||||
|
||||
|
||||
use strict ;
|
||||
|
||||
package Backwards ;
|
||||
|
||||
use Symbol ;
|
||||
use Fcntl ;
|
||||
use Carp ;
|
||||
use integer ;
|
||||
|
||||
#my $max_read_size = 3 ;
|
||||
|
||||
my $max_read_size = 1 << 13 ;
|
||||
|
||||
# support tied handles. the tied calls map directly to the object methods
|
||||
|
||||
*TIEHANDLE = \&new ;
|
||||
*READLINE = \&readline ;
|
||||
|
||||
# create a new Backwards object
|
||||
|
||||
sub new {
|
||||
|
||||
my( $class, $filename ) = @_ ;
|
||||
|
||||
my( $handle, $seek_pos, $read_size, $self ) ;
|
||||
|
||||
# get a new handle symbol and the real file handle
|
||||
|
||||
$handle = gensym() ;
|
||||
|
||||
# open the file for reading
|
||||
|
||||
unless( sysopen( $handle, $filename, O_RDONLY ) ) {
|
||||
carp "Can't open $filename $!" ;
|
||||
return ;
|
||||
}
|
||||
|
||||
# seek to the end of the file
|
||||
|
||||
seek( $handle, 0, 2 ) ;
|
||||
$seek_pos = tell( $handle ) ;
|
||||
|
||||
# get the size of the first block to read,
|
||||
# either a trailing partial one (the % size) or full sized one (max read size)
|
||||
|
||||
$read_size = $seek_pos % $max_read_size || $max_read_size ;
|
||||
|
||||
# create the hash for the object, bless and return it
|
||||
|
||||
$self = {
|
||||
'file_name' => $filename,
|
||||
'handle' => $handle,
|
||||
'read_size' => $read_size,
|
||||
'seek_pos' => $seek_pos,
|
||||
'lines' => [],
|
||||
} ;
|
||||
|
||||
return( bless( $self, $class ) ) ;
|
||||
}
|
||||
|
||||
sub readline {
|
||||
|
||||
my( $self, $line_ref ) = @_ ;
|
||||
|
||||
my( $handle, $lines_ref, $seek_pos, $read_cnt, $read_buf,
|
||||
$file_size, $read_size, $text ) ;
|
||||
|
||||
# get the buffer of lines
|
||||
|
||||
$lines_ref = $self->{'lines'} ;
|
||||
|
||||
while( 1 ) {
|
||||
|
||||
# see if there is more than 1 line in the buffer
|
||||
|
||||
if ( @{$lines_ref} > 1 ) {
|
||||
|
||||
# we have a complete line so return it
|
||||
|
||||
return( pop @{$lines_ref} ) ;
|
||||
}
|
||||
|
||||
# we don't have a complete, so have to read blocks until we do
|
||||
|
||||
$seek_pos = $self->{'seek_pos'} ;
|
||||
|
||||
# see if we are at the beginning of the file
|
||||
|
||||
if ( $seek_pos == 0 ) {
|
||||
|
||||
# the last read never made more lines, so return the last line in the buffer
|
||||
# if no lines left then undef will be returned
|
||||
|
||||
return( pop @{$lines_ref} ) ;
|
||||
}
|
||||
|
||||
#print "c size $read_size\n" ;
|
||||
|
||||
# we have to read more text so get the handle and the current read size
|
||||
|
||||
$handle = $self->{'handle'} ;
|
||||
$read_size = $self->{'read_size'} ;
|
||||
|
||||
# after the first read, always read the maximum size
|
||||
|
||||
$self->{'read_size'} = $max_read_size ;
|
||||
|
||||
# seek to the beginning of this block and save the new seek position
|
||||
|
||||
$seek_pos -= $read_size ;
|
||||
$self->{'seek_pos'} = $seek_pos ;
|
||||
seek( $handle, $seek_pos, 0 ) ;
|
||||
|
||||
#print "seek $seek_pos\n" ;
|
||||
|
||||
# read in the next (previous) block of text
|
||||
|
||||
$read_cnt = sysread( $handle, $read_buf, $read_size ) ;
|
||||
|
||||
#print "Read <$read_buf>\n" ;
|
||||
|
||||
# if ( $read_cnt != $read_size ) {
|
||||
# print "bad read cnt $read_cnt != size $read_size\n" ;
|
||||
# return( undef ) ;
|
||||
# }
|
||||
|
||||
# prepend the read buffer to the leftover (possibly partial) line
|
||||
|
||||
$text = $read_buf . ( pop @{$lines_ref} || '' ) ;
|
||||
|
||||
# split the buffer into a list of lines
|
||||
# this may want to be $/ but reading files backwards assumes plain text and
|
||||
# newline separators
|
||||
|
||||
@{$lines_ref} = $text =~ m[(^.*\n|^.+)]mg ;
|
||||
|
||||
#print "Lines \n=>", join( "<=\n=>", @{$lines_ref} ), "<=\n" ;
|
||||
}
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Backwards.pm -- Read a file backwards by lines.
|
||||
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Backwards ;
|
||||
|
||||
# Object interface
|
||||
|
||||
$bw = Backwards->new( 'log_file' ) ;
|
||||
|
||||
while( $log_line = $bw->readline ) {
|
||||
print $log_line ;
|
||||
}
|
||||
|
||||
# Tied Handle Interface
|
||||
|
||||
tie *BW, 'log_file' ;
|
||||
|
||||
while( <BW> ) {
|
||||
print ;
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
||||
This module reads a file backwards line by line. It is simple to use,
|
||||
memory efficient and fast. It supports both an object and a tied handle
|
||||
interface.
|
||||
|
||||
It is intended for processing log and other similar text files which
|
||||
typically have new entries appended. It uses newline as the separator
|
||||
and not $/ since it is only meant to be used for text.
|
||||
|
||||
It works by reading large (8kb) blocks of text from the end of the file,
|
||||
splits them on newlines and stores the other lines until the buffer runs
|
||||
out. Then it seeks to the previous block and splits it. When it reaches
|
||||
the beginning of the file, it stops reading more blocks. All boundary
|
||||
conditions are handled correctly. If there is a trailing partial line
|
||||
(no newline) it will be the first line returned. Lines larger than the
|
||||
read buffer size are ok.
|
||||
|
||||
=head2 Object Interface
|
||||
|
||||
|
||||
There are only 2 methods in Backwards' object interface, new and
|
||||
readline.
|
||||
|
||||
=head2 new
|
||||
|
||||
New takes just a filename for an argument and it either returns the
|
||||
object on a successful open on that file or undef.
|
||||
|
||||
=head2 readline
|
||||
|
||||
Readline takes no arguments and it returns the previous line in the file
|
||||
or undef when there are no more lines in the file.
|
||||
|
||||
|
||||
=head2 Tied Handle Interface
|
||||
|
||||
The only tied handle calls supported are TIEHANDLE and READLINE and they
|
||||
are typeglobbed to new and readline respectively. All other tied handle
|
||||
operations will generate an unknown method error. Do not seek, write or
|
||||
do any other operation other than <> on the handle.
|
||||
1
mozilla/webtools/tinderbox/Empty.html
Normal file
1
mozilla/webtools/tinderbox/Empty.html
Normal file
@@ -0,0 +1 @@
|
||||
<font size=+2>Click on the <b>filename and line number</b> in the log and the source will appear in this window.</font>
|
||||
77
mozilla/webtools/tinderbox/Makefile
Executable file
77
mozilla/webtools/tinderbox/Makefile
Executable file
@@ -0,0 +1,77 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
# This Makefile helps you install Tinderbox. Define PERL and MYSQLTCL to
|
||||
# the full pathnames of where you have these utilities. Define PREFIX
|
||||
# to where you will install the running Tinderbox. Then "make install" should
|
||||
# copy things for you.
|
||||
|
||||
#BONSAI = /home/httpd/html/bonsai
|
||||
#CVSROOT = /cvsroot
|
||||
#GZIP = /usr/bin/gzip
|
||||
#PERL = /usr/bin/perl
|
||||
#PREFIX = /home/httpd/html/tinderbox
|
||||
#UUDECODE = /usr/bin/uudecode
|
||||
|
||||
FILES = addimage.cgi \
|
||||
addnote.cgi \
|
||||
admintree.cgi \
|
||||
buildwho.pl \
|
||||
clean.pl \
|
||||
copydata.pl \
|
||||
doadmin.cgi \
|
||||
ep_mac.pl \
|
||||
ep_unix.pl \
|
||||
ep_windows.pl \
|
||||
fixupimages.pl \
|
||||
globals.pl \
|
||||
handlemail.pl \
|
||||
imagelog.pl \
|
||||
processbuild.pl \
|
||||
showbuilds.cgi \
|
||||
showimages.cgi \
|
||||
showlog.cgi \
|
||||
Empty.html \
|
||||
faq.html \
|
||||
index.html \
|
||||
examples/mozilla-unix.pl \
|
||||
examples/mozilla-windows.pl
|
||||
|
||||
PICS = \
|
||||
1afi003r.gif \
|
||||
reledanim.gif \
|
||||
star.gif
|
||||
|
||||
install:
|
||||
mkdir -p $(PREFIX) && \
|
||||
for I in $(FILES); do \
|
||||
echo Installing $$I && \
|
||||
sed -e s#/usr/bonsaitools/bin/perl#$(PERL)#g \
|
||||
-e s#/tools/ns/bin/perl5#$(PERL)#g \
|
||||
-e s#/m/src#$(CVSROOT)#g \
|
||||
-e s#/usr/local/bin/gzip#$(GZIP)#g \
|
||||
-e s#/tools/ns/bin/uudecode#$(UUDECODE)#g \
|
||||
-e s#/d/webdocs/projects/bonsai#$(BONSAI)#g \
|
||||
$$I > $(PREFIX)/$$I && \
|
||||
chmod 755 $(PREFIX)/$$I; done && \
|
||||
for I in $(PICS); do \
|
||||
echo Installing $$I && \
|
||||
cp -f $$I $(PREFIX) && \
|
||||
chmod 755 $(PREFIX)/$$I; done
|
||||
|
||||
287
mozilla/webtools/tinderbox/README
Normal file
287
mozilla/webtools/tinderbox/README
Normal file
@@ -0,0 +1,287 @@
|
||||
This is Tinderbox. See <http://www.mozilla.org/tinderbox.html>.
|
||||
|
||||
|
||||
==========
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
This is not very well packaged code. It's not packaged at all. Don't
|
||||
come here expecting something you plop in a directory, twiddle a few
|
||||
things, and you're off and using it. Much work has to be done to get
|
||||
there. We'd like to get there, but it wasn't clear when that would be,
|
||||
and so we decided to let people see it first.
|
||||
|
||||
Don't believe for a minute that you can use this stuff without first
|
||||
understanding most of the code.
|
||||
|
||||
|
||||
============
|
||||
DEPENDENCIES
|
||||
============
|
||||
|
||||
To use tinderbox, you must first have bonsai up and running.
|
||||
See <http://www.mozilla.org/bonsai.html>.
|
||||
|
||||
Be warned now that bonsai is not easily installed.
|
||||
|
||||
|
||||
====================================
|
||||
What's What in the Tinderbox sources:
|
||||
====================================
|
||||
|
||||
This is a rough first pass at cataloging and documenting the Tinderbox
|
||||
sources. Many hands have been in this code over the years, and it has
|
||||
accreted wildly. There is probably quite a lot of dead code in here.
|
||||
|
||||
|
||||
PROGRAMS
|
||||
========
|
||||
|
||||
handlemail.pl This is the mail deliverty agent (MDA) for tinderbox,
|
||||
the local message transfer agent (MTA) calls this
|
||||
program to deliver the tinderbox mail into the system.
|
||||
It is a wrapper for processbuild.pl.
|
||||
|
||||
processbuild.pl Update the "$tbx{tree}/build.dat" database as new
|
||||
mail comes in then run "./buildwho.pl $tree" and
|
||||
"./showbuilds.cgi" (to build static versions of
|
||||
tinderbox data.
|
||||
|
||||
buildwho.pl Update the who.dat file with the list of authors who
|
||||
checked in in the last two days. This is run from
|
||||
processbuild.pl, always, and from showbuild.cgi when
|
||||
'rebuildguilty' is clicked
|
||||
|
||||
|
||||
Conceptually, the three programs, handlemail.pl, processbuild.pl, and
|
||||
buildwho.pl, make up the MDA for tinderbox.
|
||||
|
||||
|
||||
showbuilds.cgi Create the Tinderbox web page.
|
||||
|
||||
showlog.cgi Show a build log (brief and full) update the brief_log if
|
||||
necessary. Requires the ep_$form{errorparser}.pl error
|
||||
parser.
|
||||
|
||||
ep_unix.pl Knows how to parse Unix build error logs. Used by
|
||||
processbuild.pl There needs to be one ep_* file for
|
||||
each distinct parsing algorithm used, typically this
|
||||
is per platform. This file defines the regular
|
||||
expressions which locate error lines: has_error()
|
||||
has_warning() and the function has_errorline() which
|
||||
parses the line into the global variables:
|
||||
$error_file, $error_file_ref, $error_line, $error_guess,
|
||||
|
||||
admintree.cgi Displays the admin cgi which depends on:
|
||||
$message_of_day, $ignore_builds
|
||||
|
||||
doadmin.cgi Actually do the work to admin a tinderbox tree
|
||||
(change message of the day, turn off displays for a
|
||||
channel)
|
||||
|
||||
clean.pl Run `find . -name \"*.gz\" -mtime +7 -print ` and
|
||||
unlink those files. Does not appear to be run from
|
||||
other tools. It is a good candidate for a cron job.
|
||||
|
||||
|
||||
|
||||
OPTIONS to showbuilds.cgi
|
||||
=========================
|
||||
|
||||
Options to showbuilds are specified in the URL and are undocumented
|
||||
elsewhere.
|
||||
|
||||
If called with no 'tree' option display the possible build trees to
|
||||
pick from. The 'tree' picks the build to display. An additional tree
|
||||
can be specified with 'tree2'.
|
||||
|
||||
Interesting visual params are:
|
||||
|
||||
current state monitoring mode:
|
||||
express=1
|
||||
or
|
||||
panel=1
|
||||
text mode state monitoring:
|
||||
quickparse=1
|
||||
|
||||
These modes do not show on my browser:
|
||||
flash=1
|
||||
rdf=1
|
||||
static=1
|
||||
|
||||
These are self explanatory:
|
||||
nocrap=1;
|
||||
hours=n;
|
||||
|
||||
|
||||
EMAIL FORMAT
|
||||
============
|
||||
|
||||
Each tinderbox client mails status updates to the tinderbox server.
|
||||
These mails contain special tinderbox data lines describing the
|
||||
progress of the build it may also contain the log of the build process
|
||||
and could contain a uuencoded binary.
|
||||
|
||||
|
||||
The email to the tinderbox server looks like:
|
||||
|
||||
tinderbox: tree: Mozilla
|
||||
tinderbox: builddate: 900002087
|
||||
tinderbox: status: building
|
||||
tinderbox: build: IRIX 6.3 Depend
|
||||
tinderbox: errorparser: unix
|
||||
|
||||
If binaryname is set then the mail message is run through uudecode to
|
||||
create a file called "$binaryname" on the tinderbox server.
|
||||
|
||||
# NOT USED tinderbox: buildfamily: unix
|
||||
|
||||
|
||||
DATA STRUCTURES IN showbuilds.cgi
|
||||
=================================
|
||||
|
||||
load_buildlog() creates build_list a list of hash refernces of this
|
||||
type
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => ($tree2 ne '' ? $t->{name} . ' ' : '' ) . $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => $t
|
||||
};
|
||||
|
||||
the $buildrec->{rowspan} variable holds the number of rows that the build
|
||||
should occupy on the table and is not stored in the build.dat file.
|
||||
|
||||
These are other add ons to the data structure
|
||||
$buildrec->{hasnote}=1;
|
||||
$buildrec->{noteid} = (0+@note_array);
|
||||
|
||||
commonly buildrec's are accessed through:
|
||||
$build_table->[$build_time][$build_name] = $buildrec;
|
||||
|
||||
The list of users who updated this build is stored as:
|
||||
$who_list->[$checkin_time]->{$author} = 1;
|
||||
|
||||
There are numerous duplicate data structures which hold partial
|
||||
information:
|
||||
|
||||
hashes which hold all indices:
|
||||
$build_name_index->{$br->{buildname}} = 1;
|
||||
$build_time_index->{$br->{buildtime}} = 1;
|
||||
other access into $build_table:
|
||||
$build_name_names->[$i] = $n;
|
||||
$build_time_times->[$i] = $n;
|
||||
|
||||
|
||||
loadquickparseinfo creates these references
|
||||
$build->{$buildname} = $buildstatus;
|
||||
$times->{$buildname} = $buildtime;
|
||||
|
||||
|
||||
|
||||
DATA FILES
|
||||
==========
|
||||
|
||||
These files are used to store data structures. They are a persistent
|
||||
store of data between executions of the same program and they pass the
|
||||
data between cooperating program. This data is often databases with
|
||||
rows separated by "\n" and columns by '|'.
|
||||
|
||||
|
||||
$tree/${logfile}
|
||||
$tree/${logfile}.brief.html
|
||||
$tree/ignorebuilds.pl
|
||||
$tree/mod.pl
|
||||
$tree/notes.txt
|
||||
$tree/treedata.pl
|
||||
$tree/who.dat
|
||||
$treename/build.dat
|
||||
|
||||
The logfile that the tinderbox client sent stored in gziped format.
|
||||
The filename is ${tree}/$builddate.$$.gz so its quite random and does
|
||||
not depend on the clients$build string and multiple logs are kept for
|
||||
each build, one for each mail message sent.
|
||||
|
||||
The brief.html file is a cache of the error log summary for this log
|
||||
file and is recreated when the logfile gets updated.
|
||||
|
||||
ignorebuilds.pl is a file which specifies builds that should not be
|
||||
performed. It is valid perl code which sets the hash reference
|
||||
$ignore_builds, each key is a tree name.
|
||||
|
||||
mod.pl stores the tree specific message of the day. This is not to be
|
||||
confused with mod perl the CGI library. Its contents looks like:
|
||||
$message_of_day = 'message';
|
||||
|
||||
notes.txt store the database of notes:
|
||||
$buildtime|$buildname||$author|$time_now|$note
|
||||
|
||||
|
||||
treedata.pl stores the cvs information pertaining to this tree and
|
||||
looks like this:
|
||||
$cvs_module='$modulename';
|
||||
$cvs_branch='$branchname';
|
||||
$cvs_root='$repository';
|
||||
|
||||
who.dat file has lines like:
|
||||
$checkin_time|$author
|
||||
This gets stored in the data structure, where checkin_time
|
||||
gets fudged up so that is is a time already in the
|
||||
build_table:
|
||||
$who_list->[$checkin_time]->{$author} = 1;
|
||||
|
||||
build.dat stores the build results table. It is a flat file
|
||||
representation of $build_table
|
||||
|
||||
build.dat is a database file each row is a build and has pipe
|
||||
separated columns:
|
||||
|
||||
1) the time stamp of the tinderbox server
|
||||
2) time stamp of the build machine
|
||||
3) the official build name (should include build machine name)
|
||||
( note: that 2 & 3 together uniquely identify the build
|
||||
and all relevant build data)
|
||||
4) the architecture dependent error parser to use on the log files
|
||||
5) status of the build (success|busted|building|testfailed)
|
||||
6) The log file for this build (if completed)
|
||||
7) the name of the binary (if any) that came from the build
|
||||
|
||||
|
||||
Other Files
|
||||
====================
|
||||
1afi003r.gif The "flames" animation used by showbuilds.cgi
|
||||
|
||||
Empty.html Document used for an empty frame by ???
|
||||
|
||||
addimage.cgi The form that lets you add a new image to the list of
|
||||
images that Tinderbox picks from randomly.
|
||||
|
||||
addnote.cgi Add a note to a build log.
|
||||
|
||||
admintree.cgi Lets you perform various admin tasks on a Tinderbox tree.
|
||||
This just prompts for a password and posts to doadmin.cgi.
|
||||
|
||||
clean.pl ???
|
||||
copydata.pl ???
|
||||
|
||||
doadmin.cgi Actually do the work to admin a tinderbox tree
|
||||
|
||||
ep_mac.pl Knows how to parse Mac build error logs. Used by ???
|
||||
ep_unix.pl Knows how to parse Unix build error logs. Used by ???
|
||||
ep_windows.pl Knows how to parse Windows build error logs. Used by ???
|
||||
|
||||
faq.html Wildly out of date.
|
||||
|
||||
fixupimages.pl ???
|
||||
globals.pl ???
|
||||
imagelog.pl ???
|
||||
index.html ???
|
||||
reledanim.gif ???
|
||||
|
||||
showimages.cgi Show all the images in the Tinderbox list. Password-protected.
|
||||
|
||||
star.gif The "star" image used to annotate builds by ???
|
||||
404
mozilla/webtools/tinderbox/addimage.cgi
Executable file
404
mozilla/webtools/tinderbox/addimage.cgi
Executable file
@@ -0,0 +1,404 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use Socket;
|
||||
|
||||
use lib "../bonsai";
|
||||
require 'header.pl';
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
EmitHtmlTitleAndHeader("tinderbox: add images", "add images");
|
||||
|
||||
$| = 1;
|
||||
|
||||
require "globals.pl";
|
||||
require "imagelog.pl";
|
||||
|
||||
&split_cgi_args;
|
||||
|
||||
|
||||
sub Error {
|
||||
my ($msg) = @_;
|
||||
print "<BR><BR><BR>";
|
||||
print "<UL><FONT SIZE='+1'><B>Something went wrong:</B><P>";
|
||||
print "<UL>";
|
||||
print $msg;
|
||||
print "</UL>";
|
||||
print "<P>";
|
||||
print "Hit <B>\`Back'</B> and try again.";
|
||||
print "</UL>";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
if( $url = $form{"url"} ){
|
||||
$quote = $form{"quote"};
|
||||
|
||||
$quote =~ s/[\r\n]/ /g;
|
||||
$url =~ s/[\r\n]/ /g;
|
||||
|
||||
$width = "";
|
||||
$height = "";
|
||||
# I think we don't want to allow this --jwz
|
||||
# $width = $form{"width"};
|
||||
# $height = $form{"height"};
|
||||
|
||||
if ($width eq "" || $height eq "") {
|
||||
$size = &URLsize($url);
|
||||
if ($size =~ /WIDTH=([0-9]*)/) {
|
||||
$width = $1;
|
||||
}
|
||||
if ($size =~ /HEIGHT=([0-9]*)/) {
|
||||
$height = $1;
|
||||
}
|
||||
if ($width eq "" || $height eq "") {
|
||||
Error "Couldn't get image size for \"$url\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "
|
||||
|
||||
<P><center><img border=2 src='$url' width=$width height=$height><br>
|
||||
<i>$quote</i><br><br>
|
||||
";
|
||||
|
||||
if( $form{"submit"} ne "Yes" ){
|
||||
my $u2 = $url;
|
||||
my $q2 = $quote;
|
||||
$u2 =~ s@&@&@g; $u2 =~ s@<@<@g; $u2 =~ s@\"@"@g;
|
||||
$q2 =~ s@&@&@g; $q2 =~ s@<@<@g; $q2 =~ s@\"@"@g;
|
||||
|
||||
print "
|
||||
<form action='addimage.cgi' METHOD='get'>
|
||||
<input type=hidden name=url value=\"$u2\">
|
||||
<input type=hidden name=quote value=\"$q2\">
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TH ALIGN=RIGHT NOWRAP>Image URL:</TH>
|
||||
<TD><TT><B>$u2</B></TT></TD>
|
||||
</TR><TR>
|
||||
<TH ALIGN=RIGHT>Caption:</TH>
|
||||
<TD><TT><B>$q2</B></TT></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD></TD>
|
||||
<TD>
|
||||
<FONT SIZE=+2><B>
|
||||
Does that look right?
|
||||
<SPACER SIZE=10>
|
||||
<INPUT Type='submit' name='submit' value='Yes'>
|
||||
</B><BR>(If not, hit \`Back' and fix it.)
|
||||
</FONT>
|
||||
</TD>
|
||||
</TABLE>
|
||||
</form>
|
||||
";
|
||||
}
|
||||
else {
|
||||
&add_imagelog( $url, $quote, $width, $height );
|
||||
print "<br><br>
|
||||
<font size=+2>Has been added</font><br><br>
|
||||
<a href=showbuilds.cgi>Return to Log</a>";
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
print "
|
||||
<h2>Add an image and a funny caption.</h2>
|
||||
|
||||
<ul>
|
||||
<p>This is about fun, and making your daily excursion to
|
||||
<A HREF=http://www.mozilla.org/tinderbox.html>Tinderbox</A> a
|
||||
novel experience. Engineers spend a lot of time here; it might as well
|
||||
have some entertainment value.
|
||||
|
||||
<p>Please play nice. We don't have the time or inclination to look at
|
||||
everything you people submit, but if we get nastygrams or legalgrams
|
||||
and have to take something down, we will curse your IP address, and you
|
||||
might even make it so the whole thing goes away forever. Please don't
|
||||
make us go there. You might also avoid links to big images or slow
|
||||
servers.
|
||||
|
||||
<p><ul><B>Thank you for playing nice.</B></UL>
|
||||
|
||||
<p>If you really find an image offensive, please
|
||||
<A HREF=mailto:terry\@netscape.com?Subject=offensive%20tinderbox%20image>tell us</A>
|
||||
nicely before someone causes a stink. Be sure to include the URL of
|
||||
the image. Remember, we don't screen these submissions and may not
|
||||
have even seen it.
|
||||
|
||||
<p><ul><B>P.S. Please, no more pictures of Bill Gates.</B></UL>
|
||||
</ul>
|
||||
|
||||
<p><form action='addimage.cgi' METHOD='get'>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TH ALIGN=RIGHT NOWRAP>Image URL:</TH>
|
||||
<TD><INPUT NAME='url' SIZE=60></TD>
|
||||
</TR><TR>
|
||||
<TH ALIGN=RIGHT>Caption:</TH>
|
||||
<TD><INPUT NAME='quote' SIZE=60></TD>
|
||||
</TR><TR>
|
||||
<TD></TD>
|
||||
<TD><B>
|
||||
<INPUT Type='submit' name='submit' value='Test'>
|
||||
<SPACER SIZE=25>
|
||||
<INPUT Type='reset' name='reset' value='Reset'>
|
||||
</B></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
</form>
|
||||
<br><br>
|
||||
";
|
||||
}
|
||||
|
||||
sub split_cgi_args {
|
||||
local($i,$var,$value, $s);
|
||||
|
||||
$s = $ENV{"QUERY_STRING"};
|
||||
|
||||
@args= split(/\&/, $s );
|
||||
|
||||
for $i (@args) {
|
||||
($var, $value) = split(/=/, $i);
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
$form{$var} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#sub imgsize {
|
||||
# local($file)= @_;
|
||||
#
|
||||
# #first try to open the file
|
||||
# if( !open(STREAM, "<$file") ){
|
||||
# Error "Can't open IMG $file";
|
||||
## $size="";
|
||||
# } else {
|
||||
# if ($file =~ /.jpg/i || $file =~ /.jpeg/i) {
|
||||
# $size = &jpegsize(STREAM);
|
||||
# } elsif($file =~ /.gif/i) {
|
||||
# $size = &gifsize(STREAM);
|
||||
# } elsif($file =~ /.xbm/i) {
|
||||
# $size = &xbmsize(STREAM);
|
||||
# } else {
|
||||
# return "";
|
||||
# }
|
||||
# $_ = $size;
|
||||
# if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
# ($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
# }
|
||||
# if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
# ($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
# }
|
||||
# close(STREAM);
|
||||
# }
|
||||
# return $size;
|
||||
#}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine gets the size of the specified GIF
|
||||
###########################################################################
|
||||
|
||||
# bug: it thinks that
|
||||
# http://cvs1.mozilla.org/webtools/tinderbox/data/knotts.gif
|
||||
# is 640x400, but it's really 200x245.
|
||||
# giftrans says of that image:
|
||||
#
|
||||
# Header: "GIF87a"
|
||||
# Logical Screen Descriptor:
|
||||
# Logical Screen Width: 640 pixels
|
||||
# Logical Screen Height: 480 pixels
|
||||
# Image Descriptor:
|
||||
# Image Width: 200 pixels
|
||||
# Image Height: 245 pixels
|
||||
|
||||
|
||||
sub gifsize {
|
||||
local($GIF) = @_;
|
||||
read($GIF, $type, 6);
|
||||
if(!($type =~ /GIF8[7,9]a/) ||
|
||||
!(read($GIF, $s, 4) == 4) ){
|
||||
Error "Invalid or Corrupted GIF";
|
||||
$size="";
|
||||
} else {
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join ("", 'WIDTH=', $b<<8|$a, ' HEIGHT=', $d<<8|$c);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub xbmsize {
|
||||
local($XBM) = @_;
|
||||
local($input)="";
|
||||
|
||||
$input .= <$XBM>;
|
||||
$input .= <$XBM>;
|
||||
$_ = $input;
|
||||
if( /#define\s*\S*\s*\d*\s*\n#define\s*\S*\s*\d*\s*\n/i ){
|
||||
($a,$b)=/#define\s*\S*\s*(\d*)\s*\n#define\s*\S*\s*(\d*)\s*\n/i;
|
||||
$size=join ("", 'WIDTH=', $a, ' HEIGHT=', $b );
|
||||
} else {
|
||||
Error "Doesn't look like an XBM file";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
# jpegsize : gets the width and height (in pixels) of a jpeg file
|
||||
# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
|
||||
# modified slightly by alex@ed.ac.uk
|
||||
sub jpegsize {
|
||||
local($JPEG) = @_;
|
||||
local($done)=0;
|
||||
$size="";
|
||||
|
||||
read($JPEG, $c1, 1); read($JPEG, $c2, 1);
|
||||
if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
|
||||
my $s = sprintf "This is not a JPEG! (Codes %02X %02X)\n", ord($c1), ord($c2);
|
||||
Error $s;
|
||||
$done=1;
|
||||
}
|
||||
while (ord($ch) != 0xDA && !$done) {
|
||||
# Find next marker (JPEG markers begin with 0xFF)
|
||||
# This can hang the program!!
|
||||
while (ord($ch) != 0xFF) { read($JPEG, $ch, 1); }
|
||||
# JPEG markers can be padded with unlimited 0xFF's
|
||||
while (ord($ch) == 0xFF) { read($JPEG, $ch, 1); }
|
||||
# Now, $ch contains the value of the marker.
|
||||
$marker=ord($ch);
|
||||
|
||||
if (($marker >= 0xC0) && ($marker <= 0xCF) &&
|
||||
($marker != 0xC4) && ($marker != 0xCC)) { # it's a SOFn marker
|
||||
read ($JPEG, $junk, 3); read($JPEG, $s, 4);
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join("", 'HEIGHT=',$a<<8|$b,' WIDTH=',$c<<8|$d );
|
||||
$done=1;
|
||||
} else {
|
||||
# We **MUST** skip variables, since FF's within variable
|
||||
# names are NOT valid JPEG markers
|
||||
read ($JPEG, $s, 2);
|
||||
($c1, $c2) = unpack("C"x2,$s);
|
||||
$length = $c1<<8|$c2;
|
||||
if( ($length < 2) ){
|
||||
Error "Bad JPEG file: erroneous marker length";
|
||||
$done=1;
|
||||
} else {
|
||||
read($JPEG, $junk, $length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine grabs a gif from another server and gets its size
|
||||
###########################################################################
|
||||
|
||||
|
||||
sub URLsize {
|
||||
my ($fullurl) = @_;
|
||||
|
||||
$_ = $fullurl;
|
||||
if ( ! m@^http://@ ) {
|
||||
Error "HTTP URLs only, please: \"$_\" is no good.";
|
||||
}
|
||||
|
||||
my($dummy, $dummy, $serverstring, $url) = split(/\//, $fullurl, 4);
|
||||
my($them,$port) = split(/:/, $serverstring);
|
||||
my $port = 80 unless $port;
|
||||
my $size="";
|
||||
|
||||
$_ = $them;
|
||||
if ( m@^[^.]*$@ ) {
|
||||
Error "Fully-qualified host names only, please: \"$_\" is no good.";
|
||||
}
|
||||
|
||||
$_=$url;
|
||||
my ($remote, $iaddr, $paddr, $proto, $line);
|
||||
$remote = $them;
|
||||
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
|
||||
die "No port" unless $port;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
|
||||
connect(S, $paddr) || die "connect: $!";
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
print S "GET /$url HTTP/1.0\r\n";
|
||||
print S "Host: $them\r\n";
|
||||
print S "User-Agent: Tinderbox/0.0\r\n";
|
||||
print S "\r\n";
|
||||
|
||||
$_ = <S>;
|
||||
if (! m@^HTTP/[0-9.]+ 200@ ) {
|
||||
Error "$them responded:<BR> $_";
|
||||
}
|
||||
|
||||
my $ctype = "";
|
||||
while (<S>) {
|
||||
# print "read: $_<br>\n";
|
||||
if ( m@^Content-Type:[ \t]*([^ \t\r\n]+)@io ) {
|
||||
$ctype = $1;
|
||||
}
|
||||
last if (/^[\r\n]/);
|
||||
}
|
||||
|
||||
$_ = $ctype;
|
||||
if ( $_ eq "" ) {
|
||||
Error "Server returned no content-type for \"$fullurl\"?";
|
||||
} elsif ( m@image/jpeg@i || m@image/pjpeg@i ) {
|
||||
$size = &jpegsize(S);
|
||||
} elsif ( m@image/gif@i ) {
|
||||
$size = &gifsize(S);
|
||||
} elsif ( m@image/xbm@i || m@image/x-xbm@i || m@image/x-xbitmap@i ) {
|
||||
$size = &xbmsize(S);
|
||||
} else {
|
||||
Error "Not a GIF, JPEG, or XBM: that was of type \"$ctype\".";
|
||||
}
|
||||
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
|
||||
if ( $newwidth eq "" || $newheight eq "" ) {
|
||||
return "";
|
||||
} else {
|
||||
if ( $newwidth <= 5 || $newheight <= 5 ) {
|
||||
Error "${newwidth}x${newheight} seems small, don't you think?";
|
||||
} elsif ( $newwidth >= 400 || $newheight >= 400 ) {
|
||||
Error "${newwidth}x${newheight} is too big; please" .
|
||||
" keep it under 400x400."
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
}
|
||||
|
||||
sub dokill {
|
||||
kill 9,$child if $child;
|
||||
}
|
||||
206
mozilla/webtools/tinderbox/addnote.cgi
Executable file
206
mozilla/webtools/tinderbox/addnote.cgi
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib "../bonsai";
|
||||
use Fcntl;
|
||||
|
||||
require "globals.pl";
|
||||
require 'lloydcgi.pl';
|
||||
|
||||
if (defined($args = $form{log})) {
|
||||
|
||||
($tree, $logfile) = split /\//, $args;
|
||||
|
||||
my $br = find_build_record($tree, $logfile);
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
$buildtime = $br->{buildtime};
|
||||
} else {
|
||||
$tree = $form{'tree'};
|
||||
$logfile = $form{'logfile'};
|
||||
$errorparser = $form{'errorparser'};
|
||||
$buildname = $form{'buildname'};
|
||||
$buildtime = $form{'buildtime'};
|
||||
}
|
||||
|
||||
$enc_buildname = &url_encode($buildname);
|
||||
|
||||
$note = $form{'note'};
|
||||
$who = $form{'who'};
|
||||
|
||||
$now = time;
|
||||
$now_str = &print_time($now);
|
||||
|
||||
$|=1;
|
||||
|
||||
if( -r "$tree/ignorebuilds.pl" ){
|
||||
require "$tree/ignorebuilds.pl";
|
||||
}
|
||||
|
||||
print "Content-Type:text/html\n";
|
||||
if ($ENV{"REQUEST_METHOD"} eq 'POST' && defined($form{'note'})) {
|
||||
# Expire the cookie 5 months from now
|
||||
print "Set-Cookie: email=$form{who}; expires="
|
||||
. toGMTString(time + 86400 * 152) . "; path=/\n";
|
||||
}
|
||||
print "\n<HTML>\n";
|
||||
|
||||
if( $url = $form{"note"} ){
|
||||
|
||||
$note =~ s/\&/&/gi;
|
||||
$note =~ s/\</</gi;
|
||||
$note =~ s/\>/>/gi;
|
||||
$enc_note = url_encode( $note );
|
||||
|
||||
open( NOTES,">>$tree/notes.txt");
|
||||
flock(NOTES, LOCK_EX);
|
||||
print NOTES "$buildtime|$buildname|$who|$now|$enc_note\n";
|
||||
|
||||
&LoadBuildTable;
|
||||
|
||||
foreach $element (keys %form) {
|
||||
|
||||
if(exists ${$build_name_index}{$element}) {
|
||||
print NOTES "${$build_name_index}{$element}|$element|$who|$now|$enc_note\n";
|
||||
} #EndIf
|
||||
} #Endforeach
|
||||
close(NOTES);
|
||||
|
||||
print "<H1>The following comment has been added to the log</h1>\n";
|
||||
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
print "<pre>\n[<b>$who - $now_str</b>]\n$note\n</pre>";
|
||||
|
||||
print"
|
||||
<p><a href=\"showlog.cgi?tree=$tree\&buildname=$enc_buildname\&buildtime=$buildtime\&logfile=$logfile\&errorparser=$errorparser\">
|
||||
Go back to the Error Log</a>
|
||||
<a href=\"showbuilds.cgi?tree=$tree\">
|
||||
<br>Go back to the build Page</a>";
|
||||
|
||||
# Build tinderbox static pages
|
||||
$ENV{QUERY_STRING}="tree=$tree&static=1";
|
||||
$ENV{REQUEST_METHOD}="GET";
|
||||
system './showbuilds.cgi >/dev/null';
|
||||
|
||||
} else {
|
||||
|
||||
&GetBuildNameIndex;
|
||||
|
||||
@names = sort (keys %$build_name_index);
|
||||
|
||||
if ($buildname eq '' || $buildtime == 0) {
|
||||
print "<h1>Invalid parameters</h1>\n";
|
||||
die "\n";
|
||||
}
|
||||
|
||||
#print "$buildname \n $buildtime \n $errorparser \n $logfile \n $tree \n $enc_buildname \n";
|
||||
|
||||
$emailvalue = '';
|
||||
$emailvalue = " value='$cookie_jar{email}'" if defined($cookie_jar{email});
|
||||
|
||||
print qq(
|
||||
<head><title>Add a Comment to $buildname log</title></head>
|
||||
<body BGCOLOR="#FFFFFF" TEXT="#000000"LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
|
||||
<table><tr><td>
|
||||
<b><font size="+2">Add a Log Comment</font></b>
|
||||
</td></tr><tr><td>
|
||||
<b><code>$buildname</code></b>
|
||||
</td></tr></table>
|
||||
|
||||
<form action='addnote.cgi' METHOD='post'>
|
||||
|
||||
<INPUT Type='hidden' name='buildname' value='${buildname}'>
|
||||
<INPUT Type='hidden' name='buildtime' value='${buildtime}'>
|
||||
<INPUT Type='hidden' name='errorparser' value='$errorparser'>
|
||||
<INPUT Type='hidden' name='logfile' value='$logfile'>
|
||||
<INPUT Type='hidden' name='tree' value='$tree'>
|
||||
|
||||
<table border=0 cellpadding=4 cellspacing=1>
|
||||
<tr valign=top>
|
||||
<td align=right>
|
||||
<NOWRAP>Email address:</NOWRAP>
|
||||
</td><td>
|
||||
<INPUT Type='input' name='who' size=32$emailvalue><BR>
|
||||
</td>
|
||||
</tr><tr valign=top>
|
||||
<td align=right>
|
||||
Comment:
|
||||
</td><td>
|
||||
<TEXTAREA NAME=note ROWS=10 COLS=30 WRAP=HARD></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br><b><font size="+2">Addition Builds</font></b><br>
|
||||
(Comment will be added to the most recent cycle.)<br>
|
||||
);
|
||||
|
||||
for $other_build (@names){
|
||||
if( $other_build ne "" ){
|
||||
|
||||
if (not exists ${$ignore_builds}{$other_build}) {
|
||||
if( $other_build ne $buildname ){
|
||||
print "<INPUT TYPE=checkbox NAME=\"$other_build\">";
|
||||
print "$other_build<BR>\n";
|
||||
}
|
||||
} #EndIf
|
||||
}
|
||||
} #Endfor
|
||||
|
||||
print "<INPUT Type='submit' name='submit' value='Add Comment'><BR>
|
||||
</form>\n</body>\n</html>";
|
||||
}
|
||||
|
||||
sub GetBuildNameIndex {
|
||||
local($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname);
|
||||
|
||||
open(BUILDLOG, "$tree/build.dat") or die "Couldn't open build.dat: $!\n";
|
||||
|
||||
while(<BUILDLOG>) {
|
||||
chomp;
|
||||
($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
|
||||
$build_name_index->{$buildname} = 0;
|
||||
|
||||
} #EndWhile
|
||||
close(BUILDLOG);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub LoadBuildTable {
|
||||
local($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname);
|
||||
|
||||
open(BUILDLOG, "$tree/build.dat") or die "Couldn't open build.dat: $!\n";
|
||||
|
||||
while(<BUILDLOG>) {
|
||||
chomp;
|
||||
($mailtime, $buildtime, $buildname, $errorparser, $buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
|
||||
if ($buildtime > $build_name_index->{$buildname} ) {
|
||||
$build_name_index->{$buildname} = $buildtime;
|
||||
}
|
||||
|
||||
} #EndWhile
|
||||
close(BUILDLOG);
|
||||
|
||||
}
|
||||
|
||||
131
mozilla/webtools/tinderbox/admintree.cgi
Executable file
131
mozilla/webtools/tinderbox/admintree.cgi
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
require 'header.pl';
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
EmitHtmlHeader("administer tinderbox", "tree: $tree");
|
||||
|
||||
$form{noignore} = 1; # Force us to load all build info, not
|
||||
# paying any attention to ignore_builds stuff.
|
||||
$maxdate = time();
|
||||
$mindate = $maxdate - 24*60*60;
|
||||
&load_data;
|
||||
|
||||
if (defined($tree)) {
|
||||
if( -r "$tree/mod.pl" ){
|
||||
require "$tree/mod.pl";
|
||||
}
|
||||
else {
|
||||
$message_of_day = "";
|
||||
}
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=set_message>
|
||||
<br><b>Message of the Day
|
||||
<br><TEXTAREA NAME=message ROWS=10 COLS=70 WRAP=SOFT>$message_of_day
|
||||
</TEXTAREA>
|
||||
<br><INPUT TYPE=SUBMIT VALUE='Set Message of the Day'>
|
||||
</FORM>
|
||||
<hr>
|
||||
";
|
||||
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=trim_logs>
|
||||
<br><b>Trim Logs to <INPUT NAME=days size=5 VALUE='7'> days.</b> (Tinderbox
|
||||
shows 2 days history by default. You can see more by clicking show all).
|
||||
<br><INPUT TYPE=SUBMIT VALUE='Trim Logs'>
|
||||
</FORM>
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<hr>
|
||||
" ;
|
||||
}
|
||||
|
||||
print "
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=create_tree>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><B>tinderbox tree name:</B></TD>
|
||||
<TD><INPUT NAME=treename VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs repository:</B></TD>
|
||||
<TD><INPUT NAME=repository VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs module name:</B></TD>
|
||||
<TD><INPUT NAME=modulename VALUE=''></TD>
|
||||
</TR><TR>
|
||||
<TD><B>cvs branch:</B></TD>
|
||||
<TD><INPUT NAME=branchname VALUE='HEAD'></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<INPUT TYPE=SUBMIT VALUE='Create a new Tinderbox page'>
|
||||
</FORM>
|
||||
<FORM method=post action=doadmin.cgi>
|
||||
<hr>
|
||||
";
|
||||
|
||||
if (defined($tree)) {
|
||||
print "
|
||||
<B><font size=+1>If builds are behaving badly you can turn them off.</font></b><br> Uncheck
|
||||
the build that is misbehaving and click the button. You can still see all the
|
||||
builds even if some are disabled by adding the parameter <b><tt>&noignore=1</tt></b> to
|
||||
the tinderbox URL.<br>
|
||||
<B>Password:</B> <INPUT NAME=password TYPE=password> <BR>
|
||||
<INPUT TYPE=HIDDEN NAME=tree VALUE=$tree>
|
||||
<INPUT TYPE=HIDDEN NAME=command VALUE=disable_builds>
|
||||
";
|
||||
|
||||
@names = sort (@$build_name_names) ;
|
||||
|
||||
for $i (@names){
|
||||
if( $i ne "" ){
|
||||
$checked = ($ignore_builds->{$i} != 0 ? "": "CHECKED" );
|
||||
print "<INPUT TYPE=checkbox NAME='build_$i' $checked >";
|
||||
print "$i<br>\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "
|
||||
<INPUT TYPE=SUBMIT VALUE='Show only checked builds'>
|
||||
</FORM>
|
||||
<hr>
|
||||
";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
97
mozilla/webtools/tinderbox/buildwho.pl
Executable file
97
mozilla/webtools/tinderbox/buildwho.pl
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
|
||||
$F_DEBUG=1;
|
||||
|
||||
|
||||
$days = 2;
|
||||
|
||||
if ($ARGV[0] eq "-days") {
|
||||
shift @ARGV;
|
||||
$days = shift @ARGV;
|
||||
}
|
||||
|
||||
$tree = $ARGV[0];
|
||||
|
||||
open(SEMFILE, ">>$tree/buildwho.sem") || die "Couldn't open semaphore file!";
|
||||
if (!flock(SEMFILE, 2 + 4)) { # 2 means "lock"; 4 means "fail immediately if
|
||||
# lock already taken".
|
||||
print "buildwho.pl: Another process is currently building the database.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
require "$tree/treedata.pl";
|
||||
|
||||
if( $cvs_root eq '' ){
|
||||
$CVS_ROOT = '/m/src';
|
||||
}
|
||||
else {
|
||||
$CVS_ROOT = $cvs_root;
|
||||
}
|
||||
|
||||
$CVS_REPOS_SUFIX = $CVS_ROOT;
|
||||
$CVS_REPOS_SUFIX =~ s/\//_/g;
|
||||
|
||||
$CHECKIN_DATA_FILE = "/d/webdocs/projects/bonsai/data/checkinlog${CVS_REPOS_SUFIX}";
|
||||
$CHECKIN_INDEX_FILE = "/d/webdocs/projects/bonsai/data/index${CVS_REPOS_SUFIX}";
|
||||
|
||||
require 'cvsquery.pl';
|
||||
|
||||
print "cvsroot='$CVS_ROOT'\n";
|
||||
|
||||
&build_who;
|
||||
|
||||
flock(SEMFILE, 8); # '8' is magic 'unlock' const.
|
||||
close SEMFILE;
|
||||
|
||||
|
||||
sub build_who {
|
||||
open(BUILDLOG, "<$tree/build.dat" );
|
||||
$line = <BUILDLOG>;
|
||||
close(BUILDLOG);
|
||||
|
||||
#($j,$query_date_min) = split(/\|/, $line);
|
||||
$query_date_min = time - (60 * 60 * 24 * $days);
|
||||
|
||||
if( $F_DEBUG ){
|
||||
print "Minimum date: $query_date_min\n";
|
||||
}
|
||||
|
||||
$query_module=$cvs_module;
|
||||
$query_branch=$cvs_branch;
|
||||
|
||||
$result = &query_checkins;
|
||||
|
||||
|
||||
$last_who='';
|
||||
$last_date=0;
|
||||
open(WHOLOG, ">$tree/who.dat" );
|
||||
for $ci (@$result) {
|
||||
if( $ci->[$CI_DATE] != $last_date || $ci->[$CI_WHO] != $last_who ){
|
||||
print WHOLOG "$ci->[$CI_DATE]|$ci->[$CI_WHO]\n";
|
||||
}
|
||||
$last_who=$ci->[$CI_WHO];
|
||||
$last_date=$ci->[$CI_DATE];
|
||||
}
|
||||
close( WHOLOG );
|
||||
}
|
||||
124
mozilla/webtools/tinderbox/bustagestats.cgi
Executable file
124
mozilla/webtools/tinderbox/bustagestats.cgi
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
require 'header.pl';
|
||||
|
||||
use Date::Parse;
|
||||
use Date::Format;
|
||||
|
||||
my $TIMEFORMAT = "%D %T";
|
||||
|
||||
$|=1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
# &load_data;
|
||||
|
||||
EmitHtmlHeader("Statistics");
|
||||
|
||||
my $tree = $form{'tree'};
|
||||
my $start = $form{'start'};
|
||||
my $end = $form{'end'};
|
||||
|
||||
sub str2timeAndCheck {
|
||||
my ($str) = (@_);
|
||||
my $result = str2time($str);
|
||||
if (defined $result && $result > 7000000) {
|
||||
return $result;
|
||||
}
|
||||
print "<p><font color=red>Can't parse as a date: $str</font><p>\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (defined $tree && defined $start && defined $end) {
|
||||
my $first = str2timeAndCheck($start);
|
||||
my $last = str2timeAndCheck($end);
|
||||
if ($first > 0 && $last > 0) {
|
||||
if (open(IN, "<$tree/build.dat")) {
|
||||
print "<hr><center><h1>Bustage stats for $tree</H1><H3>from " .
|
||||
time2str($TIMEFORMAT, $first) . " to " .
|
||||
time2str($TIMEFORMAT, $last) . "</H3></center>\n";
|
||||
my %stats;
|
||||
while (<IN>) {
|
||||
chomp;
|
||||
my ($mailtime, $buildtime, $buildname, $errorparser,
|
||||
$buildstatus, $logfile, $binaryname) =
|
||||
split( /\|/ );
|
||||
if ($buildtime >= $first && $buildtime <= $last) {
|
||||
if (!defined $stats{$buildname}) {
|
||||
$stats{$buildname} = 0;
|
||||
}
|
||||
if ($buildstatus eq "busted") {
|
||||
$stats{$buildname}++;
|
||||
}
|
||||
}
|
||||
}
|
||||
print "<table>\n";
|
||||
print "<tr><th>Build name</th><th>Number of bustages</th></tr>\n";
|
||||
foreach my $key (sort (keys %stats)) {
|
||||
print "<tr><td>$key</td><td>$stats{$key}</td></tr>\n";
|
||||
}
|
||||
print "</table>\n";
|
||||
} else {
|
||||
print "<p><font color=red>There does not appear to be a tree " .
|
||||
"named '$tree'.</font><p>";
|
||||
}
|
||||
|
||||
}
|
||||
print "<hr>\n";
|
||||
}
|
||||
|
||||
if (!defined $tree) {
|
||||
$tree = "";
|
||||
}
|
||||
|
||||
if (!defined $start) {
|
||||
$start = time2str($TIMEFORMAT, time() - 7*24*60*60); # One week ago.
|
||||
}
|
||||
|
||||
if (!defined $end) {
|
||||
$end = time2str($TIMEFORMAT, time()); # #now
|
||||
}
|
||||
|
||||
|
||||
print qq|
|
||||
<form>
|
||||
<table>
|
||||
<tr>
|
||||
<th align=right>Tree:</th>
|
||||
<td><input name=tree size=30 value="$tree"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>Start time:</th>
|
||||
<td><input name=start size=30 value="$start"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>End time:</th>
|
||||
<td><input name=end size=30 value="$end"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<INPUT TYPE=\"submit\" VALUE=\"Generate stats \">
|
||||
|
||||
</form>
|
||||
|;
|
||||
BIN
mozilla/webtools/tinderbox/channelflames.gif
Normal file
BIN
mozilla/webtools/tinderbox/channelflames.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
mozilla/webtools/tinderbox/channelok.gif
Normal file
BIN
mozilla/webtools/tinderbox/channelok.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 295 B |
42
mozilla/webtools/tinderbox/clean.pl
Executable file
42
mozilla/webtools/tinderbox/clean.pl
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Figure out which directory tinderbox is in by looking at argv[0]
|
||||
|
||||
$tinderboxdir = $0;
|
||||
$tinderboxdir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($tinderboxdir eq "") {
|
||||
$tinderboxdir = ".";
|
||||
}
|
||||
|
||||
#print "tinderbox = $tinderboxdir\n";
|
||||
|
||||
chdir $tinderboxdir || die "Couldn't chdir to $tinderboxdir";
|
||||
|
||||
#print "cd ok\n";
|
||||
|
||||
open FL, "find . -name \"*.gz\" -mtime +7 -print |";
|
||||
|
||||
#print "find ok\n";
|
||||
|
||||
while( <FL> ){
|
||||
chop();
|
||||
#print "unlink $_\n";
|
||||
unlink $_;
|
||||
}
|
||||
BIN
mozilla/webtools/tinderbox/cont.gif
Normal file
BIN
mozilla/webtools/tinderbox/cont.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 B |
91
mozilla/webtools/tinderbox/copydata.pl
Executable file
91
mozilla/webtools/tinderbox/copydata.pl
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/tools/ns/bin/perl5
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# to run this script execute 'nohup copydata.pl &' from the tinderbox directory
|
||||
#
|
||||
|
||||
$start_dir = `pwd`;
|
||||
chop($start_dir);
|
||||
$scp_cmd = "scp -o 'User snapshot' -o'Port 22' -o 'UserKnownHostsFile /u/shaver/snapshot/known_hosts' -o 'IdentityFile /u/shaver/snapshot/identity'";
|
||||
|
||||
|
||||
$last_time = 0;
|
||||
|
||||
$min_cycle_time = 3 * 60; # 3 minutes
|
||||
|
||||
print "starting dir is :$start_dir\n";
|
||||
|
||||
while( 1 ){
|
||||
chdir("$start_dir");
|
||||
if( time - $last_time < $min_cycle_time ){
|
||||
$sleep_time = $min_cycle_time - (time - $last_time);
|
||||
print "\n\nSleeping $sleep_time seconds ...\n";
|
||||
sleep( $sleep_time );
|
||||
}
|
||||
|
||||
©_data("Mozilla");
|
||||
©_data("raptor");
|
||||
|
||||
chdir( "$start_dir");
|
||||
print "$scp_cmd * cvs1.mozilla.org:/e/webtools/tinderbox\n";
|
||||
system "$scp_cmd * cvs1.mozilla.org:/e/webtools/tinderbox";
|
||||
|
||||
chdir( "$start_dir/../bonsai");
|
||||
print "$scp_cmd * cvs1.mozilla.org:/e/webtools/bonsai\n";
|
||||
system "$scp_cmd * cvs1.mozilla.org:/e/webtools/bonsai";
|
||||
|
||||
|
||||
$last_time = time;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
sub copy_data {
|
||||
local($data_dir) = @_;
|
||||
local($zips,$qry);
|
||||
|
||||
chdir $data_dir || die "couldn't chdir to $data_dir";
|
||||
|
||||
system "echo hello >lastup.new";
|
||||
|
||||
if( -r 'lastup' ) {
|
||||
$qry = '-newer lastup.old';
|
||||
rename 'lastup', 'lastup.old'
|
||||
}
|
||||
rename 'lastup.new', 'lastup';
|
||||
|
||||
|
||||
open( FINDER, "find . $qry -name \"*.gz\" -print|" );
|
||||
while(<FINDER>){
|
||||
print;
|
||||
chop;
|
||||
$zips .= "$_ ";
|
||||
}
|
||||
close( FINDER );
|
||||
|
||||
unlink 'lastup.old';
|
||||
|
||||
print "$scp_cmd *.txt $zips *.dat cvs1.mozilla.org:/e/webtools/tinderbox/$data_dir\n";
|
||||
system "$scp_cmd *.txt $zips *.dat cvs1.mozilla.org:/e/webtools/tinderbox/$data_dir";
|
||||
|
||||
|
||||
chdir $start_dir || die "couldn't chdir to $start_dir";
|
||||
}
|
||||
217
mozilla/webtools/tinderbox/doadmin.cgi
Executable file
217
mozilla/webtools/tinderbox/doadmin.cgi
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
use lib "../bonsai";
|
||||
require 'lloydcgi.pl';
|
||||
require 'globals.pl';
|
||||
|
||||
umask O666;
|
||||
|
||||
|
||||
$|=1;
|
||||
|
||||
check_password();
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
$command = $form{'command'};
|
||||
$tree= $form{'tree'};
|
||||
|
||||
if( $command eq 'create_tree' ){
|
||||
&create_tree;
|
||||
}
|
||||
elsif( $command eq 'remove_build' ){
|
||||
&remove_build;
|
||||
}
|
||||
elsif( $command eq 'trim_logs' ){
|
||||
&trim_logs;
|
||||
}
|
||||
elsif( $command eq 'set_message' ){
|
||||
&set_message;
|
||||
}
|
||||
elsif( $command eq 'disable_builds' ){
|
||||
&disable_builds;
|
||||
} else {
|
||||
print "Unknown command: \"$command\".";
|
||||
}
|
||||
|
||||
sub trim_logs {
|
||||
$days = $form{'days'};
|
||||
$tree = $form{'tree'};
|
||||
|
||||
print "<h2>Trimming Log files for $tree...</h2>\n<p>";
|
||||
|
||||
$min_date = time - (60*60*24 * $days);
|
||||
|
||||
#
|
||||
# Nuke the old log files
|
||||
#
|
||||
$i = 0;
|
||||
opendir( D, 'DogbertTip' );
|
||||
while( $fn = readdir( D ) ){
|
||||
if( $fn =~ /\.gz$/ ){
|
||||
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
|
||||
$ctime,$blksize,$blocks) = stat("$tree/$fn");
|
||||
if( $mtime && ($mtime < $min_date) ){
|
||||
print "$fn\n";
|
||||
$tblocks += $blocks;
|
||||
unlink( "$tree/$fn" );
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir( D );
|
||||
$k = $tblocks*512/1024;
|
||||
print "<br><b>$i Logfiles ( $k K bytes ) removed</b><br>\n";
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
$builds_removed = 0;
|
||||
open(BD, "<$tree/build.dat");
|
||||
open(NBD, ">$tree/build.dat.new");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$buildname) = split( /\|/ );
|
||||
if( $buildtime >= $min_date ){
|
||||
print NBD $_;
|
||||
}
|
||||
else {
|
||||
$builds_removed++;
|
||||
}
|
||||
}
|
||||
close( BD );
|
||||
close( NBD );
|
||||
|
||||
rename( "$tree/build.dat", "$tree/build.dat.old" );
|
||||
rename( "$tree/build.dat.new", "$tree/build.dat" );
|
||||
|
||||
print "<h2>$builds_removed Builds removed from build.dat</h2>\n";
|
||||
}
|
||||
|
||||
sub create_tree {
|
||||
$treename = $form{'treename'};
|
||||
my $repository = $form{'repository'};
|
||||
$modulename = $form{'modulename'};
|
||||
$branchname = $form{'branchname'};
|
||||
|
||||
if( -r $treename ){
|
||||
chmod 0777, $treename;
|
||||
}
|
||||
else {
|
||||
mkdir( $treename, 0777 ) || die "<h1> Cannot mkdir $treename</h1>";
|
||||
}
|
||||
open( F, ">$treename/treedata.pl" );
|
||||
print F "\$cvs_module='$modulename';\n";
|
||||
print F "\$cvs_branch='$branchname';\n";
|
||||
if ($repository ne "") {
|
||||
print F "\$cvs_root='$repository';\n";
|
||||
}
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/build.dat" );
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/who.dat" );
|
||||
close( F );
|
||||
|
||||
open( F, ">$treename/notes.txt" );
|
||||
close( F );
|
||||
|
||||
chmod 0777, "$treename/build.dat", "$treename/who.dat", "$treename/notes.txt",
|
||||
"$treename/treedata.pl";
|
||||
|
||||
print "<h2><a href=showbuilds.cgi?tree=$treename>Tree created or modified</a></h2>\n";
|
||||
}
|
||||
|
||||
sub remove_build {
|
||||
$build_name = $form{'build'};
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
$builds_removed = 0;
|
||||
open(BD, "<$tree/build.dat");
|
||||
open(NBD, ">$tree/build.dat.new");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$bname) = split( /\|/ );
|
||||
if( $bname ne $build_name ){
|
||||
print NBD $_;
|
||||
}
|
||||
else {
|
||||
$builds_removed++;
|
||||
}
|
||||
}
|
||||
close( BD );
|
||||
close( NBD );
|
||||
chmod( 0777, "$tree/build.dat.new");
|
||||
|
||||
rename( "$tree/build.dat", "$tree/build.dat.old" );
|
||||
rename( "$tree/build.dat.new", "$tree/build.dat" );
|
||||
|
||||
print "<h2><a href=showbuilds.cgi?tree=$tree>
|
||||
$builds_removed Builds removed from build.dat</a></h2>\n";
|
||||
}
|
||||
|
||||
sub disable_builds {
|
||||
my $i,%buildnames;
|
||||
$build_name = $form{'build'};
|
||||
|
||||
#
|
||||
# Trim build.dat
|
||||
#
|
||||
open(BD, "<$tree/build.dat");
|
||||
while( <BD> ){
|
||||
($mailtime,$buildtime,$bname) = split( /\|/ );
|
||||
$buildnames{$bname} = 0;
|
||||
}
|
||||
close( BD );
|
||||
|
||||
for $i (keys %form) {
|
||||
if ($i =~ /^build_/ ){
|
||||
$i =~ s/^build_//;
|
||||
$buildnames{$i} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
open(IGNORE, ">$tree/ignorebuilds.pl");
|
||||
print IGNORE '$ignore_builds = {' . "\n";
|
||||
for $i ( sort keys %buildnames ){
|
||||
if( $buildnames{$i} == 0 ){
|
||||
print IGNORE "\t\t'$i' => 1,\n";
|
||||
}
|
||||
}
|
||||
print IGNORE "\t};\n";
|
||||
|
||||
chmod( 0777, "$tree/ignorebuilds.pl");
|
||||
print "<h2><a href=showbuilds.cgi?tree=$treename>Build state Changed</a></h2>\n";
|
||||
}
|
||||
|
||||
|
||||
sub set_message {
|
||||
$m = $form{'message'};
|
||||
$m =~ s/\'/\\'/g;
|
||||
open(MOD, ">$tree/mod.pl");
|
||||
print MOD "\$message_of_day = \'$m\'\;\n1;";
|
||||
close(MOD);
|
||||
chmod( 0777, "$tree/mod.pl");
|
||||
print "<h2><a href=showbuilds.cgi?tree=$tree>
|
||||
Message Changed</a></h2>\n";
|
||||
}
|
||||
|
||||
45
mozilla/webtools/tinderbox/ep_mac.pl
Executable file
45
mozilla/webtools/tinderbox/ep_mac.pl
Executable file
@@ -0,0 +1,45 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ /Error / # C error
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /Couldn\'t find project file / # CW project error
|
||||
;
|
||||
}
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /^[A-Za-z0-9_]+\.[A-Za-z0-9]+\ line [0-9]+/ ;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
if( $line =~ /^(([A-Za-z0-9_]+\.[A-Za-z0-9]+) line ([0-9]+))/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
59
mozilla/webtools/tinderbox/ep_unix.pl
Executable file
59
mozilla/webtools/tinderbox/ep_unix.pl
Executable file
@@ -0,0 +1,59 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ /^C / # cvs merge conflict
|
||||
|| $line =~ / Error: / # C error
|
||||
|| $line =~ / error\([0-9]*\)\:/ # C error
|
||||
|| ($line =~ /gmake/ && $line =~ / Error /)
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /\: cannot find module/ #cvs error
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /^[A-Za-z0-9_]+\.[A-Za-z0-9]+\:[0-9]+\:/
|
||||
|| $line =~ /^\"[A-Za-z0-9_]+\.[A-Za-z0-9]+\"\, line [0-9]+\:/
|
||||
;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
if( $line =~ /^(([A-Za-z0-9_]+\.[A-Za-z0-9]+)\:([0-9]+)\:)/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
if ( $line =~ /^(\"([A-Za-z0-9_]+\.[A-Za-z0-9]+)\"\, line ([0-9]+)\:)/ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = $2;
|
||||
$error_line = $3;
|
||||
$error_guess = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
73
mozilla/webtools/tinderbox/ep_windows.pl
Executable file
73
mozilla/webtools/tinderbox/ep_windows.pl
Executable file
@@ -0,0 +1,73 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
1;
|
||||
#
|
||||
# Scan a line and see if it has an error
|
||||
#
|
||||
sub has_error {
|
||||
$line =~ /fatal error/ # link error
|
||||
|| $line =~ / error / # C error
|
||||
|| $line =~ /^C / # cvs merge conflict
|
||||
|| $line =~ /error C/ # C error
|
||||
|| $line =~ /Creating new precompiled header/ # Wastes time.
|
||||
|| $line =~ /error:/ # java error
|
||||
|| $line =~ /jmake.MakerFailedException:/ # java error
|
||||
|| $line =~ /Unknown host / # cvs error
|
||||
|| $line =~ /: build failed\;/ # nmake error
|
||||
|| ($line =~ /gmake/ && $line =~ / Error /)
|
||||
|| $line =~ /\[checkout aborted\]/ #cvs error
|
||||
|| $line =~ /\: cannot find module/ #cvs error
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
sub has_warning {
|
||||
$line =~ /: warning/ # link error
|
||||
|| $line =~ / error / # C error
|
||||
;
|
||||
}
|
||||
|
||||
sub has_errorline {
|
||||
local( $line ) = @_;
|
||||
$error_file = ''; #'NS\CMD\WINFE\CXICON.cpp';
|
||||
$error_line = 0;
|
||||
|
||||
if( $line =~ m@(ns([\\/][a-z0-9\._]+)*)@i ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = lc $error_file;
|
||||
$error_file_ref =~ s@\\@/@g;
|
||||
|
||||
$line =~ m/\(([0-9]+)\)/;
|
||||
$error_line = $1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( $line =~ m@(^([A-Za-z0-9_]+\.[A-Za-z])+\(([0-9]+)\))@ ){
|
||||
$error_file = $1;
|
||||
$error_file_ref = lc $2;
|
||||
$error_line = $3;
|
||||
$error_guess=1;
|
||||
$error_file_ref =~ s@\\@/@g;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
44
mozilla/webtools/tinderbox/examples/README
Normal file
44
mozilla/webtools/tinderbox/examples/README
Normal file
@@ -0,0 +1,44 @@
|
||||
This directory contains example Tinderbox client scripts. These scripts are
|
||||
for illustration/documentation purposes only and are not maintained
|
||||
regularly. Current scripts to build mozilla will live in an another spot
|
||||
in the mozilla tree.
|
||||
|
||||
Three examples have been provided:
|
||||
|
||||
mozilla-windows.pl: perl script that drives mozilla tinderbox builds for Win32
|
||||
mozilla-unix.pl : perl script that drives mozilla tinderbox builds for UNIX
|
||||
build-moz-smoke.pl: perl script that drives mozilla tinderbox builds for UNIX,
|
||||
and subsequently runs the executable returning a green tree only if
|
||||
it does not crash.
|
||||
|
||||
These scripts show the basic elements of a Tinderbox client script. These
|
||||
elements are:
|
||||
|
||||
1) Sending a start e-mail to the Tinderbox server, in the form of a formatted
|
||||
mail message. Example:
|
||||
|
||||
tinderbox: tree: Mozilla
|
||||
tinderbox: builddate: 900002087
|
||||
tinderbox: status: building
|
||||
tinderbox: build: IRIX 6.3 Depend
|
||||
tinderbox: errorparser: unix
|
||||
tinderbox: buildfamily: unix
|
||||
|
||||
2) Obtain a source tree by performing a cvs checkout.
|
||||
|
||||
3) Perform the build, saving the output to a log file.
|
||||
|
||||
4) Determine if the build was successful or failed. This could be done either
|
||||
by checking for the presence of a binary, or being using error codes returned
|
||||
from the compile command.
|
||||
|
||||
5) Send a completion message to Tinderbox, identifying build success or
|
||||
failure. Example:
|
||||
|
||||
tinderbox: tree: Mozilla
|
||||
tinderbox: builddate: 900002087
|
||||
tinderbox: status: success
|
||||
tinderbox: build: IRIX 6.3 Depend
|
||||
tinderbox: errorparser: unix
|
||||
tinderbox: buildfamily: unix
|
||||
|
||||
594
mozilla/webtools/tinderbox/examples/build-moz-smoke.pl
Executable file
594
mozilla/webtools/tinderbox/examples/build-moz-smoke.pl
Executable file
@@ -0,0 +1,594 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
require 5.000;
|
||||
|
||||
use Sys::Hostname;
|
||||
use POSIX "sys_wait_h";
|
||||
use Cwd;
|
||||
|
||||
$Version = "1.000";
|
||||
|
||||
sub InitVars {
|
||||
|
||||
# PLEASE FILL THIS IN WITH YOUR PROPER EMAIL ADDRESS
|
||||
$BuildAdministrator = "$ENV{'USER'}\@$ENV{'HOST'}";
|
||||
|
||||
#Default values of cmdline opts
|
||||
$BuildDepend = 1; #depend or clobber
|
||||
$ReportStatus = 1; # Send results to server or not
|
||||
$BuildOnce = 0; # Build once, don't send results to server
|
||||
$BuildClassic = 0; # Build classic source
|
||||
|
||||
#relative path to binary
|
||||
$BinaryName{'x'} = 'mozilla-export';
|
||||
$BinaryName{'qt'} = 'qtmozilla-export';
|
||||
$BinaryName{'gnome'} = 'gnuzilla-export';
|
||||
$BinaryName{'webshell'} = '/webshell/tests/viewer/viewer';
|
||||
|
||||
# Set these to what makes sense for your system
|
||||
$cpus = 1;
|
||||
$Make = 'gmake'; # Must be gnu make
|
||||
$mail = '/bin/mail';
|
||||
$Autoconf = 'autoconf -l build/autoconf';
|
||||
$CVS = 'cvs -z3';
|
||||
$CVSCO = 'co -P';
|
||||
|
||||
# Set these proper values for your tinderbox server
|
||||
$Tinderbox_server = 'tinderbox-daemon\@cvs-mirror.mozilla.org';
|
||||
#$Tinderbox_server = 'external-tinderbox-incoming\@tinderbox.seawood.org';
|
||||
|
||||
# These shouldn't really need to be changed
|
||||
$BuildSleep = 10; # Minimum wait period from start of build to start
|
||||
# of next build in minutes
|
||||
$BuildTree = 'SeaMonkey';
|
||||
$BuildTag = '';
|
||||
$BuildName = '';
|
||||
$TopLevel = '.';
|
||||
$Topsrcdir = 'mozilla';
|
||||
$BuildObjName = '';
|
||||
$BuildConfigDir = 'mozilla/config';
|
||||
$ClobberStr = 'realclean';
|
||||
$ConfigureEnvArgs = 'CFLAGS=-pipe CXXFLAGS=-pipe';
|
||||
#$ConfigureEnvArgs = '';
|
||||
$ConfigureArgs = "--with-nspr=/usr/local/nspr --cache-file=/dev/null --with-static-gtk --enable-editor";
|
||||
$ConfigGuess = './build/autoconf/config.guess';
|
||||
$Logfile = '${BuildDir}.log';
|
||||
} #EndSub-InitVars
|
||||
|
||||
sub ConditionalArgs {
|
||||
if ( $BuildClassic ) {
|
||||
$FE = 'x';
|
||||
$ConfigureArgs .= " --enable-fe=$FE";
|
||||
# $BuildTree = 'raptor';
|
||||
$BuildModule = 'Raptor';
|
||||
$BuildTag = ''
|
||||
if ($BuildTag eq '');
|
||||
$TopLevel = "mozilla-classic";
|
||||
} else {
|
||||
# $BuildTree = 'raptor';
|
||||
# $Toolkit = 'gtk';
|
||||
$FE = 'webshell';
|
||||
# $BuildModule = 'Raptor';
|
||||
$BuildModule = 'SeaMonkeyAll';
|
||||
# $ConfigureArgs .= " --enable-toolkit=$Toolkit";
|
||||
}
|
||||
$CVSCO .= " -r $BuildTag" if ( $BuildTag ne '');
|
||||
}
|
||||
sub SetupEnv {
|
||||
umask(0);
|
||||
$ENV{"CVSROOT"} = ':pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot';
|
||||
$ENV{"LD_LIBRARY_PATH"} = '/usr/local/nspr:/builds/tinderbox/SeaMonkey/Linux_2.0.34_clobber/mozilla/obj-i586-pc-linux-gnu/dist/bin:/usr/lib/png:/usr/local/lib';
|
||||
$ENV{"DISPLAY"} = 'crucible.mcom.com:0.0';
|
||||
} #EndSub-SetupEnv
|
||||
|
||||
sub SetupPath {
|
||||
my($Path);
|
||||
$Path = $ENV{PATH};
|
||||
print "Path before: $Path\n";
|
||||
|
||||
if ( $OS eq 'SunOS' ) {
|
||||
$ENV{'PATH'} = '/usr/ccs/bin:' . $ENV{'PATH'};
|
||||
}
|
||||
|
||||
$Path = $ENV{PATH};
|
||||
print "Path After: $Path\n";
|
||||
} #EndSub-SetupPath
|
||||
|
||||
##########################################################################
|
||||
# NO USER CONFIGURABLE PIECES BEYOND THIS POINT #
|
||||
##########################################################################
|
||||
|
||||
sub GetSystemInfo {
|
||||
|
||||
$OS = `uname -s`;
|
||||
$OSVer = `uname -r`;
|
||||
|
||||
chop($OS, $OSVer);
|
||||
|
||||
if ( $OS eq 'AIX' ) {
|
||||
$OSVer = `uname -v`;
|
||||
chop($OSVer);
|
||||
$OSVer = $OSVer . "." . `uname -r`;
|
||||
chop($OSVer);
|
||||
}
|
||||
|
||||
if ( $OS eq 'IRIX64' ) {
|
||||
$OS = 'IRIX';
|
||||
}
|
||||
|
||||
if ( $OS eq 'SCO_SV' ) {
|
||||
$OS = 'SCOOS';
|
||||
$OSVer = '5.0';
|
||||
}
|
||||
|
||||
my $host, $myhost = hostname;
|
||||
chomp($myhost);
|
||||
($host, $junk) = split(/\./, $myhost);
|
||||
|
||||
$BuildName = "";
|
||||
|
||||
if ( "$host" ne "" ) {
|
||||
$BuildName = $host . ' ';
|
||||
}
|
||||
$BuildName .= $OS . ' ' . $OSVer . ' ' . ($BuildDepend?'Depend':'Clobber');
|
||||
$DirName = $OS . '_' . $OSVer . '_' . ($BuildDepend?'depend':'clobber');
|
||||
|
||||
$RealOS = $OS;
|
||||
$RealOSVer = $OSVer;
|
||||
|
||||
if ( $OS eq 'HP-UX' ) {
|
||||
$RealOSVer = substr($OSVer,0,4);
|
||||
}
|
||||
|
||||
if ( $OS eq 'Linux' ) {
|
||||
$RealOSVer = substr($OSVer,0,3);
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
$logfile = "${DirName}-classic.log";
|
||||
} else {
|
||||
$logfile = "${DirName}.log";
|
||||
}
|
||||
} #EndSub-GetSystemInfo
|
||||
|
||||
sub BuildIt {
|
||||
my ($fe, @felist, $EarlyExit, $LastTime, $StartTimeStr);
|
||||
|
||||
mkdir("$DirName", 0777);
|
||||
chdir("$DirName") || die "Couldn't enter $DirName";
|
||||
|
||||
$StartDir = getcwd();
|
||||
$LastTime = 0;
|
||||
|
||||
print "Starting dir is : $StartDir\n";
|
||||
|
||||
$EarlyExit = 0;
|
||||
|
||||
while ( ! $EarlyExit ) {
|
||||
chdir("$StartDir");
|
||||
if ( time - $LastTime < (60 * $BuildSleep) ) {
|
||||
$SleepTime = (60 * $BuildSleep) - (time - $LastTime);
|
||||
print "\n\nSleeping $SleepTime seconds ...\n";
|
||||
sleep($SleepTime);
|
||||
}
|
||||
|
||||
$LastTime = time;
|
||||
|
||||
$StartTime = time - 60 * 10;
|
||||
$StartTimeStr = &CVSTime($StartTime);
|
||||
|
||||
&StartBuild if ($ReportStatus);
|
||||
$CurrentDir = getcwd();
|
||||
if ( $CurrentDir ne $StartDir ) {
|
||||
print "startdir: $StartDir, curdir $CurrentDir\n";
|
||||
die "curdir != startdir";
|
||||
}
|
||||
|
||||
$BuildDir = $CurrentDir;
|
||||
|
||||
unlink( "$logfile" );
|
||||
|
||||
print "opening $logfile\n";
|
||||
open( LOG, ">$logfile" ) || print "can't open $?\n";
|
||||
print LOG "current dir is -- $hostname:$CurrentDir\n";
|
||||
print LOG "Build Administrator is $BuildAdministrator\n";
|
||||
&PrintEnv;
|
||||
|
||||
$BuildStatus = 0;
|
||||
|
||||
mkdir($TopLevel, 0777);
|
||||
chdir($TopLevel) || die "chdir($TopLevel): $!\n";
|
||||
|
||||
if ( $BuildClassic ) {
|
||||
print"$CVS $CVSCO $BuildModule\n";
|
||||
print LOG "$CVS $CVSCO $BuildModule\n";
|
||||
open (PULL, "$CVS $CVSCO $BuildModule 2>&1 |") || die "open: $!\n";
|
||||
} else {
|
||||
# print "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# print LOG "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# open (PULL, "$CVS $CVSCO mozilla/nglayout.mk 2>&1 |") || die "open: $!\n";
|
||||
print "$CVS $CVSCO mozilla/client.mk\n";
|
||||
print LOG "$CVS $CVSCO mozilla/client.mk\n";
|
||||
open (PULL, "$CVS $CVSCO mozilla/client.mk 2>&1 |") || die "open: $!\n";
|
||||
}
|
||||
while (<PULL>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(PULL);
|
||||
|
||||
# Move to topsrcdir
|
||||
#chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
|
||||
# Do a separate checkout with toplevel makefile
|
||||
if (! $BuildClassic) {
|
||||
# print LOG "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO'|\n";
|
||||
# open (PULLALL, "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO' |\n");
|
||||
print LOG "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO'|\n";
|
||||
open (PULLALL, "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO' |\n");
|
||||
while (<PULLALL>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(PULLALL);
|
||||
}
|
||||
|
||||
chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
print LOG "$Autoconf\n";
|
||||
open (AUTOCONF, "$Autoconf 2>&1 | ") || die "$Autoconf: $!\n";
|
||||
while (<AUTOCONF>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(AUTOCONF);
|
||||
|
||||
print LOG "$ConfigGuess\n";
|
||||
$BuildObjName = "obj-";
|
||||
open (GETOBJ, "$ConfigGuess 2>&1 |") || die "$ConfigGuess: $!\n";
|
||||
while (<GETOBJ>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
chomp($BuildObjName .= $_);
|
||||
}
|
||||
close (GETOBJ);
|
||||
|
||||
mkdir($BuildObjName, 0777);
|
||||
chdir($BuildObjName) || die "chdir($BuildObjName): $!\n";
|
||||
|
||||
print LOG "$ConfigureEnvArgs ../configure $ConfigureArgs\n";
|
||||
open (CONFIGURE, "$ConfigureEnvArgs ../configure $ConfigureArgs 2>&1 |") || die "../configure: $!\n";
|
||||
while (<CONFIGURE>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(CONFIGURE);
|
||||
|
||||
# if we are building depend, rebuild dependencies
|
||||
|
||||
if ($BuildDepend) {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n";
|
||||
open ( MAKEDEPEND, "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n");
|
||||
while ( <MAKEDEPEND> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close (MAKEDEPEND);
|
||||
system("rm -rf dist");
|
||||
|
||||
} else {
|
||||
# Building clobber
|
||||
print LOG "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |\n";
|
||||
open( MAKECLOBBER, "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |");
|
||||
while ( <MAKECLOBBER> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( MAKECLOBBER );
|
||||
}
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "deleting existing binary\n";
|
||||
&DeleteBinary($fe);
|
||||
}
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
# Build the BE only
|
||||
print LOG "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |\n";
|
||||
open( BEBUILD, "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |");
|
||||
|
||||
while ( <BEBUILD> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( BEBUILD );
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
# Now build each front end
|
||||
print LOG "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n";
|
||||
open(FEBUILD, "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n");
|
||||
while (<FEBUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(FEBUILD);
|
||||
}
|
||||
} else {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' 2>&1 |\n";
|
||||
open(BUILD, "$Make MAKE='$Make -j $cpus' 2>&1 |\n");
|
||||
while (<BUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(BUILD);
|
||||
}
|
||||
|
||||
foreach $fe (@felist) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "export binary exists, build successful. Testing...\n";
|
||||
#return 0 if no problem, else 333 for a runtime error
|
||||
$BuildStatus = &RunSmokeTest($fe);
|
||||
}
|
||||
else {
|
||||
print LOG "export binary missing, build FAILED\n";
|
||||
$BuildStatus = 666;
|
||||
}
|
||||
|
||||
if ( $BuildStatus == 0 ) {
|
||||
$BuildStatusStr = 'success';
|
||||
}
|
||||
elsif ( $BuildStatus == 333 ) {
|
||||
$BuildStatusStr = 'testfailed';
|
||||
}
|
||||
else {
|
||||
$BuildStatusStr = 'busted';
|
||||
}
|
||||
# replaced by above lines
|
||||
# $BuildStatusStr = ( $BuildStatus ? 'busted' : 'success' );
|
||||
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: $BuildStatusStr\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
}
|
||||
close(LOG);
|
||||
chdir("$StartDir");
|
||||
|
||||
# this fun line added on 2/5/98. do not remove. Translated to english,
|
||||
# that's "take any line longer than 1000 characters, and split it into less
|
||||
# than 1000 char lines. If any of the resulting lines is
|
||||
# a dot on a line by itself, replace that with a blank line."
|
||||
# This is to prevent cases where a <cr>.<cr> occurs in the log file. Sendmail
|
||||
# interprets that as the end of the mail, and truncates the log before
|
||||
# it gets to Tinderbox. (terry weismann, chris yeh)
|
||||
#
|
||||
# This was replaced by a perl 'port' of the above, writen by
|
||||
# preed@netscape.com; good things: no need for system() call, and now it's
|
||||
# all in perl, so we don't have to do OS checking like before.
|
||||
|
||||
open(LOG, "$logfile") || die "Couldn't open logfile: $!\n";
|
||||
open(OUTLOG, ">${logfile}.last") || die "Couldn't open logfile: $!\n";
|
||||
|
||||
while (<LOG>) {
|
||||
$q = 0;
|
||||
|
||||
for (;;) {
|
||||
$val = $q * 1000;
|
||||
$Output = substr($_, $val, 1000);
|
||||
|
||||
last if $Output eq undef;
|
||||
|
||||
$Output =~ s/^\.$//g;
|
||||
$Output =~ s/\n//g;
|
||||
print OUTLOG "$Output\n";
|
||||
$q++;
|
||||
} #EndFor
|
||||
|
||||
} #EndWhile
|
||||
|
||||
close(LOG);
|
||||
close(OUTLOG);
|
||||
|
||||
system( "$mail $Tinderbox_server < ${logfile}.last" )
|
||||
if ($ReportStatus );
|
||||
unlink("$logfile");
|
||||
|
||||
# if this is a test run, set early_exit to 0.
|
||||
#This mean one loop of execution
|
||||
$EarlyExit++ if ($BuildOnce);
|
||||
}
|
||||
|
||||
} #EndSub-BuildIt
|
||||
|
||||
sub CVSTime {
|
||||
my($StartTimeArg) = @_;
|
||||
my($RetTime, $StartTimeArg, $sec, $minute, $hour, $mday, $mon, $year);
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime($StartTimeArg);
|
||||
$mon++; # month is 0 based.
|
||||
|
||||
sprintf("%02d/%02d/%02d %02d:%02d:00", $mon,$mday,$year,$hour,$minute );
|
||||
}
|
||||
|
||||
sub StartBuild {
|
||||
|
||||
my($fe, @felist);
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
# die "SERVER: " . $Tinderbox_server . "\n";
|
||||
open( LOG, "|$mail $Tinderbox_server" );
|
||||
foreach $fe ( @felist ) {
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
print LOG "\n";
|
||||
}
|
||||
close( LOG );
|
||||
}
|
||||
|
||||
# check for the existence of the binary
|
||||
sub BinaryExists {
|
||||
my($fe) = @_;
|
||||
my($Binname);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/'. $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG $BinName . "\n";
|
||||
if ((-e $BinName) && (-x $BinName) && (-s $BinName)) {
|
||||
1;
|
||||
}
|
||||
else {
|
||||
0;
|
||||
}
|
||||
}
|
||||
|
||||
sub DeleteBinary {
|
||||
my($fe) = @_;
|
||||
my($BinName);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG "unlinking $BinName\n";
|
||||
unlink ($BinName) || print LOG "unlinking $BinName failed\n";
|
||||
}
|
||||
|
||||
sub ParseArgs {
|
||||
my($i, $manArg);
|
||||
|
||||
if( @ARGV == 0 ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
$i = 0;
|
||||
$manArg = 0;
|
||||
while( $i < @ARGV ) {
|
||||
if ($ARGV[$i] eq '--depend') {
|
||||
$BuildDepend = 1;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--clobber') {
|
||||
$BuildDepend = 0;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--once' ) {
|
||||
$BuildOnce = 1;
|
||||
#$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--classic') {
|
||||
$BuildClassic = 1;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--noreport') {
|
||||
$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--version' || $ARGV[$i] eq '-v') {
|
||||
die "$0: version $Version\n";
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-tag' ) {
|
||||
$i++;
|
||||
$BuildTag = $ARGV[$i];
|
||||
if ( $BuildTag eq '' || $BuildTag eq '-t') {
|
||||
&PrintUsage;
|
||||
}
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-t' ) {
|
||||
$i++;
|
||||
$BuildTree = $ARGV[$i];
|
||||
if ( $BuildTree eq '' ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
} else {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
$i++;
|
||||
} #EndWhile
|
||||
|
||||
if ( $BuildTree =~ /^\s+$/i ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
if ($BuildDepend eq undef) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
&PrintUsage if (! $manArg );
|
||||
|
||||
} #EndSub-ParseArgs
|
||||
|
||||
sub PrintUsage {
|
||||
die "usage: $0 [--depend | --clobber] [-v | --version ] [--once --classic --noreport -tag TREETAG -t TREENAME ]\n";
|
||||
}
|
||||
|
||||
sub PrintEnv {
|
||||
my ($key);
|
||||
foreach $key (keys %ENV) {
|
||||
print LOG "$key = $ENV{$key}\n";
|
||||
print "$key = $ENV{$key}\n";
|
||||
}
|
||||
} #EndSub-PrintEnv
|
||||
|
||||
sub RunSmokeTest {
|
||||
my($fe) = @_;
|
||||
my($Binary);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
$Binary = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
print LOG $BinName . "\n";
|
||||
|
||||
$waittime = 30;
|
||||
|
||||
$pid = fork;
|
||||
|
||||
exec $Binary if !$pid;
|
||||
|
||||
# parent - wait $waittime seconds then check on child
|
||||
sleep $waittime;
|
||||
$status = waitpid $pid, WNOHANG();
|
||||
if ($status != 0) {
|
||||
print LOG "$BinName has crashed or quit. Turn the tree orange now.\n";
|
||||
return 333;
|
||||
}
|
||||
|
||||
print LOG "Success! $BinName is still running. Killing..\n";
|
||||
# try to kill 3 times, then try a kill -9
|
||||
for ($i=0 ; $i<3 ; $i++) {
|
||||
kill 'TERM',$pid,;
|
||||
# give it 3 seconds to actually die
|
||||
sleep 3;
|
||||
$status = waitpid $pid, WNOHANG();
|
||||
last if ($status != 0);
|
||||
}
|
||||
return 0;
|
||||
} #EndSub-RunSmokeTest
|
||||
|
||||
# Main function
|
||||
&InitVars;
|
||||
&ParseArgs;
|
||||
&ConditionalArgs;
|
||||
&GetSystemInfo;
|
||||
&SetupEnv;
|
||||
&SetupPath;
|
||||
&BuildIt;
|
||||
|
||||
1;
|
||||
63
mozilla/webtools/tinderbox/examples/buildit.config
Executable file
63
mozilla/webtools/tinderbox/examples/buildit.config
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
sub InitVars {
|
||||
|
||||
#initialize variables
|
||||
#$binary_name = '/netscape-export';
|
||||
$BinaryName = '/mozilla-export';
|
||||
$BuildDepend = 1; #depend or clobber
|
||||
$BuildTree = '';
|
||||
$BuildTag = '';
|
||||
$BuildName = '';
|
||||
#$BuildContinue = 0;
|
||||
$TopLevel = 'mozilla/';
|
||||
$BuildObjName = '';
|
||||
$BuildSleep = 10;
|
||||
$BuildUnixclasses = 0;
|
||||
$EarlyExit = 1;
|
||||
$BuildStartDir = 'ns/';
|
||||
$BuildConfigDir = 'mozilla/config';
|
||||
|
||||
} #EndSub-InitVars
|
||||
|
||||
sub SetupEnv {
|
||||
|
||||
umask(0);
|
||||
$ENV{'MOZILLA_CLIENT'} = 1;
|
||||
$ENV{'NETSCAPE_HIERARCHY'} = 1;
|
||||
$ENV{'BUILD_OFFICIAL'} = 1;
|
||||
$ENV{'NSPR20'} = 1;
|
||||
$ENV{'AWT_11'} = 1;
|
||||
$ENV{'MOZ_SECURITY'} = 1;
|
||||
$ENV{"CVSROOT"} = '/m/src';
|
||||
$ENV{"MAKE"} = 'gmake -e';
|
||||
$ENV{'MOZ_MEDIUM'} = 1;
|
||||
$ENV{'NO_MDUPDATE'} = 1;
|
||||
$ENV{'EDITOR'} = 1;
|
||||
|
||||
} #EndSub-SetupEnv
|
||||
|
||||
sub SetupPath {
|
||||
|
||||
my($Path);
|
||||
$Path = $ENV{PATH};
|
||||
print "Path before: $Path\n";
|
||||
$ENV{'PATH'} = '/tools/ns/bin:/tools/contrib/bin:/usr/local/bin:/usr/sbin:/usr/bsd:/sbin:/usr/bin:/bin:/usr/bin/X11:/usr/etc:/usr/hosts:/usr/ucb:';
|
||||
|
||||
# This won't work on x86 or sunos4 systems....
|
||||
if ( $OS eq 'SunOS' ) {
|
||||
$ENV{'PATH'} = '/usr/ccs/bin:/tools/ns/soft/gcc-2.6.3/run/default/sparc_sun_solaris2.4/bin:' . $ENV{'PATH'};
|
||||
$ENV{'NO_MDUPDATE'} = 1;
|
||||
}
|
||||
|
||||
if ( $OS eq 'AIX' ) {
|
||||
$ENV{'PATH'} = $ENV{'PATH'} . '/usr/lpp/xlC/bin:/usr/local-aix/bin:';
|
||||
}
|
||||
|
||||
$Path = $ENV{PATH};
|
||||
print "Path After: $Path\n";
|
||||
|
||||
} #EndSub-SetupPath
|
||||
|
||||
|
||||
1;
|
||||
548
mozilla/webtools/tinderbox/examples/mozilla-unix.pl
Executable file
548
mozilla/webtools/tinderbox/examples/mozilla-unix.pl
Executable file
@@ -0,0 +1,548 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
require 5.000;
|
||||
|
||||
use Sys::Hostname;
|
||||
use Cwd;
|
||||
|
||||
$Version = "1.000";
|
||||
|
||||
sub InitVars {
|
||||
|
||||
# PLEASE FILL THIS IN WITH YOUR PROPER EMAIL ADDRESS
|
||||
$BuildAdministrator = "$ENV{'USER'}\@$ENV{'HOST'}";
|
||||
|
||||
#Default values of cmdline opts
|
||||
$BuildDepend = 1; #depend or clobber
|
||||
$ReportStatus = 1; # Send results to server or not
|
||||
$BuildOnce = 0; # Build once, don't send results to server
|
||||
$BuildClassic = 0; # Build classic source
|
||||
|
||||
#relative path to binary
|
||||
$BinaryName{'x'} = 'mozilla-export';
|
||||
$BinaryName{'qt'} = 'qtmozilla-export';
|
||||
$BinaryName{'gnome'} = 'gnuzilla-export';
|
||||
$BinaryName{'webshell'} = '/webshell/tests/viewer/viewer';
|
||||
$BinaryName{'xpfe'} = '/xpfe/xpviewer/src/xpviewer';
|
||||
|
||||
# Set these to what makes sense for your system
|
||||
$cpus = 1;
|
||||
$Make = 'gmake'; # Must be gnu make
|
||||
$mail = '/bin/mail';
|
||||
$Autoconf = 'autoconf -l build/autoconf';
|
||||
$CVS = 'cvs -z3';
|
||||
$CVSCO = 'co -P';
|
||||
|
||||
# Set these proper values for your tinderbox server
|
||||
$Tinderbox_server = 'tinderbox-daemon\@warp.mcom.com';
|
||||
#$Tinderbox_server = 'external-tinderbox-incoming\@tinderbox.seawood.org';
|
||||
|
||||
# These shouldn't really need to be changed
|
||||
$BuildSleep = 10; # Minimum wait period from start of build to start
|
||||
# of next build in minutes
|
||||
$BuildTree = 'raptor';
|
||||
$BuildTag = '';
|
||||
$BuildName = '';
|
||||
$TopLevel = '.';
|
||||
$Topsrcdir = 'mozilla';
|
||||
$BuildObjName = '';
|
||||
$BuildConfigDir = 'mozilla/config';
|
||||
$ClobberStr = 'realclean';
|
||||
$ConfigureEnvArgs = 'CFLAGS=-pipe CXXFLAGS=-pipe';
|
||||
#$ConfigureEnvArgs = '';
|
||||
$ConfigureArgs = "--cache-file=/dev/null";
|
||||
$ConfigGuess = './build/autoconf/config.guess';
|
||||
$Logfile = '${BuildDir}.log';
|
||||
} #EndSub-InitVars
|
||||
|
||||
sub ConditionalArgs {
|
||||
if ( $BuildClassic ) {
|
||||
$FE = 'x';
|
||||
$ConfigureArgs .= " --enable-fe=$FE";
|
||||
$BuildTree = 'raptor';
|
||||
$BuildModule = 'Raptor';
|
||||
$BuildTag = ''
|
||||
if ($BuildTag eq '');
|
||||
$TopLevel = "mozilla-classic";
|
||||
} else {
|
||||
$BuildTree = 'raptor';
|
||||
# $Toolkit = 'gtk';
|
||||
$FE = 'webshell,xpfe';
|
||||
$BuildModule = 'Raptor';
|
||||
# $ConfigureArgs .= " --enable-toolkit=$Toolkit";
|
||||
}
|
||||
$CVSCO .= " -r $BuildTag" if ( $BuildTag ne '');
|
||||
}
|
||||
sub SetupEnv {
|
||||
umask(0);
|
||||
$ENV{"CVSROOT"} = ':pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot';
|
||||
} #EndSub-SetupEnv
|
||||
|
||||
sub SetupPath {
|
||||
my($Path);
|
||||
$Path = $ENV{PATH};
|
||||
print "Path before: $Path\n";
|
||||
|
||||
if ( $OS eq 'SunOS' ) {
|
||||
$ENV{'PATH'} = '/usr/ccs/bin:' . $ENV{'PATH'};
|
||||
}
|
||||
|
||||
$Path = $ENV{PATH};
|
||||
print "Path After: $Path\n";
|
||||
} #EndSub-SetupPath
|
||||
|
||||
##########################################################################
|
||||
# NO USER CONFIGURABLE PIECES BEYOND THIS POINT #
|
||||
##########################################################################
|
||||
|
||||
sub GetSystemInfo {
|
||||
|
||||
$OS = `uname -s`;
|
||||
$OSVer = `uname -r`;
|
||||
|
||||
chop($OS, $OSVer);
|
||||
|
||||
if ( $OS eq 'AIX' ) {
|
||||
$OSVer = `uname -v`;
|
||||
chop($OSVer);
|
||||
$OSVer = $OSVer . "." . `uname -r`;
|
||||
chop($OSVer);
|
||||
}
|
||||
|
||||
if ( $OS eq 'IRIX64' ) {
|
||||
$OS = 'IRIX';
|
||||
}
|
||||
|
||||
if ( $OS eq 'SCO_SV' ) {
|
||||
$OS = 'SCOOS';
|
||||
$OSVer = '5.0';
|
||||
}
|
||||
|
||||
my $host, $myhost = hostname;
|
||||
chomp($myhost);
|
||||
($host, $junk) = split(/\./, $myhost);
|
||||
|
||||
$BuildName = "";
|
||||
|
||||
if ( "$host" ne "" ) {
|
||||
$BuildName = $host . ' ';
|
||||
}
|
||||
$BuildName .= $OS . ' ' . $OSVer . ' ' . ($BuildDepend?'Depend':'Clobber');
|
||||
$DirName = $OS . '_' . $OSVer . '_' . ($BuildDepend?'depend':'clobber');
|
||||
|
||||
$RealOS = $OS;
|
||||
$RealOSVer = $OSVer;
|
||||
|
||||
if ( $OS eq 'HP-UX' ) {
|
||||
$RealOSVer = substr($OSVer,0,4);
|
||||
}
|
||||
|
||||
if ( $OS eq 'Linux' ) {
|
||||
$RealOSVer = substr($OSVer,0,3);
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
$logfile = "${DirName}-classic.log";
|
||||
} else {
|
||||
$logfile = "${DirName}.log";
|
||||
}
|
||||
} #EndSub-GetSystemInfo
|
||||
|
||||
sub BuildIt {
|
||||
my ($fe, @felist, $EarlyExit, $LastTime, $StartTimeStr);
|
||||
|
||||
mkdir("$DirName", 0777);
|
||||
chdir("$DirName") || die "Couldn't enter $DirName";
|
||||
|
||||
$StartDir = getcwd();
|
||||
$LastTime = 0;
|
||||
|
||||
print "Starting dir is : $StartDir\n";
|
||||
|
||||
$EarlyExit = 0;
|
||||
|
||||
while ( ! $EarlyExit ) {
|
||||
chdir("$StartDir");
|
||||
if ( time - $LastTime < (60 * $BuildSleep) ) {
|
||||
$SleepTime = (60 * $BuildSleep) - (time - $LastTime);
|
||||
print "\n\nSleeping $SleepTime seconds ...\n";
|
||||
sleep($SleepTime);
|
||||
}
|
||||
|
||||
$LastTime = time;
|
||||
|
||||
$StartTime = time - 60 * 10;
|
||||
$StartTimeStr = &CVSTime($StartTime);
|
||||
|
||||
&StartBuild if ($ReportStatus);
|
||||
$CurrentDir = getcwd();
|
||||
if ( $CurrentDir ne $StartDir ) {
|
||||
print "startdir: $StartDir, curdir $CurrentDir\n";
|
||||
die "curdir != startdir";
|
||||
}
|
||||
|
||||
$BuildDir = $CurrentDir;
|
||||
|
||||
unlink( "$logfile" );
|
||||
|
||||
print "opening $logfile\n";
|
||||
open( LOG, ">$logfile" ) || print "can't open $?\n";
|
||||
print LOG "current dir is -- $hostname:$CurrentDir\n";
|
||||
print LOG "Build Administrator is $BuildAdministrator\n";
|
||||
&PrintEnv;
|
||||
|
||||
$BuildStatus = 0;
|
||||
|
||||
mkdir($TopLevel, 0777);
|
||||
chdir($TopLevel) || die "chdir($TopLevel): $!\n";
|
||||
|
||||
if ( $BuildClassic ) {
|
||||
print"$CVS $CVSCO $BuildModule\n";
|
||||
print LOG "$CVS $CVSCO $BuildModule\n";
|
||||
open (PULL, "$CVS $CVSCO $BuildModule 2>&1 |") || die "open: $!\n";
|
||||
} else {
|
||||
# print "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# print LOG "$CVS $CVSCO mozilla/nglayout.mk\n";
|
||||
# open (PULL, "$CVS $CVSCO mozilla/nglayout.mk 2>&1 |") || die "open: $!\n";
|
||||
print "$CVS $CVSCO mozilla/client.mk\n";
|
||||
print LOG "$CVS $CVSCO mozilla/client.mk\n";
|
||||
open (PULL, "$CVS $CVSCO mozilla/client.mk 2>&1 |") || die "open: $!\n";
|
||||
}
|
||||
while (<PULL>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(PULL);
|
||||
|
||||
# Move to topsrcdir
|
||||
#chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
|
||||
# Do a separate checkout with toplevel makefile
|
||||
if (! $BuildClassic) {
|
||||
# print LOG "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO'|\n";
|
||||
# open (PULLALL, "$Make -f nglayout.mk pull_all CVSCO='$CVS $CVSCO' |\n");
|
||||
print LOG "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO'|\n";
|
||||
open (PULLALL, "$Make -f mozilla/client.mk checkout CVSCO='$CVS $CVSCO' |\n");
|
||||
while (<PULLALL>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(PULLALL);
|
||||
}
|
||||
|
||||
chdir($Topsrcdir) || die "chdir($Topsrcdir): $!\n";
|
||||
|
||||
print LOG "$Autoconf\n";
|
||||
open (AUTOCONF, "$Autoconf 2>&1 | ") || die "$Autoconf: $!\n";
|
||||
while (<AUTOCONF>) {
|
||||
print LOG $_;
|
||||
print $_;
|
||||
}
|
||||
close(AUTOCONF);
|
||||
|
||||
print LOG "$ConfigGuess\n";
|
||||
$BuildObjName = "obj-";
|
||||
open (GETOBJ, "$ConfigGuess 2>&1 |") || die "$ConfigGuess: $!\n";
|
||||
while (<GETOBJ>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
chomp($BuildObjName .= $_);
|
||||
}
|
||||
close (GETOBJ);
|
||||
|
||||
mkdir($BuildObjName, 0777);
|
||||
chdir($BuildObjName) || die "chdir($BuildObjName): $!\n";
|
||||
|
||||
print LOG "$ConfigureEnvArgs ../configure $ConfigureArgs\n";
|
||||
open (CONFIGURE, "$ConfigureEnvArgs ../configure $ConfigureArgs 2>&1 |") || die "../configure: $!\n";
|
||||
while (<CONFIGURE>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(CONFIGURE);
|
||||
|
||||
# if we are building depend, rebuild dependencies
|
||||
|
||||
if ($BuildDepend) {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n";
|
||||
open ( MAKEDEPEND, "$Make MAKE='$Make -j $cpus' depend 2>&1 |\n");
|
||||
while ( <MAKEDEPEND> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close (MAKEDEPEND);
|
||||
system("rm -rf dist");
|
||||
|
||||
} else {
|
||||
# Building clobber
|
||||
print LOG "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |\n";
|
||||
open( MAKECLOBBER, "$Make MAKE='$Make -j $cpus' $ClobberStr 2>&1 |");
|
||||
while ( <MAKECLOBBER> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( MAKECLOBBER );
|
||||
}
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "deleting existing binary\n";
|
||||
&DeleteBinary($fe);
|
||||
}
|
||||
}
|
||||
|
||||
if ($BuildClassic) {
|
||||
# Build the BE only
|
||||
print LOG "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |\n";
|
||||
open( BEBUILD, "$Make MAKE='$Make -j $cpus' MOZ_FE= 2>&1 |");
|
||||
|
||||
while ( <BEBUILD> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( BEBUILD );
|
||||
|
||||
foreach $fe ( @felist ) {
|
||||
# Now build each front end
|
||||
print LOG "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n";
|
||||
open(FEBUILD, "$Make MAKE='$Make -j $cpus' -C cmd/${fe}fe 2>&1 |\n");
|
||||
while (<FEBUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(FEBUILD);
|
||||
}
|
||||
} else {
|
||||
print LOG "$Make MAKE='$Make -j $cpus' 2>&1 |\n";
|
||||
open(BUILD, "$Make MAKE='$Make -j $cpus' 2>&1 |\n");
|
||||
while (<BUILD>) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close(BUILD);
|
||||
}
|
||||
|
||||
foreach $fe (@felist) {
|
||||
if (&BinaryExists($fe)) {
|
||||
print LOG "export binary exists, build SUCCESSFUL!\n";
|
||||
$BuildStatus = 0;
|
||||
}
|
||||
else {
|
||||
print LOG "export binary missing, build FAILED\n";
|
||||
$BuildStatus = 666;
|
||||
}
|
||||
|
||||
print LOG "\nBuild Status = $BuildStatus\n";
|
||||
|
||||
$BuildStatusStr = ( $BuildStatus ? 'busted' : 'success' );
|
||||
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: $BuildStatusStr\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
}
|
||||
close(LOG);
|
||||
chdir("$StartDir");
|
||||
|
||||
# this fun line added on 2/5/98. do not remove. Translated to english,
|
||||
# that's "take any line longer than 1000 characters, and split it into less
|
||||
# than 1000 char lines. If any of the resulting lines is
|
||||
# a dot on a line by itself, replace that with a blank line."
|
||||
# This is to prevent cases where a <cr>.<cr> occurs in the log file. Sendmail
|
||||
# interprets that as the end of the mail, and truncates the log before
|
||||
# it gets to Tinderbox. (terry weismann, chris yeh)
|
||||
#
|
||||
# This was replaced by a perl 'port' of the above, writen by
|
||||
# preed@netscape.com; good things: no need for system() call, and now it's
|
||||
# all in perl, so we don't have to do OS checking like before.
|
||||
|
||||
open(LOG, "$logfile") || die "Couldn't open logfile: $!\n";
|
||||
open(OUTLOG, ">${logfile}.last") || die "Couldn't open logfile: $!\n";
|
||||
|
||||
while (<LOG>) {
|
||||
$q = 0;
|
||||
|
||||
for (;;) {
|
||||
$val = $q * 1000;
|
||||
$Output = substr($_, $val, 1000);
|
||||
|
||||
last if $Output eq undef;
|
||||
|
||||
$Output =~ s/^\.$//g;
|
||||
$Output =~ s/\n//g;
|
||||
print OUTLOG "$Output\n";
|
||||
$q++;
|
||||
} #EndFor
|
||||
|
||||
} #EndWhile
|
||||
|
||||
close(LOG);
|
||||
close(OUTLOG);
|
||||
|
||||
system( "$mail $Tinderbox_server < ${logfile}.last" )
|
||||
if ($ReportStatus );
|
||||
unlink("$logfile");
|
||||
|
||||
# if this is a test run, set early_exit to 0.
|
||||
#This mean one loop of execution
|
||||
$EarlyExit++ if ($BuildOnce);
|
||||
}
|
||||
|
||||
} #EndSub-BuildIt
|
||||
|
||||
sub CVSTime {
|
||||
my($StartTimeArg) = @_;
|
||||
my($RetTime, $StartTimeArg, $sec, $minute, $hour, $mday, $mon, $year);
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime($StartTimeArg);
|
||||
$mon++; # month is 0 based.
|
||||
|
||||
sprintf("%02d/%02d/%02d %02d:%02d:00", $mon,$mday,$year,$hour,$minute );
|
||||
}
|
||||
|
||||
sub StartBuild {
|
||||
|
||||
my($fe, @felist);
|
||||
|
||||
@felist = split(/,/, $FE);
|
||||
|
||||
# die "SERVER: " . $Tinderbox_server . "\n";
|
||||
open( LOG, "|$mail $Tinderbox_server" );
|
||||
foreach $fe ( @felist ) {
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $BuildTree\n";
|
||||
print LOG "tinderbox: builddate: $StartTime\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $BuildName $fe\n";
|
||||
print LOG "tinderbox: errorparser: unix\n";
|
||||
print LOG "tinderbox: buildfamily: unix\n";
|
||||
print LOG "tinderbox: END\n";
|
||||
print LOG "\n";
|
||||
}
|
||||
close( LOG );
|
||||
}
|
||||
|
||||
# check for the existence of the binary
|
||||
sub BinaryExists {
|
||||
my($fe) = @_;
|
||||
my($Binname);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/'. $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG $BinName . "\n";
|
||||
if ((-e $BinName) && (-x $BinName) && (-s $BinName)) {
|
||||
1;
|
||||
}
|
||||
else {
|
||||
0;
|
||||
}
|
||||
}
|
||||
|
||||
sub DeleteBinary {
|
||||
my($fe) = @_;
|
||||
my($BinName);
|
||||
$fe = 'x' if (!defined($fe));
|
||||
|
||||
if ($BuildClassic) {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . "/cmd/${fe}fe/" . $BinaryName{"$fe"};
|
||||
} else {
|
||||
$BinName = $BuildDir . '/' . $TopLevel . '/' . $Topsrcdir . '/' . $BuildObjName . $BinaryName{"$fe"};
|
||||
}
|
||||
print LOG "unlinking $BinName\n";
|
||||
unlink ($BinName) || print LOG "unlinking $BinName failed\n";
|
||||
}
|
||||
|
||||
sub ParseArgs {
|
||||
my($i, $manArg);
|
||||
|
||||
if( @ARGV == 0 ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
$i = 0;
|
||||
$manArg = 0;
|
||||
while( $i < @ARGV ) {
|
||||
if ($ARGV[$i] eq '--depend') {
|
||||
$BuildDepend = 1;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--clobber') {
|
||||
$BuildDepend = 0;
|
||||
$manArg++;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--once' ) {
|
||||
$BuildOnce = 1;
|
||||
#$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--classic') {
|
||||
$BuildClassic = 1;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--noreport') {
|
||||
$ReportStatus = 0;
|
||||
}
|
||||
elsif ($ARGV[$i] eq '--version' || $ARGV[$i] eq '-v') {
|
||||
die "$0: version $Version\n";
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-tag' ) {
|
||||
$i++;
|
||||
$BuildTag = $ARGV[$i];
|
||||
if ( $BuildTag eq '' || $BuildTag eq '-t') {
|
||||
&PrintUsage;
|
||||
}
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-t' ) {
|
||||
$i++;
|
||||
$BuildTree = $ARGV[$i];
|
||||
if ( $BuildTree eq '' ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
} else {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
$i++;
|
||||
} #EndWhile
|
||||
|
||||
if ( $BuildTree =~ /^\s+$/i ) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
if ($BuildDepend eq undef) {
|
||||
&PrintUsage;
|
||||
}
|
||||
|
||||
&PrintUsage if (! $manArg );
|
||||
|
||||
} #EndSub-ParseArgs
|
||||
|
||||
sub PrintUsage {
|
||||
die "usage: $0 [--depend | --clobber] [-v | --version ] [--once --classic --noreport -tag TREETAG -t TREENAME ]\n";
|
||||
}
|
||||
|
||||
sub PrintEnv {
|
||||
my ($key);
|
||||
foreach $key (keys %ENV) {
|
||||
print LOG "$key = $ENV{$key}\n";
|
||||
print "$key = $ENV{$key}\n";
|
||||
}
|
||||
} #EndSub-PrintEnv
|
||||
|
||||
# Main function
|
||||
&InitVars;
|
||||
&ParseArgs;
|
||||
&ConditionalArgs;
|
||||
&GetSystemInfo;
|
||||
&SetupEnv;
|
||||
&SetupPath;
|
||||
&BuildIt;
|
||||
|
||||
1;
|
||||
416
mozilla/webtools/tinderbox/examples/mozilla-windows.pl
Executable file
416
mozilla/webtools/tinderbox/examples/mozilla-windows.pl
Executable file
@@ -0,0 +1,416 @@
|
||||
#!c:/nstools/bin/perl5
|
||||
|
||||
use Cwd;
|
||||
|
||||
$build_depend=1; #depend or clobber
|
||||
$build_tree = '';
|
||||
$build_tag = '';
|
||||
$build_name = '';
|
||||
$build_continue = 0;
|
||||
$build_sleep=10;
|
||||
$no32 = 0;
|
||||
$no16 = 0;
|
||||
$original_path = $ENV{'PATH'};
|
||||
$early_exit = 1;
|
||||
$doawt11 = 0;
|
||||
|
||||
$do_clobber = '';
|
||||
$client_param = 'pull_and_build_all';
|
||||
|
||||
&parse_args;
|
||||
|
||||
if( $build_test ){
|
||||
$build_sleep=1;
|
||||
}
|
||||
|
||||
$dirname = ($build_depend?'dep':'clob');
|
||||
|
||||
|
||||
$logfile = "${dirname}.log";
|
||||
|
||||
if( $build_depend ){
|
||||
$clobber_str = 'depend';
|
||||
}
|
||||
else {
|
||||
$clobber_str = 'clobber_all';
|
||||
}
|
||||
|
||||
|
||||
mkdir("$dirname", 0777);
|
||||
chdir("$dirname") || die "couldn't cd to $dirname";
|
||||
|
||||
$start_dir = cwd;
|
||||
$last_time = 0;
|
||||
|
||||
print "starting dir is :$start_dir\n";
|
||||
|
||||
|
||||
while( $early_exit ){
|
||||
chdir("$start_dir");
|
||||
if( time - $last_time < (60 * $build_sleep) ){
|
||||
$sleep_time = (60 * $build_sleep) - (time - $last_time);
|
||||
print "\n\nSleeping $sleep_time seconds ...\n";
|
||||
sleep( $sleep_time );
|
||||
}
|
||||
$last_time = time;
|
||||
|
||||
$start_time = time-60*10;
|
||||
$start_time_str = &cvs_time( $start_time );
|
||||
# call setup_env here in the loop, to update MOZ_DATE with each pass.
|
||||
# setup_env uses start_time_str for MOZ_DATE.
|
||||
&setup_env;
|
||||
|
||||
|
||||
$cur_dir = cwd;
|
||||
|
||||
if( $cur_dir ne $start_dir ){
|
||||
print "startdir: $start_dir, curdir $cur_dir\n";
|
||||
die "curdir != startdir";
|
||||
}
|
||||
|
||||
# build 32-bit with AWT_11=1
|
||||
&setup32("1");
|
||||
if( !$no32 ){
|
||||
if( !$noawt11 ){
|
||||
&do_build(1,$do_clobber);
|
||||
}
|
||||
}
|
||||
|
||||
if ($build_test) {
|
||||
$early_exit = 0; # stops this while loop after one pass.
|
||||
}
|
||||
if( !$no16 ){
|
||||
|
||||
# build 32-bit with AWT_11=0
|
||||
# necessary before building 16-bit because 16-bit cannot use AWT 1.1 classes
|
||||
&setup32("0");
|
||||
if( !$no32 ){
|
||||
if( !$noawt11 ){
|
||||
&do_build(0,'');
|
||||
} else {
|
||||
&do_build(1,$do_clobber);
|
||||
}
|
||||
}
|
||||
|
||||
&setup16;
|
||||
|
||||
# strip_conf fails to strip any variables from the real environemnt
|
||||
# &strip_config;
|
||||
&do_build(0,'');
|
||||
# &restore_config;
|
||||
}
|
||||
}
|
||||
|
||||
sub copy_win16_dist {
|
||||
|
||||
system 'xcopy w:\ y:\ns\dist /S /E /F';
|
||||
print "COPYCOPYCOPY\n";
|
||||
|
||||
}
|
||||
|
||||
sub build_NSPR20_Win16 {
|
||||
|
||||
&start_build;
|
||||
unlink( "${logname}.last" );
|
||||
rename( "${logname}","${logname}.last");
|
||||
|
||||
print "opening ${logname}\n";
|
||||
open( LOG, ">${logname}" ) || print "can't open $?\n";
|
||||
print LOG "current dir is :$cur_dir\n";
|
||||
|
||||
&print_env;
|
||||
|
||||
chdir("$moz_src/ns/nspr20") || die "couldn't chdir to '$moz_src/ns/nspr20'";
|
||||
print LOG "gmake |\n";
|
||||
open( BUILDNSPR, "gmake 2>&1 |") || print "couldn't execute gmake\n";;
|
||||
|
||||
while( <BUILDNSPR> ) {
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close ( BUILDNSPR );
|
||||
|
||||
close( LOG );
|
||||
}
|
||||
|
||||
sub setup32 {
|
||||
local ($awt) = @_;
|
||||
|
||||
$ENV{"MOZ_BITS"} = '32';
|
||||
$ENV{"AWT_11"} = $awt;
|
||||
$doawt11 = $awt;
|
||||
|
||||
$ENV{"INCLUDE"} = "$msdev\\include;$msdev\\mfc\\include";
|
||||
$ENV{"LIB"} = "$msdev\\lib;$msdev\\mfc\\lib";
|
||||
$ENV{"PATH"} = $original_path . ";$msdev\\bin";
|
||||
$ENV{"OS_TARGET"} = 'WIN95';
|
||||
$moz_src = $ENV{'MOZ_SRC'} = $start_dir;
|
||||
$build_name = 'Win32 ' . ($build_depend?'Depend':'Clobber');
|
||||
$do_clobber = $clobber_str;
|
||||
$logname = "win32.log";
|
||||
}
|
||||
|
||||
sub setup16 {
|
||||
$moz_src = $ENV{'MOZ_SRC'} = $start_dir;
|
||||
$ENV{"MOZ_BITS"} = '16';
|
||||
# perl 5 is fucked up. you MUST set AWT_11=0. deleting the environment
|
||||
# variable doesn't work. it's removed from the environment entry, but
|
||||
# is still defined as true for a build.
|
||||
$ENV{"AWT_11"} = '0';
|
||||
$moz_src = $ENV{'MOZ_SRC'} = "$src_16_drive";
|
||||
$ENV{"OS_TARGET"} = 'WIN16';
|
||||
|
||||
$msvc_inc = "$moz_src\\ns\\msvc15\\include;$moz_src\\ns\\msvc15\\mfc\\include";
|
||||
$msvc_lib = "$msvc\\lib;$msvc\\mfc\\lib";
|
||||
$msvcpath = "$msvc\\bin;c:\\nstools\\bin;c:\\WINNT40;c:\\WINNT40\\system32;c:\\utils";
|
||||
$ENV{"MSVC_INC"} = $msvc_inc;
|
||||
$ENV{"MSVC_LIB"} = $msvc_lib;
|
||||
$ENV{"MSVCPATH"} = $msvcpath;
|
||||
|
||||
$ENV{"INCLUDE"} = $msvc_inc;
|
||||
$ENV{"LIB"} = $msvc_lib;
|
||||
$ENV{"PATH"} = $msvcpath;
|
||||
|
||||
$watcom = $ENV{"WATCOM"} = "C:\\WATCOM";
|
||||
$ENV{"EDPATH"} = "$watcom\\EDDAT";
|
||||
$ENV{"WATC_INC"} = "$watcom\\h;$watcom\\h\win;$msvc_inc";
|
||||
$ENV{"WATC_LIB"} = $msvc_lib;
|
||||
$ENV{"WATCPATH"} = "$watcom\\BINNT;$watcom\\BINW;c:\\nstools\\bin";
|
||||
|
||||
$build_name = 'Win16 ' . ($build_depend?'Depend':'Clobber');
|
||||
$do_clobber = $clobber_str;
|
||||
$logname = "win16.log";
|
||||
|
||||
system "subst l: /d";
|
||||
system "subst r: /d";
|
||||
system "subst $src_16_drive /d";
|
||||
|
||||
system "subst $src_16_drive $start_dir";
|
||||
system "subst r: $src_16_drive\\ns\\netsite\\ldap\\libraries\\msdos\\winsock";
|
||||
system "subst l: $src_16_drive\\ns\\netsite";
|
||||
}
|
||||
|
||||
sub do_build {
|
||||
local ($pull, $do_clobber) = @_;
|
||||
|
||||
&start_build;
|
||||
|
||||
print "opening ${logname}\n";
|
||||
open( LOG, ">${logname}" ) || print "can't open $?\n";
|
||||
print LOG "current dir is :$cur_dir\n";
|
||||
|
||||
&print_env;
|
||||
$build_status = 0;
|
||||
if( $pull ){
|
||||
if ( $build_tag eq '' ){
|
||||
print LOG "cvs co -D\"$start_time_str\" mozilla/client.mak 2>&1 |\n";
|
||||
open( PULL, "cvs co -D\"$start_time_str\" mozilla/client.mak 2>&1 |") || print "couldn't execute cvs\n";;
|
||||
} else{
|
||||
print LOG "cvs co -r $build_tag mozilla/client.mak 2>&1 |\n";
|
||||
open( PULL, "cvs co -r $build_tag mozilla/client.mak 2>&1 |") || print "couldn't execute cvs\n";;
|
||||
}
|
||||
|
||||
# tee the output
|
||||
while( <PULL> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( PULL );
|
||||
|
||||
$build_status = $?;
|
||||
}
|
||||
|
||||
chdir("$moz_src/mozilla") || die "couldn't chdir to '$moz_src/mozilla'";
|
||||
|
||||
if( $do_clobber ne '' ){
|
||||
print LOG "nmake -f client.mak $do_clobber |\n";
|
||||
print "nmake -f client.mak $do_clobber |\n";
|
||||
open( PULL, "nmake -f client.mak $do_clobber 2>&1 |") || print "couldn't execute nmake\n";;
|
||||
|
||||
# tee the output
|
||||
while( <PULL> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( PULL );
|
||||
}
|
||||
|
||||
|
||||
if (!$pull) {
|
||||
$client_param = 'build_all';
|
||||
}
|
||||
else {
|
||||
$client_param = 'pull_and_build_all';
|
||||
}
|
||||
if (!$doawt11) {
|
||||
$client_param = 'build_dist';
|
||||
}
|
||||
|
||||
print LOG "nmake -f client.mak $client_param 2>&1 |\n";
|
||||
open( BUILD, "nmake -f client.mak $client_param 2>&1 |");
|
||||
|
||||
# tee the output
|
||||
while( <BUILD> ){
|
||||
print $_;
|
||||
print LOG $_;
|
||||
}
|
||||
close( BUILD );
|
||||
$build_status |= $?;
|
||||
|
||||
$build_status_str = ( $build_status ? 'busted' : 'success' );
|
||||
|
||||
print LOG "tinderbox: tree: $build_tree\n";
|
||||
print LOG "tinderbox: builddate: $start_time\n";
|
||||
print LOG "tinderbox: status: $build_status_str\n";
|
||||
print LOG "tinderbox: build: $build_name\n";
|
||||
print LOG "tinderbox: errorparser: windows\n";
|
||||
print LOG "tinderbox: buildfamily: windows\n";
|
||||
|
||||
close( LOG );
|
||||
chdir("$start_dir");
|
||||
system( "$nstools\\bin\\blat ${logname} -t tinderbox-daemon\@warp" );
|
||||
}
|
||||
|
||||
sub cvs_time {
|
||||
local( $ret_time );
|
||||
|
||||
($sec,$minute,$hour,$mday,$mon,$year) = localtime( $_[0] );
|
||||
$mon++; # month is 0 based.
|
||||
|
||||
sprintf("%02d/%02d/%02d %02d:%02d:00",
|
||||
$mon,$mday,$year,$hour,$minute );
|
||||
}
|
||||
|
||||
|
||||
sub start_build {
|
||||
open( LOG, ">>logfile" );
|
||||
print LOG "\n";
|
||||
print LOG "tinderbox: tree: $build_tree\n";
|
||||
print LOG "tinderbox: builddate: $start_time\n";
|
||||
print LOG "tinderbox: status: building\n";
|
||||
print LOG "tinderbox: build: $build_name\n";
|
||||
print LOG "tinderbox: errorparser: windows\n";
|
||||
print LOG "tinderbox: buildfamily: windows\n";
|
||||
print LOG "\n";
|
||||
close( LOG );
|
||||
system("$nstools\\bin\\blat logfile -t tinderbox-daemon\@warp" );
|
||||
}
|
||||
|
||||
sub parse_args {
|
||||
local($i);
|
||||
|
||||
if( @ARGV == 0 ){
|
||||
&usage;
|
||||
}
|
||||
$i = 0;
|
||||
while( $i < @ARGV ){
|
||||
if( $ARGV[$i] eq '--depend' ){
|
||||
$build_depend = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--clobber' ){
|
||||
$build_depend = 0;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--continue' ){
|
||||
$build_continue = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--noawt11' ){
|
||||
$noawt11 = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--no32' ){
|
||||
$no32 = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--no16' ){
|
||||
$no16 = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '--test' ){
|
||||
$build_test = 1;
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-tag' ){
|
||||
$i++;
|
||||
$build_tag = $ARGV[$i];
|
||||
if( $build_tag eq '' || $build_tag eq '-t'){
|
||||
&usage;
|
||||
}
|
||||
}
|
||||
elsif ( $ARGV[$i] eq '-t' ){
|
||||
$i++;
|
||||
$build_tree = $ARGV[$i];
|
||||
if( $build_tree eq '' ){
|
||||
&usage;
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if( $build_tree eq '' ){
|
||||
&usage;
|
||||
}
|
||||
}
|
||||
|
||||
sub usage {
|
||||
die "usage: buildit.pl [--depend | --clobber] [--no16] [--continue] [--test] [-tag TAGNAME] -t TREENAME\n";
|
||||
}
|
||||
|
||||
sub setup_env {
|
||||
local($p);
|
||||
$ENV{"MOZ_DEBUG"} = '1';
|
||||
$ENV{"MOZ_GOLD"} = '1';
|
||||
$ENV{"NO_SECURITY"} = '1';
|
||||
$ENV{"MOZ_MEDIUM"} = '1';
|
||||
$ENV{"MOZ_CAFE"} = '1';
|
||||
$ENV{"NSPR20"} = '1';
|
||||
$ENV{"VERBOSE"} = '1';
|
||||
$nstools = $ENV{"MOZ_TOOLS"};
|
||||
if( $nstools eq '' ){
|
||||
die "error: environment variable MOZ_TOOLS not set\n";
|
||||
}
|
||||
$msdev = $ENV{"MOZ_MSDEV"} = 'c:\msdev';
|
||||
if( $msdev eq '' ){
|
||||
die "error: environment variable MOZ_MSDEV not set\n";
|
||||
}
|
||||
$msvc = $ENV{"MOZ_MSVC"} = 'c:\msvc';
|
||||
if( $msvc eq '' ){
|
||||
die "error: environment variable MOZ_VC not set\n";
|
||||
}
|
||||
if ( $build_tag ne '' ) {
|
||||
$ENV{"MOZ_BRANCH"} = $build_tag;
|
||||
}
|
||||
$moz_src = $ENV{"MOZ_SRC"} = $start_dir;
|
||||
$ENV{"MOZ_DATE"} = $start_time_str;
|
||||
$src_16_drive = 'y:';
|
||||
}
|
||||
|
||||
sub print_env {
|
||||
local( $k, $v);
|
||||
print LOG "\nEnvironment\n";
|
||||
print "\nEnvironment\n";
|
||||
for $k (sort keys %ENV){
|
||||
$v = $ENV{$k};
|
||||
print LOG " $k=$v\n";
|
||||
print " $k=$v\n";
|
||||
}
|
||||
print LOG "\n";
|
||||
print "\n";
|
||||
system 'set';
|
||||
}
|
||||
|
||||
sub strip_config {
|
||||
$save_compname=$ENV{"COMPUTERNAME"};
|
||||
$save_userdomain=$ENV{"USERDOMAIN"};
|
||||
$save_username=$ENV{"USERNAME"};
|
||||
$save_userprofile=$ENV{"USERPROFILE"};
|
||||
# most of these deletes have no effect.
|
||||
delete($ENV{"COMPUTERNAME"});
|
||||
delete($ENV{"USERDOMAIN"});
|
||||
delete($ENV{"USERNAME"});
|
||||
delete($ENV{"USERPROFILE"});
|
||||
# delete($ENV{"WATCOM"});
|
||||
|
||||
}
|
||||
|
||||
sub restore_config {
|
||||
$ENV{"COMPUTERNAME"}=$save_compname;
|
||||
$ENV{"USERDOMAIN"}=$save_userdomain;
|
||||
$ENV{"USERNAME"}=$save_username;
|
||||
$ENV{"MSDevDir"}=$save_userprofile;
|
||||
&print_env;
|
||||
}
|
||||
31
mozilla/webtools/tinderbox/faq.html
Executable file
31
mozilla/webtools/tinderbox/faq.html
Executable file
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<META NAME="GENERATOR" CONTENT="Mozilla/4.0b2 (WinNT; I) [Netscape]">
|
||||
</HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
FAQ on Tinderbox </H1>
|
||||
<B><FONT SIZE=+2>Q. What is Tinderbox.</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. Your very own automated build page. It shows you how builds
|
||||
are going on various platforms. fs</FONT>
|
||||
<BR><FONT SIZE=+2></FONT>
|
||||
<BR><B><FONT SIZE=+2>Q. I just checked in some code. How can I tell when
|
||||
I'm OK.</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. You name will appear in the <I>guilty </I>column.
|
||||
When there are successful (<FONT COLOR="#00FF00">green</FONT>) builds in
|
||||
all the columns in a row <B>above</B> your name, you know you are ok.</FONT>
|
||||
<BR>
|
||||
<BR><B><FONT SIZE=+2>Q. The tree is broken, how do I find out what is busted
|
||||
(or who busted it).</FONT></B>
|
||||
<BR><FONT SIZE=+2>A. Clicking 'L' in the first red box (first build to break)
|
||||
above a green will show you a build log for the broken build. You
|
||||
can also click 'C' in this box and see what code was checked in.</FONT>
|
||||
<BR>
|
||||
<BR><B><FONT SIZE=+2>More Questions? Mail me <A HREF="mailto:ltabb@netscape.com">ltabb@netscape.com</A></FONT></B>
|
||||
<BR>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
217
mozilla/webtools/tinderbox/fixupimages.pl
Executable file
217
mozilla/webtools/tinderbox/fixupimages.pl
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use Socket;
|
||||
|
||||
require 'globals.pl';
|
||||
require 'imagelog.pl';
|
||||
|
||||
# Port an old-style imagelog thing to a newstyle one
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" ) || die "can't open file";
|
||||
open (OUT, ">$data_dir/newimagelog.txt") || die "can't open output file";
|
||||
select(OUT); $| = 1; select(STDOUT);
|
||||
|
||||
while( <IMAGELOG> ){
|
||||
chop;
|
||||
($url,$quote) = split(/\`/);
|
||||
print "$url\n";
|
||||
$size = &URLsize($url);
|
||||
$width = "";
|
||||
$height = "";
|
||||
if ($size =~ /WIDTH=([0-9]*)/) {
|
||||
$width = $1;
|
||||
}
|
||||
if ($size =~ /HEIGHT=([0-9]*)/) {
|
||||
$height = $1;
|
||||
}
|
||||
if ($width eq "" || $height eq "") {
|
||||
print "Couldn't get image size; skipping.\n";
|
||||
} else {
|
||||
print OUT "$url`$width`$height`$quote\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub imgsize {
|
||||
local($file)= @_;
|
||||
|
||||
#first try to open the file
|
||||
if( !open(STREAM, "<$file") ){
|
||||
print "Can't open IMG $file";
|
||||
$size="";
|
||||
} else {
|
||||
if ($file =~ /.jpg/i || $file =~ /.jpeg/i) {
|
||||
$size = &jpegsize(STREAM);
|
||||
} elsif($file =~ /.gif/i) {
|
||||
$size = &gifsize(STREAM);
|
||||
} elsif($file =~ /.xbm/i) {
|
||||
$size = &xbmsize(STREAM);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
close(STREAM);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine gets the size of the specified GIF
|
||||
###########################################################################
|
||||
sub gifsize {
|
||||
local($GIF) = @_;
|
||||
read($GIF, $type, 6);
|
||||
if(!($type =~ /GIF8[7,9]a/) ||
|
||||
!(read($GIF, $s, 4) == 4) ){
|
||||
print "Invalid or Corrupted GIF";
|
||||
$size="";
|
||||
} else {
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join ("", 'WIDTH=', $b<<8|$a, ' HEIGHT=', $d<<8|$c);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub xbmsize {
|
||||
local($XBM) = @_;
|
||||
local($input)="";
|
||||
|
||||
$input .= <$XBM>;
|
||||
$input .= <$XBM>;
|
||||
$_ = $input;
|
||||
if( /#define\s*\S*\s*\d*\s*\n#define\s*\S*\s*\d*\s*\n/i ){
|
||||
($a,$b)=/#define\s*\S*\s*(\d*)\s*\n#define\s*\S*\s*(\d*)\s*\n/i;
|
||||
$size=join ("", 'WIDTH=', $a, ' HEIGHT=', $b );
|
||||
} else {
|
||||
print "Hmmm... Doesn't look like an XBM file";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
# jpegsize : gets the width and height (in pixels) of a jpeg file
|
||||
# Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
|
||||
# modified slightly by alex@ed.ac.uk
|
||||
sub jpegsize {
|
||||
local($JPEG) = @_;
|
||||
local($done)=0;
|
||||
$size="";
|
||||
|
||||
read($JPEG, $c1, 1); read($JPEG, $c2, 1);
|
||||
if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
|
||||
printf "This is not a JPEG! (Codes %02X %02X)\n", ord($c1), ord($c2);
|
||||
$done=1;
|
||||
}
|
||||
while (ord($ch) != 0xDA && !$done) {
|
||||
# Find next marker (JPEG markers begin with 0xFF)
|
||||
# This can hang the program!!
|
||||
while (ord($ch) != 0xFF) { read($JPEG, $ch, 1); }
|
||||
# JPEG markers can be padded with unlimited 0xFF's
|
||||
while (ord($ch) == 0xFF) { read($JPEG, $ch, 1); }
|
||||
# Now, $ch contains the value of the marker.
|
||||
$marker=ord($ch);
|
||||
|
||||
if (($marker >= 0xC0) && ($marker <= 0xCF) &&
|
||||
($marker != 0xC4) && ($marker != 0xCC)) { # it's a SOFn marker
|
||||
read ($JPEG, $junk, 3); read($JPEG, $s, 4);
|
||||
($a,$b,$c,$d)=unpack("C"x4,$s);
|
||||
$size=join("", 'HEIGHT=',$a<<8|$b,' WIDTH=',$c<<8|$d );
|
||||
$done=1;
|
||||
} else {
|
||||
# We **MUST** skip variables, since FF's within variable
|
||||
# names are NOT valid JPEG markers
|
||||
read ($JPEG, $s, 2);
|
||||
($c1, $c2) = unpack("C"x2,$s);
|
||||
$length = $c1<<8|$c2;
|
||||
if( ($length < 2) ){
|
||||
print "Erroneous JPEG marker length";
|
||||
$done=1;
|
||||
} else {
|
||||
read($JPEG, $junk, $length-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Subroutine grabs a gif from another server and gets its size
|
||||
###########################################################################
|
||||
|
||||
|
||||
sub URLsize {
|
||||
my ($fullurl) = @_;
|
||||
my($dummy, $dummy, $serverstring, $url) = split(/\//, $fullurl, 4);
|
||||
my($them,$port) = split(/:/, $serverstring);
|
||||
my $port = 80 unless $port;
|
||||
$them = 'localhost' unless $them;
|
||||
my $size="";
|
||||
|
||||
$_=$url;
|
||||
if( /gif/i || /jpeg/i || /jpg/i || /xbm/i ) {
|
||||
my ($remote, $iaddr, $paddr, $proto, $line);
|
||||
$remote = $them;
|
||||
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
|
||||
die "No port" unless $port;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) || return "socket: $!";
|
||||
connect(S, $paddr) || return "connect: $!";
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
|
||||
|
||||
print S "GET /$url\n";
|
||||
if ($url =~ /.jpg/i || $url =~ /.jpeg/i) {
|
||||
$size = &jpegsize(S);
|
||||
} elsif($url =~ /.gif/i) {
|
||||
$size = &gifsize(S);
|
||||
} elsif($url =~ /.xbm/i) {
|
||||
$size = &xbmsize(S);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
$_ = $size;
|
||||
if( /\s*width\s*=\s*([0-9]*)\s*/i ){
|
||||
($newwidth)= /\s*width\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
if( /\s*height\s*=\s*([0-9]*)\s*/i ){
|
||||
($newheight)=/\s*height\s*=\s*(\d*)\s*/i;
|
||||
}
|
||||
} else {
|
||||
$size="";
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
sub dokill {
|
||||
kill 9,$child if $child;
|
||||
}
|
||||
556
mozilla/webtools/tinderbox/globals.pl
Executable file
556
mozilla/webtools/tinderbox/globals.pl
Executable file
@@ -0,0 +1,556 @@
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Global variabls and functions for tinderbox
|
||||
#
|
||||
|
||||
#
|
||||
# Global variables
|
||||
#
|
||||
|
||||
$td1 = {};
|
||||
$td2 = {};
|
||||
|
||||
$build_list = []; # array of all build records
|
||||
$build_name_index = {};
|
||||
$ignore_builds = {};
|
||||
$build_name_names = [];
|
||||
$name_count = 0;
|
||||
|
||||
$build_time_index = {};
|
||||
$build_time_times = [];
|
||||
$time_count = 0;
|
||||
$mindate_time_count = 0; # time_count that corresponds to the mindate
|
||||
|
||||
$build_table = [];
|
||||
$who_list = [];
|
||||
$who_list2 = [];
|
||||
@note_array = ();
|
||||
|
||||
|
||||
#$body_tag = "<BODY TEXT=#000000 BGCOLOR=#8080C0 LINK=#FFFFFF VLINK=#800080 ALINK=#FFFF00>";
|
||||
#$body_tag = "<BODY TEXT=#000000 BGCOLOR=#FFFFC0 LINK=#0000FF VLINK=#800080 ALINK=#FF00FF>";
|
||||
if( $ENV{'USERNAME'} eq 'ltabb' ){
|
||||
$gzip = 'gzip';
|
||||
}
|
||||
else {
|
||||
$gzip = '/usr/local/bin/gzip';
|
||||
}
|
||||
|
||||
$data_dir='data';
|
||||
|
||||
$lock_count = 0;
|
||||
|
||||
1;
|
||||
|
||||
sub lock{
|
||||
#if( $lock_count == 0 ){
|
||||
# print "locking $tree/LOCKFILE.lck\n";
|
||||
# open( LOCKFILE_LOCK, ">$tree/LOCKFILE.lck" );
|
||||
# flock( LOCKFILE_LOCK, 2 );
|
||||
#}
|
||||
#$lock_count++;
|
||||
|
||||
}
|
||||
|
||||
sub unlock{
|
||||
#$lock_count--;
|
||||
#if( $lock_count == 0 ){
|
||||
# flock( LOCKFILE_LOCK, 8 );
|
||||
# close( LOCKFILE_LOCK );
|
||||
#}
|
||||
}
|
||||
|
||||
sub print_time {
|
||||
my ($t) = @_;
|
||||
my ($minute,$hour,$mday,$mon);
|
||||
(undef,$minute,$hour,$mday,$mon,undef) = localtime($t);
|
||||
sprintf("%02d/%02d %02d:%02d",$mon+1,$mday,$hour,$minute);
|
||||
}
|
||||
|
||||
sub url_encode {
|
||||
my ($s) = @_;
|
||||
|
||||
$s =~ s/\%/\%25/g;
|
||||
$s =~ s/\=/\%3d/g;
|
||||
$s =~ s/\?/\%3f/g;
|
||||
$s =~ s/ /\%20/g;
|
||||
$s =~ s/\n/\%0a/g;
|
||||
$s =~ s/\r//g;
|
||||
$s =~ s/\"/\%22/g;
|
||||
$s =~ s/\'/\%27/g;
|
||||
$s =~ s/\|/\%7c/g;
|
||||
$s =~ s/\&/\%26/g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub url_decode {
|
||||
my ($value) = @_;
|
||||
$value =~ tr/+/ /;
|
||||
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
sub value_encode {
|
||||
my ($s) = @_;
|
||||
$s =~ s@&@&@g;
|
||||
$s =~ s@<@<@g;
|
||||
$s =~ s@>@>@g;
|
||||
$s =~ s@\"@"@g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
sub load_data {
|
||||
$tree2 = $form{'tree2'};
|
||||
if( $tree2 ne '' ){
|
||||
require "$tree2/treedata.pl";
|
||||
if( -r "$tree2/ignorebuilds.pl" ){
|
||||
require "$tree2/ignorebuilds.pl";
|
||||
}
|
||||
|
||||
$td2 = {};
|
||||
$td2->{name} = $tree2;
|
||||
$td2->{cvs_module} = $cvs_module;
|
||||
$td2->{cvs_branch} = $cvs_branch;
|
||||
$td2->{num} = 1;
|
||||
$td2->{ignore_builds} = $ignore_builds;
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
$td2->{cvs_root} = $cvs_root;
|
||||
|
||||
$tree = $form{'tree'};
|
||||
require "$tree/treedata.pl";
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
}
|
||||
|
||||
$tree = $form{'tree'};
|
||||
|
||||
return unless $tree;
|
||||
#die "the 'tree' parameter must be provided\n" unless $tree;
|
||||
|
||||
if ( -r "$tree/treedata.pl" ) {
|
||||
require "$tree/treedata.pl";
|
||||
}
|
||||
|
||||
$ignore_builds = {};
|
||||
if( -r "$tree/ignorebuilds.pl" ){
|
||||
require "$tree/ignorebuilds.pl";
|
||||
}
|
||||
|
||||
$td1 = {};
|
||||
$td1->{name} = $tree;
|
||||
$td1->{num} = 0;
|
||||
$td1->{cvs_module} = $cvs_module;
|
||||
$td1->{cvs_branch} = $cvs_branch;
|
||||
$td1->{ignore_builds} = $ignore_builds;
|
||||
if( $cvs_root eq '' ){
|
||||
$cvs_root = '/m/src';
|
||||
}
|
||||
$td1->{cvs_root} = $cvs_root;
|
||||
|
||||
&lock;
|
||||
&load_buildlog;
|
||||
&unlock;
|
||||
|
||||
&get_build_name_index;
|
||||
&get_build_time_index;
|
||||
|
||||
&load_who($who_list, $td1);
|
||||
if( $tree2 ne '' ){
|
||||
&load_who($who_list2, $td2);
|
||||
}
|
||||
|
||||
&make_build_table;
|
||||
}
|
||||
|
||||
sub load_buildlog {
|
||||
my $mailtime, $buildtime, $buildname, $errorparser;
|
||||
my $buildstatus, $logfile,$binaryname;
|
||||
my $buildrec, @treelist, $t;
|
||||
|
||||
if (not defined $maxdate) {
|
||||
$maxdate = time();
|
||||
}
|
||||
if (not defined $mindate) {
|
||||
$mindate = $maxdate - 24*60*60;
|
||||
}
|
||||
|
||||
if ($tree2 ne '') {
|
||||
@treelist = ($td1, $td2);
|
||||
}
|
||||
else {
|
||||
@treelist = ($td1);
|
||||
}
|
||||
|
||||
for $t (@treelist) {
|
||||
use Backwards;
|
||||
my ($bw) = Backwards->new("$t->{name}/build.dat") or die;
|
||||
|
||||
my $tooearly = 0;
|
||||
while( $_ = $bw->readline ) {
|
||||
chomp;
|
||||
($mailtime, $buildtime, $buildname,
|
||||
$errorparser, $buildstatus, $logfile, $binaryname) = split /\|/;
|
||||
|
||||
# Ignore stuff in the future.
|
||||
next if $buildtime > $maxdate;
|
||||
|
||||
# Ignore stuff in the past (but get a 2 hours of extra data)
|
||||
if ($buildtime < $mindate - 2*60*60) {
|
||||
# Occasionally, a build might show up with a bogus time. So,
|
||||
# we won't judge ourselves as having hit the end until we
|
||||
# hit a full 20 lines in a row that are too early.
|
||||
last if $tooearly++ > 20;
|
||||
|
||||
next;
|
||||
}
|
||||
$tooearly = 0;
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => ($tree2 ne '' ? $t->{name} . ' ' : '' ) . $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => $t
|
||||
};
|
||||
if ($form{noignore} or not $t->{ignore_builds}->{$buildname}) {
|
||||
push @{$build_list}, $buildrec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub loadquickparseinfo {
|
||||
my ($tree, $build, $times) = (@_);
|
||||
|
||||
do "$tree/ignorebuilds.pl";
|
||||
|
||||
use Backwards;
|
||||
|
||||
my ($bw) = Backwards->new("$form{tree}/build.dat") or die;
|
||||
|
||||
my $latest_time = 0;
|
||||
my $tooearly = 0;
|
||||
while( $_ = $bw->readline ) {
|
||||
chop;
|
||||
my ($buildtime, $buildname, $buildstatus) = (split /\|/)[1,2,4];
|
||||
|
||||
if ($buildstatus =~ /^success|busted|testfailed$/) {
|
||||
|
||||
# Ignore stuff in the future.
|
||||
next if $buildtime > $maxdate;
|
||||
|
||||
$latest_time = $buildtime if $buildtime > $latest_time;
|
||||
|
||||
# Ignore stuff more than 12 hours old
|
||||
if ($buildtime < $latest_time - 12*60*60) {
|
||||
# Hack: A build may give a bogus time. To compensate, we will
|
||||
# not stop until we hit 20 consecutive lines that are too early.
|
||||
|
||||
last if $tooearly++ > 20;
|
||||
next;
|
||||
}
|
||||
$tooearly = 0;
|
||||
|
||||
next if exists $ignore_builds->{$buildname};
|
||||
next if exists $build->{$buildname}
|
||||
and $times->{$buildname} >= $buildtime;
|
||||
|
||||
$build->{$buildname} = $buildstatus;
|
||||
$times->{$buildname} = $buildtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub load_who {
|
||||
my ($who_list, $td) = @_;
|
||||
my $d, $w, $i, $bfound;
|
||||
|
||||
open(WHOLOG, "<$td->{name}/who.dat");
|
||||
while (<WHOLOG>) {
|
||||
$i = $time_count;
|
||||
chop;
|
||||
($d,$w) = split /\|/;
|
||||
$bfound = 0;
|
||||
while ($i > 0 and not $bfound) {
|
||||
if ($d <= $build_time_times->[$i]) {
|
||||
$who_list->[$i+1]->{$w} = 1;
|
||||
$bfound = 1;
|
||||
}
|
||||
else {
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Ignore the last one
|
||||
#
|
||||
if ($time_count > 0) {
|
||||
$who_list->[$time_count] = {};
|
||||
}
|
||||
}
|
||||
|
||||
sub get_build_name_index {
|
||||
my $i,$br;
|
||||
|
||||
# Get all the unique build names.
|
||||
#
|
||||
foreach $br (@{$build_list}) {
|
||||
$build_name_index->{$br->{buildname}} = 1;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
foreach $n (sort keys (%{$build_name_index})) {
|
||||
$build_name_names->[$i] = $n;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$name_count = @{$build_name_names}-1;
|
||||
|
||||
# Update the map so it points to the right index
|
||||
#
|
||||
for ($i=1; $i < $name_count+1; $i++) {
|
||||
$build_name_index->{$build_name_names->[$i]} = $i;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_build_time_index {
|
||||
my $i,$br;
|
||||
|
||||
# Get all the unique build names.
|
||||
#
|
||||
foreach $br (@{$build_list}) {
|
||||
$build_time_index->{$br->{buildtime}} = 1;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
foreach $n (sort {$b <=> $a} keys (%{$build_time_index})) {
|
||||
$build_time_times->[$i] = $n;
|
||||
$mindate_time_count = $i if $n >= $mindate;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$time_count = @{$build_time_times}-1;
|
||||
|
||||
# Update the map so it points to the right index
|
||||
#
|
||||
for ($i=1; $i < $time_count+1; $i++) {
|
||||
$build_time_index->{$build_time_times->[$i]} = $i;
|
||||
}
|
||||
|
||||
#for $i (@{$build_time_times}) {
|
||||
# print $i . "\n";
|
||||
#}
|
||||
|
||||
#while( ($k,$v) = each(%{$build_time_index})) {
|
||||
# print "$k=$v\n";
|
||||
#}
|
||||
}
|
||||
|
||||
sub make_build_table {
|
||||
my $i,$ti,$bi,$ti1,$br;
|
||||
|
||||
# Create the build table
|
||||
#
|
||||
for ($i=1; $i <= $time_count; $i++){
|
||||
$build_table->[$i] = [];
|
||||
}
|
||||
|
||||
# Populate the build table with build data
|
||||
#
|
||||
foreach $br (reverse @{$build_list}) {
|
||||
$ti = $build_time_index->{$br->{buildtime}};
|
||||
$bi = $build_name_index->{$br->{buildname}};
|
||||
$build_table->[$ti][$bi] = $br;
|
||||
}
|
||||
|
||||
&load_notes;
|
||||
|
||||
for ($bi = $name_count; $bi > 0; $bi--) {
|
||||
for ($ti = $time_count; $ti > 0; $ti--) {
|
||||
if (defined($br = $build_table->[$ti][$bi])
|
||||
and not defined($br->{rowspan})) {
|
||||
|
||||
# If the cell immediately after us is defined, then we
|
||||
# can have a previousbuildtime.
|
||||
if (defined($br1 = $build_table->[$ti+1][$bi])) {
|
||||
$br->{previousbuildtime} = $br1->{buildtime};
|
||||
}
|
||||
|
||||
$ti1 = $ti-1;
|
||||
while ($ti1 > 0 and not defined($build_table->[$ti1][$bi])) {
|
||||
$build_table->[$ti1][$bi] = -1;
|
||||
$ti1--;
|
||||
}
|
||||
$br->{rowspan} = $ti - $ti1;
|
||||
if ($br->{rowspan} != 1) {
|
||||
$build_table->[$ti1+1][$bi] = $br;
|
||||
$build_table->[$ti][$bi] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub load_notes {
|
||||
if ($tree2 ne '') {
|
||||
@treelist = ($td1, $td2);
|
||||
}
|
||||
else {
|
||||
@treelist = ($td1);
|
||||
}
|
||||
|
||||
foreach $t (@treelist) {
|
||||
open(NOTES,"<$t->{name}/notes.txt")
|
||||
or print "<h2>warning: Couldn't open $t->{name}/notes.txt </h2>\n";
|
||||
while (<NOTES>) {
|
||||
chop;
|
||||
($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note) = split /\|/;
|
||||
$nbuildname = "$t->{name} $nbuildname" if $tree2 ne '';
|
||||
$ti = $build_time_index->{$nbuildtime};
|
||||
$bi = $build_name_index->{$nbuildname};
|
||||
#print "[ti = $ti][bi=$bi][buildname='$nbuildname' $_<br>";
|
||||
if ($ti != 0 and $bi != 0) {
|
||||
$build_table->[$ti][$bi]->{hasnote} = 1;
|
||||
if (not defined($build_table->[$ti][$bi]->{noteid})) {
|
||||
$build_table->[$ti][$bi]->{noteid} = (0+@note_array);
|
||||
}
|
||||
$noteid = $build_table->[$ti][$bi]->{noteid};
|
||||
$now_str = &print_time($nnow);
|
||||
$note = &url_decode($nenc_note);
|
||||
$note_array[$noteid] = "<pre>\n[<b><a href=mailto:$nwho>"
|
||||
."$nwho</a> - $now_str</b>]\n$note\n</pre>"
|
||||
.$note_array[$noteid];
|
||||
}
|
||||
}
|
||||
close(NOTES);
|
||||
}
|
||||
}
|
||||
|
||||
sub last_success_time {
|
||||
my ($row) = @_;
|
||||
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
my $br = $build_table->[$tt][$row];
|
||||
next unless defined $br;
|
||||
next unless $br->{buildstatus} eq 'success';
|
||||
return $build_time_times->[$tt + $br->{rowspan} ];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub last_status {
|
||||
my ($row) = @_;
|
||||
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
my $br = $build_table->[$tt][$row];
|
||||
next unless defined $br;
|
||||
next unless $br->{buildstatus} =~ /^(success|busted|testfailed)$/;
|
||||
return $br->{buildstatus};
|
||||
}
|
||||
return 'building';
|
||||
}
|
||||
|
||||
sub check_password {
|
||||
if ($form{password} eq '') {
|
||||
if (defined $cookie_jar{tinderbox_password}) {
|
||||
$form{password} = $cookie_jar{tinderbox_password};
|
||||
}
|
||||
}
|
||||
my $correct = '';
|
||||
if (open(REAL, '<data/passwd')) {
|
||||
$correct = <REAL>;
|
||||
close REAL;
|
||||
$correct =~ s/\s+$//; # Strip trailing whitespace.
|
||||
}
|
||||
$form{password} =~ s/\s+$//; # Strip trailing whitespace.
|
||||
if ($form{password} ne '') {
|
||||
open(TRAPDOOR, "../bonsai/data/trapdoor $form{'password'} |")
|
||||
or die "Can't run trapdoor func!";
|
||||
my $encoded = <TRAPDOOR>;
|
||||
close TRAPDOOR;
|
||||
$encoded =~ s/\s+$//; # Strip trailing whitespace.
|
||||
if ($encoded eq $correct) {
|
||||
if ($form{rememberpassword} ne '') {
|
||||
print "Set-Cookie: tinderbox_password=$form{'password'} ;"
|
||||
." path=/ ; expires = Sun, 1-Mar-2020 00:00:00 GMT\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
require 'header.pl';
|
||||
|
||||
print "Content-type: text/html\n";
|
||||
print "Set-Cookie: tinderbox_password= ; path=/ ; "
|
||||
." expires = Sun, 1-Mar-2020 00:00:00 GMT\n";
|
||||
print "\n";
|
||||
|
||||
EmitHtmlHeader("What's the magic word?",
|
||||
"You need to know the magic word to use this page.");
|
||||
|
||||
if ($form{password} ne '') {
|
||||
print "<B>Invalid password; try again.<BR></B>";
|
||||
}
|
||||
print q(
|
||||
<FORM method=post>
|
||||
<B>Password:</B>
|
||||
<INPUT NAME=password TYPE=password><BR>
|
||||
<INPUT NAME=rememberpassword TYPE=checkbox>
|
||||
If correct, remember password as a cookie<BR>
|
||||
);
|
||||
|
||||
while (my ($key,$value) = each %form) {
|
||||
next if $key eq "password" or $key eq "rememberpassword";
|
||||
|
||||
my $enc = value_encode($value);
|
||||
print "<INPUT TYPE=HIDDEN NAME=$key VALUE='$enc'>\n";
|
||||
}
|
||||
print "<INPUT TYPE=SUBMIT value=Submit></FORM>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
sub find_build_record {
|
||||
my ($tree, $logfile) = @_;
|
||||
|
||||
my $log_entry = `grep $logfile $tree/build.dat`;
|
||||
|
||||
chomp($log_entry);
|
||||
my ($mailtime, $buildtime, $buildname, $errorparser,
|
||||
$buildstatus, $logfile, $binaryname) = split /\|/, $log_entry;
|
||||
|
||||
$buildrec = {
|
||||
mailtime => $mailtime,
|
||||
buildtime => $buildtime,
|
||||
buildname => $buildname,
|
||||
errorparser => $errorparser,
|
||||
buildstatus => $buildstatus,
|
||||
logfile => $logfile,
|
||||
binaryname => $binaryname,
|
||||
td => undef
|
||||
};
|
||||
return $buildrec;
|
||||
}
|
||||
49
mozilla/webtools/tinderbox/handlemail.pl
Executable file
49
mozilla/webtools/tinderbox/handlemail.pl
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Figure out which directory tinderbox is in by looking at argv[0]. Unless
|
||||
# there is a command line argument; if there is, just use that.
|
||||
|
||||
$tinderboxdir = $0;
|
||||
$tinderboxdir =~ s:/[^/]*$::; # Remove last word, and slash before it.
|
||||
if ($tinderboxdir eq "") {
|
||||
$tinderboxdir = ".";
|
||||
}
|
||||
|
||||
if (@ARGV > 0) {
|
||||
$tinderboxdir = $ARGV[0];
|
||||
}
|
||||
|
||||
print "tinderbox = $tinderboxdir\n";
|
||||
|
||||
chdir $tinderboxdir || die "Couldn't chdir to $tinderboxdir";
|
||||
|
||||
|
||||
open(DF, ">data/tbx.$$") || die "could not open data/tbx.$$";
|
||||
while(<STDIN>){
|
||||
print DF $_;
|
||||
}
|
||||
close(DF);
|
||||
|
||||
$err = system("./processbuild.pl data/tbx.$$");
|
||||
|
||||
if( $err ) {
|
||||
die "processbuild.pl returned an error\n";
|
||||
}
|
||||
|
||||
43
mozilla/webtools/tinderbox/imagelog.pl
Executable file
43
mozilla/webtools/tinderbox/imagelog.pl
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
1;
|
||||
|
||||
sub add_imagelog {
|
||||
local($url,$quote,$width,$height) = @_;
|
||||
open( IMAGELOG, ">>$data_dir/imagelog.txt" ) || die "Oops; can't open imagelog.txt";
|
||||
print IMAGELOG "$url`$width`$height`$quote\n";
|
||||
close( IMAGELOG );
|
||||
}
|
||||
|
||||
sub get_image{
|
||||
local(@log,@ret,$i);
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" );
|
||||
@log = <IMAGELOG>;
|
||||
|
||||
# return a random line
|
||||
srand;
|
||||
@ret = split(/\`/,$log[rand @log]);
|
||||
|
||||
close( IMAGELOG );
|
||||
@ret;
|
||||
}
|
||||
|
||||
|
||||
12
mozilla/webtools/tinderbox/index.html
Executable file
12
mozilla/webtools/tinderbox/index.html
Executable file
@@ -0,0 +1,12 @@
|
||||
<TITLE>tinderbox</TITLE>
|
||||
<META HTTP-EQUIV="Refresh" CONTENT="1; URL=showbuilds.cgi">
|
||||
<BODY BGCOLOR="#FFFFFF" TEXT="#000000"
|
||||
LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
<CENTER>
|
||||
<TABLE BORDER=0 WIDTH="100%" HEIGHT="100%"><TR><TD ALIGN=CENTER VALIGN=CENTER>
|
||||
<FONT SIZE="+2">
|
||||
You're looking for
|
||||
<A HREF="showbuilds.cgi">showbuilds.cgi</A>.
|
||||
</FONT>
|
||||
</TD></TR></TABLE>
|
||||
</CENTER>
|
||||
241
mozilla/webtools/tinderbox/processbuild.pl
Executable file
241
mozilla/webtools/tinderbox/processbuild.pl
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
require 'globals.pl';
|
||||
require 'timelocal.pl';
|
||||
|
||||
umask 0;
|
||||
|
||||
#$logfile = '';
|
||||
|
||||
%MAIL_HEADER = ();
|
||||
$DONE = 0;
|
||||
$building = 0;
|
||||
$endsection = 0;
|
||||
|
||||
open( LOG, "<$ARGV[0]") || die "cant open $!";
|
||||
&parse_mail_header;
|
||||
while ($DONE == 0) {
|
||||
%tbx = ();
|
||||
&get_variables;
|
||||
|
||||
# run thru if EOF and we haven't hit our section end marker
|
||||
|
||||
if ( !$DONE || !$endsection) {
|
||||
&check_required_vars;
|
||||
$tree = $tbx{'tree'} if (!defined($tree));
|
||||
$logfile = "$builddate.$$.gz" if (!defined($logfile));
|
||||
$building++ if ($tbx{'status'} =~ m/building/);
|
||||
&lock;
|
||||
&write_build_data;
|
||||
&unlock;
|
||||
}
|
||||
}
|
||||
close(LOG);
|
||||
|
||||
&compress_log_file;
|
||||
&unlink_log_file;
|
||||
|
||||
system "./buildwho.pl $tree";
|
||||
|
||||
# Build static pages for Sidebar flash and tinderbox panels.
|
||||
$ENV{QUERY_STRING}="tree=$tree&static=1";
|
||||
system './showbuilds.cgi';
|
||||
|
||||
# end of main
|
||||
######################################################################
|
||||
|
||||
|
||||
# This routine will scan through log looking for 'tinderbox:' variables
|
||||
#
|
||||
sub get_variables{
|
||||
|
||||
#while( ($k,$v) = each( %MAIL_HEADER ) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
|
||||
&parse_log_variables;
|
||||
|
||||
#while( ($k,$v) = each( %tbx ) ){
|
||||
# print "$k='$v'\n";
|
||||
#}
|
||||
}
|
||||
|
||||
|
||||
sub parse_log_variables {
|
||||
my ($line, $stop);
|
||||
$stop = 0;
|
||||
while($stop == 0){
|
||||
$line = <LOG>;
|
||||
$DONE++, return if !defined($line);
|
||||
chomp($line);
|
||||
if( $line =~ /^tinderbox\:/ ){
|
||||
if( $line =~ /^tinderbox\:[ \t]*([^:]*)\:[ \t]*([^\n]*)/ ){
|
||||
$tbx{$1} = $2;
|
||||
} elsif ( $line =~ /^tinderbox: END/ ) {
|
||||
$stop++, $endsection++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_mail_header {
|
||||
my $line;
|
||||
my $name = '';
|
||||
while($line = <LOG> ){
|
||||
chomp($line);
|
||||
|
||||
if( $line eq '' ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( $line =~ /([^ :]*)\:[ \t]+([^\n]*)/ ){
|
||||
$name = $1;
|
||||
$name =~ tr/A-Z/a-z/;
|
||||
$MAIL_HEADER{$name} = $2;
|
||||
#print "$name $2\n";
|
||||
}
|
||||
elsif( $name ne '' ){
|
||||
$MAIL_HEADER{$name} .= $2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub check_required_vars {
|
||||
$err_string = '';
|
||||
if( $tbx{'tree'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:tree' not set.\n";
|
||||
}
|
||||
elsif( ! -r $tbx{'tree'} ){
|
||||
$err_string .= "Variable 'tinderbox:tree' not set to a valid tree.\n";
|
||||
}
|
||||
elsif(($MAIL_HEADER{'to'} =~ /external/i ||
|
||||
$MAIL_HEADER{'cc'} =~ /external/i) &&
|
||||
$tbx{'tree'} !~ /external/i) {
|
||||
$err_string .= "Data from an external source didn't specify an 'external' tree.";
|
||||
}
|
||||
if( $tbx{'build'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:build' not set.\n";
|
||||
}
|
||||
if( $tbx{'errorparser'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:errorparser' not set.\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Grab the date in the form of mm/dd/yy hh:mm:ss
|
||||
#
|
||||
# Or a GMT unix date
|
||||
#
|
||||
if( $tbx{'builddate'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:builddate' not set.\n";
|
||||
}
|
||||
else {
|
||||
if( $tbx{'builddate'} =~
|
||||
/([0-9]*)\/([0-9]*)\/([0-9]*)[ \t]*([0-9]*)\:([0-9]*)\:([0-9]*)/ ){
|
||||
|
||||
$builddate = timelocal($6,$5,$4,$2,$1-1,$3);
|
||||
|
||||
}
|
||||
elsif( $tbx{'builddate'} > 7000000 ){
|
||||
$builddate = $tbx{'builddate'};
|
||||
}
|
||||
else {
|
||||
$err_string .= "Variable 'tinderbox:builddate' not of the form MM/DD/YY HH:MM:SS or unix date\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Build Status
|
||||
#
|
||||
if( $tbx{'status'} eq ''){
|
||||
$err_string .= "Variable 'tinderbox:status' not set.\n";
|
||||
}
|
||||
elsif( ! $tbx{'status'} =~ /success|busted|building|testfailed/ ){
|
||||
$err_string .= "Variable 'tinderbox:status' must be 'success', 'busted', 'testfailed', or 'building'\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Report errors
|
||||
#
|
||||
if( $err_string ne '' ){
|
||||
die $err_string;
|
||||
}
|
||||
}
|
||||
|
||||
sub write_build_data {
|
||||
$t = time;
|
||||
open( BUILDDATA, ">>$tbx{'tree'}/build.dat" )|| die "can't open $! for writing";
|
||||
print BUILDDATA "$t|$builddate|$tbx{'build'}|$tbx{'errorparser'}|$tbx{'status'}|$logfile|$tbx{binaryname}\n";
|
||||
close( BUILDDATA );
|
||||
}
|
||||
|
||||
sub compress_log_file {
|
||||
local( $done, $line);
|
||||
|
||||
return if ( $building );
|
||||
|
||||
open( LOG2, "<$ARGV[0]") || die "cant open $!";
|
||||
|
||||
#
|
||||
# Skip past the the RFC822.HEADER
|
||||
#
|
||||
$done = 0;
|
||||
while( !$done && ($line = <LOG2>) ){
|
||||
chomp($line);
|
||||
$done = ($line eq '');
|
||||
}
|
||||
|
||||
open( ZIPLOG, "| $gzip -c > ${tree}/$logfile" ) || die "can't open $! for writing";
|
||||
$inBinary = 0;
|
||||
$hasBinary = ($tbx{'binaryname'} ne '');
|
||||
while( $line = <LOG2> ){
|
||||
if( !$inBinary ){
|
||||
print ZIPLOG $line;
|
||||
if( $hasBinary ){
|
||||
$inBinary = ($line =~ /^begin [0-7][0-7][0-7] /);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( $line =~ /^end\n/ ){
|
||||
$inBinary = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
close( ZIPLOG );
|
||||
close( LOG2 );
|
||||
|
||||
#
|
||||
# If a uuencoded binary is part of the build, unpack it.
|
||||
#
|
||||
if( $hasBinary ){
|
||||
$bin_dir = "$tbx{'tree'}/bin/$builddate/$tbx{'build'}";
|
||||
$bin_dir =~ s/ //g;
|
||||
|
||||
system("mkdir -m 0777 -p $bin_dir");
|
||||
|
||||
# LTNOTE: I'm not sure this is cross platform.
|
||||
system("/tools/ns/bin/uudecode --output-file=$bin_dir/$tbx{binaryname} < $ARGV[0]");
|
||||
}
|
||||
}
|
||||
|
||||
sub unlink_log_file {
|
||||
unlink( $ARGV[0] );
|
||||
}
|
||||
BIN
mozilla/webtools/tinderbox/reledanim.gif
Normal file
BIN
mozilla/webtools/tinderbox/reledanim.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
782
mozilla/webtools/tinderbox/showbuilds.cgi
Executable file
782
mozilla/webtools/tinderbox/showbuilds.cgi
Executable file
@@ -0,0 +1,782 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib '../bonsai';
|
||||
require 'globals.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'imagelog.pl';
|
||||
require 'header.pl';
|
||||
$|=1;
|
||||
|
||||
# Hack this until I can figure out how to do get default root. -slamm
|
||||
$default_root = '/cvsroot';
|
||||
|
||||
# Show 12 hours by default
|
||||
#
|
||||
$nowdate = time;
|
||||
if (not defined($maxdate = $form{maxdate})) {
|
||||
$maxdate = $nowdate;
|
||||
}
|
||||
if ($form{showall}) {
|
||||
$mindate = 0;
|
||||
}
|
||||
else {
|
||||
$default_hours = 12;
|
||||
$hours = $default_hours;
|
||||
$hours = $form{hours} if $form{hours};
|
||||
$mindate = $maxdate - ($hours*60*60);
|
||||
}
|
||||
|
||||
%colormap = (
|
||||
success => '00ff00',
|
||||
busted => 'red',
|
||||
building => 'yellow',
|
||||
testfailed => 'orange'
|
||||
);
|
||||
|
||||
%images = (
|
||||
flames => '1afi003r.gif',
|
||||
star => 'star.gif'
|
||||
);
|
||||
|
||||
$tree = $form{tree};
|
||||
|
||||
if (exists $form{rebuildguilty} or exists $form{showall}) {
|
||||
system ("./buildwho.pl -days 7 $tree > /dev/null");
|
||||
undef $form{rebuildguilty};
|
||||
}
|
||||
&show_tree_selector, exit if $form{tree} eq '';
|
||||
&do_quickparse, exit if $form{quickparse};
|
||||
&do_express, exit if $form{express};
|
||||
&do_rdf, exit if $form{rdf};
|
||||
&do_static, exit if $form{static};
|
||||
&do_flash, exit if $form{flash};
|
||||
&do_panel, exit if $form{panel};
|
||||
&do_tinderbox, exit;
|
||||
|
||||
# end of main
|
||||
#=====================================================================
|
||||
|
||||
sub make_tree_list {
|
||||
my @result;
|
||||
while(<*>) {
|
||||
if( -d $_ && $_ ne 'data' && $_ ne 'CVS' && -f "$_/treedata.pl") {
|
||||
push @result, $_;
|
||||
}
|
||||
}
|
||||
return @result;
|
||||
}
|
||||
|
||||
sub show_tree_selector {
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
EmitHtmlHeader("tinderbox");
|
||||
|
||||
print "<P><TABLE WIDTH=\"100%\">";
|
||||
print "<TR><TD ALIGN=CENTER>Select one of the following trees:</TD></TR>";
|
||||
print "<TR><TD ALIGN=CENTER>\n";
|
||||
print " <TABLE><TR><TD><UL>\n";
|
||||
|
||||
my @list = make_tree_list();
|
||||
|
||||
foreach (@list) {
|
||||
print "<LI><a href=showbuilds.cgi?tree=$_>$_</a>\n";
|
||||
}
|
||||
print "<//UL></TD></TR></TABLE></TD></TR></TABLE>";
|
||||
|
||||
print "<P><TABLE WIDTH=\"100%\">";
|
||||
print "<TR><TD ALIGN=CENTER><a href=admintree.cgi>";
|
||||
print "Administer</a> one of the following trees:</TD></TR>";
|
||||
print "<TR><TD ALIGN=CENTER>\n";
|
||||
print " <TABLE><TR><TD><UL>\n";
|
||||
|
||||
foreach (@list) {
|
||||
print "<LI><a href=admintree.cgi?tree=$_>$_</a>\n";
|
||||
}
|
||||
print "<//UL></TD></TR></TABLE></TD></TR></TABLE>";
|
||||
}
|
||||
|
||||
sub do_static {
|
||||
local *OUT;
|
||||
|
||||
$form{nocrap}=1;
|
||||
|
||||
my @pages = ( ['index.html', 'do_tinderbox'],
|
||||
['flash.rdf', 'do_flash'],
|
||||
['panel.html', 'do_panel'] );
|
||||
|
||||
$rel_path = '../';
|
||||
while (($key, $value) = each %images) {
|
||||
$images{$key} = "$rel_path$value";
|
||||
}
|
||||
|
||||
my $oldfh = select;
|
||||
|
||||
foreach $pair (@pages) {
|
||||
my ($page, $call) = @{$pair};
|
||||
my $outfile = "$form{tree}/$page";
|
||||
|
||||
open(OUT,">$outfile.$$");
|
||||
select OUT;
|
||||
|
||||
eval "$call";
|
||||
|
||||
close(OUT);
|
||||
system "mv $outfile.$$ $outfile";
|
||||
}
|
||||
select $oldfh;
|
||||
}
|
||||
|
||||
sub do_tinderbox {
|
||||
&load_data;
|
||||
&print_page_head;
|
||||
&print_table_header;
|
||||
&print_table_body;
|
||||
&print_table_footer;
|
||||
}
|
||||
|
||||
sub print_page_head {
|
||||
|
||||
print "Content-type: text/html",
|
||||
($nowdate eq $maxdate ? "\nRefresh: 900" : ''),
|
||||
"\n\n<HTML>\n" unless $form{static};
|
||||
|
||||
# Get the message of the day only on the first pageful
|
||||
do "$tree/mod.pl" if $nowdate eq $maxdate;
|
||||
|
||||
use POSIX qw(strftime);
|
||||
# Print time in format, "HH:MM timezone"
|
||||
my $now = strftime("%H:%M %Z", localtime);
|
||||
|
||||
EmitHtmlTitleAndHeader("tinderbox: $tree", "tinderbox",
|
||||
"tree: $tree ($now)");
|
||||
|
||||
&print_javascript;
|
||||
|
||||
print "$message_of_day\n";
|
||||
|
||||
# Quote and Lengend
|
||||
#
|
||||
unless ($form{nocrap}) {
|
||||
my ($imageurl,$imagewidth,$imageheight,$quote) = &get_image;
|
||||
print qq{
|
||||
<table width="100%" cellpadding=0 cellspacing=0>
|
||||
<tr>
|
||||
<td valign=bottom>
|
||||
<p><center><a href=addimage.cgi><img src="$rel_path$imageurl"
|
||||
width=$imagewidth height=$imageheight><br>
|
||||
$quote</a><br>
|
||||
</center>
|
||||
<p>
|
||||
<td align=right valign=bottom>
|
||||
<table cellspacing=0 cellpadding=1 border=0><tr><td align=center>
|
||||
<TT>L</TT></td><td>= Show Build Log
|
||||
</td></tr><tr><td align=center>
|
||||
<img src="$images{star}"></td><td>= Show Log comments
|
||||
</td></tr><tr><td colspan=2>
|
||||
<table cellspacing=1 cellpadding=1 border=1>
|
||||
<tr bgcolor="$colormap{success}"><td>Successful Build
|
||||
<tr bgcolor="$colormap{building}"><td>Build in Progress
|
||||
<tr bgcolor="$colormap{testfailed}"><td>Successful Build,
|
||||
but Tests Failed
|
||||
<tr bgcolor="$colormap{busted}"><td>Build Failed
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
};
|
||||
}
|
||||
if ($bonsai_tree) {
|
||||
print "The tree is currently <font size=+2>";
|
||||
print (&tree_open ? 'OPEN' : 'CLOSED');
|
||||
print "</font>\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub print_table_body {
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
last if $build_time_times->[$tt] < $mindate;
|
||||
print_table_row($tt);
|
||||
}
|
||||
}
|
||||
|
||||
sub print_table_row {
|
||||
my ($tt) = @_;
|
||||
|
||||
# Time column
|
||||
#
|
||||
my $query_link = '';
|
||||
my $end_query = '';
|
||||
my $pretty_time = &print_time($build_time_times->[$tt]);
|
||||
|
||||
($hour) = $pretty_time =~ /(\d\d):/;
|
||||
|
||||
if ($lasthour != $hour or &has_who_list($tt)) {
|
||||
$query_link = &query_ref($td1, $build_time_times->[$tt]);
|
||||
$end_query = '</a>';
|
||||
}
|
||||
if ($lasthour == $hour) {
|
||||
$pretty_time =~ s/^.* //;
|
||||
} else {
|
||||
$lasthour = $hour;
|
||||
}
|
||||
|
||||
my $hour_color = '';
|
||||
$hour_color = ' bgcolor=#e7e7e7' if $build_time_times->[$tt] % 7200 <= 3600;
|
||||
print "<tr align=center><td align=right$hour_color>",
|
||||
"$query_link\n$pretty_time$end_query</td>\n";
|
||||
|
||||
# Guilty
|
||||
#
|
||||
print '<td>';
|
||||
for $who (sort keys %{$who_list->[$tt]} ){
|
||||
$qr = &who_menu($td1, $build_time_times->[$tt],
|
||||
$build_time_times->[$tt-1],$who);
|
||||
$who =~ s/%.*$//;
|
||||
print " ${qr}$who</a>\n";
|
||||
}
|
||||
print '</td>';
|
||||
|
||||
# Build Status
|
||||
#
|
||||
for ($bn=1; $bn <= $name_count; $bn++) {
|
||||
if (not defined($br = $build_table->[$tt][$bn])) {
|
||||
# No build data for this time
|
||||
print "<td></td>\n";
|
||||
next;
|
||||
}
|
||||
next if $br == -1; # rowspan has covered this row
|
||||
|
||||
$hasnote = $br->{hasnote};
|
||||
$noteid = $hasnote ? $br->{noteid} : 0;
|
||||
$rowspan = $br->{rowspan};
|
||||
$rowspan = $mindate_time_count - $tt + 1
|
||||
if $tt + $rowspan - 1 > $mindate_time_count;
|
||||
$color = $colormap{$br->{buildstatus}};
|
||||
$status = $br->{buildstatus};
|
||||
print "<td rowspan=$rowspan bgcolor=${color}>\n";
|
||||
|
||||
$logfile = $br->{logfile};
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
$buildtime = $br->{buildtime};
|
||||
$buildtree = $br->{td}->{name};
|
||||
|
||||
print "<tt>\n";
|
||||
|
||||
# Build Note
|
||||
#
|
||||
$buildname = &url_encode($buildname);
|
||||
my $logurl = "${rel_path}showlog.cgi?log=$buildtree/$logfile";
|
||||
|
||||
if ($hasnote) {
|
||||
print "<a href='$logurl' onclick=\"return ",
|
||||
"note(event,$noteid,'$logfile');\">",
|
||||
"<img src='$images{star}' border=0></a>\n";
|
||||
}
|
||||
|
||||
# Build Log
|
||||
#
|
||||
print "<A HREF='$logurl' onclick=\"return log(event,$bn,'$logfile');\">";
|
||||
print "L</a>";
|
||||
|
||||
# What Changed
|
||||
#
|
||||
if( $br->{previousbuildtime} ){
|
||||
my $previous_br = $build_table->[$tt+$rowspan][$bn];
|
||||
my $previous_rowspan = $previous_br->{rowspan};
|
||||
if (&has_who_list($tt+$rowspan,
|
||||
$tt+$rowspan+$previous_rowspan-1)) {
|
||||
print "\n", &query_ref($br->{td},
|
||||
$br->{previousbuildtime},
|
||||
$br->{buildtime});
|
||||
print "C</a>";
|
||||
}
|
||||
}
|
||||
|
||||
if ($br->{binaryname} ne '') {
|
||||
$binfile = "$buildtree/bin/$buildtime/$br->{buildname}/"
|
||||
."$br->{binaryname}";
|
||||
$binfile =~ s/ //g;
|
||||
print " <a href=$rel_path$binfile>B</a>";
|
||||
}
|
||||
print "</tt>\n</td>";
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
sub print_table_header {
|
||||
my $ii, $nspan;
|
||||
|
||||
print "<table border=1 bgcolor='#FFFFFF' cellspacing=1 cellpadding=1>\n";
|
||||
|
||||
print "<tr align=center>\n";
|
||||
print "<td rowspan=1><font size=-1>Click time to <br>see changes <br>",
|
||||
"since time</font></td>";
|
||||
print "<td><font size=-1>",
|
||||
"Click name to see what they did</font>";
|
||||
print "<br><font size=-2>",
|
||||
&open_showbuilds_href(rebuildguilty=>'1'),
|
||||
"Rebuild guilty list</a></td>";
|
||||
|
||||
for ($ii=1; $ii <= $name_count; $ii++) {
|
||||
|
||||
my $bn = $build_name_names->[$ii];
|
||||
$bn =~ s/Clobber/Clbr/g;
|
||||
$bn =~ s/Depend/Dep/g;
|
||||
$bn = "<font face='Helvetica,Arial' size=-1>$bn</font>";
|
||||
|
||||
my $last_status = &last_status($ii);
|
||||
if ($last_status eq 'busted') {
|
||||
if ($form{nocrap}) {
|
||||
print "<td rowspan=2 bgcolor=$colormap{busted}>$bn</td>";
|
||||
} else {
|
||||
print "<td rowspan=2 bgcolor=000000 background='$images{flames}'>";
|
||||
print "<font color=white>$bn</font></td>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
print "<td rowspan=2 bgcolor=$colormap{$last_status}>$bn</td>";
|
||||
}
|
||||
}
|
||||
print "</tr><tr>\n";
|
||||
print "<TH>Build Time</TH>\n";
|
||||
print "<TH>Guilty</th>\n";
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
sub print_table_footer {
|
||||
print "</table>\n";
|
||||
|
||||
my $nextdate = $maxdate - $hours*60*60;
|
||||
print &open_showbuilds_href(maxdate=>"$nextdate", nocrap=>'1')
|
||||
."Show next $hours hours</a>";
|
||||
|
||||
print "<p><a href='${rel_path}admintree.cgi?tree=$tree'>",
|
||||
"Administrate Tinderbox Trees</a><br>\n";
|
||||
}
|
||||
|
||||
sub open_showbuilds_url {
|
||||
my %args = (
|
||||
nocrap => "$form{nocrap}",
|
||||
@_
|
||||
);
|
||||
|
||||
my $url = "${rel_path}showbuilds.cgi?tree=$form{tree}";
|
||||
$url .= "&hours=$hours" if $hours ne $default_hours;
|
||||
while (my ($key, $value) = each %args) {
|
||||
$url .= "&$key=$value" if $value ne '';
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
sub open_showbuilds_href {
|
||||
return "<a href=".open_showbuilds_url(@_).">";
|
||||
}
|
||||
|
||||
sub query_ref {
|
||||
my ($td, $mindate, $maxdate, $who) = @_;
|
||||
my $output = '';
|
||||
|
||||
$output = "<a href=${rel_path}../bonsai/cvsquery.cgi";
|
||||
$output .= "?module=$td->{cvs_module}";
|
||||
$output .= "&branch=$td->{cvs_branch}" if $td->{cvs_branch} ne 'HEAD';
|
||||
$output .= "&cvsroot=$td->{cvs_root}" if $td->{cvs_root} ne $default_root;
|
||||
$output .= "&date=explicit&mindate=$mindate";
|
||||
$output .= "&maxdate=$maxdate" if $maxdate ne '';
|
||||
$output .= "&who=$who" if $who ne '';
|
||||
$output .= ">";
|
||||
}
|
||||
|
||||
sub query_ref2 {
|
||||
my ($td, $mindate, $maxdate, $who) = @_;
|
||||
return "${rel_path}../bonsai/cvsquery.cgi?module=$td->{cvs_module}"
|
||||
."&branch=$td->{cvs_branch}&cvsroot=$td->{cvs_root}"
|
||||
."&date=explicit&mindate=$mindate&maxdate=$maxdate&who="
|
||||
. url_encode($who);
|
||||
}
|
||||
|
||||
sub who_menu {
|
||||
my ($td, $mindate, $maxdate, $who) = @_;
|
||||
my $treeflag;
|
||||
|
||||
$qr = "${rel_path}../registry/who.cgi?email=". url_encode($who)
|
||||
. "&d=$td->{cvs_module}|$td->{cvs_branch}|$td->{cvs_root}|$mindate|$maxdate";
|
||||
|
||||
return "<a href='$qr' onclick=\"return who(event);\">";
|
||||
}
|
||||
|
||||
# Check to see if anyone checked in during time slot.
|
||||
# ex. has_who_list(1); # Check for checkins in most recent time slot.
|
||||
# ex. has_who_list(1,5); # Check range of times.
|
||||
sub has_who_list {
|
||||
my ($time1, $time2) = @_;
|
||||
|
||||
if (not defined(@who_check_list)) {
|
||||
# Build a static array of true/false values for each time slot.
|
||||
$who_check_list[$time_count] = 0;
|
||||
my ($t) = 1;
|
||||
for (; $t<=$time_count; $t++) {
|
||||
$who_check_list[$t] = 1 if each %{$who_list->[$t]};
|
||||
}
|
||||
}
|
||||
if ($time2) {
|
||||
for ($ii=$time1; $ii<=$time2; $ii++) {
|
||||
return 1 if $who_check_list[$ii]
|
||||
}
|
||||
return 0
|
||||
} else {
|
||||
return $who_check_list[$time1];
|
||||
}
|
||||
}
|
||||
|
||||
sub tree_open {
|
||||
my $done, $line, $a, $b;
|
||||
open(BID, "<../bonsai/data/$bonsai_tree/batchid")
|
||||
or print "can't open batchid<br>";
|
||||
($a,$b,$bid) = split / /, <BID>;
|
||||
close(BID);
|
||||
open(BATCH, "<../bonsai/data/$bonsai_tree/batch-${bid}")
|
||||
or print "can't open batch-${bid}<br>";;
|
||||
$done = 0;
|
||||
while (($line = <BATCH>) and not $done){
|
||||
if ($line =~ /^set treeopen/) {
|
||||
chop $line;
|
||||
($a,$b,$treestate) = split / /, $line ;
|
||||
$done = 1;
|
||||
}
|
||||
}
|
||||
close(BATCH);
|
||||
return $treestate;
|
||||
}
|
||||
|
||||
sub print_javascript {
|
||||
my $script;
|
||||
($script = <<"__ENDJS") =~ s/^ //gm;
|
||||
<script>
|
||||
if (parseInt(navigator.appVersion) < 4) {
|
||||
window.event = 0;
|
||||
}
|
||||
|
||||
function who(d) {
|
||||
var version = parseInt(navigator.appVersion);
|
||||
if (version < 4 || version >= 5) {
|
||||
return true;
|
||||
}
|
||||
var l = document.layers['popup'];
|
||||
l.src = d.target.href;
|
||||
l.top = d.target.y - 6;
|
||||
l.left = d.target.x - 6;
|
||||
if (l.left + l.clipWidth > window.width) {
|
||||
l.left = window.width - l.clipWidth;
|
||||
}
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
function log_url(logfile) {
|
||||
return "showlog.cgi?log=" + buildtree + "/" + logfile;
|
||||
}
|
||||
function note(d,noteid,logfile) {
|
||||
var version = parseInt(navigator.appVersion);
|
||||
if (version < 4 || version >= 5) {
|
||||
document.location = log_url(logfile);
|
||||
return false;
|
||||
}
|
||||
var l = document.layers['popup'];
|
||||
l.document.write("<table border=1 cellspacing=1><tr><td>"
|
||||
+ notes[noteid] + "</tr></table>");
|
||||
l.document.close();
|
||||
|
||||
l.top = d.y-10;
|
||||
var zz = d.x;
|
||||
if (zz + l.clip.right > window.innerWidth) {
|
||||
zz = (window.innerWidth-30) - l.clip.right;
|
||||
if (zz < 0) { zz = 0; }
|
||||
}
|
||||
l.left = zz;
|
||||
l.visibility="show";
|
||||
return false;
|
||||
}
|
||||
function log(e,buildindex,logfile)
|
||||
{
|
||||
var logurl = log_url(logfile);
|
||||
var commenturl = "addnote.cgi?log=" + buildtree + "/" + logfile;
|
||||
var version = parseInt(navigator.appVersion);
|
||||
|
||||
if (version < 4 || version >= 5) {
|
||||
document.location = logurl;
|
||||
return false;
|
||||
}
|
||||
var q = document.layers["logpopup"];
|
||||
q.top = e.target.y - 6;
|
||||
|
||||
var yy = e.target.x;
|
||||
if ( yy + q.clip.right > window.innerWidth) {
|
||||
yy = (window.innerWidth-30) - q.clip.right;
|
||||
if (yy < 0) { yy = 0; }
|
||||
}
|
||||
q.left = yy;
|
||||
q.visibility="show";
|
||||
q.document.write("<TABLE BORDER=1><TR><TD><B>"
|
||||
+ builds[buildindex] + "</B><BR>"
|
||||
+ "<A HREF=$rel_path" + logurl + ">View Brief Log</A><BR>"
|
||||
+ "<A HREF=$rel_path" + logurl + "&fulltext=1"+">View Full Log</A><BR>"
|
||||
+ "<A HREF=$rel_path" + commenturl + ">Add a Comment</A><BR>"
|
||||
+ "</TD></TR></TABLE>");
|
||||
q.document.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
notes = new Array();
|
||||
builds = new Array();
|
||||
|
||||
__ENDJS
|
||||
print $script;
|
||||
|
||||
$ii = 0;
|
||||
while ($ii < @note_array) {
|
||||
$ss = $note_array[$ii];
|
||||
while ($ii < @note_array && $note_array[$ii] eq $ss) {
|
||||
print "notes[$ii] = ";
|
||||
$ii++;
|
||||
}
|
||||
$ss =~ s/\\/\\\\/g;
|
||||
$ss =~ s/\"/\\\"/g;
|
||||
$ss =~ s/\n/\\n/g;
|
||||
print "\"$ss\";\n";
|
||||
}
|
||||
for ($ii=1; $ii <= $name_count; $ii++) {
|
||||
if (defined($br = $build_table->[1][$ii]) and $br != -1) {
|
||||
my $bn = $build_name_names->[$ii];
|
||||
print "builds[$ii]='$bn';\n";
|
||||
}
|
||||
}
|
||||
print "buildtree = '$form{tree}';\n";
|
||||
|
||||
($script = <<'__ENDJS') =~ s/^ //gm;
|
||||
</script>
|
||||
|
||||
<layer name="popup" onMouseOut="this.visibility='hide';"
|
||||
left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
|
||||
<layer name="logpopup" onMouseOut="this.visibility='hide';"
|
||||
left=0 top=0 bgcolor="#ffffff" visibility="hide">
|
||||
</layer>
|
||||
__ENDJS
|
||||
print $script;
|
||||
}
|
||||
|
||||
sub do_express {
|
||||
print "Content-type: text/html\nRefresh: 900\n\n<HTML>\n";
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($form{tree}, \%build, \%times);
|
||||
|
||||
my @keys = sort keys %build;
|
||||
my $keycount = @keys;
|
||||
my $tm = &print_time(time);
|
||||
print "<table border=1 cellpadding=1 cellspacing=1><tr>";
|
||||
print "<th align=left colspan=$keycount>";
|
||||
print &open_showbuilds_href."$tree as of $tm</a></tr><tr>\n";
|
||||
foreach my $buildname (@keys) {
|
||||
print "<td bgcolor='$colormap{$build{$buildname}}'>$buildname</td>";
|
||||
}
|
||||
print "</tr></table>\n";
|
||||
}
|
||||
|
||||
# This is essentially do_express but it outputs a different format
|
||||
sub do_panel {
|
||||
print "Content-type: text/html\n\n<HTML>\n" unless $form{static};
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($form{tree}, \%build, \%times);
|
||||
|
||||
print q(
|
||||
<head>
|
||||
<META HTTP-EQUIV="Refresh" CONTENT="300">
|
||||
<style>
|
||||
body, td {
|
||||
font-family: Verdana, Sans-Serif;
|
||||
font-size: 8pt;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body BGCOLOR="#FFFFFF" TEXT="#000000"
|
||||
LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
|
||||
);
|
||||
# Hack the panel link for now.
|
||||
print "<a target='_content' href='http://tinderbox.mozilla.org/seamonkey/'>$tree";
|
||||
|
||||
$bonsai_tree = '';
|
||||
require "$tree/treedata.pl";
|
||||
if ($bonsai_tree ne '') {
|
||||
print " is ", tree_open() ? "OPEN" : "CLOSED";
|
||||
}
|
||||
# Add the current time
|
||||
my ($minute,$hour,$mday,$mon) = (localtime)[1..4];
|
||||
my $tm = sprintf("%d/%d %d:%02d",$mon+1,$mday,$hour,$minute);
|
||||
print " as of $tm</a><br>";
|
||||
|
||||
print "<table border=0 cellpadding=1 cellspacing=1>";
|
||||
while (my ($name, $status) = each %build) {
|
||||
print "<tr><td bgcolor='$colormap{$status}'>$name</td></tr>";
|
||||
}
|
||||
print "</table></body>";
|
||||
}
|
||||
|
||||
sub do_flash {
|
||||
print "Content-type: text/rdf\n\n" unless $form{static};
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($form{tree}, \%build, \%times);
|
||||
|
||||
my ($mac,$unix,$win) = (0,0,0);
|
||||
|
||||
while (my ($name, $status) = each %build) {
|
||||
next if $status eq 'success';
|
||||
$mac = 1, next if $name =~ /Mac/;
|
||||
$win = 1, next if $name =~ /Win/;
|
||||
$unix = 1;
|
||||
}
|
||||
|
||||
print q{
|
||||
<RDF:RDF xmlns:RDF='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
|
||||
xmlns:NC='http://home.netscape.com/NC-rdf#'>
|
||||
<RDF:Description about='NC:FlashRoot'>
|
||||
};
|
||||
|
||||
my $busted = $mac + $unix + $win;
|
||||
if ($busted) {
|
||||
|
||||
# Construct a legible sentence; e.g., "Mac, Unix, and Windows
|
||||
# are busted", "Windows is busted", etc. This is hideous. If
|
||||
# you can think of something better, please fix it.
|
||||
|
||||
my $text;
|
||||
if ($mac) {
|
||||
$text .= 'Mac' . ($busted > 2 ? ', ' : ($busted > 1 ? ' and ' : ''));
|
||||
}
|
||||
if ($unix) {
|
||||
$text .= 'Unix' . ($busted > 2 ? ', and ' : ($win ? ' and ' : ''));
|
||||
}
|
||||
if ($win) {
|
||||
$text .= 'Windows';
|
||||
}
|
||||
$text .= ($busted > 1 ? ' are ' : ' is ') . 'busted';
|
||||
|
||||
# The Flash spec says we need to give ctime.
|
||||
use POSIX;
|
||||
my $tm = POSIX::ctime(time());
|
||||
$tm =~ s/^...\s//; # Strip day of week
|
||||
$tm =~ s/:\d\d\s/ /; # Strip seconds
|
||||
chop $tm;
|
||||
|
||||
print qq{
|
||||
<NC:child>
|
||||
<RDF:Description ID='flash'>
|
||||
<NC:type resource='http://www.mozilla.org/RDF#TinderboxFlash' />
|
||||
<NC:source>$tree</NC:source>
|
||||
<NC:description>$text</NC:description>
|
||||
<NC:timestamp>$tm</NC:timestamp>
|
||||
</RDF:Description>
|
||||
</NC:child>
|
||||
};
|
||||
}
|
||||
print q{
|
||||
</RDF:Description>
|
||||
</RDF:RDF>
|
||||
};
|
||||
}
|
||||
|
||||
sub do_quickparse {
|
||||
print "Content-type: text/plain\n\n";
|
||||
|
||||
my @treelist = split /,/, $tree;
|
||||
foreach my $t (@treelist) {
|
||||
$bonsai_tree = "";
|
||||
require "$t/treedata.pl";
|
||||
if ($bonsai_tree ne "") {
|
||||
my $state = tree_open() ? "Open" : "Close";
|
||||
print "State|$t|$bonsai_tree|$state\n";
|
||||
}
|
||||
my %build, %times;
|
||||
loadquickparseinfo($t, \%build, \%times);
|
||||
|
||||
foreach my $buildname (sort keys %build) {
|
||||
print "Build|$t|$buildname|$build{$buildname}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_rdf {
|
||||
print "Content-type: text/plain\n\n";
|
||||
|
||||
my $mainurl = "http://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}?tree=$tree";
|
||||
my $dirurl = $mainurl;
|
||||
|
||||
$dirurl =~ s@/[^/]*$@@;
|
||||
|
||||
my %build, %times;
|
||||
loadquickparseinfo($tree, \%build, \%times);
|
||||
|
||||
my $image = "channelok.gif";
|
||||
my $imagetitle = "OK";
|
||||
foreach my $buildname (sort keys %build) {
|
||||
if ($build{$buildname} eq 'busted') {
|
||||
$image = "channelflames.gif";
|
||||
$imagetitle = "Bad";
|
||||
last;
|
||||
}
|
||||
}
|
||||
print qq{<?xml version="1.0"?>
|
||||
<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://my.netscape.com/rdf/simple/0.9/">
|
||||
<channel>
|
||||
<title>Tinderbox - $tree</title>
|
||||
<description>Build bustages for $tree</description>
|
||||
<link>$mainurl</link>
|
||||
</channel>
|
||||
<image>
|
||||
<title>$imagetitle</title>
|
||||
<url>$dirurl/$image</url>
|
||||
<link>$mainurl</link>
|
||||
</image>
|
||||
};
|
||||
|
||||
$bonsai_tree = '';
|
||||
require "$tree/treedata.pl";
|
||||
if ($bonsai_tree ne '') {
|
||||
my $state = tree_open() ? "OPEN" : "CLOSED";
|
||||
print "<item><title>The tree is currently $state</title>",
|
||||
"<link>$mainurl</link></item>\n";
|
||||
}
|
||||
|
||||
foreach my $buildname (sort keys %build) {
|
||||
if ($build{$buildname} eq 'busted') {
|
||||
print "<item><title>$buildname is in flames</title>",
|
||||
"<link>$mainurl</link></item>\n";
|
||||
}
|
||||
}
|
||||
print "</rdf:RDF>\n";
|
||||
}
|
||||
|
||||
136
mozilla/webtools/tinderbox/showimages.cgi
Executable file
136
mozilla/webtools/tinderbox/showimages.cgi
Executable file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
$| = 1;
|
||||
|
||||
use lib "../bonsai";
|
||||
|
||||
require 'globals.pl';
|
||||
require 'imagelog.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
check_password();
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
@url = ();
|
||||
@quote = ();
|
||||
@width = ();
|
||||
@height = ();
|
||||
$i = 0;
|
||||
|
||||
EmitHtmlHeader("tinderbox: all images");
|
||||
|
||||
print '<UL>
|
||||
<P>These are all of the images currently in
|
||||
<A HREF=http://www.mozilla.org/tinderbox.html>Tinderbox</A>.
|
||||
<P>Please don\'t give out this URL: this is only here for our debugging
|
||||
needs, and isn\'t linked to by the rest of Tinderbox: because looking at
|
||||
all the images at once would be be cheating! you\'re supposed to let them
|
||||
surprise you over time. What, do you read ahead in your desktop calendar,
|
||||
too? Where\'s your sense of mystery and anticipation?
|
||||
|
||||
<P>
|
||||
</UL>
|
||||
';
|
||||
|
||||
|
||||
|
||||
|
||||
if ($form{'url'} ne "") {
|
||||
$oldname = "$data_dir/imagelog.txt";
|
||||
open (OLD, "<$oldname") || die "Oops; can't open imagelog.txt";
|
||||
$newname = "$oldname-$$";
|
||||
open (NEW, ">$newname") || die "Can't open $newname";
|
||||
$foundit = 0;
|
||||
while (<OLD>) {
|
||||
chop;
|
||||
($url, $width, $height, $quote) = split(/\`/);
|
||||
if ($url eq $form{'url'} && $quote eq $form{'origquote'}) {
|
||||
$foundit = 1;
|
||||
if ($form{'nukeit'} ne "") {
|
||||
next;
|
||||
}
|
||||
$quote = $form{'quote'};
|
||||
}
|
||||
print NEW "$url`$width`$height`$quote\n";
|
||||
}
|
||||
close OLD;
|
||||
close NEW;
|
||||
if (!$foundit) {
|
||||
print "<font color=red>Hey, couldn't find it!</font> Did someone\n";
|
||||
print "else already edit it?<P>\n";
|
||||
unlink $newname;
|
||||
} else {
|
||||
print "Change made.<P>";
|
||||
rename ($newname, $oldname) || die "Couldn't rename $newname to $oldname";
|
||||
}
|
||||
$form{'doedit'} = "1";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$doedit = ($form{'doedit'} ne "");
|
||||
|
||||
if (!$doedit) {
|
||||
print "
|
||||
<form method=post>
|
||||
<input type=hidden name=password value=\"$form{'password'}\">
|
||||
<input type=hidden name=doedit value=1>
|
||||
<input type=submit value='Let me edit text or remove pictures.'>
|
||||
</form><P>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
open( IMAGELOG, "<$data_dir/imagelog.txt" ) || die "can't open file";
|
||||
while( <IMAGELOG> ){
|
||||
chop;
|
||||
($url[$i],$width[$i],$height[$i],$quote[$i]) = split(/\`/);
|
||||
$i++;
|
||||
}
|
||||
close( IMAGELOG );
|
||||
|
||||
$i--;
|
||||
print "<center>";
|
||||
while( $i >= 0 ){
|
||||
$qurl = value_encode($url[$i]);
|
||||
$qquote = value_encode($quote[$i]);
|
||||
print "
|
||||
<img border=2 src='$url[$i]' width='$width[$i]' height='$height[$i]'><br>
|
||||
<i>$quote[$i]</i>";
|
||||
if ($doedit) {
|
||||
print "
|
||||
<form method=post>
|
||||
<input type=submit name=nukeit value='Delete this image'><br>
|
||||
<input name=quote size=60 value=\"$qquote\"><br>
|
||||
<input type=submit name=edit value='Change text'><hr>
|
||||
<input type=hidden name=url value=\"$qurl\">
|
||||
<input type=hidden name=origquote value=\"$qquote\">
|
||||
<input type=hidden name=password value=\"$form{'password'}\">
|
||||
</form>";
|
||||
}
|
||||
print "<br><br>\n";
|
||||
$i--;
|
||||
}
|
||||
|
||||
|
||||
375
mozilla/webtools/tinderbox/showlog.cgi
Executable file
375
mozilla/webtools/tinderbox/showlog.cgi
Executable file
@@ -0,0 +1,375 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib '../bonsai';
|
||||
|
||||
require 'globals.pl';
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
#############################################################
|
||||
# Global variables
|
||||
|
||||
$LINES_AFTER_ERROR = 5;
|
||||
$LINES_BEFORE_ERROR = 30;
|
||||
|
||||
# These variables are set by the error parser functions:
|
||||
# has_error(), has_warning(), and has_errorline().
|
||||
$error_file = '';
|
||||
$error_file_ref = '';
|
||||
$error_line = 0;
|
||||
$error_guess = 0;
|
||||
|
||||
$next_err = 0;
|
||||
@log_errors = ();
|
||||
$log_line = 0;
|
||||
|
||||
#############################################################
|
||||
# CGI inputs
|
||||
|
||||
if (defined($args = $form{log}) or defined($args = $form{exerpt})) {
|
||||
|
||||
($full_logfile, $linenum) = split /:/, $args;
|
||||
($tree, $logfile) = split /\//, $full_logfile;
|
||||
|
||||
my $br = find_build_record($tree, $logfile);
|
||||
$errorparser = $br->{errorparser};
|
||||
$buildname = $br->{buildname};
|
||||
$buildtime = $br->{buildtime};
|
||||
|
||||
$numlines = 50;
|
||||
$numlines = $form{numlines} if exists $form{numlines};
|
||||
} else {
|
||||
$tree = $form{tree};
|
||||
$errorparser = $form{errorparser};
|
||||
$logfile = $form{logfile};
|
||||
$buildname = $form{buildname};
|
||||
$buildtime = $form{buildtime};
|
||||
}
|
||||
$fulltext = $form{fulltext};
|
||||
|
||||
$enc_buildname = &url_encode($buildname);
|
||||
|
||||
die "the \"tree\" parameter must be provided\n" unless $tree;
|
||||
require "$tree/treedata.pl";
|
||||
|
||||
$time_str = print_time( $buildtime );
|
||||
|
||||
$|=1;
|
||||
|
||||
if ($linenum) {
|
||||
|
||||
&print_fragment;
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
&print_header;
|
||||
&print_notes;
|
||||
|
||||
# Dynamically load the error parser
|
||||
#
|
||||
die "the \"errorparser\" parameter must be provided\n" unless $errorparser;
|
||||
require "ep_${errorparser}.pl";
|
||||
|
||||
if ($fulltext)
|
||||
{
|
||||
&print_summary;
|
||||
&print_log;
|
||||
}
|
||||
else
|
||||
{
|
||||
$brief_filename = $logfile;
|
||||
$brief_filename =~ s/.gz$/.brief.html/;
|
||||
if (-T "$tree/$brief_filename" and -M _ > -M $tree/$logfile)
|
||||
{
|
||||
open (BRIEFFILE, "<$tree/$brief_filename");
|
||||
print while (<BRIEFFILE>)
|
||||
}
|
||||
else
|
||||
{
|
||||
open (BRIEFFILE, ">$tree/$brief_filename");
|
||||
|
||||
&print_summary;
|
||||
&print_log;
|
||||
}
|
||||
}
|
||||
|
||||
# end of main
|
||||
############################################################
|
||||
|
||||
sub print_fragment {
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
print "<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"1\">\n";
|
||||
|
||||
my $heading = "Build Log (Fragment)";
|
||||
my $subheading = "$buildname on $time_str";
|
||||
my $title = "$heading - $subheading";
|
||||
|
||||
EmitHtmlTitleAndHeader($title, $heading, $subheading);
|
||||
|
||||
print "<a href='showlog.cgi?tree=$tree&errorparser=$errorparser&logfile=$logfile&buildtime=$buildtime&buildname=$enc_buildname&fulltext=1'>Show Full Build Log</a>";
|
||||
|
||||
open(BUILD_IN, "$gzip -d -c $tree/$logfile|");
|
||||
|
||||
my $first_line = $linenum - ($numlines/2);
|
||||
my $last_line = $linenum + ($numlines/2);
|
||||
|
||||
print "<pre><b>.<br>.<br>.<br></b>";
|
||||
while(<BUILD_IN>) {
|
||||
next if $. < $first_line;
|
||||
last if $. > $last_line;
|
||||
print "<b><font color='red'>" if $. == $linenum;
|
||||
print;
|
||||
print "</font></b>" if $. == $linenum;
|
||||
}
|
||||
print "<b>.<br>.<br>.<br></b></pre>";
|
||||
|
||||
}
|
||||
|
||||
sub print_header {
|
||||
print "Content-type: text/html\n\n";
|
||||
|
||||
if( $fulltext ){
|
||||
$s = 'Show <b>Brief</b> Log';
|
||||
$s1 = '';
|
||||
$s2 = 'Full';
|
||||
}
|
||||
else {
|
||||
$s = 'Show <b>Full</b> Log';
|
||||
$s1 = 1;
|
||||
$s2 = 'Brief';
|
||||
}
|
||||
|
||||
print "<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"1\">\n";
|
||||
|
||||
my $heading = "Build Log ($s2)";
|
||||
my $subheading = "$buildname on $time_str";
|
||||
my $title = "$heading - $subheading";
|
||||
|
||||
EmitHtmlTitleAndHeader($title, $heading, $subheading);
|
||||
|
||||
print "
|
||||
<font size=+1>
|
||||
<dt><a href='showlog.cgi?tree=$tree&errorparser=$errorparser&logfile=$logfile&buildtime=$buildtime&buildname=$enc_buildname&fulltext=$s1'>$s</a>
|
||||
<dt><a href=\"showbuilds.cgi?tree=$tree\">Return to the Build Page</a>
|
||||
<dt><a href=\"addnote.cgi?tree=$tree\&buildname=$enc_buildname\&buildtime=$buildtime\&logfile=$logfile\&errorparser=$errorparser\">
|
||||
Add a Comment to the Log</a>
|
||||
</font>
|
||||
";
|
||||
}
|
||||
|
||||
sub print_notes {
|
||||
#
|
||||
# Print notes
|
||||
#
|
||||
$found_note = 0;
|
||||
open(NOTES,"<$tree/notes.txt")
|
||||
or print "<h2>warning: Couldn't open $tree/notes.txt </h2>\n";
|
||||
print "$buildtime, $buildname<br>\n";
|
||||
while(<NOTES>){
|
||||
chop;
|
||||
($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note) = split(/\|/);
|
||||
#print "$_<br>\n";
|
||||
if( $nbuildtime == $buildtime && $nbuildname eq $buildname ){
|
||||
if( !$found_note ){
|
||||
print "<H2>Build Comments</H2>\n";
|
||||
$found_note = 1;
|
||||
}
|
||||
$now_str = &print_time($nnow);
|
||||
$note = &url_decode($nenc_note);
|
||||
print "<pre>\n[<b><a href=mailto:$nwho>$nwho</a> - $now_str</b>]\n$note\n</pre>";
|
||||
}
|
||||
}
|
||||
close(NOTES);
|
||||
}
|
||||
|
||||
sub print_summary {
|
||||
#
|
||||
# Print the summary first
|
||||
#
|
||||
logprint('<H2>Build Error Summary</H2><PRE>');
|
||||
|
||||
$log_line = 0;
|
||||
open( BUILD_IN, "$gzip -d -c $tree/$logfile|" );
|
||||
while( $line = <BUILD_IN> ){
|
||||
&output_summary_line( $line );
|
||||
}
|
||||
close( BUILD_IN );
|
||||
push @log_errors, 9999999;
|
||||
|
||||
logprint('</PRE>');
|
||||
}
|
||||
|
||||
sub print_log_section {
|
||||
my ($tree, $logfile, $line_of_interest, $num_lines) = shift;
|
||||
local $_;
|
||||
|
||||
my $first_line = $line_of_interest - $num_lines / 2;
|
||||
my $last_line = $first_line + $num_lines;
|
||||
|
||||
print "<a href='showlog.cgi?tree=$tree&logfile=$logfile&line="
|
||||
.($line_of_interest-$num_lines)."&numlines=$num_lines'>"
|
||||
."Previous $num_lines</a>";
|
||||
print "<font size='+1'><b>.<br>.<br>.<br></b></font>";
|
||||
print "<pre>";
|
||||
my $ii = 0;
|
||||
open BUILD_IN, "$gzip -d -c $tree/$logfile|";
|
||||
while (<BUILD_IN>) {
|
||||
$ii++;
|
||||
next if $ii < $first_line;
|
||||
last if $ii > $last_line;
|
||||
if ($ii == $line_of_intested) {
|
||||
print "<b>$_</b>";
|
||||
} else {
|
||||
print;
|
||||
}
|
||||
}
|
||||
close BUILD_IN;
|
||||
print "</pre>";
|
||||
print "<font size='+1'><b>.<br>.<br>.<br></b></font>";
|
||||
print "<a href='showlog.cgi?tree=$tree&logfile=$logfile&line="
|
||||
.($line_of_interest+$num_lines)."&numlines=$num_lines'>"
|
||||
."Next $num_lines</a>";
|
||||
}
|
||||
|
||||
sub print_log {
|
||||
#
|
||||
# reset the error counter
|
||||
#
|
||||
$next_err = 0;
|
||||
|
||||
logprint('<H2>Build Error Log</H2><pre>');
|
||||
|
||||
$log_line = 0;
|
||||
open( BUILD_IN, "$gzip -d -c $tree/$logfile|" );
|
||||
while( $line = <BUILD_IN> ){
|
||||
&output_log_line( $line );
|
||||
}
|
||||
close( BUILD_IN );
|
||||
|
||||
logprint('</PRE><p>'
|
||||
."<font size=+1><a name=\"err$next_err\">No More Errors</a></font>"
|
||||
.'<br><br><br>');
|
||||
}
|
||||
|
||||
sub output_summary_line {
|
||||
my( $line ) = $_[0];
|
||||
my( $has_error );
|
||||
|
||||
$has_error = &has_error( $line );
|
||||
|
||||
$line =~ s/&/&/g;
|
||||
$line =~ s/</</g;
|
||||
|
||||
if( $has_error ){
|
||||
push @log_errors, $log_line + $LINES_AFTER_ERROR;
|
||||
if( ! $last_was_error ) {
|
||||
logprint("<a href=\"#err$next_err\">$line</a>");
|
||||
$next_err++;
|
||||
}
|
||||
$last_was_error = 1;
|
||||
}
|
||||
else {
|
||||
$last_was_error = 0;
|
||||
}
|
||||
|
||||
$log_line++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub output_log_line {
|
||||
my( $line ) = $_[0];
|
||||
my( $has_error, $dur, $dur_min,$dur_sec, $dur_str, $logline );
|
||||
|
||||
$has_error = &has_error( $line );
|
||||
$has_warning = &has_warning( $line );
|
||||
|
||||
$line =~ s/&/&/g;
|
||||
$line =~ s/</</g;
|
||||
|
||||
$logline = '';
|
||||
|
||||
if( ($has_error || $has_warning) && &has_errorline( $line ) ) {
|
||||
$q = quotemeta( $error_file );
|
||||
#$goto_line = ($error_line ? 10 > $error_line - 10 : 1 );
|
||||
$goto_line = ($error_line > 10 ? $error_line - 10 : 1 );
|
||||
$cvsblame = ($error_guess ? "cvsguess.cgi" : "cvsblame.cgi");
|
||||
$line =~ s@$q@<a href=../bonsai/$cvsblame?file=$error_file_ref&rev=$cvs_branch&mark=$error_line#$goto_line $source_target>$error_file</a>@
|
||||
}
|
||||
|
||||
|
||||
if( $has_error ){
|
||||
if( ! $last_was_error ) {
|
||||
$logline .= "<a name=\"err$next_err\"></a>";
|
||||
$next_err++;
|
||||
$logline .= "<a href=\"#err$next_err\">NEXT</a> ";
|
||||
}
|
||||
else {
|
||||
$logline .= " ";
|
||||
}
|
||||
|
||||
$logline .= "<font color=\"000080\">$line</font>";
|
||||
|
||||
$last_was_error = 1;
|
||||
}
|
||||
elsif( $has_warning ){
|
||||
$logline .= " ";
|
||||
$logline .= "<font color=000080>$line</font>";
|
||||
}
|
||||
else {
|
||||
$logline .= " $line";
|
||||
$last_was_error = 0;
|
||||
}
|
||||
|
||||
&push_log_line( $logline );
|
||||
}
|
||||
|
||||
|
||||
sub push_log_line {
|
||||
my( $line ) = $_[0];
|
||||
if( $fulltext ){
|
||||
logprint($line);
|
||||
return;
|
||||
}
|
||||
|
||||
if( $log_line > $log_errors[$cur_error] ){
|
||||
$cur_error++;
|
||||
}
|
||||
|
||||
if( $log_line >= $log_errors[$cur_error] - $LINES_BEFORE_ERROR ){
|
||||
if( $log_skip != 0 ){
|
||||
logprint("\n<i><font size=+1> Skipping $log_skip Lines...</i></font>\n\n");
|
||||
$log_skip = 0;
|
||||
}
|
||||
logprint($line);
|
||||
}
|
||||
else {
|
||||
$log_skip++;
|
||||
}
|
||||
$log_line++;
|
||||
}
|
||||
|
||||
sub logprint {
|
||||
my $line = $_[0];
|
||||
print $line;
|
||||
print BRIEFFILE $line if not $fulltext;
|
||||
}
|
||||
BIN
mozilla/webtools/tinderbox/star.gif
Normal file
BIN
mozilla/webtools/tinderbox/star.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 227 B |
75
mozilla/webtools/tinderbox/tinderbox.spec
Normal file
75
mozilla/webtools/tinderbox/tinderbox.spec
Normal file
@@ -0,0 +1,75 @@
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (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 Tinderbox CVS Tool rpm spec file.
|
||||
#
|
||||
# The Initial Developer of this code under the MPL is Christopher
|
||||
# Seawood, <cls@seawood.org>. Portions created by Christopher Seawood
|
||||
# are Copyright (C) 1998 Christopher Seawood. All Rights Reserved.
|
||||
|
||||
%define ver SNAP
|
||||
%define perl /usr/bin/perl
|
||||
%define cvsroot /cvsroot
|
||||
%define gzip /usr/bin/gzip
|
||||
%define uudecode /usr/bin/uudecode
|
||||
%define bonsai ../bonsai
|
||||
%define prefix /home/httpd/html/tinderbox
|
||||
# This rpm is not relocateable
|
||||
Summary: automated build tool
|
||||
Name: tinderbox
|
||||
Version: %{ver}
|
||||
Release: 1
|
||||
Copyright: NPL
|
||||
Group: Networking/Admin
|
||||
Source: %{name}-%{ver}.tar.gz
|
||||
BuildRoot: /var/tmp/build-%{name}
|
||||
Requires: bonsai
|
||||
Packager: Christopher Seawood <cls@seawood.org>
|
||||
|
||||
%changelog
|
||||
* Thu Nov 12 1998 Christopher Seawood <cls@seawood.org>
|
||||
- Replaced ver with SNAP
|
||||
|
||||
* Mon Oct 26 1998 Christopher Seawood <cls@seawood.org>
|
||||
- Added MPL header
|
||||
|
||||
* Sun Aug 31 1998 Christopher Seawood <cls@seawood.org>
|
||||
- Made rpm from cvs snapshot
|
||||
|
||||
%description
|
||||
Essentially, Tinderbox is a detective tool. It allows you to see what
|
||||
is happening in the source tree. It shows you who checked in what (by
|
||||
asking Bonsai); what platforms have built successfully; what platforms
|
||||
are broken and exactly how they are broken (the build logs); and the
|
||||
state of the files that made up the build (cvsblame) so you can figure
|
||||
out who broke the build, so you can do the most important thing, hold
|
||||
them accountable for their actions.
|
||||
|
||||
%prep
|
||||
%setup -n %{name}
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{prefix}/{data,examples}
|
||||
make install PERL=%perl UUDECODE=%uudecode GZIP=%gzip BONSAI=%bonsai CVSROOT=%cvsroot PREFIX=${RPM_BUILD_ROOT}%prefix
|
||||
|
||||
%post
|
||||
echo "Remember to set the admin passwd via '%{bonsai}/data/trapdoor password > %{prefix}/data/passwd"
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr (-, nobody, nobody)
|
||||
%doc README Makefile
|
||||
%{prefix}
|
||||
|
||||
123
mozilla/webtools/tinderbox/viewallnotes.cgi
Executable file
123
mozilla/webtools/tinderbox/viewallnotes.cgi
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bonsaitools/bin/perl --
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (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 the Tinderbox build tool.
|
||||
#
|
||||
# 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.
|
||||
|
||||
use lib '../bonsai';
|
||||
require "globals.pl";
|
||||
require 'lloydcgi.pl';
|
||||
require 'header.pl';
|
||||
|
||||
use Date::Parse;
|
||||
use Date::Format;
|
||||
|
||||
my $TIMEFORMAT = "%D %T";
|
||||
|
||||
$| = 1;
|
||||
|
||||
print "Content-type: text/html\n\n<HTML>\n";
|
||||
|
||||
my $tree = $form{'tree'};
|
||||
my $start = $form{'start'};
|
||||
my $end = $form{'end'};
|
||||
|
||||
sub str2timeAndCheck {
|
||||
my ($str) = (@_);
|
||||
my $result = str2time($str);
|
||||
if (defined $result && $result > 7000000) {
|
||||
return $result;
|
||||
}
|
||||
print "<p><font color=red>Can't parse as a date: $str</font><p>\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $header = "<table border=1><th>Build time</th><th>Build name</th><th>Who</th><th>Note time</th><th>Note</th>";
|
||||
|
||||
if (defined $tree && defined $start && defined $end) {
|
||||
my $first = str2timeAndCheck($start);
|
||||
my $last = str2timeAndCheck($end);
|
||||
if ($first > 0 && $last > 0) {
|
||||
if (open(IN, "<$tree/notes.txt")) {
|
||||
print "<hr><center><h1>Notes for $tree</H1><H3>from " .
|
||||
time2str($TIMEFORMAT, $first) . " to " .
|
||||
time2str($TIMEFORMAT, $last) . "</H3></center>\n";
|
||||
my %stats;
|
||||
print "$header\n";
|
||||
while (<IN>) {
|
||||
chop;
|
||||
my ($nbuildtime,$nbuildname,$nwho,$nnow,$nenc_note)
|
||||
= split /\|/;
|
||||
if ($nbuildtime >= $first && $nbuildtime <= $last) {
|
||||
my $note = &url_decode($nenc_note);
|
||||
$nbuildtime = print_time($nbuildtime);
|
||||
$nnow = print_time($nnow);
|
||||
print "<tr>";
|
||||
print "<td>$nbuildtime</td>";
|
||||
print "<td>$nbuildname</td>";
|
||||
print "<td>$nwho</td>";
|
||||
print "<td>$nnow</td>";
|
||||
print "<td>$note</td>";
|
||||
print "</tr>\n";
|
||||
if (++$count % 100 == 0) {
|
||||
print "</table>$header\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print "<p><font color=red>There does not appear to be a tree " .
|
||||
"named '$tree'.</font><p>";
|
||||
}
|
||||
}
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
if (!defined $tree) {
|
||||
$tree = "";
|
||||
}
|
||||
|
||||
if (!defined $start) {
|
||||
$start = time2str($TIMEFORMAT, time() - 7*24*60*60); # One week ago.
|
||||
}
|
||||
|
||||
|
||||
if (!defined $end) {
|
||||
$end = time2str($TIMEFORMAT, time()); # #now
|
||||
}
|
||||
|
||||
print qq|
|
||||
<form>
|
||||
<table>
|
||||
<tr>
|
||||
<th align=right>Tree:</th>
|
||||
<td><input name=tree size=30 value="$tree"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>Start time:</th>
|
||||
<td><input name=start size=30 value="$start"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align=right>End time:</th>
|
||||
<td><input name=end size=30 value="$end"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<INPUT TYPE=\"submit\" VALUE=\"View Notes \">
|
||||
|
||||
</form>
|
||||
|;
|
||||
437
mozilla/webtools/tinderbox/warnings.pl
Executable file
437
mozilla/webtools/tinderbox/warnings.pl
Executable file
@@ -0,0 +1,437 @@
|
||||
#! /usr/bonsaitools/bin/perl
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# 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 Tinderbox
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are Copyright (C) 1999
|
||||
# Netscape Communications Corporation. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Stephen Lamm <slamm@mozilla.org>
|
||||
|
||||
use FileHandle;
|
||||
|
||||
$tree = 'SeaMonkey';
|
||||
# tinderbox/globals.pl uses many shameful globals
|
||||
$form{tree} = $tree;
|
||||
require 'globals.pl';
|
||||
|
||||
$cvsroot = '/cvsroot/mozilla';
|
||||
$lxr_data_root = '/export2/lxr-data';
|
||||
@ignore = (
|
||||
'long long',
|
||||
'__cmsg_data',
|
||||
'location of the previous definition',
|
||||
'\' was hidden',
|
||||
'declaration of \`index\'',
|
||||
);
|
||||
$ignore_pat = "(?:".join('|',@ignore).")";
|
||||
|
||||
print STDERR "Building hash of file names...";
|
||||
($file_bases, $file_fullpaths) = build_file_hash($cvsroot, $tree);
|
||||
print STDERR "done.\n";
|
||||
|
||||
for $br (last_successful_builds($tree)) {
|
||||
next unless $br->{buildname} =~ /shrike.*\b(Clobber|Clbr)\b/;
|
||||
|
||||
my $log_file = "$br->{logfile}";
|
||||
|
||||
warn "Parsing build log, $log_file\n";
|
||||
|
||||
$fh = new FileHandle "gunzip -c $tree/$log_file |";
|
||||
&gcc_parser($fh, $cvsroot, $tree, $log_file, $file_bases, $file_fullpaths);
|
||||
$fh->close;
|
||||
|
||||
&build_blame;
|
||||
|
||||
my $warn_file = "$tree/warn$log_file";
|
||||
$warn_file =~ s/.gz$/.html/;
|
||||
|
||||
$fh->open(">$warn_file") or die "Unable to open $warn_file: $!\n";
|
||||
&print_warnings_as_html($fh, $br);
|
||||
$fh->close;
|
||||
warn "Wrote output to $warn_file\n";
|
||||
|
||||
last;
|
||||
}
|
||||
|
||||
# end of main
|
||||
# ===================================================================
|
||||
|
||||
sub build_file_hash {
|
||||
my ($cvsroot, $tree) = @_;
|
||||
|
||||
$lxr_data_root = "/export2/lxr-data/\L$tree";
|
||||
|
||||
$lxr_file_list = "\L$lxr_data_root/.glimpse_filenames";
|
||||
open(LXR_FILENAMES, "<$lxr_file_list")
|
||||
or die "Unable to open $lxr_file_list: $!\n";
|
||||
|
||||
use File::Basename;
|
||||
|
||||
while (<LXR_FILENAMES>) {
|
||||
my ($base, $dir, $ext) = fileparse($_,'\.[^/]*');
|
||||
|
||||
next unless $ext =~ /^\.(cpp|h|C|s|c|mk|in)$/;
|
||||
|
||||
$base = "$base$ext";
|
||||
$dir =~ s|$lxr_data_root/mozilla/||;
|
||||
$dir =~ s|/$||;
|
||||
|
||||
$fullpath{"$dir/$base"}=1;
|
||||
|
||||
unless (exists $bases{$base}) {
|
||||
$bases{$base} = $dir;
|
||||
} else {
|
||||
$bases{$base} = '[multiple]';
|
||||
}
|
||||
}
|
||||
return \%bases, \%fullpath;
|
||||
}
|
||||
|
||||
sub last_successful_builds {
|
||||
my $tree = shift;
|
||||
my @build_records = ();
|
||||
my $br;
|
||||
|
||||
|
||||
$maxdate = time;
|
||||
$mindate = $maxdate - 5*60*60; # Go back 5 hours
|
||||
|
||||
print STDERR "Loading build data...";
|
||||
&load_data;
|
||||
print STDERR "done\n";
|
||||
|
||||
for (my $ii=1; $ii <= $name_count; $ii++) {
|
||||
for (my $tt=1; $tt <= $time_count; $tt++) {
|
||||
if (defined($br = $build_table->[$tt][$ii])
|
||||
and $br->{buildstatus} eq 'success') {
|
||||
push @build_records, $br;
|
||||
last;
|
||||
} } }
|
||||
return @build_records;
|
||||
}
|
||||
|
||||
sub gcc_parser {
|
||||
my ($fh, $cvsroot, $tree, $log_file, $file_bases, $file_fullnames) = @_;
|
||||
my $dir = '';
|
||||
|
||||
while (<$fh>) {
|
||||
# Directory
|
||||
#
|
||||
if (/^gmake\[\d\]: Entering directory \`(.*)\'$/) {
|
||||
($build_dir = $1) =~ s|.*/mozilla/||;
|
||||
next;
|
||||
}
|
||||
|
||||
# Now only match lines with "warning:"
|
||||
next unless /warning:/;
|
||||
next if /$ignore_pat/o;
|
||||
|
||||
chomp; # Yum, yum
|
||||
|
||||
my ($filename, $line, $warning_text);
|
||||
($filename, $line, undef, $warning_text) = split /:\s*/, $_, 4;
|
||||
$filename =~ s/.*\///;
|
||||
|
||||
# Special case for Makefiles
|
||||
$filename =~ s/Makefile$/Makefile.in/;
|
||||
|
||||
my $dir = '';
|
||||
if ($file_fullnames->{"$build_dir/$filename"}) {
|
||||
$dir = $build_dir;
|
||||
} else {
|
||||
unless(defined($dir = $file_bases->{$filename})) {
|
||||
$dir = '[no_match]';
|
||||
}
|
||||
}
|
||||
my $file = "$dir/$filename";
|
||||
|
||||
unless (defined($warnings{$file}{$line})) {
|
||||
|
||||
# Special case for "`foo' was hidden\nby `foo2'"
|
||||
$warning_text = "...was hidden " . $warning_text
|
||||
if $warning_text =~ /^by \`/;
|
||||
|
||||
# Remember where in the build log the warning occured
|
||||
$warnings{$file}{$line} = {
|
||||
first_seen_line => $.,
|
||||
log_file => $log_file,
|
||||
warning_text => $warning_text,
|
||||
};
|
||||
}
|
||||
$warnings{$file}{$line}->{count}++;
|
||||
$total_warnings_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub dump_warning_data {
|
||||
while (my ($file, $lines_hash) = each %warnings) {
|
||||
while (my ($line, $record) = each %{$lines_hash}) {
|
||||
print join ':',
|
||||
$file,$line,
|
||||
$record->{first_seen_line},
|
||||
$record->{count},
|
||||
$record->{warning_text};
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub build_blame {
|
||||
use lib '../bonsai';
|
||||
require 'utils.pl';
|
||||
require 'cvsblame.pl';
|
||||
|
||||
while (($file, $lines_hash) = each %warnings) {
|
||||
|
||||
my $rcs_filename = "$cvsroot/$file,v";
|
||||
|
||||
unless (-e $rcs_filename) {
|
||||
warn "Unable to find $rcs_filename\n";
|
||||
$unblamed{$file} = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
my $revision = &parse_cvs_file($rcs_filename);
|
||||
@text = &extract_revision($revision);
|
||||
while (my ($line, $warn_rec) = each %{$lines_hash}) {
|
||||
my $line_rev = $revision_map[$line-1];
|
||||
my $who = $revision_author{$line_rev};
|
||||
my $source_text = join '', @text[$line-3..$line+1];
|
||||
$source_text =~ s/\t/ /g;
|
||||
|
||||
$who = "$who%netscape.com" unless $who =~ /[%]/;
|
||||
|
||||
$warn_rec->{line_rev} = $line_rev;
|
||||
$warn_rec->{source} = $source_text;
|
||||
|
||||
$warnings_by_who{$who}{$file}{$line} = $warn_rec;
|
||||
|
||||
$total_who_count++ unless exists $who_count{$who};
|
||||
$who_count{$who} += $warn_rec->{count};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub print_warnings_as_html {
|
||||
my ($fh, $br) = @_;
|
||||
my ($buildname, $buildtime) = ($br->{buildname}, $br->{buildtime});
|
||||
|
||||
my $time_str = print_time( $buildtime );
|
||||
|
||||
# Change the default destination for print to $fh
|
||||
my $old_fh = select($fh);
|
||||
|
||||
print <<"__END_HEADER";
|
||||
<html>
|
||||
<head>
|
||||
<title>Blamed Build Warnings</title>
|
||||
</head>
|
||||
<body>
|
||||
<font size="+2" face="Helvetica,Arial"><b>
|
||||
Blamed Build Warnings
|
||||
</b></font><br>
|
||||
<font size="+1" face="Helvetica,Arial">
|
||||
$buildname on $time_str<br>
|
||||
$total_warnings_count total warnings
|
||||
</font><p>
|
||||
|
||||
__END_HEADER
|
||||
|
||||
for $who (sort { $who_count{$b} <=> $who_count{$a}
|
||||
|| $a cmp $b } keys %who_count) {
|
||||
push @who_list, $who;
|
||||
}
|
||||
|
||||
# Summary Table (name, count)
|
||||
#
|
||||
use POSIX;
|
||||
print "<table border=0 cellpadding=1 cellspacing=0 bgcolor=#ededed>\n";
|
||||
my $num_columns = 6;
|
||||
my $num_rows = ceil($#who_list / $num_columns);
|
||||
for (my $ii=0; $ii < $num_rows; $ii++) {
|
||||
print "<tr>";
|
||||
for (my $jj=0; $jj < $num_columns; $jj++) {
|
||||
my $index = $ii + $jj * $num_rows;
|
||||
next if $index > $#who_list;
|
||||
my $name = $who_list[$index];
|
||||
my $count = $who_count{$name};
|
||||
$name =~ s/%.*//;
|
||||
print " " x $jj;
|
||||
print "<td><a href='#$name'>$name</a>";
|
||||
print "</td><td>";
|
||||
print "$count";
|
||||
print "</td><td> </td>\n";
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
print "</table><p>\n";
|
||||
|
||||
# Count Unblamed warnings
|
||||
#
|
||||
my $total_unblamed_warnigns=0;
|
||||
for my $file (keys %unblamed) {
|
||||
for my $linenum (keys %{$warnings{$file}}) {
|
||||
$total_unblamed_warnings += $warnings{$file}{$linenum}{count};
|
||||
$warnings_by_who{Unblamed}{$file}{$linenum} = $warnings{$file}{$linenum};
|
||||
}
|
||||
}
|
||||
$who_count{Unblamed} = $total_unblamed_warnings;
|
||||
|
||||
# Print all the warnings
|
||||
#
|
||||
for $who (@who_list, "Unblamed") {
|
||||
my $total_count = $who_count{$who};
|
||||
my ($name, $email);
|
||||
($name = $who) =~ s/%.*//;
|
||||
($email = $who) =~ s/%/@/;
|
||||
|
||||
print "<h2>";
|
||||
print "<a name='$name' href='mailto:$email'>" unless $name eq 'Unblamed';
|
||||
print "$name";
|
||||
print "</a>" unless $name eq 'Unblamed';
|
||||
print " (1 warning)" if $total_count == 1;
|
||||
print " ($total_count warnings)" if $total_count > 1;
|
||||
print "</h2>";
|
||||
|
||||
print "\n<table>\n";
|
||||
my $count = 1;
|
||||
for $file (sort keys %{$warnings_by_who{$who}}) {
|
||||
for $linenum (sort keys %{$warnings_by_who{$who}{$file}}) {
|
||||
my $warn_rec = $warnings_by_who{$who}{$file}{$linenum};
|
||||
print_count($count, $warn_rec->{count});
|
||||
print_warning($tree, $br, $file, $linenum, $warn_rec);
|
||||
print_source_code($linenum, $warn_rec) unless $unblamed{$file};
|
||||
$count += $warn_rec->{count};
|
||||
}
|
||||
}
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
print <<"__END_FOOTER";
|
||||
<p>
|
||||
<hr align=left>
|
||||
Send questions or comments to
|
||||
<<a href="mailto:slamm\@netscape.com?subject=About the Blamed Build Warnings">slamm\@netcape.com</a>>.
|
||||
</body></html>
|
||||
__END_FOOTER
|
||||
|
||||
# Change default destination back.
|
||||
select($old_fh);
|
||||
}
|
||||
|
||||
sub print_count {
|
||||
my ($start, $count) = @_;
|
||||
|
||||
print "<tr><td align=right>$start";
|
||||
print "-".($start+$count-1) if $count > 1;
|
||||
print ".</td>";
|
||||
}
|
||||
|
||||
sub print_warning {
|
||||
my ($tree, $br, $file, $linenum, $warn_rec) = @_;
|
||||
|
||||
my $warning = $warn_rec->{warning_text};
|
||||
|
||||
print "<td>";
|
||||
|
||||
# File link
|
||||
if ($file =~ /\[multiple\]/) {
|
||||
$file =~ s/\[multiple\]\///;
|
||||
print "<a href='http://lxr.mozilla.org/seamonkey/find?string=$file'>";
|
||||
print "$file:$linenum";
|
||||
print "</a> (multiple file matches)";
|
||||
} elsif ($file =~ /\[no_match\]/) {
|
||||
$file =~ s/\[no_match\]\///;
|
||||
print "<b>$file:$linenum</b> (no file match)";
|
||||
} else {
|
||||
print "<a href='"
|
||||
.file_url($file,$linenum)."'>";
|
||||
print "$file:$linenum";
|
||||
print "</a> ";
|
||||
}
|
||||
print "</td></tr><tr><td></td><td>";
|
||||
# Warning text
|
||||
print "\u$warning";
|
||||
# Build log link
|
||||
my $log_line = $warn_rec->{first_seen_line};
|
||||
print " (<a href='"
|
||||
.build_url($tree, $br, $log_line)
|
||||
."'>";
|
||||
if ($warn_rec->{count} == 1) {
|
||||
print "See build log excerpt";
|
||||
} else {
|
||||
print "See 1st of $warn_rec->{count} occurrences in build log";
|
||||
}
|
||||
print "</a>)</td></tr>";
|
||||
}
|
||||
|
||||
sub print_source_code {
|
||||
my ($linenum, $warn_rec) = @_;
|
||||
my $warning = $warn_rec->{warning_text};
|
||||
|
||||
# Source code fragment
|
||||
#
|
||||
my ($keyword) = $warning =~ /\`([^\']*)\'/;
|
||||
print "<tr><td></td><td bgcolor=#ededed>";
|
||||
print "<pre><font size='-1'>";
|
||||
|
||||
my $source_text = trim_common_leading_whitespace($warn_rec->{source});
|
||||
$source_text =~ s/&/&/gm;
|
||||
$source_text =~ s/</</gm;
|
||||
$source_text =~ s/>/>/gm;
|
||||
$source_text =~ s|\b\Q$keyword\E\b|<b>$keyword</b>|gm unless $keyword eq '';
|
||||
my $line_index = $linenum - 2;
|
||||
$source_text =~ s/^(.*)$/$line_index++." $1"/gme;
|
||||
$source_text =~ s|^($linenum.*)$|<font color='red'>\1</font>|gm;
|
||||
chomp $source_text;
|
||||
print $source_text;
|
||||
|
||||
print "</font>";
|
||||
#print "</pre>";
|
||||
print "</td></tr>\n";
|
||||
}
|
||||
|
||||
sub build_url {
|
||||
my ($tree, $br, $linenum) = @_;
|
||||
|
||||
my $name = $br->{buildname};
|
||||
$name =~ s/ /%20/g;
|
||||
|
||||
return "../showlog.cgi?log=$tree/$br->{logfile}:$linenum";
|
||||
}
|
||||
|
||||
sub file_url {
|
||||
my ($file, $linenum) = @_;
|
||||
|
||||
return "http://cvs-mirror.mozilla.org/webtools/bonsai/cvsblame.cgi"
|
||||
."?file=mozilla/$file&mark=$linenum#".($linenum-10);
|
||||
|
||||
}
|
||||
|
||||
sub trim_common_leading_whitespace {
|
||||
# Adapted from dequote() in Perl Cookbook by Christiansen and Torkington
|
||||
local $_ = shift;
|
||||
my $white; # common whitespace
|
||||
if (/(?:(\s*).*\n)(?:(?:\1.*\n)|(?:\s*\n))+$/) {
|
||||
$white = $1;
|
||||
} else {
|
||||
$white = /^(\s+)/;
|
||||
}
|
||||
s/^(?:$white)?//gm;
|
||||
s/^\s+$//gm;
|
||||
return $_;
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
nsAVLTree.h
|
||||
nsCppSharedAllocator.h
|
||||
nsCRT.h
|
||||
nsDeque.h
|
||||
nsEnumeratorUtils.h
|
||||
nsHashtable.h
|
||||
nsHashtableEnumerator.h
|
||||
nsIArena.h
|
||||
nsIBuffer.h
|
||||
nsIByteBuffer.h
|
||||
nsIObserverList.h
|
||||
nsIPageManager.h
|
||||
nsIProperties.h
|
||||
nsISimpleEnumerator.h
|
||||
nsISizeOfHandler.h
|
||||
nsIUnicharBuffer.h
|
||||
nsIVariant.h
|
||||
nsInt64.h
|
||||
nsQuickSort.h
|
||||
nsStr.h
|
||||
nsString.h
|
||||
nsString2.h
|
||||
nsSupportsPrimitives.h
|
||||
nsTime.h
|
||||
nsUnitConversion.h
|
||||
nsVector.h
|
||||
nsVoidArray.h
|
||||
nsXPIDLString.h
|
||||
plvector.h
|
||||
nsTextFormater.h
|
||||
@@ -1,6 +0,0 @@
|
||||
nsIAtom.idl
|
||||
nsICollection.idl
|
||||
nsIEnumerator.idl
|
||||
nsIObserver.idl
|
||||
nsIObserverService.idl
|
||||
nsISupportsArray.idl
|
||||
@@ -1,113 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = xpcom
|
||||
XPIDL_MODULE = xpcom_ds
|
||||
LIBRARY_NAME = xpcomds_s
|
||||
|
||||
REQUIRES = xpcom uconv unicharutil
|
||||
|
||||
CPPSRCS = \
|
||||
nsArena.cpp \
|
||||
nsAtomTable.cpp \
|
||||
nsAVLTree.cpp \
|
||||
nsByteBuffer.cpp \
|
||||
nsCRT.cpp \
|
||||
nsConjoiningEnumerator.cpp \
|
||||
nsDeque.cpp \
|
||||
nsEmptyEnumerator.cpp \
|
||||
nsEnumeratorUtils.cpp \
|
||||
nsHashtable.cpp \
|
||||
nsHashtableEnumerator.cpp \
|
||||
nsObserver.cpp \
|
||||
nsObserverList.cpp \
|
||||
nsObserverService.cpp \
|
||||
nsProperties.cpp \
|
||||
nsQuickSort.cpp \
|
||||
nsSizeOfHandler.cpp \
|
||||
nsStr.cpp \
|
||||
nsString.cpp \
|
||||
nsString2.cpp \
|
||||
nsSupportsArray.cpp \
|
||||
nsSupportsArrayEnumerator.cpp \
|
||||
nsSupportsPrimitives.cpp \
|
||||
nsUnicharBuffer.cpp \
|
||||
nsVariant.cpp \
|
||||
nsVoidArray.cpp \
|
||||
nsXPIDLString.cpp \
|
||||
plvector.cpp \
|
||||
nsTextFormater.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsAVLTree.h \
|
||||
nsCppSharedAllocator.h \
|
||||
nsCRT.h \
|
||||
nsDeque.h \
|
||||
nsEnumeratorUtils.h \
|
||||
nsHashtable.h \
|
||||
nsHashtableEnumerator.h \
|
||||
nsIArena.h \
|
||||
nsIByteBuffer.h \
|
||||
nsIObserverList.h \
|
||||
nsIProperties.h \
|
||||
nsISimpleEnumerator.h \
|
||||
nsISizeOfHandler.h \
|
||||
nsIUnicharBuffer.h \
|
||||
nsIVariant.h \
|
||||
nsInt64.h \
|
||||
nsQuickSort.h \
|
||||
nsStr.h \
|
||||
nsString.h \
|
||||
nsString2.h \
|
||||
nsSupportsPrimitives.h \
|
||||
nsTime.h \
|
||||
nsUnitConversion.h \
|
||||
nsVector.h \
|
||||
nsVoidArray.h \
|
||||
nsXPIDLString.h \
|
||||
plvector.h \
|
||||
nsTextFormater.h \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIAtom.idl \
|
||||
nsICollection.idl \
|
||||
nsIEnumerator.idl \
|
||||
nsIObserver.idl \
|
||||
nsIObserverService.idl \
|
||||
nsISupportsArray.idl \
|
||||
nsISupportsPrimitives.idl \
|
||||
$(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
|
||||
|
||||
@@ -1,758 +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.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.
|
||||
*/
|
||||
|
||||
/******************************************************************************************
|
||||
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.
|
||||
|
||||
*******************************************************************************************/
|
||||
|
||||
#ifndef _BUFFERROUTINES_H
|
||||
#define _BUFFERROUTINES_H
|
||||
|
||||
#include "nsCRT.h"
|
||||
|
||||
#ifndef RICKG_TESTBED
|
||||
#include "nsUnicharUtilCIID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICaseConversion.h"
|
||||
#endif
|
||||
|
||||
#define KSHIFTLEFT (0)
|
||||
#define KSHIFTRIGHT (1)
|
||||
|
||||
|
||||
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;
|
||||
|
||||
//now loop over characters, shifting them left...
|
||||
while(first<last) {
|
||||
*to=(PRUnichar)(*first);
|
||||
to++;
|
||||
first++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
//now loop over characters, shifting them left...
|
||||
while(first<last) {
|
||||
if(*first<256)
|
||||
*to=(char)*first;
|
||||
else *to='.';
|
||||
to++;
|
||||
first++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 3/25/98
|
||||
* @param aDest is the buffer to be searched
|
||||
* @param aLength 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
|
||||
* @return index of pos if found, else -1 (kNotFound)
|
||||
*/
|
||||
inline PRInt32 FindChar1(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
|
||||
|
||||
if(aIgnoreCase) {
|
||||
char theChar=(char)nsCRT::ToUpper(aChar);
|
||||
const char* ptr=aDest+(anOffset-1);
|
||||
const char* last=aDest+aLength;
|
||||
while(++ptr<last){
|
||||
if(nsCRT::ToUpper(*ptr)==theChar)
|
||||
return ptr-aDest;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
const char* ptr = aDest+anOffset;
|
||||
char theChar=(char)aChar;
|
||||
const char* result=(const char*)memchr(ptr, theChar,aLength-anOffset);
|
||||
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 aLength 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
|
||||
* @return index of pos if found, else -1 (kNotFound)
|
||||
*/
|
||||
inline PRInt32 FindChar2(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
|
||||
const PRUnichar* root=(PRUnichar*)aDest;
|
||||
const PRUnichar* ptr=root+(anOffset-1);
|
||||
const PRUnichar* last=root+aLength;
|
||||
|
||||
if(aIgnoreCase) {
|
||||
PRUnichar theChar=nsCRT::ToUpper(aChar);
|
||||
while(++ptr<last){
|
||||
if(nsCRT::ToUpper(*ptr)==theChar)
|
||||
return ptr-root;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(++ptr<last){
|
||||
if(*ptr==aChar)
|
||||
return (ptr-root);
|
||||
}
|
||||
}
|
||||
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This methods cans the given buffer (in reverse) for the given char
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @param aDest is the buffer to be searched
|
||||
* @param aLength 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
|
||||
* @return index of pos if found, else -1 (kNotFound)
|
||||
*/
|
||||
inline PRInt32 RFindChar1(const char* aDest,PRUint32 aDestLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
|
||||
PRInt32 theIndex=0;
|
||||
|
||||
if(aIgnoreCase) {
|
||||
PRUnichar theChar=nsCRT::ToUpper(aChar);
|
||||
for(theIndex=(PRInt32)anOffset;theIndex>=0;theIndex--){
|
||||
if(nsCRT::ToUpper(aDest[theIndex])==theChar)
|
||||
return theIndex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(theIndex=(PRInt32)anOffset;theIndex>=0;theIndex--){
|
||||
if(aDest[theIndex]==aChar)
|
||||
return theIndex;
|
||||
}
|
||||
}
|
||||
|
||||
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 aLength 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
|
||||
* @return index of pos if found, else -1 (kNotFound)
|
||||
*/
|
||||
inline PRInt32 RFindChar2(const char* aDest,PRUint32 aDestLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
|
||||
|
||||
PRInt32 theIndex=0;
|
||||
PRUnichar* theBuf=(PRUnichar*)aDest;
|
||||
|
||||
if(aIgnoreCase) {
|
||||
PRUnichar theChar=nsCRT::ToUpper(aChar);
|
||||
for(theIndex=(PRInt32)anOffset;theIndex>=0;theIndex--){
|
||||
if(nsCRT::ToUpper(theBuf[theIndex])==theChar)
|
||||
return theIndex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(theIndex=(PRInt32)anOffset;theIndex>=0;theIndex--){
|
||||
if(theBuf[theIndex]==aChar)
|
||||
return theIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
typedef PRInt32 (*FindChars)(const char* aDest,PRUint32 aDestLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase);
|
||||
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=strncmp(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 RICKG_TESTBED
|
||||
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 NS_DEFINE_IID(kICaseConversionIID, NS_ICASECONVERSION_IID);
|
||||
static NS_DEFINE_IID(kIShutdownListenerIID, NS_ISHUTDOWNLISTENER_IID);
|
||||
static nsICaseConversion * gCaseConv = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS(HandleCaseConversionShutdown3, kIShutdownListenerIID);
|
||||
|
||||
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(){
|
||||
mListener = new HandleCaseConversionShutdown3();
|
||||
if(mListener){
|
||||
mListener->AddRef();
|
||||
nsServiceManager::GetService(kUnicharUtilCID, kICaseConversionIID,(nsISupports**) &gCaseConv, mListener);
|
||||
}
|
||||
}
|
||||
protected:
|
||||
HandleCaseConversionShutdown3* mListener;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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 RICKG_TESTBED
|
||||
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
|
||||
|
||||
|
||||
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 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 CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
|
||||
|
||||
typedef char chartype;
|
||||
chartype* from = aString;
|
||||
chartype* end = aString + aLength-1;
|
||||
chartype* 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) {
|
||||
chartype theChar = *from++;
|
||||
if(kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE)){
|
||||
*to++=theChar;
|
||||
while (from <= end) {
|
||||
theChar = *from++;
|
||||
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE)){
|
||||
*to++ = theChar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*to++ = theChar;
|
||||
}
|
||||
}
|
||||
*to = 0;
|
||||
}
|
||||
return to - (chartype*)aString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method compresses duplicate runs of a given char 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 CompressChars2(char* aString,PRUint32 aLength,const char* aSet){
|
||||
|
||||
typedef PRUnichar chartype;
|
||||
chartype* from = (chartype*)aString;
|
||||
chartype* end = from + aLength-1;
|
||||
chartype* 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) {
|
||||
chartype theChar = *from++;
|
||||
if(kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE)){
|
||||
*to++=theChar;
|
||||
while (from <= end) {
|
||||
theChar = *from++;
|
||||
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE)){
|
||||
*to++ = theChar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*to++ = theChar;
|
||||
}
|
||||
}
|
||||
*to = 0;
|
||||
}
|
||||
return to - (chartype*)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){
|
||||
|
||||
typedef char chartype;
|
||||
chartype* to = aString;
|
||||
chartype* from = aString-1;
|
||||
chartype* end = aString + aLength;
|
||||
|
||||
if(aSet && aString && (0 < aLength)){
|
||||
PRUint32 aSetLen=strlen(aSet);
|
||||
while (++from < end) {
|
||||
chartype theChar = *from;
|
||||
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE)){
|
||||
*to++ = theChar;
|
||||
}
|
||||
}
|
||||
*to = 0;
|
||||
}
|
||||
return to - (chartype*)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){
|
||||
|
||||
typedef PRUnichar chartype;
|
||||
chartype* to = (chartype*)aString;
|
||||
chartype* from = (chartype*)aString-1;
|
||||
chartype* end = to + aLength;
|
||||
|
||||
if(aSet && aString && (0 < aLength)){
|
||||
PRUint32 aSetLen=strlen(aSet);
|
||||
while (++from < end) {
|
||||
chartype theChar = *from;
|
||||
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE)){
|
||||
*to++ = theChar;
|
||||
}
|
||||
}
|
||||
*to = 0;
|
||||
}
|
||||
return to - (chartype*)aString;
|
||||
}
|
||||
|
||||
typedef PRInt32 (*StripChars)(char* aString,PRUint32 aCount,const char* aSet);
|
||||
StripChars gStripChars[]={&StripChars1,&StripChars2};
|
||||
|
||||
#endif
|
||||
@@ -1,120 +0,0 @@
|
||||
#!nmake
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
|
||||
DEPTH=..\..
|
||||
MODULE = xpcom
|
||||
|
||||
################################################################################
|
||||
## exports
|
||||
|
||||
EXPORTS = \
|
||||
nsTextFormater.h \
|
||||
nsAVLTree.h \
|
||||
nsCppSharedAllocator.h \
|
||||
nsCRT.h \
|
||||
nsDeque.h \
|
||||
nsEnumeratorUtils.h \
|
||||
nsHashtable.h \
|
||||
nsHashtableEnumerator.h \
|
||||
nsIArena.h \
|
||||
nsIByteBuffer.h \
|
||||
nsIObserverList.h \
|
||||
nsIProperties.h \
|
||||
nsISimpleEnumerator.h \
|
||||
nsISizeOfHandler.h \
|
||||
nsIUnicharBuffer.h \
|
||||
nsIVariant.h \
|
||||
nsInt64.h \
|
||||
nsQuickSort.h \
|
||||
nsStr.h \
|
||||
nsString.h \
|
||||
nsString2.h \
|
||||
nsSupportsPrimitives.h \
|
||||
nsTime.h \
|
||||
nsUnitConversion.h \
|
||||
nsVector.h \
|
||||
nsVoidArray.h \
|
||||
nsXPIDLString.h \
|
||||
plvector.h \
|
||||
$(NULL)
|
||||
|
||||
XPIDL_MODULE = xpcom_ds
|
||||
|
||||
XPIDLSRCS = \
|
||||
.\nsIAtom.idl \
|
||||
.\nsICollection.idl \
|
||||
.\nsIEnumerator.idl \
|
||||
.\nsIObserver.idl \
|
||||
.\nsIObserverService.idl \
|
||||
.\nsISupportsArray.idl \
|
||||
.\nsISupportsPrimitives.idl \
|
||||
$(NULL)
|
||||
|
||||
################################################################################
|
||||
## library
|
||||
|
||||
LIBRARY_NAME=xpcomds_s
|
||||
|
||||
LINCS = \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
-I$(PUBLIC)\uconv \
|
||||
-I$(PUBLIC)\unicharutil \
|
||||
$(NULL)
|
||||
|
||||
LCFLAGS = -D_IMPL_NS_COM -D_IMPL_NS_BASE -DWIN32_LEAN_AND_MEAN
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsTextFormater.obj \
|
||||
.\$(OBJDIR)\nsArena.obj \
|
||||
.\$(OBJDIR)\nsAtomTable.obj \
|
||||
.\$(OBJDIR)\nsAVLTree.obj \
|
||||
.\$(OBJDIR)\nsByteBuffer.obj \
|
||||
.\$(OBJDIR)\nsCRT.obj \
|
||||
.\$(OBJDIR)\nsConjoiningEnumerator.obj \
|
||||
.\$(OBJDIR)\nsDeque.obj \
|
||||
.\$(OBJDIR)\nsEmptyEnumerator.obj \
|
||||
.\$(OBJDIR)\nsEnumeratorUtils.obj \
|
||||
.\$(OBJDIR)\nsHashtable.obj \
|
||||
.\$(OBJDIR)\nsHashtableEnumerator.obj \
|
||||
.\$(OBJDIR)\nsObserver.obj \
|
||||
.\$(OBJDIR)\nsObserverList.obj \
|
||||
.\$(OBJDIR)\nsObserverService.obj \
|
||||
.\$(OBJDIR)\nsProperties.obj \
|
||||
.\$(OBJDIR)\nsQuickSort.obj \
|
||||
.\$(OBJDIR)\nsSizeOfHandler.obj \
|
||||
.\$(OBJDIR)\nsStr.obj \
|
||||
.\$(OBJDIR)\nsString.obj \
|
||||
.\$(OBJDIR)\nsString2.obj \
|
||||
.\$(OBJDIR)\nsSupportsArray.obj \
|
||||
.\$(OBJDIR)\nsSupportsArrayEnumerator.obj \
|
||||
.\$(OBJDIR)\nsSupportsPrimitives.obj \
|
||||
.\$(OBJDIR)\nsUnicharBuffer.obj \
|
||||
.\$(OBJDIR)\nsVariant.obj \
|
||||
.\$(OBJDIR)\nsVoidArray.obj \
|
||||
.\$(OBJDIR)\nsXPIDLString.obj \
|
||||
.\$(OBJDIR)\plvector.obj \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
libs:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
@@ -1,617 +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.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) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsAVLTree.h"
|
||||
|
||||
|
||||
enum eLean {eLeft,eNeutral,eRight};
|
||||
|
||||
struct NS_COM nsAVLNode {
|
||||
public:
|
||||
|
||||
nsAVLNode(void* aValue) {
|
||||
mLeft=0;
|
||||
mRight=0;
|
||||
mSkew=eNeutral;
|
||||
mValue=aValue;
|
||||
}
|
||||
|
||||
nsAVLNode* mLeft;
|
||||
nsAVLNode* mRight;
|
||||
eLean mSkew;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************
|
||||
Now begin the tree class. Don't forget that the comparison
|
||||
between nodes must occur via the comparitor function,
|
||||
otherwise all you're testing is pointer addresses.
|
||||
************************************************************/
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
|
||||
nsAVLNodeFunctor* aDeallocator) :
|
||||
mComparitor(aComparitor), mDeallocator(aDeallocator) {
|
||||
mRoot=0;
|
||||
mCount=0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
avlDeleteTree(nsAVLNode* aNode){
|
||||
if (aNode) {
|
||||
avlDeleteTree(aNode->mLeft);
|
||||
avlDeleteTree(aNode->mRight);
|
||||
delete aNode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsAVLTree::~nsAVLTree(){
|
||||
if (mDeallocator) {
|
||||
ForEachDepthFirst(*mDeallocator);
|
||||
}
|
||||
avlDeleteTree(mRoot);
|
||||
}
|
||||
|
||||
|
||||
class CDoesntExist: public nsAVLNodeFunctor {
|
||||
public:
|
||||
CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
|
||||
}
|
||||
virtual void* operator()(void* anItem) {
|
||||
void* result=mOtherTree.FindItem(anItem);
|
||||
if(result)
|
||||
return nsnull;
|
||||
return anItem;
|
||||
}
|
||||
protected:
|
||||
const nsAVLTree& mOtherTree;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method compares two trees (members by identity).
|
||||
* @update gess12/27/98
|
||||
* @param tree to compare against
|
||||
* @return true if they are identical (contain same stuff).
|
||||
*/
|
||||
PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
|
||||
CDoesntExist functor(aCopy);
|
||||
void* theItem=FirstThat(functor);
|
||||
PRBool result=PRBool(!theItem);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlRotateRight(nsAVLNode*& aRootNode){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
|
||||
ptr2=aRootNode->mRight;
|
||||
if(ptr2->mSkew==eRight) {
|
||||
aRootNode->mRight=ptr2->mLeft;
|
||||
ptr2->mLeft=aRootNode;
|
||||
aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else {
|
||||
ptr3=ptr2->mLeft;
|
||||
ptr2->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=ptr2;
|
||||
aRootNode->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=aRootNode;
|
||||
if(ptr3->mSkew==eLeft)
|
||||
ptr2->mSkew=eRight;
|
||||
else ptr2->mSkew=eNeutral;
|
||||
if(ptr3->mSkew==eRight)
|
||||
aRootNode->mSkew=eLeft;
|
||||
else aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr3;
|
||||
}
|
||||
aRootNode->mSkew=eNeutral;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/27/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlRotateLeft(nsAVLNode*& aRootNode){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
|
||||
ptr2=aRootNode->mLeft;
|
||||
if(ptr2->mSkew==eLeft) {
|
||||
aRootNode->mLeft=ptr2->mRight;
|
||||
ptr2->mRight=aRootNode;
|
||||
aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else {
|
||||
ptr3=ptr2->mRight;
|
||||
ptr2->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=ptr2;
|
||||
aRootNode->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=aRootNode;
|
||||
if(ptr3->mSkew==eRight)
|
||||
ptr2->mSkew=eLeft;
|
||||
else ptr2->mSkew=eNeutral;
|
||||
if(ptr3->mSkew==eLeft)
|
||||
aRootNode->mSkew=eRight;
|
||||
else aRootNode->mSkew=eNeutral;
|
||||
aRootNode=ptr3;
|
||||
}
|
||||
aRootNode->mSkew=eNeutral;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
|
||||
nsAVLNodeComparitor& aComparitor) {
|
||||
eAVLStatus result=eAVL_unknown;
|
||||
|
||||
if(!aRootNode) {
|
||||
aRootNode = aNewNode;
|
||||
return eAVL_ok;
|
||||
}
|
||||
|
||||
if(aNewNode==aRootNode->mValue) {
|
||||
return eAVL_duplicate;
|
||||
}
|
||||
|
||||
PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
|
||||
if(0 < theCompareResult) { //if(anItem<aRootNode->mValue)
|
||||
result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
|
||||
if(eAVL_ok==result) {
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
avlRotateLeft(aRootNode);
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eRight:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eLeft;
|
||||
break;
|
||||
} //switch
|
||||
}//if
|
||||
} //if
|
||||
else {
|
||||
result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
|
||||
if(eAVL_ok==result) {
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eRight:
|
||||
avlRotateRight(aRootNode);
|
||||
result=eAVL_fail;
|
||||
break;
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eRight;
|
||||
break;
|
||||
} //switch
|
||||
}
|
||||
} //if
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static void
|
||||
avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
eLean balnc2;
|
||||
eLean balnc3;
|
||||
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
ptr2=aRootNode->mLeft;
|
||||
balnc2=ptr2->mSkew;
|
||||
if(balnc2!=eRight) {
|
||||
aRootNode->mLeft=ptr2->mRight;
|
||||
ptr2->mRight=aRootNode;
|
||||
if(balnc2==eNeutral){
|
||||
aRootNode->mSkew=eLeft;
|
||||
ptr2->mSkew=eRight;
|
||||
delOk=PR_FALSE;
|
||||
}
|
||||
else{
|
||||
aRootNode->mSkew=eNeutral;
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else{
|
||||
ptr3=ptr2->mRight;
|
||||
balnc3=ptr3->mSkew;
|
||||
ptr2->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=ptr2;
|
||||
aRootNode->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=aRootNode;
|
||||
if(balnc3==eRight) {
|
||||
ptr2->mSkew=eLeft;
|
||||
}
|
||||
else {
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
if(balnc3==eLeft) {
|
||||
aRootNode->mSkew=eRight;
|
||||
}
|
||||
else {
|
||||
aRootNode->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr3;
|
||||
ptr3->mSkew=eNeutral;
|
||||
}
|
||||
break;
|
||||
|
||||
case eRight:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
break;
|
||||
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eLeft;
|
||||
delOk=PR_FALSE;
|
||||
break;
|
||||
}//switch
|
||||
return;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static void
|
||||
avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
|
||||
nsAVLNode* ptr2;
|
||||
nsAVLNode* ptr3;
|
||||
eLean balnc2;
|
||||
eLean balnc3;
|
||||
|
||||
switch(aRootNode->mSkew){
|
||||
case eLeft:
|
||||
aRootNode->mSkew=eNeutral;
|
||||
break;
|
||||
|
||||
case eRight:
|
||||
ptr2=aRootNode->mRight;
|
||||
balnc2=ptr2->mSkew;
|
||||
if(balnc2!=eLeft) {
|
||||
aRootNode->mRight=ptr2->mLeft;
|
||||
ptr2->mLeft=aRootNode;
|
||||
if(balnc2==eNeutral){
|
||||
aRootNode->mSkew=eRight;
|
||||
ptr2->mSkew=eLeft;
|
||||
delOk=PR_FALSE;
|
||||
}
|
||||
else{
|
||||
aRootNode->mSkew=eNeutral;
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr2;
|
||||
}
|
||||
else{
|
||||
ptr3=ptr2->mLeft;
|
||||
balnc3=ptr3->mSkew;
|
||||
ptr2->mLeft=ptr3->mRight;
|
||||
ptr3->mRight=ptr2;
|
||||
aRootNode->mRight=ptr3->mLeft;
|
||||
ptr3->mLeft=aRootNode;
|
||||
if(balnc3==eLeft) {
|
||||
ptr2->mSkew=eRight;
|
||||
}
|
||||
else {
|
||||
ptr2->mSkew=eNeutral;
|
||||
}
|
||||
if(balnc3==eRight) {
|
||||
aRootNode->mSkew=eLeft;
|
||||
}
|
||||
else {
|
||||
aRootNode->mSkew=eNeutral;
|
||||
}
|
||||
aRootNode=ptr3;
|
||||
ptr3->mSkew=eNeutral;
|
||||
}
|
||||
break;
|
||||
|
||||
case eNeutral:
|
||||
aRootNode->mSkew=eRight;
|
||||
delOk=PR_FALSE;
|
||||
break;
|
||||
}//switch
|
||||
return;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
if(!anotherNode->mRight){
|
||||
aRootNode->mValue=anotherNode->mValue; //swap
|
||||
anotherNode=anotherNode->mLeft;
|
||||
delOk=PR_TRUE;
|
||||
}
|
||||
else{
|
||||
avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
|
||||
if(delOk)
|
||||
avlBalanceLeft(anotherNode,delOk);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
static eAVLStatus
|
||||
avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
|
||||
nsAVLNodeComparitor& aComparitor){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
if(!aRootNode)
|
||||
delOk=PR_FALSE;
|
||||
else {
|
||||
PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
|
||||
if(cmp<0){
|
||||
avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
|
||||
if(delOk)
|
||||
avlBalanceRight(aRootNode,delOk);
|
||||
}
|
||||
else if(cmp>0){
|
||||
avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
|
||||
if(delOk)
|
||||
avlBalanceLeft(aRootNode,delOk);
|
||||
}
|
||||
else{ //they match...
|
||||
nsAVLNode* temp=aRootNode;
|
||||
if(!aRootNode->mRight) {
|
||||
aRootNode=aRootNode->mLeft;
|
||||
delOk=PR_TRUE;
|
||||
delete temp;
|
||||
}
|
||||
else if(!aRootNode->mLeft) {
|
||||
aRootNode=aRootNode->mRight;
|
||||
delOk=PR_TRUE;
|
||||
delete temp;
|
||||
}
|
||||
else {
|
||||
avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
|
||||
if(delOk)
|
||||
avlBalanceRight(aRootNode,delOk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
eAVLStatus
|
||||
nsAVLTree::AddItem(void* anItem){
|
||||
eAVLStatus result=eAVL_ok;
|
||||
|
||||
nsAVLNode* theNewNode=new nsAVLNode(anItem);
|
||||
result=avlInsert(mRoot,theNewNode,mComparitor);
|
||||
if(eAVL_duplicate!=result)
|
||||
mCount++;
|
||||
else {
|
||||
delete theNewNode;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** ------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @update gess 4/22/98
|
||||
* @param
|
||||
* @return
|
||||
*/ //----------------------------------------------
|
||||
void* nsAVLTree::FindItem(void* aValue) const{
|
||||
nsAVLNode* result=mRoot;
|
||||
PRInt32 count=0;
|
||||
while(result) {
|
||||
count++;
|
||||
PRInt32 cmp=mComparitor(aValue,result->mValue);
|
||||
if(0==cmp) {
|
||||
//we matched...
|
||||
break;
|
||||
}
|
||||
else if(0>cmp){
|
||||
//theNode was greater...
|
||||
result=result->mLeft;
|
||||
}
|
||||
else {
|
||||
//aValue is greater...
|
||||
result=result->mRight;
|
||||
}
|
||||
}
|
||||
if(result) {
|
||||
return result->mValue;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/30/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
eAVLStatus
|
||||
nsAVLTree::RemoveItem(void* aValue){
|
||||
PRBool delOk=PR_TRUE;
|
||||
eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
|
||||
if(eAVL_ok==result)
|
||||
mCount--;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
|
||||
if(aNode) {
|
||||
avlForEachDepthFirst(aNode->mLeft,aFunctor);
|
||||
avlForEachDepthFirst(aNode->mRight,aFunctor);
|
||||
aFunctor(aNode->mValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void
|
||||
nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
|
||||
::avlForEachDepthFirst(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void
|
||||
avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
|
||||
if(aNode) {
|
||||
avlForEach(aNode->mLeft,aFunctor);
|
||||
aFunctor(aNode->mValue);
|
||||
avlForEach(aNode->mRight,aFunctor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void
|
||||
nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
|
||||
::avlForEach(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void*
|
||||
avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
|
||||
void* result=nsnull;
|
||||
if(aNode) {
|
||||
result = avlFirstThat(aNode->mLeft,aFunctor);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = aFunctor(aNode->mValue);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = avlFirstThat(aNode->mRight,aFunctor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess9/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void*
|
||||
nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
|
||||
return ::avlFirstThat(mRoot,aFunctor);
|
||||
}
|
||||
|
||||
@@ -1,74 +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.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) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsAVLTree_h___
|
||||
#define nsAVLTree_h___
|
||||
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
|
||||
enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
|
||||
|
||||
|
||||
struct nsAVLNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/26/98
|
||||
* @param anObject1 is the first object to be compared
|
||||
* @param anObject2 is the second object to be compared
|
||||
* @return -1,0,1 if object1 is less, equal, greater than object2
|
||||
*/
|
||||
class NS_COM nsAVLNodeComparitor {
|
||||
public:
|
||||
virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
|
||||
};
|
||||
|
||||
class NS_COM nsAVLNodeFunctor {
|
||||
public:
|
||||
virtual void* operator()(void* anItem)=0;
|
||||
};
|
||||
|
||||
class NS_COM nsAVLTree {
|
||||
public:
|
||||
nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
|
||||
~nsAVLTree(void);
|
||||
|
||||
PRBool operator==(const nsAVLTree& aOther) const;
|
||||
PRInt32 GetCount(void) const {return mCount;}
|
||||
|
||||
//main functions...
|
||||
eAVLStatus AddItem(void* anItem);
|
||||
eAVLStatus RemoveItem(void* anItem);
|
||||
void* FindItem(void* anItem) const;
|
||||
void ForEach(nsAVLNodeFunctor& aFunctor) const;
|
||||
void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
|
||||
void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
|
||||
|
||||
protected:
|
||||
|
||||
nsAVLNode* mRoot;
|
||||
PRInt32 mCount;
|
||||
nsAVLNodeComparitor& mComparitor;
|
||||
nsAVLNodeFunctor* mDeallocator;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsAVLTree_h___ */
|
||||
|
||||
@@ -1,97 +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.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.
|
||||
*/
|
||||
|
||||
#include "nsArena.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
ArenaImpl::ArenaImpl(void)
|
||||
: mInitialized(PR_FALSE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
nsCRT::memset(&mPool, 0, sizeof(PLArenaPool));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ArenaImpl::Init(PRUint32 aBlockSize)
|
||||
{
|
||||
if (aBlockSize < NS_MIN_ARENA_BLOCK_SIZE) {
|
||||
aBlockSize = NS_DEFAULT_ARENA_BLOCK_SIZE;
|
||||
}
|
||||
PL_INIT_ARENA_POOL(&mPool, "nsIArena", aBlockSize);
|
||||
mBlockSize = aBlockSize;
|
||||
mInitialized = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ArenaImpl, nsIArena)
|
||||
|
||||
ArenaImpl::~ArenaImpl()
|
||||
{
|
||||
if (mInitialized)
|
||||
PL_FinishArenaPool(&mPool);
|
||||
|
||||
mInitialized = PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void*)
|
||||
ArenaImpl::Alloc(PRUint32 size)
|
||||
{
|
||||
// Adjust size so that it's a multiple of sizeof(double)
|
||||
PRUint32 align = size & (sizeof(double) - 1);
|
||||
if (0 != align) {
|
||||
size += sizeof(double) - align;
|
||||
}
|
||||
|
||||
void* p;
|
||||
PL_ARENA_ALLOCATE(p, &mPool, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
ArenaImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
ArenaImpl* it = new ArenaImpl();
|
||||
if (nsnull == it)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(it);
|
||||
nsresult rv = it->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(it);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_COM nsresult NS_NewHeapArena(nsIArena** aInstancePtrResult,
|
||||
PRUint32 aArenaBlockSize)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIArena* arena;
|
||||
rv = ArenaImpl::Create(NULL, nsIArena::GetIID(), (void**)&arena);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = arena->Init(aArenaBlockSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(arena);
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aInstancePtrResult = arena;
|
||||
return rv;
|
||||
}
|
||||
@@ -1,50 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsArena_h__
|
||||
#define nsArena_h__
|
||||
|
||||
#include "nsIArena.h"
|
||||
|
||||
#define PL_ARENA_CONST_ALIGN_MASK 7
|
||||
#include "plarena.h"
|
||||
|
||||
// Simple arena implementation layered on plarena
|
||||
class ArenaImpl : public nsIArena {
|
||||
public:
|
||||
ArenaImpl(void);
|
||||
virtual ~ArenaImpl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
NS_IMETHOD Init(PRUint32 arenaBlockSize);
|
||||
|
||||
NS_IMETHOD_(void*) Alloc(PRUint32 size);
|
||||
|
||||
protected:
|
||||
PLArenaPool mPool;
|
||||
PRUint32 mBlockSize;
|
||||
|
||||
private:
|
||||
PRBool mInitialized;
|
||||
};
|
||||
|
||||
#endif // nsArena_h__
|
||||
@@ -1,172 +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.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.
|
||||
*/
|
||||
|
||||
#include "nsAtomTable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "plhash.h"
|
||||
#include "nsISizeOfHandler.h"
|
||||
|
||||
/**
|
||||
* The shared hash table for atom lookups.
|
||||
*/
|
||||
static nsrefcnt gAtoms;
|
||||
static struct PLHashTable* gAtomHashTable;
|
||||
|
||||
#if defined(DEBUG) && (defined(XP_UNIX) || defined(XP_PC))
|
||||
static PRIntn
|
||||
DumpAtomLeaks(PLHashEntry *he, PRIntn index, void *arg)
|
||||
{
|
||||
AtomImpl* atom = (AtomImpl*) he->value;
|
||||
if (atom) {
|
||||
nsAutoString tmp;
|
||||
atom->ToString(tmp);
|
||||
fputs(tmp, stdout);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_COM void NS_PurgeAtomTable(void)
|
||||
{
|
||||
if (gAtomHashTable) {
|
||||
#if defined(DEBUG) && (defined(XP_UNIX) || defined(XP_PC))
|
||||
if (gAtoms) {
|
||||
if (getenv("MOZ_DUMP_ATOM_LEAKS")) {
|
||||
printf("*** leaking %d atoms\n", gAtoms);
|
||||
PL_HashTableEnumerateEntries(gAtomHashTable, DumpAtomLeaks, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
PL_HashTableDestroy(gAtomHashTable);
|
||||
gAtomHashTable = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
AtomImpl::AtomImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
// Every live atom holds a reference on the atom hashtable
|
||||
gAtoms++;
|
||||
}
|
||||
|
||||
AtomImpl::~AtomImpl()
|
||||
{
|
||||
NS_PRECONDITION(nsnull != gAtomHashTable, "null atom hashtable");
|
||||
if (nsnull != gAtomHashTable) {
|
||||
PL_HashTableRemove(gAtomHashTable, mString);
|
||||
nsrefcnt cnt = --gAtoms;
|
||||
if (0 == cnt) {
|
||||
// When the last atom is destroyed, the atom arena is destroyed
|
||||
NS_ASSERTION(0 == gAtomHashTable->nentries, "bad atom table");
|
||||
PL_HashTableDestroy(gAtomHashTable);
|
||||
gAtomHashTable = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AtomImpl, nsIAtom)
|
||||
|
||||
void* AtomImpl::operator new(size_t size, const PRUnichar* us, PRInt32 uslen)
|
||||
{
|
||||
size = size + uslen * sizeof(PRUnichar);
|
||||
AtomImpl* ii = (AtomImpl*) ::operator new(size);
|
||||
nsCRT::memcpy(ii->mString, us, uslen * sizeof(PRUnichar));
|
||||
ii->mString[uslen] = 0;
|
||||
return ii;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AtomImpl::ToString(nsString& aBuf) /*FIX: const */
|
||||
{
|
||||
aBuf.SetLength(0);
|
||||
aBuf.Append(mString, nsCRT::strlen(mString));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AtomImpl::GetUnicode(const PRUnichar **aResult) /*FIX: const */
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mString;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AtomImpl::SizeOf(nsISizeOfHandler* aHandler, PRUint32* _retval) /*FIX: const */
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
PRUint32 sum = sizeof(*this) + nsCRT::strlen(mString) * sizeof(PRUnichar);
|
||||
*_retval = sum;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static PLHashNumber HashKey(const PRUnichar* k)
|
||||
{
|
||||
return (PLHashNumber) nsCRT::HashValue(k);
|
||||
}
|
||||
|
||||
static PRIntn CompareKeys(const PRUnichar* k1, const PRUnichar* k2)
|
||||
{
|
||||
return nsCRT::strcmp(k1, k2) == 0;
|
||||
}
|
||||
|
||||
NS_COM nsIAtom* NS_NewAtom(const char* isolatin1)
|
||||
{
|
||||
nsAutoString tmp(isolatin1);
|
||||
return NS_NewAtom(tmp.GetUnicode());
|
||||
}
|
||||
|
||||
NS_COM nsIAtom* NS_NewAtom(const nsString& aString)
|
||||
{
|
||||
return NS_NewAtom(aString.GetUnicode());
|
||||
}
|
||||
|
||||
NS_COM nsIAtom* NS_NewAtom(const PRUnichar* us)
|
||||
{
|
||||
if (nsnull == gAtomHashTable) {
|
||||
gAtomHashTable = PL_NewHashTable(8, (PLHashFunction) HashKey,
|
||||
(PLHashComparator) CompareKeys,
|
||||
(PLHashComparator) nsnull,
|
||||
nsnull, nsnull);
|
||||
}
|
||||
PRUint32 uslen;
|
||||
PRUint32 hashCode = nsCRT::HashValue(us, &uslen);
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(gAtomHashTable, hashCode, us);
|
||||
PLHashEntry* he = *hep;
|
||||
if (nsnull != he) {
|
||||
nsIAtom* id = (nsIAtom*) he->value;
|
||||
NS_ADDREF(id);
|
||||
return id;
|
||||
}
|
||||
AtomImpl* id = new(us, uslen) AtomImpl();
|
||||
PL_HashTableRawAdd(gAtomHashTable, hep, hashCode, id->mString, id);
|
||||
NS_ADDREF(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
NS_COM nsrefcnt NS_GetNumberOfAtoms(void)
|
||||
{
|
||||
if (nsnull != gAtomHashTable) {
|
||||
NS_PRECONDITION(nsrefcnt(gAtomHashTable->nentries) == gAtoms, "bad atom table");
|
||||
}
|
||||
return gAtoms;
|
||||
}
|
||||
@@ -1,43 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsAtomTable_h__
|
||||
#define nsAtomTable_h__
|
||||
|
||||
#include "nsIAtom.h"
|
||||
|
||||
class AtomImpl : public nsIAtom {
|
||||
public:
|
||||
AtomImpl();
|
||||
virtual ~AtomImpl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIATOM
|
||||
|
||||
void* operator new(size_t size, const PRUnichar* us, PRInt32 uslen);
|
||||
|
||||
void operator delete(void* ptr) {
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
// Actually more; 0 terminated. This slot is reserved for the
|
||||
// terminating zero.
|
||||
PRUnichar mString[1];
|
||||
};
|
||||
|
||||
#endif // nsAtomTable_h__
|
||||
@@ -1,723 +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.
|
||||
*/
|
||||
|
||||
#include "nsBuffer.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIPageManager.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsBuffer::nsBuffer()
|
||||
: mGrowBySize(0),
|
||||
mMaxSize(0),
|
||||
mAllocator(nsnull),
|
||||
mObserver(nsnull),
|
||||
mBufferSize(0),
|
||||
mReadSegment(nsnull),
|
||||
mReadCursor(0),
|
||||
mWriteSegment(nsnull),
|
||||
mWriteCursor(0),
|
||||
mReaderClosed(PR_FALSE),
|
||||
mCondition(NS_OK)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
PR_INIT_CLIST(&mSegments);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::Init(PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer, nsIAllocator* allocator)
|
||||
{
|
||||
NS_ASSERTION(sizeof(PRCList) <= SEGMENT_OVERHEAD,
|
||||
"need to change SEGMENT_OVERHEAD size");
|
||||
NS_ASSERTION(growBySize > SEGMENT_OVERHEAD, "bad growBySize");
|
||||
mGrowBySize = growBySize;
|
||||
mMaxSize = maxSize;
|
||||
mObserver = observer;
|
||||
NS_IF_ADDREF(mObserver);
|
||||
mAllocator = allocator;
|
||||
NS_ADDREF(mAllocator);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsBuffer::~nsBuffer()
|
||||
{
|
||||
// Free any allocated pages...
|
||||
while (!PR_CLIST_IS_EMPTY(&mSegments)) {
|
||||
PRCList* header = (PRCList*)mSegments.next;
|
||||
char* segment = (char*)header;
|
||||
|
||||
PR_REMOVE_LINK(header); // unlink from mSegments
|
||||
(void) mAllocator->Free(segment);
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mObserver);
|
||||
NS_IF_RELEASE(mAllocator);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsBuffer, nsIBuffer)
|
||||
|
||||
NS_METHOD
|
||||
nsBuffer::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsBuffer* buf = new nsBuffer();
|
||||
if (buf == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(buf);
|
||||
nsresult rv = buf->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
nsBuffer::PushWriteSegment()
|
||||
{
|
||||
nsAutoCMonitor mon(this); // protect mSegments
|
||||
|
||||
if (mBufferSize >= mMaxSize) {
|
||||
if (mObserver) {
|
||||
nsresult rv = mObserver->OnFull(this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
// allocate a new segment to write into
|
||||
PRCList* header;
|
||||
|
||||
header = (PRCList*)mAllocator->Alloc(mGrowBySize);
|
||||
if (header == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mBufferSize += mGrowBySize;
|
||||
|
||||
PR_INSERT_BEFORE(header, &mSegments); // insert at end
|
||||
|
||||
// initialize the write segment
|
||||
mWriteSegment = header;
|
||||
mWriteSegmentEnd = (char*)mWriteSegment + mGrowBySize;
|
||||
mWriteCursor = (char*)mWriteSegment + sizeof(PRCList);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBuffer::PopReadSegment()
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoCMonitor mon(this); // protect mSegments
|
||||
|
||||
PRCList* header = (PRCList*)mSegments.next;
|
||||
char* segment = (char*)header;
|
||||
|
||||
NS_ASSERTION(mReadSegment == header, "wrong segment");
|
||||
|
||||
// make sure that the writer isn't still in this segment (that the
|
||||
// reader is removing)
|
||||
NS_ASSERTION(!(segment <= mWriteCursor && mWriteCursor < segment + mGrowBySize),
|
||||
"removing writer's segment");
|
||||
|
||||
PR_REMOVE_LINK(header); // unlink from mSegments
|
||||
|
||||
mBufferSize -= mGrowBySize;
|
||||
|
||||
rv = mAllocator->Free(segment);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// initialize the read segment
|
||||
if (PR_CLIST_IS_EMPTY(&mSegments)) {
|
||||
mReadSegment = nsnull;
|
||||
mReadSegmentEnd = nsnull;
|
||||
mReadCursor = nsnull;
|
||||
if (mObserver) {
|
||||
rv = mObserver->OnEmpty(this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
else {
|
||||
mReadSegment = mSegments.next;
|
||||
mReadSegmentEnd = (char*)mReadSegment + mGrowBySize;
|
||||
mReadCursor = (char*)mReadSegment + sizeof(PRCList);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIBuffer methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
|
||||
PRUint32 *readCount)
|
||||
{
|
||||
NS_ASSERTION(!mReaderClosed, "state change error");
|
||||
|
||||
nsAutoCMonitor mon(this);
|
||||
nsresult rv = NS_OK;
|
||||
PRUint32 readBufferLen;
|
||||
const char* readBuffer;
|
||||
|
||||
*readCount = 0;
|
||||
while (count > 0) {
|
||||
rv = GetReadSegment(0, &readBuffer, &readBufferLen);
|
||||
if (NS_FAILED(rv) || readBufferLen == 0) {
|
||||
return *readCount == 0 ? rv : NS_OK;
|
||||
}
|
||||
|
||||
readBufferLen = PR_MIN(readBufferLen, count);
|
||||
while (readBufferLen > 0) {
|
||||
PRUint32 writeCount;
|
||||
rv = writer(closure, readBuffer, *readCount, readBufferLen, &writeCount);
|
||||
NS_ASSERTION(rv != NS_BASE_STREAM_EOF, "Write should not return EOF");
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv) || writeCount == 0) {
|
||||
// if we failed to write just report what we were
|
||||
// able to read so far
|
||||
return *readCount == 0 ? rv : NS_OK;
|
||||
}
|
||||
NS_ASSERTION(writeCount <= readBufferLen, "writer returned bad writeCount");
|
||||
readBuffer += writeCount;
|
||||
readBufferLen -= writeCount;
|
||||
*readCount += writeCount;
|
||||
count -= writeCount;
|
||||
|
||||
if (mReadCursor + writeCount == mReadSegmentEnd) {
|
||||
rv = PopReadSegment();
|
||||
if (NS_FAILED(rv)) {
|
||||
return *readCount == 0 ? rv : NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mReadCursor += writeCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
nsWriteToRawBuffer(void* closure,
|
||||
const char* fromRawSegment,
|
||||
PRUint32 offset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount)
|
||||
{
|
||||
char* toBuf = (char*)closure;
|
||||
nsCRT::memcpy(&toBuf[offset], fromRawSegment, count);
|
||||
*writeCount = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount)
|
||||
{
|
||||
return ReadSegments(nsWriteToRawBuffer, toBuf, bufLen, readCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::GetReadSegment(PRUint32 segmentLogicalOffset,
|
||||
const char* *resultSegment,
|
||||
PRUint32 *resultSegmentLen)
|
||||
{
|
||||
nsAutoCMonitor mon(this);
|
||||
|
||||
// set the read segment and cursor if not already set
|
||||
if (mReadSegment == nsnull) {
|
||||
if (PR_CLIST_IS_EMPTY(&mSegments)) {
|
||||
*resultSegmentLen = 0;
|
||||
*resultSegment = nsnull;
|
||||
return mCondition;
|
||||
}
|
||||
else {
|
||||
mReadSegment = mSegments.next;
|
||||
mReadSegmentEnd = (char*)mReadSegment + mGrowBySize;
|
||||
mReadCursor = (char*)mReadSegment + sizeof(PRCList);
|
||||
}
|
||||
}
|
||||
|
||||
// now search for the segment starting from segmentLogicalOffset and return it
|
||||
PRCList* curSeg = mReadSegment;
|
||||
char* curSegStart = mReadCursor;
|
||||
char* curSegEnd = mReadSegmentEnd;
|
||||
PRInt32 amt;
|
||||
PRInt32 offset = (PRInt32)segmentLogicalOffset;
|
||||
while (offset >= 0) {
|
||||
// snapshot the write cursor into a local variable -- this allows
|
||||
// a writer to freely change it while we're reading while avoiding
|
||||
// using a lock
|
||||
char* snapshotWriteCursor = mWriteCursor; // atomic
|
||||
|
||||
// next check if the write cursor is in our segment
|
||||
if (curSegStart <= snapshotWriteCursor &&
|
||||
snapshotWriteCursor < curSegEnd) {
|
||||
// same segment -- read up to the snapshotWriteCursor
|
||||
curSegEnd = snapshotWriteCursor;
|
||||
|
||||
amt = curSegEnd - curSegStart;
|
||||
if (offset < amt) {
|
||||
// segmentLogicalOffset is in this segment, so read up to its end
|
||||
*resultSegmentLen = amt - offset;
|
||||
*resultSegment = curSegStart + offset;
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
// don't continue past the write segment
|
||||
*resultSegmentLen = 0;
|
||||
*resultSegment = nsnull;
|
||||
return mCondition;
|
||||
}
|
||||
}
|
||||
else {
|
||||
amt = curSegEnd - curSegStart;
|
||||
if (offset < amt) {
|
||||
// segmentLogicalOffset is in this segment, so read up to its end
|
||||
*resultSegmentLen = amt - offset;
|
||||
*resultSegment = curSegStart + offset;
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
curSeg = PR_NEXT_LINK(curSeg);
|
||||
if (curSeg == mReadSegment) {
|
||||
// been all the way around
|
||||
*resultSegmentLen = 0;
|
||||
*resultSegment = nsnull;
|
||||
return mCondition;
|
||||
}
|
||||
curSegEnd = (char*)curSeg + mGrowBySize;
|
||||
curSegStart = (char*)curSeg + sizeof(PRCList);
|
||||
offset -= amt;
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_NOTREACHED("nsBuffer::GetReadSegment failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::GetReadableAmount(PRUint32 *result)
|
||||
{
|
||||
NS_ASSERTION(!mReaderClosed, "state change error");
|
||||
|
||||
nsAutoCMonitor mon(this);
|
||||
*result = 0;
|
||||
|
||||
// first set the read segment and cursor if not already set
|
||||
if (mReadSegment == nsnull) {
|
||||
if (PR_CLIST_IS_EMPTY(&mSegments)) {
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
mReadSegment = mSegments.next;
|
||||
mReadSegmentEnd = (char*)mReadSegment + mGrowBySize;
|
||||
mReadCursor = (char*)mReadSegment + sizeof(PRCList);
|
||||
}
|
||||
}
|
||||
|
||||
// now search for the segment starting from segmentLogicalOffset and return it
|
||||
PRCList* curSeg = mReadSegment;
|
||||
char* curSegStart = mReadCursor;
|
||||
char* curSegEnd = mReadSegmentEnd;
|
||||
PRInt32 amt;
|
||||
while (PR_TRUE) {
|
||||
// snapshot the write cursor into a local variable -- this allows
|
||||
// a writer to freely change it while we're reading while avoiding
|
||||
// using a lock
|
||||
char* snapshotWriteCursor = mWriteCursor; // atomic
|
||||
|
||||
// next check if the write cursor is in our segment
|
||||
if (curSegStart <= snapshotWriteCursor &&
|
||||
snapshotWriteCursor < curSegEnd) {
|
||||
// same segment -- read up to the snapshotWriteCursor
|
||||
curSegEnd = snapshotWriteCursor;
|
||||
|
||||
amt = curSegEnd - curSegStart;
|
||||
*result += amt;
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
amt = curSegEnd - curSegStart;
|
||||
*result += amt;
|
||||
curSeg = PR_NEXT_LINK(curSeg);
|
||||
if (curSeg == mReadSegment) {
|
||||
// been all the way around
|
||||
return NS_OK;
|
||||
}
|
||||
curSegEnd = (char*)curSeg + mGrowBySize;
|
||||
curSegStart = (char*)curSeg + sizeof(PRCList);
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#define COMPARE(s1, s2, i) ignoreCase ? nsCRT::strncasecmp((const char *)s1, (const char *)s2, (PRUint32)i) : nsCRT::strncmp((const char *)s1, (const char *)s2, (PRUint32)i)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::Search(const char* string, PRBool ignoreCase,
|
||||
PRBool *found, PRUint32 *offsetSearchedTo)
|
||||
{
|
||||
NS_ASSERTION(!mReaderClosed, "state change error");
|
||||
|
||||
nsresult rv;
|
||||
const char* bufSeg1;
|
||||
PRUint32 bufSegLen1;
|
||||
PRUint32 segmentPos = 0;
|
||||
PRUint32 strLen = nsCRT::strlen(string);
|
||||
|
||||
rv = GetReadSegment(segmentPos, &bufSeg1, &bufSegLen1);
|
||||
if (NS_FAILED(rv) || bufSegLen1 == 0) {
|
||||
*found = PR_FALSE;
|
||||
*offsetSearchedTo = segmentPos;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
while (PR_TRUE) {
|
||||
PRUint32 i;
|
||||
// check if the string is in the buffer segment
|
||||
for (i = 0; i < bufSegLen1 - strLen + 1; i++) {
|
||||
if (COMPARE(&bufSeg1[i], string, strLen) == 0) {
|
||||
*found = PR_TRUE;
|
||||
*offsetSearchedTo = segmentPos + i;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// get the next segment
|
||||
const char* bufSeg2;
|
||||
PRUint32 bufSegLen2;
|
||||
segmentPos += bufSegLen1;
|
||||
rv = GetReadSegment(segmentPos, &bufSeg2, &bufSegLen2);
|
||||
if (NS_FAILED(rv) || bufSegLen2 == 0) {
|
||||
*found = PR_FALSE;
|
||||
if (mCondition != NS_OK) // XXX NS_FAILED?
|
||||
*offsetSearchedTo = segmentPos - bufSegLen1;
|
||||
else
|
||||
*offsetSearchedTo = segmentPos - bufSegLen1 - strLen + 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// check if the string is straddling the next buffer segment
|
||||
PRUint32 limit = PR_MIN(strLen, bufSegLen2 + 1);
|
||||
for (i = 0; i < limit; i++) {
|
||||
PRUint32 strPart1Len = strLen - i - 1;
|
||||
PRUint32 strPart2Len = strLen - strPart1Len;
|
||||
const char* strPart2 = &string[strLen - strPart2Len];
|
||||
PRUint32 bufSeg1Offset = bufSegLen1 - strPart1Len;
|
||||
if (COMPARE(&bufSeg1[bufSeg1Offset], string, strPart1Len) == 0 &&
|
||||
COMPARE(bufSeg2, strPart2, strPart2Len) == 0) {
|
||||
*found = PR_TRUE;
|
||||
*offsetSearchedTo = segmentPos - strPart1Len;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// finally continue with the next buffer
|
||||
bufSeg1 = bufSeg2;
|
||||
bufSegLen1 = bufSegLen2;
|
||||
}
|
||||
NS_NOTREACHED("can't get here");
|
||||
return NS_ERROR_FAILURE; // keep compiler happy
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::ReaderClosed()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoCMonitor mon(this); // protect mSegments
|
||||
|
||||
// first prevent any more writing
|
||||
mReaderClosed = PR_TRUE;
|
||||
|
||||
// then free any unread segments...
|
||||
|
||||
// first set the read segment and cursor if not already set
|
||||
if (mReadSegment == nsnull) {
|
||||
if (!PR_CLIST_IS_EMPTY(&mSegments)) {
|
||||
mReadSegment = mSegments.next;
|
||||
mReadSegmentEnd = (char*)mReadSegment + mGrowBySize;
|
||||
mReadCursor = (char*)mReadSegment + sizeof(PRCList);
|
||||
}
|
||||
}
|
||||
|
||||
while (mReadSegment) {
|
||||
// snapshot the write cursor into a local variable -- this allows
|
||||
// a writer to freely change it while we're reading while avoiding
|
||||
// using a lock
|
||||
char* snapshotWriteCursor = mWriteCursor; // atomic
|
||||
|
||||
// next check if the write cursor is in our segment
|
||||
if (mReadCursor <= snapshotWriteCursor &&
|
||||
snapshotWriteCursor < mReadSegmentEnd) {
|
||||
// same segment -- we've discarded all the unread segments we
|
||||
// can, so just updatethe read cursor
|
||||
mReadCursor = mWriteCursor;
|
||||
break;
|
||||
}
|
||||
// else advance to the next segment, freeing this one
|
||||
rv = PopReadSegment();
|
||||
if (NS_FAILED(rv)) break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRUint32 amt;
|
||||
const char* buf;
|
||||
rv = GetReadSegment(0, &buf, &amt);
|
||||
NS_ASSERTION(rv == NS_BASE_STREAM_EOF ||
|
||||
(NS_SUCCEEDED(rv) && amt == 0), "ReaderClosed failed");
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::GetCondition(nsresult *result)
|
||||
{
|
||||
*result = mCondition;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
|
||||
PRUint32 *writeCount)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsAutoCMonitor mon(this);
|
||||
*writeCount = 0;
|
||||
|
||||
if (mReaderClosed) {
|
||||
rv = NS_BASE_STREAM_CLOSED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
rv = mCondition;
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
PRUint32 writeBufLen;
|
||||
char* writeBuf;
|
||||
rv = GetWriteSegment(&writeBuf, &writeBufLen);
|
||||
if (NS_FAILED(rv) || writeBufLen == 0) {
|
||||
// if we failed to allocate a new segment, we're probably out
|
||||
// of memory, but we don't care -- just report what we were
|
||||
// able to write so far
|
||||
rv = (*writeCount == 0) ? rv : NS_OK;
|
||||
goto done;
|
||||
}
|
||||
|
||||
writeBufLen = PR_MIN(writeBufLen, count);
|
||||
while (writeBufLen > 0) {
|
||||
PRUint32 readCount = 0;
|
||||
rv = reader(closure, writeBuf, *writeCount, writeBufLen, &readCount);
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK || readCount == 0) {
|
||||
// if the place we're putting the data would block (probably ran
|
||||
// out of room) just return what we were able to write so far
|
||||
rv = (*writeCount == 0) ? rv : NS_OK;
|
||||
goto done;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// save the failure condition so that we can get it again later
|
||||
nsresult rv2 = SetCondition(rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv2), "SetCondition failed");
|
||||
// if we failed to read just report what we were
|
||||
// able to write so far
|
||||
rv = (*writeCount == 0) ? rv : NS_OK;
|
||||
goto done;
|
||||
}
|
||||
NS_ASSERTION(readCount <= writeBufLen, "reader returned bad readCount");
|
||||
writeBuf += readCount;
|
||||
writeBufLen -= readCount;
|
||||
*writeCount += readCount;
|
||||
count -= readCount;
|
||||
|
||||
// set the write cursor after the data is valid
|
||||
if (mWriteCursor + readCount == mWriteSegmentEnd) {
|
||||
mWriteSegment = nsnull; // allocate a new segment next time around
|
||||
mWriteSegmentEnd = nsnull;
|
||||
mWriteCursor = nsnull;
|
||||
}
|
||||
else
|
||||
mWriteCursor += readCount;
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (mObserver && *writeCount) {
|
||||
mObserver->OnWrite(this, *writeCount);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
nsReadFromRawBuffer(void* closure,
|
||||
char* toRawSegment,
|
||||
PRUint32 offset,
|
||||
PRUint32 count,
|
||||
PRUint32 *readCount)
|
||||
{
|
||||
const char* fromBuf = (const char*)closure;
|
||||
nsCRT::memcpy(toRawSegment, &fromBuf[offset], count);
|
||||
*readCount = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount)
|
||||
{
|
||||
return WriteSegments(nsReadFromRawBuffer, (void*)fromBuf, bufLen, writeCount);
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
nsReadFromInputStream(void* closure,
|
||||
char* toRawSegment,
|
||||
PRUint32 offset,
|
||||
PRUint32 count,
|
||||
PRUint32 *readCount)
|
||||
{
|
||||
nsIInputStream* fromStream = (nsIInputStream*)closure;
|
||||
return fromStream->Read(toRawSegment, count, readCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount)
|
||||
{
|
||||
return WriteSegments(nsReadFromInputStream, fromStream, count, writeCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::GetWriteSegment(char* *resultSegment,
|
||||
PRUint32 *resultSegmentLen)
|
||||
{
|
||||
nsAutoCMonitor mon(this);
|
||||
if (mReaderClosed)
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
|
||||
nsresult rv;
|
||||
*resultSegmentLen = 0;
|
||||
*resultSegment = nsnull;
|
||||
if (mWriteSegment == nsnull) {
|
||||
rv = PushWriteSegment();
|
||||
if (NS_FAILED(rv) || rv == NS_BASE_STREAM_WOULD_BLOCK) return rv;
|
||||
|
||||
NS_ASSERTION(mWriteSegment != nsnull, "failed to allocate segment");
|
||||
}
|
||||
|
||||
*resultSegmentLen = mWriteSegmentEnd - mWriteCursor;
|
||||
*resultSegment = mWriteCursor;
|
||||
NS_ASSERTION(*resultSegmentLen > 0, "Failed to get write segment.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::GetWritableAmount(PRUint32 *amount)
|
||||
{
|
||||
if (mReaderClosed)
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
|
||||
nsresult rv;
|
||||
PRUint32 readableAmount;
|
||||
rv = GetReadableAmount(&readableAmount);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
*amount = mMaxSize - readableAmount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::GetReaderClosed(PRBool *result)
|
||||
{
|
||||
*result = mReaderClosed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBuffer::SetCondition(nsresult condition)
|
||||
{
|
||||
nsAutoCMonitor mon(this);
|
||||
if (mReaderClosed)
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
|
||||
mCondition = condition;
|
||||
mWriteSegment = nsnull; // allows reader to free last segment w/o asserting
|
||||
mWriteSegmentEnd = nsnull;
|
||||
// don't reset mWriteCursor here -- we need it for the EOF point in the buffer
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_CID(kAllocatorCID, NS_ALLOCATOR_CID);
|
||||
|
||||
NS_COM nsresult
|
||||
NS_NewBuffer(nsIBuffer* *result,
|
||||
PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIAllocator, alloc, kAllocatorCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsBuffer* buf;
|
||||
rv = nsBuffer::Create(NULL, nsIBuffer::GetIID(), (void**)&buf);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = buf->Init(growBySize, maxSize, observer, alloc);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
*result = buf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kPageManagerCID, NS_PAGEMANAGER_CID);
|
||||
|
||||
NS_COM nsresult
|
||||
NS_NewPageBuffer(nsIBuffer* *result,
|
||||
PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIAllocator, alloc, kPageManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsBuffer* buf;
|
||||
rv = nsBuffer::Create(NULL, nsIBuffer::GetIID(), (void**)&buf);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = buf->Init(growBySize, maxSize, observer, alloc);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
*result = buf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,87 +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.
|
||||
*/
|
||||
|
||||
#ifndef nsBuffer_h___
|
||||
#define nsBuffer_h___
|
||||
|
||||
#include "nsIBuffer.h"
|
||||
#include "nscore.h"
|
||||
#include "prclist.h"
|
||||
#include "nsIAllocator.h"
|
||||
|
||||
class nsBuffer : public nsIBuffer {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
// nsIBuffer methods:
|
||||
NS_IMETHOD Init(PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer, nsIAllocator* allocator);
|
||||
NS_IMETHOD Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount);
|
||||
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
|
||||
PRUint32 *readCount);
|
||||
NS_IMETHOD GetReadSegment(PRUint32 segmentLogicalOffset,
|
||||
const char* *resultSegment,
|
||||
PRUint32 *resultSegmentLen);
|
||||
NS_IMETHOD GetReadableAmount(PRUint32 *amount);
|
||||
NS_IMETHOD Search(const char* forString, PRBool ignoreCase,
|
||||
PRBool *found, PRUint32 *offsetSearchedTo);
|
||||
NS_IMETHOD ReaderClosed(void);
|
||||
NS_IMETHOD GetCondition(nsresult *result);
|
||||
|
||||
NS_IMETHOD Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount);
|
||||
NS_IMETHOD WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount);
|
||||
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
|
||||
PRUint32 *writeCount);
|
||||
NS_IMETHOD GetWriteSegment(char* *resultSegment,
|
||||
PRUint32 *resultSegmentLen);
|
||||
NS_IMETHOD GetWritableAmount(PRUint32 *amount);
|
||||
NS_IMETHOD GetReaderClosed(PRBool *result);
|
||||
NS_IMETHOD SetCondition(nsresult condition);
|
||||
|
||||
// nsBuffer methods:
|
||||
nsBuffer();
|
||||
virtual ~nsBuffer();
|
||||
|
||||
nsresult PushWriteSegment();
|
||||
nsresult PopReadSegment();
|
||||
|
||||
protected:
|
||||
PRUint32 mGrowBySize;
|
||||
PRUint32 mMaxSize;
|
||||
nsIAllocator* mAllocator;
|
||||
nsIBufferObserver* mObserver;
|
||||
|
||||
PRCList mSegments;
|
||||
PRUint32 mBufferSize;
|
||||
|
||||
PRCList* mReadSegment;
|
||||
char* mReadSegmentEnd;
|
||||
char* mReadCursor;
|
||||
|
||||
PRCList* mWriteSegment;
|
||||
char* mWriteSegmentEnd;
|
||||
char* mWriteCursor;
|
||||
|
||||
PRBool mReaderClosed;
|
||||
nsresult mCondition;
|
||||
};
|
||||
|
||||
#endif // nsBuffer_h___
|
||||
@@ -1,40 +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.
|
||||
*/
|
||||
|
||||
#ifndef nsBufferPoolService_h___
|
||||
#define nsBufferPoolService_h___
|
||||
|
||||
#include "nsIBufferPoolService.h"
|
||||
|
||||
class nsBufferPoolService : public nsIBufferPoolService {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIBufferPoolService methods:
|
||||
NS_IMETHOD NewBuffer(PRUint32 minSize, PRUint32 maxSize,
|
||||
nsIByteBuffer* *result);
|
||||
|
||||
// nsBufferPoolService methods:
|
||||
nsBufferPoolService();
|
||||
virtual ~nsBufferPoolService();
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif // nsBufferPoolService_h___
|
||||
@@ -1,151 +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.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.
|
||||
*/
|
||||
|
||||
#include "nsByteBuffer.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
#define MIN_BUFFER_SIZE 32
|
||||
|
||||
ByteBufferImpl::ByteBufferImpl(void)
|
||||
: mBuffer(NULL), mSpace(0), mLength(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ByteBufferImpl::Init(PRUint32 aBufferSize)
|
||||
{
|
||||
if (aBufferSize < MIN_BUFFER_SIZE) {
|
||||
aBufferSize = MIN_BUFFER_SIZE;
|
||||
}
|
||||
mSpace = aBufferSize;
|
||||
mLength = 0;
|
||||
mBuffer = new char[aBufferSize];
|
||||
return mBuffer ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ByteBufferImpl,nsIByteBuffer)
|
||||
|
||||
ByteBufferImpl::~ByteBufferImpl()
|
||||
{
|
||||
if (nsnull != mBuffer) {
|
||||
delete[] mBuffer;
|
||||
mBuffer = nsnull;
|
||||
}
|
||||
mLength = 0;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
ByteBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
ByteBufferImpl* it = new ByteBufferImpl();
|
||||
if (nsnull == it)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(it);
|
||||
nsresult rv = it->QueryInterface(aIID, (void**)aResult);
|
||||
NS_RELEASE(it);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRUint32)
|
||||
ByteBufferImpl::GetLength(void) const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRUint32)
|
||||
ByteBufferImpl::GetBufferSize(void) const
|
||||
{
|
||||
return mSpace;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(char*)
|
||||
ByteBufferImpl::GetBuffer(void) const
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
ByteBufferImpl::Grow(PRUint32 aNewSize)
|
||||
{
|
||||
if (aNewSize < MIN_BUFFER_SIZE) {
|
||||
aNewSize = MIN_BUFFER_SIZE;
|
||||
}
|
||||
char* newbuf = new char[aNewSize];
|
||||
if (nsnull != newbuf) {
|
||||
if (0 != mLength) {
|
||||
nsCRT::memcpy(newbuf, mBuffer, mLength);
|
||||
}
|
||||
delete[] mBuffer;
|
||||
mBuffer = newbuf;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRInt32)
|
||||
ByteBufferImpl::Fill(nsresult* aErrorCode, nsIInputStream* aStream,
|
||||
PRUint32 aKeep)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aStream, "null stream");
|
||||
NS_PRECONDITION(aKeep <= mLength, "illegal keep count");
|
||||
if ((nsnull == aStream) || (PRUint32(aKeep) > PRUint32(mLength))) {
|
||||
// whoops
|
||||
*aErrorCode = NS_BASE_STREAM_ILLEGAL_ARGS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != aKeep) {
|
||||
// Slide over kept data
|
||||
nsCRT::memmove(mBuffer, mBuffer + (mLength - aKeep), aKeep);
|
||||
}
|
||||
|
||||
// Read in some new data
|
||||
mLength = aKeep;
|
||||
PRUint32 nb;
|
||||
*aErrorCode = aStream->Read(mBuffer + aKeep, mSpace - aKeep, &nb);
|
||||
if (NS_SUCCEEDED(*aErrorCode)) {
|
||||
mLength += nb;
|
||||
}
|
||||
else
|
||||
nb = 0;
|
||||
return nb;
|
||||
}
|
||||
|
||||
NS_COM nsresult NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
|
||||
nsISupports* aOuter,
|
||||
PRUint32 aBufferSize)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIByteBuffer* buf;
|
||||
rv = ByteBufferImpl::Create(aOuter, nsIByteBuffer::GetIID(), (void**)&buf);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = buf->Init(aBufferSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(buf);
|
||||
return rv;
|
||||
}
|
||||
*aInstancePtrResult = buf;
|
||||
return rv;
|
||||
}
|
||||
@@ -1,47 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsByteBuffer_h__
|
||||
#define nsByteBuffer_h__
|
||||
|
||||
#include "nsIByteBuffer.h"
|
||||
|
||||
class ByteBufferImpl : public nsIByteBuffer {
|
||||
public:
|
||||
ByteBufferImpl(void);
|
||||
virtual ~ByteBufferImpl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
NS_IMETHOD Init(PRUint32 aBufferSize);
|
||||
NS_IMETHOD_(PRUint32) GetLength(void) const;
|
||||
NS_IMETHOD_(PRUint32) GetBufferSize(void) const;
|
||||
NS_IMETHOD_(char*) GetBuffer() const;
|
||||
NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize);
|
||||
NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
|
||||
PRUint32 aKeep);
|
||||
|
||||
char* mBuffer;
|
||||
PRUint32 mSpace;
|
||||
PRUint32 mLength;
|
||||
};
|
||||
|
||||
#endif // nsByteBuffer_h__
|
||||
@@ -1,555 +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.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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* MODULE NOTES:
|
||||
* @update gess7/30/98
|
||||
*
|
||||
* Much as I hate to do it, we were using string compares wrong.
|
||||
* Often, programmers call functions like strcmp(s1,s2), and pass
|
||||
* one or more null strings. Rather than blow up on these, I've
|
||||
* added quick checks to ensure that cases like this don't cause
|
||||
* us to fail.
|
||||
*
|
||||
* In general, if you pass a null into any of these string compare
|
||||
* routines, we simply return 0.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsUnicharUtilCIID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICaseConversion.h"
|
||||
|
||||
|
||||
// XXX Bug: These tables don't lowercase the upper 128 characters properly
|
||||
|
||||
// This table maps uppercase characters to lower case characters;
|
||||
// characters that are neither upper nor lower case are unaffected.
|
||||
static const unsigned char kUpper2Lower[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64,
|
||||
|
||||
// upper band mapped to lower [A-Z] => [a-z]
|
||||
97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
|
||||
112,113,114,115,116,117,118,119,120,121,122,
|
||||
|
||||
91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
|
||||
};
|
||||
|
||||
static const unsigned char kLower2Upper[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96,
|
||||
|
||||
// lower band mapped to upper [a-z] => [A-Z]
|
||||
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
|
||||
|
||||
123,124,125,126,127,
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
|
||||
};
|
||||
|
||||
// XXX bug: this doesn't map 0x80 to 0x9f properly
|
||||
const PRUnichar kIsoLatin1ToUCS2[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#define TOLOWER(_ucs2) \
|
||||
(((_ucs2) < 128) ? PRUnichar(kUpper2Lower[_ucs2]) : _ToLower(_ucs2))
|
||||
|
||||
#define TOUPPER(_ucs2) \
|
||||
(((_ucs2) < 128) ? PRUnichar(kLower2Upper[_ucs2]) : _ToUpper(_ucs2))
|
||||
|
||||
class HandleCaseConversionShutdown : public nsIShutdownListener {
|
||||
public :
|
||||
NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service);
|
||||
HandleCaseConversionShutdown(void) { NS_INIT_REFCNT(); }
|
||||
virtual ~HandleCaseConversionShutdown(void) {}
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
|
||||
|
||||
static nsICaseConversion * gCaseConv = NULL;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(HandleCaseConversionShutdown, nsIShutdownListener)
|
||||
|
||||
nsresult
|
||||
HandleCaseConversionShutdown::OnShutdown(const nsCID& cid,
|
||||
nsISupports* aService)
|
||||
{
|
||||
if (cid.Equals(kUnicharUtilCID)) {
|
||||
NS_ASSERTION(aService == gCaseConv, "wrong service!");
|
||||
gCaseConv->Release();
|
||||
gCaseConv = NULL;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static HandleCaseConversionShutdown* gListener = NULL;
|
||||
|
||||
static void StartUpCaseConversion()
|
||||
{
|
||||
nsresult err;
|
||||
|
||||
if ( NULL == gListener )
|
||||
{
|
||||
gListener = new HandleCaseConversionShutdown();
|
||||
gListener->AddRef();
|
||||
}
|
||||
err = nsServiceManager::GetService(kUnicharUtilCID, NS_GET_IID(nsICaseConversion),
|
||||
(nsISupports**) &gCaseConv, gListener);
|
||||
}
|
||||
static void CheckCaseConversion()
|
||||
{
|
||||
if(NULL == gCaseConv )
|
||||
StartUpCaseConversion();
|
||||
|
||||
NS_ASSERTION( gCaseConv != NULL , "cannot obtain UnicharUtil");
|
||||
|
||||
}
|
||||
|
||||
static PRUnichar _ToLower(PRUnichar aChar)
|
||||
{
|
||||
PRUnichar oLower;
|
||||
CheckCaseConversion();
|
||||
nsresult err = gCaseConv->ToLower(aChar, &oLower);
|
||||
NS_ASSERTION( NS_SUCCEEDED(err), "failed to communicate to UnicharUtil");
|
||||
return ( NS_SUCCEEDED(err) ) ? oLower : aChar ;
|
||||
}
|
||||
|
||||
static PRUnichar _ToUpper(PRUnichar aChar)
|
||||
{
|
||||
nsresult err;
|
||||
PRUnichar oUpper;
|
||||
CheckCaseConversion();
|
||||
err = gCaseConv->ToUpper(aChar, &oUpper);
|
||||
NS_ASSERTION( NS_SUCCEEDED(err), "failed to communicate to UnicharUtil");
|
||||
return ( NS_SUCCEEDED(err) ) ? oUpper : aChar ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PRUnichar nsCRT::ToUpper(PRUnichar aChar)
|
||||
{
|
||||
return TOUPPER(aChar);
|
||||
}
|
||||
|
||||
PRUnichar nsCRT::ToLower(PRUnichar aChar)
|
||||
{
|
||||
return TOLOWER(aChar);
|
||||
}
|
||||
|
||||
PRBool nsCRT::IsUpper(PRUnichar aChar)
|
||||
{
|
||||
return aChar != nsCRT::ToLower(aChar);
|
||||
}
|
||||
|
||||
PRBool nsCRT::IsLower(PRUnichar aChar)
|
||||
{
|
||||
return aChar != nsCRT::ToUpper(aChar);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// My lovely strtok routine
|
||||
|
||||
#define IS_DELIM(m, c) ((m)[(c) >> 3] & (1 << ((c) & 7)))
|
||||
#define SET_DELIM(m, c) ((m)[(c) >> 3] |= (1 << ((c) & 7)))
|
||||
#define DELIM_TABLE_SIZE 32
|
||||
|
||||
char* nsCRT::strtok(char* string, const char* delims, char* *newStr)
|
||||
{
|
||||
NS_ASSERTION(string, "Unlike regular strtok, the first argument cannot be null.");
|
||||
|
||||
char delimTable[DELIM_TABLE_SIZE];
|
||||
PRUint32 i;
|
||||
char* result;
|
||||
char* str = string;
|
||||
|
||||
for (i = 0; i < DELIM_TABLE_SIZE; i++)
|
||||
delimTable[i] = '\0';
|
||||
|
||||
for (i = 0; i < DELIM_TABLE_SIZE && delims[i]; i++) {
|
||||
SET_DELIM(delimTable, delims[i]);
|
||||
}
|
||||
NS_ASSERTION(delims[i] == '\0', "too many delimiters");
|
||||
|
||||
// skip to beginning
|
||||
while (*str && IS_DELIM(delimTable, *str)) {
|
||||
str++;
|
||||
}
|
||||
result = str;
|
||||
|
||||
// fix up the end of the token
|
||||
while (*str) {
|
||||
if (IS_DELIM(delimTable, *str)) {
|
||||
*str++ = '\0';
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
*newStr = str;
|
||||
|
||||
return str == result ? NULL : result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 nsCRT::strlen(const PRUnichar* s)
|
||||
{
|
||||
PRUint32 len = 0;
|
||||
if(s) {
|
||||
while (*s++ != 0) {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare unichar string ptrs, stopping at the 1st null
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 and s2 both point to unichar strings
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strcmp(const PRUnichar* s1, const PRUnichar* s2)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
for (;;) {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = *s2++;
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare unichar string ptrs, stopping at the 1st null or nth char.
|
||||
* NOTE: If either is null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 and s2 both point to unichar strings
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strncmp(const PRUnichar* s1, const PRUnichar* s2, PRUint32 n)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
if(n != 0) {
|
||||
do {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = *s2++;
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare unichar string ptrs without regard to case
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 and s2 both point to unichar strings
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strcasecmp(const PRUnichar* s1, const PRUnichar* s2)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
for (;;) {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = *s2++;
|
||||
if (c1 != c2) {
|
||||
c1 = TOLOWER(c1);
|
||||
c2 = TOLOWER(c2);
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare unichar string ptrs, stopping at the 1st null or nth char;
|
||||
* also ignoring the case of characters.
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 and s2 both point to unichar strings
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strncasecmp(const PRUnichar* s1, const PRUnichar* s2, PRUint32 n)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
if(n != 0){
|
||||
do {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = *s2++;
|
||||
if (c1 != c2) {
|
||||
c1 = TOLOWER(c1);
|
||||
c2 = TOLOWER(c2);
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare a unichar string ptr to cstring.
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 points to unichar string
|
||||
* @param s2 points to cstring
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strcmp(const PRUnichar* s1, const char* s2)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
for (;;) {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = kIsoLatin1ToUCS2[*(const unsigned char*)s2++];
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare a unichar string ptr to cstring, up to N chars.
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 points to unichar string
|
||||
* @param s2 points to cstring
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strncmp(const PRUnichar* s1, const char* s2, PRUint32 n)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
if(n != 0){
|
||||
do {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = kIsoLatin1ToUCS2[*(const unsigned char*)s2++];
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a unichar string ptr to cstring without regard to case
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 points to unichar string
|
||||
* @param s2 points to cstring
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strcasecmp(const PRUnichar* s1, const char* s2)
|
||||
{
|
||||
if(s1 && s2) {
|
||||
for (;;) {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = kIsoLatin1ToUCS2[*(const unsigned char*)s2++];
|
||||
if (c1 != c2) {
|
||||
c1 = TOLOWER(c1);
|
||||
c2 = TOLOWER(c2);
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((0==c1) || (0==c2)) break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caseless compare up to N chars between unichar string ptr to cstring.
|
||||
* NOTE: If both are null, we return 0.
|
||||
* @update gess7/30/98
|
||||
* @param s1 points to unichar string
|
||||
* @param s2 points to cstring
|
||||
* @return 0 if they match, -1 if s1<s2; 1 if s1>s2
|
||||
*/
|
||||
PRInt32 nsCRT::strncasecmp(const PRUnichar* s1, const char* s2, PRUint32 n)
|
||||
{
|
||||
if(s1 && s2){
|
||||
if(n != 0){
|
||||
do {
|
||||
PRUnichar c1 = *s1++;
|
||||
PRUnichar c2 = kIsoLatin1ToUCS2[*(const unsigned char*)s2++];
|
||||
if (c1 != c2) {
|
||||
c1 = TOLOWER(c1);
|
||||
c2 = TOLOWER(c2);
|
||||
if (c1 != c2) {
|
||||
if (c1 < c2) return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (c1 == 0) break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRUnichar* nsCRT::strdup(const PRUnichar* str)
|
||||
{
|
||||
PRUint32 len = nsCRT::strlen(str) + 1; // add one for null
|
||||
|
||||
|
||||
nsCppSharedAllocator<PRUnichar> shared_allocator;
|
||||
PRUnichar* rslt = shared_allocator.allocate(len);
|
||||
// PRUnichar* rslt = new PRUnichar[len];
|
||||
|
||||
if (rslt == NULL) return NULL;
|
||||
nsCRT::memcpy(rslt, str, len * sizeof(PRUnichar));
|
||||
return rslt;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::HashValue(const char* us)
|
||||
{
|
||||
PRUint32 rv = 0;
|
||||
if(us) {
|
||||
char ch;
|
||||
while ((ch = *us++) != 0) {
|
||||
// FYI: rv = rv*37 + ch
|
||||
rv = ((rv << 5) + (rv << 2) + rv) + ch;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::HashValue(const char* us, PRUint32* uslenp)
|
||||
{
|
||||
PRUint32 rv = 0;
|
||||
PRUint32 len = 0;
|
||||
char ch;
|
||||
while ((ch = *us++) != 0) {
|
||||
// FYI: rv = rv*37 + ch
|
||||
rv = ((rv << 5) + (rv << 2) + rv) + ch;
|
||||
len++;
|
||||
}
|
||||
*uslenp = len;
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::HashValue(const PRUnichar* us)
|
||||
{
|
||||
PRUint32 rv = 0;
|
||||
if(us) {
|
||||
PRUnichar ch;
|
||||
while ((ch = *us++) != 0) {
|
||||
// FYI: rv = rv*37 + ch
|
||||
rv = ((rv << 5) + (rv << 2) + rv) + ch;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::HashValue(const PRUnichar* us, PRUint32* uslenp)
|
||||
{
|
||||
PRUint32 rv = 0;
|
||||
PRUint32 len = 0;
|
||||
PRUnichar ch;
|
||||
while ((ch = *us++) != 0) {
|
||||
// FYI: rv = rv*37 + ch
|
||||
rv = ((rv << 5) + (rv << 2) + rv) + ch;
|
||||
len++;
|
||||
}
|
||||
*uslenp = len;
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32 nsCRT::atoi( const PRUnichar *string )
|
||||
{
|
||||
return atoi(string);
|
||||
}
|
||||
|
||||
@@ -1,239 +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.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.
|
||||
*/
|
||||
#ifndef nsCRT_h___
|
||||
#define nsCRT_h___
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "plstr.h"
|
||||
#include "nscore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsCppSharedAllocator.h"
|
||||
|
||||
#define CR '\015'
|
||||
#define LF '\012'
|
||||
#define VTAB '\013'
|
||||
#define FF '\014'
|
||||
#define TAB '\011'
|
||||
#define CRLF "\015\012" /* A CR LF equivalent string */
|
||||
|
||||
#ifdef XP_MAC
|
||||
# define NS_LINEBREAK "\015"
|
||||
# define NS_LINEBREAK_LEN 1
|
||||
#else
|
||||
# ifdef XP_PC
|
||||
# define NS_LINEBREAK "\015\012"
|
||||
# define NS_LINEBREAK_LEN 2
|
||||
# else
|
||||
# if defined(XP_UNIX) || defined(XP_BEOS)
|
||||
# define NS_LINEBREAK "\012"
|
||||
# define NS_LINEBREAK_LEN 1
|
||||
# endif /* XP_UNIX */
|
||||
# endif /* XP_PC */
|
||||
#endif /* XP_MAC */
|
||||
|
||||
|
||||
extern const PRUnichar kIsoLatin1ToUCS2[256];
|
||||
|
||||
|
||||
// This macro can be used in a class declaration for classes that want
|
||||
// to ensure that their instance memory is zeroed.
|
||||
#define NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW \
|
||||
void* operator new(size_t sz) { \
|
||||
void* rv = ::operator new(sz); \
|
||||
if (rv) { \
|
||||
nsCRT::zero(rv, sz); \
|
||||
} \
|
||||
return rv; \
|
||||
} \
|
||||
void operator delete(void* ptr) { \
|
||||
::operator delete(ptr); \
|
||||
}
|
||||
|
||||
// This macro works with the next macro to declare a non-inlined
|
||||
// version of the above.
|
||||
#define NS_DECL_ZEROING_OPERATOR_NEW \
|
||||
void* operator new(size_t sz); \
|
||||
void operator delete(void* ptr);
|
||||
|
||||
#define NS_IMPL_ZEROING_OPERATOR_NEW(_class) \
|
||||
void* _class::operator new(size_t sz) { \
|
||||
void* rv = ::operator new(sz); \
|
||||
if (rv) { \
|
||||
nsCRT::zero(rv, sz); \
|
||||
} \
|
||||
return rv; \
|
||||
} \
|
||||
void _class::operator delete(void* ptr) { \
|
||||
::operator delete(ptr); \
|
||||
}
|
||||
|
||||
// Freeing helper
|
||||
#define CRTFREEIF(x) if (x) { nsCRT::free(x); x = 0; }
|
||||
|
||||
/// This is a wrapper class around all the C runtime functions.
|
||||
|
||||
class NS_COM nsCRT {
|
||||
public:
|
||||
|
||||
/** Copy bytes from aSrc to aDest.
|
||||
@param aDest the destination address
|
||||
@param aSrc the source address
|
||||
@param aCount the number of bytes to copy
|
||||
*/
|
||||
static void memcpy(void* aDest, const void* aSrc, PRUint32 aCount) {
|
||||
::memcpy(aDest, aSrc, (size_t)aCount);
|
||||
}
|
||||
|
||||
static void memmove(void* aDest, const void* aSrc, PRUint32 aCount) {
|
||||
::memmove(aDest, aSrc, (size_t)aCount);
|
||||
}
|
||||
|
||||
static void memset(void* aDest, PRUint8 aByte, PRUint32 aCount) {
|
||||
::memset(aDest, aByte, aCount);
|
||||
}
|
||||
|
||||
static void zero(void* aDest, PRUint32 aCount) {
|
||||
::memset(aDest, 0, (size_t)aCount);
|
||||
}
|
||||
|
||||
/** Compute the string length of s
|
||||
@param s the string in question
|
||||
@return the length of s
|
||||
*/
|
||||
static PRUint32 strlen(const char* s) {
|
||||
return PRUint32(::strlen(s));
|
||||
}
|
||||
|
||||
/// Compare s1 and s2.
|
||||
static PRInt32 strcmp(const char* s1, const char* s2) {
|
||||
return PRUint32(PL_strcmp(s1, s2));
|
||||
}
|
||||
|
||||
static PRInt32 strncmp(const char* s1, const char* s2,
|
||||
PRUint32 aMaxLen) {
|
||||
return PRInt32(PL_strncmp(s1, s2, aMaxLen));
|
||||
}
|
||||
|
||||
/// Case-insensitive string comparison.
|
||||
static PRInt32 strcasecmp(const char* s1, const char* s2) {
|
||||
return PRInt32(PL_strcasecmp(s1, s2));
|
||||
}
|
||||
|
||||
/// Case-insensitive string comparison with length
|
||||
static PRInt32 strncasecmp(const char* s1, const char* s2, PRUint32 aMaxLen) {
|
||||
return PRInt32(PL_strncasecmp(s1, s2, aMaxLen));
|
||||
}
|
||||
|
||||
static PRInt32 strncmp(const char* s1, const char* s2, PRInt32 aMaxLen) {
|
||||
// inline the first test (assumes strings are not null):
|
||||
PRInt32 diff = ((const unsigned char*)s1)[0] - ((const unsigned char*)s2)[0];
|
||||
if (diff != 0) return diff;
|
||||
return PRInt32(PL_strncmp(s1,s2,aMaxLen));
|
||||
}
|
||||
|
||||
static char* strdup(const char* str) {
|
||||
return PL_strdup(str);
|
||||
}
|
||||
|
||||
static void free(char* str) {
|
||||
PL_strfree(str);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
How to use this fancy (thread-safe) version of strtok:
|
||||
|
||||
void main( void ) {
|
||||
printf( "%s\n\nTokens:\n", string );
|
||||
// Establish string and get the first token:
|
||||
char* newStr;
|
||||
token = nsCRT::strtok( string, seps, &newStr );
|
||||
while( token != NULL ) {
|
||||
// While there are tokens in "string"
|
||||
printf( " %s\n", token );
|
||||
// Get next token:
|
||||
token = nsCRT::strtok( newStr, seps, &newStr );
|
||||
}
|
||||
}
|
||||
* WARNING - STRTOK WHACKS str THE FIRST TIME IT IS CALLED *
|
||||
* MAKE A COPY OF str IF YOU NEED TO USE IT AFTER strtok() *
|
||||
*/
|
||||
static char* strtok(char* str, const char* delims, char* *newStr);
|
||||
|
||||
/// Like strlen except for ucs2 strings
|
||||
static PRUint32 strlen(const PRUnichar* s);
|
||||
|
||||
/// Like strcmp except for ucs2 strings
|
||||
static PRInt32 strcmp(const PRUnichar* s1, const PRUnichar* s2);
|
||||
/// Like strcmp except for ucs2 strings
|
||||
static PRInt32 strncmp(const PRUnichar* s1, const PRUnichar* s2,
|
||||
PRUint32 aMaxLen);
|
||||
|
||||
/// Like strcasecmp except for ucs2 strings
|
||||
static PRInt32 strcasecmp(const PRUnichar* s1, const PRUnichar* s2);
|
||||
/// Like strncasecmp except for ucs2 strings
|
||||
static PRInt32 strncasecmp(const PRUnichar* s1, const PRUnichar* s2,
|
||||
PRUint32 aMaxLen);
|
||||
|
||||
/// Like strcmp with a char* and a ucs2 string
|
||||
static PRInt32 strcmp(const PRUnichar* s1, const char* s2);
|
||||
/// Like strncmp with a char* and a ucs2 string
|
||||
static PRInt32 strncmp(const PRUnichar* s1, const char* s2,
|
||||
PRUint32 aMaxLen);
|
||||
|
||||
/// Like strcasecmp with a char* and a ucs2 string
|
||||
static PRInt32 strcasecmp(const PRUnichar* s1, const char* s2);
|
||||
/// Like strncasecmp with a char* and a ucs2 string
|
||||
static PRInt32 strncasecmp(const PRUnichar* s1, const char* s2,
|
||||
PRUint32 aMaxLen);
|
||||
|
||||
// Note: uses new[] to allocate memory, so you must use delete[] to
|
||||
// free the memory
|
||||
static PRUnichar* strdup(const PRUnichar* str);
|
||||
|
||||
static void free(PRUnichar* str) {
|
||||
nsCppSharedAllocator<PRUnichar> shared_allocator;
|
||||
shared_allocator.deallocate(str, 0 /*we never new or kept the size*/);
|
||||
}
|
||||
|
||||
/// Compute a hashcode for a C string
|
||||
static PRUint32 HashValue(const char* s1);
|
||||
|
||||
/// Same as above except that we return the length in s1len
|
||||
static PRUint32 HashValue(const char* s1, PRUint32* s1len);
|
||||
|
||||
/// Compute a hashcode for a ucs2 string
|
||||
static PRUint32 HashValue(const PRUnichar* s1);
|
||||
|
||||
/// Same as above except that we return the length in s1len
|
||||
static PRUint32 HashValue(const PRUnichar* s1, PRUint32* s1len);
|
||||
|
||||
/// String to integer.
|
||||
static PRInt32 atoi( const PRUnichar *string );
|
||||
|
||||
static PRUnichar ToUpper(PRUnichar aChar);
|
||||
|
||||
static PRUnichar ToLower(PRUnichar aChar);
|
||||
|
||||
static PRBool IsUpper(PRUnichar aChar);
|
||||
|
||||
static PRBool IsLower(PRUnichar aChar);
|
||||
};
|
||||
|
||||
#endif /* nsCRT_h___ */
|
||||
@@ -1,365 +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.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.
|
||||
*/
|
||||
|
||||
#include "nsIEnumerator.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Intersection Enumerators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsConjoiningEnumerator : public nsIBidirectionalEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIEnumerator methods:
|
||||
NS_DECL_NSIENUMERATOR
|
||||
|
||||
// nsIBidirectionalEnumerator methods:
|
||||
NS_DECL_NSIBIDIRECTIONALENUMERATOR
|
||||
|
||||
// nsConjoiningEnumerator methods:
|
||||
nsConjoiningEnumerator(nsIEnumerator* first, nsIEnumerator* second);
|
||||
virtual ~nsConjoiningEnumerator(void);
|
||||
|
||||
protected:
|
||||
nsIEnumerator* mFirst;
|
||||
nsIEnumerator* mSecond;
|
||||
nsIEnumerator* mCurrent;
|
||||
};
|
||||
|
||||
nsConjoiningEnumerator::nsConjoiningEnumerator(nsIEnumerator* first, nsIEnumerator* second)
|
||||
: mFirst(first), mSecond(second), mCurrent(first)
|
||||
{
|
||||
NS_ADDREF(mFirst);
|
||||
NS_ADDREF(mSecond);
|
||||
}
|
||||
|
||||
nsConjoiningEnumerator::~nsConjoiningEnumerator(void)
|
||||
{
|
||||
NS_RELEASE(mFirst);
|
||||
NS_RELEASE(mSecond);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsConjoiningEnumerator, nsIBidirectionalEnumerator, nsIEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsConjoiningEnumerator::First(void)
|
||||
{
|
||||
mCurrent = mFirst;
|
||||
return mCurrent->First();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsConjoiningEnumerator::Next(void)
|
||||
{
|
||||
nsresult rv = mCurrent->Next();
|
||||
if (NS_FAILED(rv) && mCurrent == mFirst) {
|
||||
mCurrent = mSecond;
|
||||
rv = mCurrent->First();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsConjoiningEnumerator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
return mCurrent->CurrentItem(aItem);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsConjoiningEnumerator::IsDone(void)
|
||||
{
|
||||
return (mCurrent == mFirst && mCurrent->IsDone() == NS_OK)
|
||||
|| (mCurrent == mSecond && mCurrent->IsDone() == NS_OK)
|
||||
? NS_OK : NS_COMFALSE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsConjoiningEnumerator::Last(void)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIBidirectionalEnumerator* be;
|
||||
rv = mSecond->QueryInterface(nsIBidirectionalEnumerator::GetIID(), (void**)&be);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mCurrent = mSecond;
|
||||
rv = be->Last();
|
||||
NS_RELEASE(be);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsConjoiningEnumerator::Prev(void)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIBidirectionalEnumerator* be;
|
||||
rv = mCurrent->QueryInterface(nsIBidirectionalEnumerator::GetIID(), (void**)&be);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = be->Prev();
|
||||
NS_RELEASE(be);
|
||||
if (NS_FAILED(rv) && mCurrent == mSecond) {
|
||||
rv = mFirst->QueryInterface(nsIBidirectionalEnumerator::GetIID(), (void**)&be);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mCurrent = mFirst;
|
||||
rv = be->Last();
|
||||
NS_RELEASE(be);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewConjoiningEnumerator(nsIEnumerator* first, nsIEnumerator* second,
|
||||
nsIBidirectionalEnumerator* *aInstancePtrResult)
|
||||
{
|
||||
if (aInstancePtrResult == 0)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsConjoiningEnumerator* e = new nsConjoiningEnumerator(first, second);
|
||||
if (e == 0)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(e);
|
||||
*aInstancePtrResult = e;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static nsresult
|
||||
nsEnumeratorContains(nsIEnumerator* e, nsISupports* item)
|
||||
{
|
||||
nsresult rv;
|
||||
for (e->First(); e->IsDone() != NS_OK; e->Next()) {
|
||||
nsISupports* other;
|
||||
rv = e->CurrentItem(&other);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (item == other) {
|
||||
NS_RELEASE(other);
|
||||
return NS_OK; // true -- exists in enumerator
|
||||
}
|
||||
NS_RELEASE(other);
|
||||
}
|
||||
return NS_COMFALSE; // false -- doesn't exist
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Intersection Enumerators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsIntersectionEnumerator : public nsIEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIEnumerator methods:
|
||||
NS_DECL_NSIENUMERATOR
|
||||
|
||||
// nsIntersectionEnumerator methods:
|
||||
nsIntersectionEnumerator(nsIEnumerator* first, nsIEnumerator* second);
|
||||
virtual ~nsIntersectionEnumerator(void);
|
||||
|
||||
protected:
|
||||
nsIEnumerator* mFirst;
|
||||
nsIEnumerator* mSecond;
|
||||
};
|
||||
|
||||
nsIntersectionEnumerator::nsIntersectionEnumerator(nsIEnumerator* first, nsIEnumerator* second)
|
||||
: mFirst(first), mSecond(second)
|
||||
{
|
||||
NS_ADDREF(mFirst);
|
||||
NS_ADDREF(mSecond);
|
||||
}
|
||||
|
||||
nsIntersectionEnumerator::~nsIntersectionEnumerator(void)
|
||||
{
|
||||
NS_RELEASE(mFirst);
|
||||
NS_RELEASE(mSecond);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsIntersectionEnumerator, nsIEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIntersectionEnumerator::First(void)
|
||||
{
|
||||
nsresult rv = mFirst->First();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return Next();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIntersectionEnumerator::Next(void)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// find the first item that exists in both
|
||||
for (; mFirst->IsDone() != NS_OK; mFirst->Next()) {
|
||||
nsISupports* item;
|
||||
rv = mFirst->CurrentItem(&item);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// see if it also exists in mSecond
|
||||
rv = nsEnumeratorContains(mSecond, item);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_RELEASE(item);
|
||||
if (rv == NS_OK) {
|
||||
// found in both, so return leaving it as the current item of mFirst
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIntersectionEnumerator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
return mFirst->CurrentItem(aItem);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIntersectionEnumerator::IsDone(void)
|
||||
{
|
||||
return mFirst->IsDone();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewIntersectionEnumerator(nsIEnumerator* first, nsIEnumerator* second,
|
||||
nsIEnumerator* *aInstancePtrResult)
|
||||
{
|
||||
if (aInstancePtrResult == 0)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsIntersectionEnumerator* e = new nsIntersectionEnumerator(first, second);
|
||||
if (e == 0)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(e);
|
||||
*aInstancePtrResult = e;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Union Enumerators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsUnionEnumerator : public nsIEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIEnumerator methods:
|
||||
NS_DECL_NSIENUMERATOR
|
||||
|
||||
// nsUnionEnumerator methods:
|
||||
nsUnionEnumerator(nsIEnumerator* first, nsIEnumerator* second);
|
||||
virtual ~nsUnionEnumerator(void);
|
||||
|
||||
protected:
|
||||
nsIEnumerator* mFirst;
|
||||
nsIEnumerator* mSecond;
|
||||
};
|
||||
|
||||
nsUnionEnumerator::nsUnionEnumerator(nsIEnumerator* first, nsIEnumerator* second)
|
||||
: mFirst(first), mSecond(second)
|
||||
{
|
||||
NS_ADDREF(mFirst);
|
||||
NS_ADDREF(mSecond);
|
||||
}
|
||||
|
||||
nsUnionEnumerator::~nsUnionEnumerator(void)
|
||||
{
|
||||
NS_RELEASE(mFirst);
|
||||
NS_RELEASE(mSecond);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsUnionEnumerator, nsIEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUnionEnumerator::First(void)
|
||||
{
|
||||
nsresult rv = mFirst->First();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return Next();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUnionEnumerator::Next(void)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// find the first item that exists in both
|
||||
for (; mFirst->IsDone() != NS_OK; mFirst->Next()) {
|
||||
nsISupports* item;
|
||||
rv = mFirst->CurrentItem(&item);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// see if it also exists in mSecond
|
||||
rv = nsEnumeratorContains(mSecond, item);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_RELEASE(item);
|
||||
if (rv != NS_OK) {
|
||||
// if it didn't exist in mSecond, return, making it the current item
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// each time around, make sure that mSecond gets reset to the beginning
|
||||
// so that when mFirst is done, we'll be ready to enumerate mSecond
|
||||
rv = mSecond->First();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return mSecond->Next();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUnionEnumerator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
if (mFirst->IsDone() != NS_OK)
|
||||
return mFirst->CurrentItem(aItem);
|
||||
else
|
||||
return mSecond->CurrentItem(aItem);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUnionEnumerator::IsDone(void)
|
||||
{
|
||||
return (mFirst->IsDone() == NS_OK && mSecond->IsDone() == NS_OK)
|
||||
? NS_OK : NS_COMFALSE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewUnionEnumerator(nsIEnumerator* first, nsIEnumerator* second,
|
||||
nsIEnumerator* *aInstancePtrResult)
|
||||
{
|
||||
if (aInstancePtrResult == 0)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsUnionEnumerator* e = new nsUnionEnumerator(first, second);
|
||||
if (e == 0)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(e);
|
||||
*aInstancePtrResult = e;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,122 +0,0 @@
|
||||
#ifndef nsCppSharedAllocator_h__
|
||||
#define nsCppSharedAllocator_h__
|
||||
|
||||
#include "nsIAllocator.h" // for |nsAllocator|
|
||||
#include "nscore.h" // for |NS_XXX_CAST|
|
||||
#include <new.h> // to allow placement |new|
|
||||
|
||||
|
||||
// under Metrowerks (Mac), we don't have autoconf yet
|
||||
#ifdef __MWERKS__
|
||||
#define HAVE_CPP_MEMBER_TEMPLATES
|
||||
#define HAVE_CPP_NUMERIC_LIMITS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CPP_NUMERIC_LIMITS
|
||||
#include <limits>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
|
||||
template <class T>
|
||||
class nsCppSharedAllocator
|
||||
/*
|
||||
...allows Standard Library containers, et al, to use our global shared
|
||||
(XP)COM-aware allocator.
|
||||
*/
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
|
||||
|
||||
|
||||
nsCppSharedAllocator() { }
|
||||
|
||||
#ifdef HAVE_CPP_MEMBER_TEMPLATES
|
||||
template <class U>
|
||||
nsCppSharedAllocator( const nsCppSharedAllocator<U>& ) { }
|
||||
#endif
|
||||
|
||||
~nsCppSharedAllocator() { }
|
||||
|
||||
|
||||
pointer
|
||||
address( reference r ) const
|
||||
{
|
||||
return &r;
|
||||
}
|
||||
|
||||
const_pointer
|
||||
address( const_reference r ) const
|
||||
{
|
||||
return &r;
|
||||
}
|
||||
|
||||
pointer
|
||||
allocate( size_type n, const void* /*hint*/=0 )
|
||||
{
|
||||
return NS_REINTERPRET_CAST(pointer, nsAllocator::Alloc(NS_STATIC_CAST(PRUint32, n*sizeof(T))));
|
||||
}
|
||||
|
||||
void
|
||||
deallocate( pointer p, size_type /*n*/ )
|
||||
{
|
||||
nsAllocator::Free(p);
|
||||
}
|
||||
|
||||
void
|
||||
construct( pointer p, const T& val )
|
||||
{
|
||||
new (p) T(val);
|
||||
}
|
||||
|
||||
void
|
||||
destroy( pointer p )
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
size_type
|
||||
max_size() const
|
||||
{
|
||||
#ifdef HAVE_CPP_NUMERIC_LIMITS
|
||||
return numeric_limits<size_type>::max() / sizeof(T);
|
||||
#else
|
||||
return ULONG_MAX / sizeof(T);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_CPP_MEMBER_TEMPLATES
|
||||
template <class U>
|
||||
struct rebind
|
||||
{
|
||||
typedef nsCppSharedAllocator<U> other;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
PRBool
|
||||
operator==( const nsCppSharedAllocator<T>&, const nsCppSharedAllocator<T>& )
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PRBool
|
||||
operator!=( const nsCppSharedAllocator<T>&, const nsCppSharedAllocator<T>& )
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#endif /* !defined(nsCppSharedAllocator_h__) */
|
||||
@@ -1,594 +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.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.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsDeque.h"
|
||||
#include "nsCRT.h"
|
||||
#include <stdio.h>
|
||||
|
||||
//#define _SELFTEST_DEQUE 1
|
||||
#undef _SELFTEST_DEQUE
|
||||
|
||||
/**
|
||||
* Standard constructor
|
||||
* @update gess4/18/98
|
||||
* @return new deque
|
||||
*/
|
||||
nsDeque::nsDeque(nsDequeFunctor* aDeallocator) {
|
||||
mDeallocator=aDeallocator;
|
||||
mOrigin=mSize=0;
|
||||
mData=mBuffer; // don't allocate space until you must
|
||||
mCapacity=sizeof(mBuffer)/sizeof(mBuffer[0]);
|
||||
nsCRT::zero(mData,mCapacity*sizeof(mBuffer[0]));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
* @update gess4/18/98
|
||||
*/
|
||||
nsDeque::~nsDeque() {
|
||||
|
||||
#if 0
|
||||
char buffer[30];
|
||||
printf("Capacity: %i\n",mCapacity);
|
||||
|
||||
static int mCaps[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
switch(mCapacity) {
|
||||
case 4: mCaps[0]++; break;
|
||||
case 8: mCaps[1]++; break;
|
||||
case 16: mCaps[2]++; break;
|
||||
case 32: mCaps[3]++; break;
|
||||
case 64: mCaps[4]++; break;
|
||||
case 128: mCaps[5]++; break;
|
||||
case 256: mCaps[6]++; break;
|
||||
case 512: mCaps[7]++; break;
|
||||
case 1024: mCaps[8]++; break;
|
||||
case 2048: mCaps[9]++; break;
|
||||
case 4096: mCaps[10]++; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
Erase();
|
||||
if(mData && (mData!=mBuffer))
|
||||
delete [] mData;
|
||||
mData=0;
|
||||
if(mDeallocator) {
|
||||
delete mDeallocator;
|
||||
}
|
||||
mDeallocator=0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void nsDeque::SetDeallocator(nsDequeFunctor* aDeallocator){
|
||||
if(mDeallocator) {
|
||||
delete mDeallocator;
|
||||
}
|
||||
mDeallocator=aDeallocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from container without destroying them.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsDeque& nsDeque::Empty() {
|
||||
if((0<mCapacity) && (mData)) {
|
||||
nsCRT::zero(mData,mCapacity*sizeof(mData));
|
||||
}
|
||||
mSize=0;
|
||||
mOrigin=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove and delete all items from container
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return this
|
||||
*/
|
||||
nsDeque& nsDeque::Erase() {
|
||||
if(mDeallocator && mSize) {
|
||||
ForEach(*mDeallocator);
|
||||
}
|
||||
return Empty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method adds an item to the end of the deque.
|
||||
* This operation has the potential to cause the
|
||||
* underlying buffer to resize.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anItem: new item to be added to deque
|
||||
* @return nada
|
||||
*/
|
||||
nsDeque& nsDeque::GrowCapacity(void) {
|
||||
|
||||
PRInt32 theNewSize = mCapacity<<2;
|
||||
void** temp=new void*[theNewSize];
|
||||
|
||||
//Here's the interesting part: You can't just move the elements
|
||||
//directy (in situ) from the old buffer to the new one.
|
||||
//Since capacity has changed, the old origin doesn't make
|
||||
//sense anymore. It's better to resequence the elements now.
|
||||
|
||||
if(mData) {
|
||||
int tempi=0;
|
||||
int i=0;
|
||||
int j=0;
|
||||
for(i=mOrigin;i<mCapacity;i++) temp[tempi++]=mData[i]; //copy the leading elements...
|
||||
for(j=0;j<mOrigin;j++) temp[tempi++]=mData[j]; //copy the trailing elements...
|
||||
if(mData!=mBuffer)
|
||||
delete [] mData;
|
||||
}
|
||||
mCapacity=theNewSize;
|
||||
mOrigin=0; //now realign the origin...
|
||||
mData=temp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds an item to the end of the deque.
|
||||
* This operation has the potential to cause the
|
||||
* underlying buffer to resize.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anItem: new item to be added to deque
|
||||
* @return nada
|
||||
*/
|
||||
nsDeque& nsDeque::Push(void* anItem) {
|
||||
if(mSize==mCapacity) {
|
||||
GrowCapacity();
|
||||
}
|
||||
int offset=mOrigin+mSize;
|
||||
if(offset<mCapacity)
|
||||
mData[offset]=anItem;
|
||||
else mData[offset-mCapacity]=anItem;
|
||||
mSize++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds an item to the front of the deque.
|
||||
* This operation has the potential to cause the
|
||||
* underlying buffer to resize.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anItem: new item to be added to deque
|
||||
* @return nada
|
||||
*/
|
||||
nsDeque& nsDeque::PushFront(void* anItem) {
|
||||
if(mSize==mCapacity) {
|
||||
GrowCapacity();
|
||||
}
|
||||
if(0==mOrigin){ //case1: [xxx..]
|
||||
//mOrigin=mCapacity-1-mSize++;
|
||||
mOrigin=mCapacity-1;
|
||||
mData[mOrigin]=anItem;
|
||||
}
|
||||
else {// if(mCapacity==(mOrigin+mSize-1)){ //case2: [..xxx] and case3: [.xxx.]
|
||||
mData[--mOrigin]=anItem;
|
||||
}
|
||||
mSize++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove and return the last item in the container.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param none
|
||||
* @return ptr to last item in container
|
||||
*/
|
||||
void* nsDeque::Pop(void) {
|
||||
void* result=0;
|
||||
if(mSize>0) {
|
||||
int offset=mOrigin+mSize-1;
|
||||
if(offset>=mCapacity)
|
||||
offset-=mCapacity;
|
||||
result=mData[offset];
|
||||
mData[offset]=0;
|
||||
mSize--;
|
||||
if(0==mSize)
|
||||
mOrigin=0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called you want to remove and return
|
||||
* the first member in the container.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param nada
|
||||
* @return last item in container
|
||||
*/
|
||||
void* nsDeque::PopFront() {
|
||||
void* result=0;
|
||||
if(mSize>0) {
|
||||
NS_ASSERTION(mOrigin<mCapacity,"Error: Bad origin");
|
||||
result=mData[mOrigin];
|
||||
mData[mOrigin++]=0; //zero it out for debugging purposes.
|
||||
mSize--;
|
||||
if(mCapacity==mOrigin) //you popped off the end, so cycle back around...
|
||||
mOrigin=0;
|
||||
if(0==mSize)
|
||||
mOrigin=0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called you want to peek at the topmost
|
||||
* member without removing it.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param nada
|
||||
* @return last item in container
|
||||
*/
|
||||
void* nsDeque::Peek() {
|
||||
void* result=0;
|
||||
if(mSize>0) {
|
||||
result=mData[mOrigin];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this to retrieve the ith element from this container.
|
||||
* Keep in mind that accessing the underlying elements is
|
||||
* done in a relative fashion. Object 0 is not necessarily
|
||||
* the first element (the first element is at mOrigin).
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIndex : 0 relative offset of item you want
|
||||
* @return void* or null
|
||||
*/
|
||||
void* nsDeque::ObjectAt(PRInt32 anIndex) const {
|
||||
void* result=0;
|
||||
|
||||
if((anIndex>=0) && (anIndex<mSize))
|
||||
{
|
||||
if(anIndex<(mCapacity-mOrigin)) {
|
||||
result=mData[mOrigin+anIndex];
|
||||
}
|
||||
else {
|
||||
result=mData[anIndex-(mCapacity-mOrigin)];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an iterator pointing to
|
||||
* the beginning of the queue. Note that this
|
||||
* takes the circular buffer semantics into account.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return new deque iterator, init'ed to 1st item
|
||||
*/
|
||||
nsDequeIterator nsDeque::Begin(void) const{
|
||||
return nsDequeIterator(*this,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an iterator pointing to
|
||||
* the last of the queue. Note that this
|
||||
* takes the circular buffer semantics into account.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return new deque iterator, init'ed to last item
|
||||
*/
|
||||
nsDequeIterator nsDeque::End(void) const{
|
||||
return nsDequeIterator(*this,mSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
void nsDeque::ForEach(nsDequeFunctor& aFunctor) const{
|
||||
int i=0;
|
||||
for(i=0;i<mSize;i++){
|
||||
void* obj=ObjectAt(i);
|
||||
obj=aFunctor(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code. Iteration continues until your
|
||||
* functor returns a non-null.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
const void* nsDeque::FirstThat(nsDequeFunctor& aFunctor) const{
|
||||
int i=0;
|
||||
for(i=0;i<mSize;i++){
|
||||
void* obj=ObjectAt(i);
|
||||
obj=aFunctor(obj);
|
||||
if(obj)
|
||||
return obj;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Here comes the nsDequeIterator class...
|
||||
******************************************************/
|
||||
|
||||
/**
|
||||
* DequeIterator is an object that knows how to iterate (forward and backward)
|
||||
* a Deque. Normally, you don't need to do this, but there are some special
|
||||
* cases where it is pretty handy, so here you go.
|
||||
*
|
||||
* This is a standard dequeiterator constructor
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param aQueue is the deque object to be iterated
|
||||
* @param anIndex is the starting position for your iteration
|
||||
*/
|
||||
nsDequeIterator::nsDequeIterator(const nsDeque& aQueue,int anIndex): mIndex(anIndex), mDeque(aQueue) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy construct a new iterator beginning with given
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aCopy is another iterator to copy from
|
||||
* @return
|
||||
*/
|
||||
nsDequeIterator::nsDequeIterator(const nsDequeIterator& aCopy) : mIndex(aCopy.mIndex), mDeque(aCopy.mDeque) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves iterator to first element in deque
|
||||
* @update gess4/18/98
|
||||
* @return this
|
||||
*/
|
||||
nsDequeIterator& nsDequeIterator::First(void){
|
||||
mIndex=0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard assignment operator for dequeiterator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param aCopy is an iterator to be copied from
|
||||
* @return *this
|
||||
*/
|
||||
nsDequeIterator& nsDequeIterator::operator=(const nsDequeIterator& aCopy) {
|
||||
//queue's are already equal.
|
||||
mIndex=aCopy.mIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* preform ! operation against to iterators to test for equivalence
|
||||
* (or lack thereof)!
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the object to be compared to
|
||||
* @return TRUE if NOT equal.
|
||||
*/
|
||||
PRBool nsDequeIterator::operator!=(nsDequeIterator& anIter) {
|
||||
return PRBool(!this->operator==(anIter));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare 2 iterators for equivalence.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the other iterator to be compared to
|
||||
* @return TRUE if EQUAL
|
||||
*/
|
||||
PRBool nsDequeIterator::operator<(nsDequeIterator& anIter) {
|
||||
return PRBool(((mIndex<anIter.mIndex) && (&mDeque==&anIter.mDeque)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 iterators for equivalence.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the other iterator to be compared to
|
||||
* @return TRUE if EQUAL
|
||||
*/
|
||||
PRBool nsDequeIterator::operator==(nsDequeIterator& anIter) {
|
||||
return PRBool(((mIndex==anIter.mIndex) && (&mDeque==&anIter.mDeque)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare 2 iterators for equivalence.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the other iterator to be compared to
|
||||
* @return TRUE if EQUAL
|
||||
*/
|
||||
PRBool nsDequeIterator::operator>=(nsDequeIterator& anIter) {
|
||||
return PRBool(((mIndex>=anIter.mIndex) && (&mDeque==&anIter.mDeque)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-increment operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return object at preincremented index
|
||||
*/
|
||||
void* nsDequeIterator::operator++() {
|
||||
return mDeque.ObjectAt(++mIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-increment operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param param is ignored
|
||||
* @return object at post-incremented index
|
||||
*/
|
||||
void* nsDequeIterator::operator++(int) {
|
||||
return mDeque.ObjectAt(mIndex++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-decrement operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return object at pre-decremented index
|
||||
*/
|
||||
void* nsDequeIterator::operator--() {
|
||||
return mDeque.ObjectAt(--mIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-decrement operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param param is ignored
|
||||
* @return object at post-decremented index
|
||||
*/
|
||||
void* nsDequeIterator::operator--(int) {
|
||||
return mDeque.ObjectAt(mIndex--);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereference operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return object at ith index
|
||||
*/
|
||||
void* nsDequeIterator::GetCurrent(void) {
|
||||
return mDeque.ObjectAt(mIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
void nsDequeIterator::ForEach(nsDequeFunctor& aFunctor) const{
|
||||
mDeque.ForEach(aFunctor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
const void* nsDequeIterator::FirstThat(nsDequeFunctor& aFunctor) const{
|
||||
return mDeque.FirstThat(aFunctor);
|
||||
}
|
||||
|
||||
#ifdef _SELFTEST_DEQUE
|
||||
/**************************************************************
|
||||
Now define the token deallocator class...
|
||||
**************************************************************/
|
||||
class _SelfTestDeallocator: public nsDequeFunctor{
|
||||
public:
|
||||
_SelfTestDeallocator::_SelfTestDeallocator() {
|
||||
nsDeque::SelfTest();
|
||||
}
|
||||
virtual void* operator()(void* anObject) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
static _SelfTestDeallocator gDeallocator;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* conduct automated self test for this class
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void nsDeque::SelfTest(void) {
|
||||
#ifdef _SELFTEST_DEQUE
|
||||
|
||||
{
|
||||
nsDeque theDeque(gDeallocator); //construct a simple one...
|
||||
|
||||
int ints[200];
|
||||
int count=sizeof(ints)/sizeof(int);
|
||||
int i=0;
|
||||
|
||||
for(i=0;i<count;i++){ //initialize'em
|
||||
ints[i]=10*(1+i);
|
||||
}
|
||||
|
||||
for(i=0;i<70;i++){
|
||||
theDeque.Push(&ints[i]);
|
||||
}
|
||||
|
||||
for(i=0;i<56;i++){
|
||||
int* temp=(int*)theDeque.Pop();
|
||||
}
|
||||
|
||||
for(i=0;i<55;i++){
|
||||
theDeque.Push(&ints[i]);
|
||||
}
|
||||
|
||||
for(i=0;i<35;i++){
|
||||
int* temp=(int*)theDeque.Pop();
|
||||
}
|
||||
|
||||
for(i=0;i<35;i++){
|
||||
theDeque.Push(&ints[i]);
|
||||
}
|
||||
|
||||
for(i=0;i<38;i++){
|
||||
int* temp=(int*)theDeque.Pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int x;
|
||||
x=10;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,410 +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.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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* MODULE NOTES:
|
||||
* @update gess 4/15/98 (tax day)
|
||||
*
|
||||
* The Deque is a very small, very efficient container object
|
||||
* than can hold elements of type void*, offering the following features:
|
||||
* It's interface supports pushing and poping of children.
|
||||
* It can iterate (via an interator class) it's children.
|
||||
* When full, it can efficently resize dynamically.
|
||||
*
|
||||
*
|
||||
* NOTE: The only bit of trickery here is that this deque is
|
||||
* built upon a ring-buffer. Like all ring buffers, the first
|
||||
* element may not be at index[0]. The mOrigin member determines
|
||||
* where the first child is. This point is quietly hidden from
|
||||
* customers of this class.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NSDEQUE
|
||||
#define _NSDEQUE
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
/**
|
||||
* The nsDequefunctor class is used when you want to create
|
||||
* callbacks between the deque and your generic code.
|
||||
* Use these objects in a call to ForEach();
|
||||
*
|
||||
* @update gess4/20/98
|
||||
*/
|
||||
class NS_COM nsDequeFunctor{
|
||||
public:
|
||||
virtual void* operator()(void* anObject)=0;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Here comes the nsDeque class itself...
|
||||
******************************************************/
|
||||
|
||||
/**
|
||||
* The deque (double-ended queue) class is a common container type,
|
||||
* whose behavior mimics a line in your favorite checkout stand.
|
||||
* Classic CS describes the common behavior of a queue as FIFO.
|
||||
* A Deque allows items to be added and removed from either end of
|
||||
* the queue.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
*/
|
||||
|
||||
class NS_COM nsDeque {
|
||||
friend class nsDequeIterator;
|
||||
public:
|
||||
nsDeque(nsDequeFunctor* aDeallocator);
|
||||
~nsDeque();
|
||||
|
||||
/**
|
||||
* Returns the number of elements currently stored in
|
||||
* this deque.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return int contains element count
|
||||
*/
|
||||
inline PRInt32 GetSize() const { return mSize;}
|
||||
|
||||
/**
|
||||
* Pushes new member onto the end of the deque
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param ptr to object to store
|
||||
* @return *this
|
||||
*/
|
||||
nsDeque& Push(void* anItem);
|
||||
|
||||
/**
|
||||
* Pushes new member onto the front of the deque
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param ptr to object to store
|
||||
* @return *this
|
||||
*/
|
||||
nsDeque& PushFront(void* anItem);
|
||||
|
||||
/**
|
||||
* Remove and return the first item in the container.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param none
|
||||
* @return ptr to first item in container
|
||||
*/
|
||||
void* Pop(void);
|
||||
|
||||
/**
|
||||
* Remove and return the first item in the container.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param none
|
||||
* @return ptr to first item in container
|
||||
*/
|
||||
void* PopFront(void);
|
||||
|
||||
|
||||
/**
|
||||
* Return topmost item without removing it.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param none
|
||||
* @return ptr to first item in container
|
||||
*/
|
||||
void* Peek(void);
|
||||
|
||||
/**
|
||||
* method used to retrieve ptr to
|
||||
* ith member in container. DOesn't remove
|
||||
* that item.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param index of desired item
|
||||
* @return ptr to ith element in list
|
||||
*/
|
||||
void* ObjectAt(int anIndex) const;
|
||||
|
||||
/**
|
||||
* Remove all items from container without destroying them
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsDeque& Empty();
|
||||
|
||||
/**
|
||||
* Remove and delete all items from container
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsDeque& Erase();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new iterator, init'ed to start of container
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return new dequeIterator
|
||||
*/
|
||||
nsDequeIterator Begin() const;
|
||||
|
||||
/**
|
||||
* Creates a new iterator, init'ed to end of container
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return new dequeIterator
|
||||
*/
|
||||
nsDequeIterator End() const;
|
||||
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
void ForEach(nsDequeFunctor& aFunctor) const;
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code. This process will interupt if
|
||||
* your function returns a null to this iterator.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
const void* FirstThat(nsDequeFunctor& aFunctor) const;
|
||||
|
||||
void SetDeallocator(nsDequeFunctor* aDeallocator);
|
||||
|
||||
/**
|
||||
* Perform automated selftest on the deque
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
static void SelfTest();
|
||||
|
||||
protected:
|
||||
|
||||
PRInt32 mSize;
|
||||
PRInt32 mCapacity;
|
||||
PRInt32 mOrigin;
|
||||
nsDequeFunctor* mDeallocator;
|
||||
void* mBuffer[8];
|
||||
void** mData;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/**
|
||||
* Simple default constructor (PRIVATE)
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsDeque();
|
||||
|
||||
/**
|
||||
* Copy constructor (PRIVATE)
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsDeque(const nsDeque& other);
|
||||
|
||||
/**
|
||||
* Deque assignment operator (PRIVATE)
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param another deque
|
||||
* @return *this
|
||||
*/
|
||||
nsDeque& operator=(const nsDeque& anOther);
|
||||
|
||||
nsDeque& GrowCapacity(void);
|
||||
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Here comes the nsDequeIterator class...
|
||||
******************************************************/
|
||||
|
||||
class NS_COM nsDequeIterator {
|
||||
public:
|
||||
|
||||
/**
|
||||
* DequeIterator is an object that knows how to iterate (forward and backward)
|
||||
* a Deque. Normally, you don't need to do this, but there are some special
|
||||
* cases where it is pretty handy, so here you go.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param aQueue is the deque object to be iterated
|
||||
* @param anIndex is the starting position for your iteration
|
||||
*/
|
||||
nsDequeIterator(const nsDeque& aQueue,int anIndex=0);
|
||||
|
||||
/**
|
||||
* DequeIterator is an object that knows how to iterate (forward and backward)
|
||||
* a Deque. Normally, you don't need to do this, but there are some special
|
||||
* cases where it is pretty handy, so here you go.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param aQueue is the deque object to be iterated
|
||||
* @param anIndex is the starting position for your iteration
|
||||
*/
|
||||
nsDequeIterator(const nsDequeIterator& aCopy);
|
||||
|
||||
/**
|
||||
* Moves iterator to first element in deque
|
||||
* @update gess4/18/98
|
||||
* @return this
|
||||
*/
|
||||
nsDequeIterator& First(void);
|
||||
|
||||
/**
|
||||
* Standard assignment operator for deque
|
||||
* @update gess4/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsDequeIterator& operator=(const nsDequeIterator& aCopy);
|
||||
|
||||
/**
|
||||
* preform ! operation against to iterators to test for equivalence
|
||||
* (or lack thereof)!
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the object to be compared to
|
||||
* @return TRUE if NOT equal.
|
||||
*/
|
||||
PRBool operator!=(nsDequeIterator& anIter);
|
||||
|
||||
/**
|
||||
* Compare 2 iterators for equivalence.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the other iterator to be compared to
|
||||
* @return TRUE if EQUAL
|
||||
*/
|
||||
PRBool operator<(nsDequeIterator& anIter);
|
||||
|
||||
/**
|
||||
* Compare 2 iterators for equivalence.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the other iterator to be compared to
|
||||
* @return TRUE if EQUAL
|
||||
*/
|
||||
PRBool operator==(nsDequeIterator& anIter);
|
||||
|
||||
/**
|
||||
* Compare 2 iterators for equivalence.
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param anIter is the other iterator to be compared to
|
||||
* @return TRUE if EQUAL
|
||||
*/
|
||||
PRBool operator>=(nsDequeIterator& anIter);
|
||||
|
||||
/**
|
||||
* Pre-increment operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return object at preincremented index
|
||||
*/
|
||||
void* operator++();
|
||||
|
||||
/**
|
||||
* Post-increment operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param param is ignored
|
||||
* @return object at post-incremented index
|
||||
*/
|
||||
void* operator++(int);
|
||||
|
||||
/**
|
||||
* Pre-decrement operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return object at pre-decremented index
|
||||
*/
|
||||
void* operator--();
|
||||
|
||||
/**
|
||||
* Post-decrement operator
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @param param is ignored
|
||||
* @return object at post-decremented index
|
||||
*/
|
||||
void* operator--(int);
|
||||
|
||||
/**
|
||||
* Retrieve the ptr to the iterators notion of current node
|
||||
*
|
||||
* @update gess4/18/98
|
||||
* @return object at ith index
|
||||
*/
|
||||
void* GetCurrent(void);
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
void ForEach(nsDequeFunctor& aFunctor) const;
|
||||
|
||||
/**
|
||||
* Call this method when you wanto to iterate all the
|
||||
* members of the container, passing a functor along
|
||||
* to call your code.
|
||||
*
|
||||
* @update gess4/20/98
|
||||
* @param aFunctor object to call for each member
|
||||
* @return *this
|
||||
*/
|
||||
const void* FirstThat(nsDequeFunctor& aFunctor) const;
|
||||
|
||||
protected:
|
||||
|
||||
PRInt32 mIndex;
|
||||
const nsDeque& mDeque;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,75 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An empty enumerator.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIEnumerator.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EmptyEnumeratorImpl : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
EmptyEnumeratorImpl(void) {};
|
||||
virtual ~EmptyEnumeratorImpl(void) {};
|
||||
|
||||
// nsISupports interface
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(nsISimpleEnumerator::GetIID()) ||
|
||||
iid.Equals(NS_GET_IID(nsISupports))) {
|
||||
*result = (nsISimpleEnumerator*) this;
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
// nsISimpleEnumerator
|
||||
NS_IMETHOD HasMoreElements(PRBool* aResult) {
|
||||
*aResult = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetNext(nsISupports** aResult) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult)
|
||||
{
|
||||
static EmptyEnumeratorImpl gEmptyEnumerator;
|
||||
*aResult = &gEmptyEnumerator;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1,228 +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.
|
||||
*/
|
||||
|
||||
#include "nsEnumeratorUtils.h"
|
||||
|
||||
|
||||
nsArrayEnumerator::nsArrayEnumerator(nsISupportsArray* aValueArray)
|
||||
: mValueArray(aValueArray),
|
||||
mIndex(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_IF_ADDREF(mValueArray);
|
||||
}
|
||||
|
||||
nsArrayEnumerator::~nsArrayEnumerator(void)
|
||||
{
|
||||
NS_IF_RELEASE(mValueArray);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsArrayEnumerator, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsArrayEnumerator::HasMoreElements(PRBool* aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != 0, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mValueArray->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
*aResult = (mIndex < (PRInt32) cnt);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsArrayEnumerator::GetNext(nsISupports** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != 0, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRUint32 cnt;
|
||||
nsresult rv = mValueArray->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (mIndex >= (PRInt32) cnt)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
*aResult = mValueArray->ElementAt(mIndex++);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
|
||||
nsISupportsArray* array)
|
||||
{
|
||||
nsArrayEnumerator* enumer = new nsArrayEnumerator(array);
|
||||
if (enumer == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(enumer);
|
||||
*result = enumer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue)
|
||||
: mValue(aValue)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_IF_ADDREF(mValue);
|
||||
mConsumed = (mValue ? PR_FALSE : PR_TRUE);
|
||||
}
|
||||
|
||||
nsSingletonEnumerator::~nsSingletonEnumerator()
|
||||
{
|
||||
NS_IF_RELEASE(mValue);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSingletonEnumerator, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSingletonEnumerator::HasMoreElements(PRBool* aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != 0, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aResult = !mConsumed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSingletonEnumerator::GetNext(nsISupports** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != 0, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mConsumed)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
mConsumed = PR_TRUE;
|
||||
|
||||
NS_ADDREF(mValue);
|
||||
*aResult = mValue;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
|
||||
nsISupports* singleton)
|
||||
{
|
||||
nsSingletonEnumerator* enumer = new nsSingletonEnumerator(singleton);
|
||||
if (enumer == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(enumer);
|
||||
*result = enumer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
nsAdapterEnumerator::nsAdapterEnumerator(nsIEnumerator* aEnum)
|
||||
: mEnum(aEnum), mCurrent(0), mStarted(PR_FALSE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mEnum);
|
||||
}
|
||||
|
||||
|
||||
nsAdapterEnumerator::~nsAdapterEnumerator()
|
||||
{
|
||||
NS_RELEASE(mEnum);
|
||||
NS_IF_RELEASE(mCurrent);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsAdapterEnumerator, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAdapterEnumerator::HasMoreElements(PRBool* aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (mCurrent) {
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (! mStarted) {
|
||||
mStarted = PR_TRUE;
|
||||
rv = mEnum->First();
|
||||
if (rv == NS_OK) {
|
||||
mEnum->CurrentItem(&mCurrent);
|
||||
*aResult = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
*aResult = PR_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*aResult = PR_FALSE;
|
||||
|
||||
rv = mEnum->IsDone();
|
||||
if (rv != NS_OK) {
|
||||
// We're not done. Advance to the next one.
|
||||
rv = mEnum->Next();
|
||||
if (rv == NS_OK) {
|
||||
mEnum->CurrentItem(&mCurrent);
|
||||
*aResult = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAdapterEnumerator::GetNext(nsISupports** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRBool hasMore;
|
||||
rv = HasMoreElements(&hasMore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasMore)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// No need to addref, we "transfer" the ownership to the caller.
|
||||
*aResult = mCurrent;
|
||||
mCurrent = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewAdapterEnumerator(nsISimpleEnumerator* *result,
|
||||
nsIEnumerator* enumerator)
|
||||
{
|
||||
nsAdapterEnumerator* enumer = new nsAdapterEnumerator(enumerator);
|
||||
if (enumer == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(enumer);
|
||||
*result = enumer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -1,97 +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.
|
||||
*/
|
||||
|
||||
#ifndef nsEnumeratorUtils_h__
|
||||
#define nsEnumeratorUtils_h__
|
||||
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
||||
class NS_COM nsArrayEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator interface
|
||||
NS_IMETHOD HasMoreElements(PRBool* aResult);
|
||||
NS_IMETHOD GetNext(nsISupports** aResult);
|
||||
|
||||
// nsRDFArrayEnumerator methods
|
||||
nsArrayEnumerator(nsISupportsArray* aValueArray);
|
||||
virtual ~nsArrayEnumerator(void);
|
||||
|
||||
protected:
|
||||
nsISupportsArray* mValueArray;
|
||||
PRInt32 mIndex;
|
||||
};
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
|
||||
nsISupportsArray* array);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NS_COM nsSingletonEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator methods
|
||||
NS_IMETHOD HasMoreElements(PRBool* aResult);
|
||||
NS_IMETHOD GetNext(nsISupports** aResult);
|
||||
|
||||
nsSingletonEnumerator(nsISupports* aValue);
|
||||
virtual ~nsSingletonEnumerator();
|
||||
|
||||
protected:
|
||||
nsISupports* mValue;
|
||||
PRBool mConsumed;
|
||||
};
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
|
||||
nsISupports* singleton);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NS_COM nsAdapterEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator methods
|
||||
NS_IMETHOD HasMoreElements(PRBool* aResult);
|
||||
NS_IMETHOD GetNext(nsISupports** aResult);
|
||||
|
||||
nsAdapterEnumerator(nsIEnumerator* aEnum);
|
||||
virtual ~nsAdapterEnumerator();
|
||||
|
||||
protected:
|
||||
nsIEnumerator* mEnum;
|
||||
nsISupports* mCurrent;
|
||||
PRBool mStarted;
|
||||
};
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewAdapterEnumerator(nsISimpleEnumerator* *result,
|
||||
nsIEnumerator* enumerator);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif /* nsEnumeratorUtils_h__ */
|
||||
@@ -1,67 +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.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.
|
||||
*/
|
||||
#ifndef nsIArena_h___
|
||||
#define nsIArena_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
#define NS_MIN_ARENA_BLOCK_SIZE 64
|
||||
#define NS_DEFAULT_ARENA_BLOCK_SIZE 4096
|
||||
|
||||
/// Interface IID for nsIArena
|
||||
#define NS_IARENA_IID \
|
||||
{ 0xa24fdad0, 0x93b4, 0x11d1, \
|
||||
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
|
||||
#define NS_ARENA_PROGID "component://netscape/arena"
|
||||
#define NS_ARENA_CLASSNAME "Arena"
|
||||
|
||||
/** Interface to a memory arena abstraction. Arena's use large blocks
|
||||
* of memory to allocate smaller objects. Arena's provide no free
|
||||
* operator; instead, all of the objects in the arena are deallocated
|
||||
* by deallocating the arena (e.g. when it's reference count goes to
|
||||
* zero)
|
||||
*/
|
||||
class nsIArena : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IARENA_IID; return iid; }
|
||||
|
||||
NS_IMETHOD Init(PRUint32 arenaBlockSize) = 0;
|
||||
|
||||
NS_IMETHOD_(void*) Alloc(PRUint32 size) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new arena using the desired block size for allocating the
|
||||
* underlying memory blocks. The underlying memory blocks are allocated
|
||||
* using the PR heap.
|
||||
*/
|
||||
extern NS_COM nsresult NS_NewHeapArena(nsIArena** aInstancePtrResult,
|
||||
PRUint32 aArenaBlockSize = 0);
|
||||
|
||||
#define NS_ARENA_CID \
|
||||
{ /* 9832ec80-0d6b-11d3-9331-00104ba0fd40 */ \
|
||||
0x9832ec80, \
|
||||
0x0d6b, \
|
||||
0x11d3, \
|
||||
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
#endif /* nsIArena_h___ */
|
||||
|
||||
|
||||
@@ -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 Netscape Public License
|
||||
* Version 1.0 (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,
|
||||
* released March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
*/
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISizeOfHandler;
|
||||
|
||||
|
||||
[ref] native nsStringRef(nsString);
|
||||
%{ C++
|
||||
class nsString;
|
||||
%}
|
||||
|
||||
|
||||
[uuid(3d1b15b0-93b4-11d1-895b-006008911b81)]
|
||||
interface nsIAtom : nsISupports
|
||||
{
|
||||
/**
|
||||
* Translate the unicode string into the stringbuf.
|
||||
*/
|
||||
void ToString(in nsStringRef aString);
|
||||
|
||||
/**
|
||||
* Return a pointer to a zero terminated unicode string.
|
||||
*/
|
||||
void GetUnicode([shared, retval] out wstring aResult);
|
||||
|
||||
/**
|
||||
* Get the size, in bytes, of the atom.
|
||||
*/
|
||||
PRUint32 SizeOf(in nsISizeOfHandler aHandler);
|
||||
};
|
||||
|
||||
|
||||
%{C++
|
||||
|
||||
/**
|
||||
* Find an atom that matches the given iso-latin1 C string. The
|
||||
* C string is translated into it's unicode equivalent.
|
||||
*/
|
||||
extern NS_COM nsIAtom* NS_NewAtom(const char* isolatin1);
|
||||
|
||||
/**
|
||||
* Find an atom that matches the given unicode string. The string is assumed
|
||||
* to be zero terminated.
|
||||
*/
|
||||
extern NS_COM nsIAtom* NS_NewAtom(const PRUnichar* unicode);
|
||||
|
||||
/**
|
||||
* Find an atom that matches the given string.
|
||||
*/
|
||||
extern NS_COM nsIAtom* NS_NewAtom(const nsString& aString);
|
||||
|
||||
/**
|
||||
* Return a count of the total number of atoms currently
|
||||
* alive in the system.
|
||||
*/
|
||||
extern NS_COM nsrefcnt NS_GetNumberOfAtoms(void);
|
||||
|
||||
extern NS_COM void NS_PurgeAtomTable(void);
|
||||
|
||||
%}
|
||||
@@ -1,312 +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.
|
||||
*/
|
||||
|
||||
#ifndef nsIBuffer_h___
|
||||
#define nsIBuffer_h___
|
||||
|
||||
/**
|
||||
* nsIBuffer is something that we use to implement pipes (buffered
|
||||
* input/output stream pairs). It might be useful to you for other
|
||||
* purposes, but if not, oh well.
|
||||
*
|
||||
* One of the important things to understand about pipes is how
|
||||
* they work with respect to EOF and result values. The following
|
||||
* table describes:
|
||||
*
|
||||
* | empty & not EOF | full | reader closed | writer closed |
|
||||
* -------------------------------------------------------------------------------------------------------------
|
||||
* buffer Read | readCount == 0 | readCount == N | N/A | readCount == N, return NS_OK -or- |
|
||||
* operations | return WOULD_BLOCK | return NS_OK | | readCount == 0, return EOF |
|
||||
* -------------------------------------------------------------------------------------------------------------
|
||||
* buffer Write | writeCount == N | writeCount == 0 | N/A | assertion! |
|
||||
* operations | return NS_OK | return WOULD_BLOCK | | |
|
||||
* -------------------------------------------------------------------------------------------------------------
|
||||
* input stream | readCount == 0 | readCount == N | assertion! | readCount == N, return NS_OK -or- |
|
||||
* Read ops | return WOULD_BLOCK | return NS_OK | | readCount == 0, return EOF |
|
||||
* -------------------------------------------------------------------------------------------------------------
|
||||
* output stream | writeCount == N | writeCount == 0 | return | assertion! |
|
||||
* Write ops | return NS_OK | return WOULD_BLOCK | STREAM_CLOSED | |
|
||||
* -------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIInputStream;
|
||||
class nsIAllocator;
|
||||
class nsIBufferInputStream;
|
||||
class nsIBufferOutputStream;
|
||||
class nsIBufferObserver;
|
||||
|
||||
#define NS_IBUFFER_IID \
|
||||
{ /* 1eebb300-fb8b-11d2-9324-00104ba0fd40 */ \
|
||||
0x1eebb300, \
|
||||
0xfb8b, \
|
||||
0x11d2, \
|
||||
{0x93, 0x24, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
#define NS_BUFFER_CID \
|
||||
{ /* 5dbe4de0-fbab-11d2-9324-00104ba0fd40 */ \
|
||||
0x5dbe4de0, \
|
||||
0xfbab, \
|
||||
0x11d2, \
|
||||
{0x93, 0x24, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
#define NS_BUFFER_PROGID "component://netscape/buffer"
|
||||
#define NS_BUFFER_CLASSNAME "Buffer"
|
||||
|
||||
/**
|
||||
* The signature for the reader function passed to WriteSegment. This
|
||||
* specifies where the data should come from that gets written into the buffer.
|
||||
* Implementers should return the following:
|
||||
* @return NS_OK and readCount - if successfully read something
|
||||
* @return NS_BASE_STREAM_EOF - if no more to read
|
||||
* @return NS_BASE_STREAM_WOULD_BLOCK - if there is currently no data (in
|
||||
* a non-blocking mode)
|
||||
* @return <other-error> - on failure
|
||||
*/
|
||||
typedef NS_CALLBACK(nsReadSegmentFun)(void* closure,
|
||||
char* toRawSegment,
|
||||
PRUint32 fromOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *readCount);
|
||||
|
||||
/**
|
||||
* The signature of the writer function passed to ReadSegments. This
|
||||
* specifies where the data should go that gets read from the buffer.
|
||||
* Implementers should return the following:
|
||||
* @return NS_OK and writeCount - if successfully wrote something
|
||||
* @return NS_BASE_STREAM_CLOSED - if no more can be written
|
||||
* @return NS_BASE_STREAM_WOULD_BLOCK - if there is currently space to write (in
|
||||
* a non-blocking mode)
|
||||
* @return <other-error> - on failure
|
||||
*/
|
||||
typedef NS_CALLBACK(nsWriteSegmentFun)(void* closure,
|
||||
const char* fromRawSegment,
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount);
|
||||
|
||||
class nsIBuffer : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBUFFER_IID);
|
||||
|
||||
/**
|
||||
* The segment overhead is the amount of space chopped out of each
|
||||
* segment for implementation purposes. The remainder of the segment
|
||||
* is available for data, e.g.:
|
||||
* segmentDataSize = growBySize - SEGMENT_OVERHEAD;
|
||||
*/
|
||||
enum { SEGMENT_OVERHEAD = 8 };
|
||||
|
||||
/**
|
||||
* Initializes a buffer. The segment size (including overhead) will
|
||||
* start from and increment by the growBySize, until reaching maxSize.
|
||||
* The size of the data that can fit in a segment will be the growBySize
|
||||
* minus SEGMENT_OVERHEAD bytes.
|
||||
*/
|
||||
NS_IMETHOD Init(PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer, nsIAllocator* allocator) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Methods for Readers
|
||||
|
||||
/**
|
||||
* Reads from the read cursor into a char buffer up to a specified length.
|
||||
*/
|
||||
NS_IMETHOD Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount) = 0;
|
||||
|
||||
/**
|
||||
* This read method allows you to pass a callback function that gets called
|
||||
* repeatedly for each buffer segment until the entire amount is read.
|
||||
* This avoids the need to copy data to/from and intermediate buffer.
|
||||
*/
|
||||
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
|
||||
PRUint32 *readCount) = 0;
|
||||
|
||||
/**
|
||||
* Returns the raw char buffer segment and its length available for reading.
|
||||
* @param segmentLogicalOffset - The offset from the current read cursor for
|
||||
* the segment to be returned. If this is beyond the available written area,
|
||||
* NULL is returned for the resultSegment.
|
||||
* @param resultSegment - The resulting read segment.
|
||||
* @param resultSegmentLength - The resulting read segment length.
|
||||
*
|
||||
* @return NS_OK - if a read segment is successfully returned, or if
|
||||
* the requested offset is at or beyond the write cursor (in which case
|
||||
* the resultSegment will be nsnull and the resultSegmentLen will be 0)
|
||||
* @return NS_BASE_STREAM_WOULD_BLOCK - if the buffer size becomes 0
|
||||
* @return any error set by SetCondition if the requested offset is at
|
||||
* or beyond the write cursor (in which case the resultSegment will be
|
||||
* nsnull and the resultSegmentLen will be 0). Note that NS_OK will be
|
||||
* returned if SetCondition has not been called.
|
||||
* @return any error returned by OnEmpty
|
||||
*/
|
||||
NS_IMETHOD GetReadSegment(PRUint32 segmentLogicalOffset,
|
||||
const char* *resultSegment,
|
||||
PRUint32 *resultSegmentLen) = 0;
|
||||
|
||||
/**
|
||||
* Returns the amount of data currently in the buffer available for reading.
|
||||
*/
|
||||
NS_IMETHOD GetReadableAmount(PRUint32 *amount) = 0;
|
||||
|
||||
/**
|
||||
* Searches for a string in the buffer. Since the buffer has a notion
|
||||
* of EOF, it is possible that the string may at some time be in the
|
||||
* buffer, but is is not currently found up to some offset. Consequently,
|
||||
* both the found and not found cases return an offset:
|
||||
* if found, return offset where it was found
|
||||
* if not found, return offset of the first byte not searched
|
||||
* In the case the buffer is at EOF and the string is not found, the first
|
||||
* byte not searched will correspond to the length of the buffer.
|
||||
*/
|
||||
NS_IMETHOD Search(const char* forString, PRBool ignoreCase,
|
||||
PRBool *found, PRUint32 *offsetSearchedTo) = 0;
|
||||
|
||||
/**
|
||||
* Sets that the reader has closed their end of the stream.
|
||||
*/
|
||||
NS_IMETHOD ReaderClosed(void) = 0;
|
||||
|
||||
/**
|
||||
* Tests whether EOF marker is set. Note that this does not necessarily mean that
|
||||
* all the data in the buffer has yet been consumed.
|
||||
*/
|
||||
NS_IMETHOD GetCondition(nsresult *result) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Methods for Writers
|
||||
|
||||
/**
|
||||
* Writes from a char buffer up to a specified length.
|
||||
* @param writeCount - The amount that could be written. If the buffer becomes full,
|
||||
* this could be less then the specified bufLen.
|
||||
*/
|
||||
NS_IMETHOD Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount) = 0;
|
||||
|
||||
/**
|
||||
* Writes from an input stream up to a specified count of bytes.
|
||||
* @param writeCount - The amount that could be written. If the buffer becomes full,
|
||||
* this could be less then the specified count.
|
||||
*/
|
||||
NS_IMETHOD WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount) = 0;
|
||||
|
||||
/**
|
||||
* This write method allows you to pass a callback function that gets called
|
||||
* repeatedly for each buffer segment until the entire amount is written.
|
||||
* This avoids the need to copy data to/from and intermediate buffer.
|
||||
*/
|
||||
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
|
||||
PRUint32 *writeCount) = 0;
|
||||
|
||||
/**
|
||||
* Returns the raw char buffer segment and its length available for writing.
|
||||
* @param resultSegment - The resulting write segment.
|
||||
* @param resultSegmentLength - The resulting write segment length.
|
||||
*
|
||||
* @return NS_OK - if there is a segment available to write to
|
||||
* @return NS_BASE_STREAM_CLOSED - if ReaderClosed has been called
|
||||
* @return NS_BASE_STREAM_WOULD_BLOCK - if the max buffer size is exceeded
|
||||
* @return NS_ERROR_OUT_OF_MEMORY - if a new segment could not be allocated
|
||||
* @return any error returned by OnFull
|
||||
*/
|
||||
NS_IMETHOD GetWriteSegment(char* *resultSegment,
|
||||
PRUint32 *resultSegmentLen) = 0;
|
||||
|
||||
/**
|
||||
* Returns the amount of space currently in the buffer available for writing.
|
||||
*/
|
||||
NS_IMETHOD GetWritableAmount(PRUint32 *amount) = 0;
|
||||
|
||||
/**
|
||||
* Returns whether the reader has closed their end of the stream.
|
||||
*/
|
||||
NS_IMETHOD GetReaderClosed(PRBool *result) = 0;
|
||||
|
||||
/**
|
||||
* Sets an EOF marker (typcially done by the writer) so that a reader can be informed
|
||||
* when all the data in the buffer is consumed. After the EOF marker has been
|
||||
* set, all subsequent calls to the above write methods will return NS_BASE_STREAM_EOF.
|
||||
*/
|
||||
NS_IMETHOD SetCondition(nsresult condition) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define NS_IBUFFEROBSERVER_IID \
|
||||
{ /* 0c18bef0-22a8-11d3-9349-00104ba0fd40 */ \
|
||||
0x0c18bef0, \
|
||||
0x22a8, \
|
||||
0x11d3, \
|
||||
{0x93, 0x49, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffer observer is used to detect when the buffer becomes completely full
|
||||
* or completely empty.
|
||||
*/
|
||||
class nsIBufferObserver : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBUFFEROBSERVER_IID);
|
||||
|
||||
NS_IMETHOD OnFull(nsIBuffer* buffer) = 0;
|
||||
|
||||
NS_IMETHOD OnWrite(nsIBuffer*, PRUint32 amount) = 0;
|
||||
|
||||
NS_IMETHOD OnEmpty(nsIBuffer* buffer) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a new buffer.
|
||||
* @param observer - may be null
|
||||
*/
|
||||
extern NS_COM nsresult
|
||||
NS_NewBuffer(nsIBuffer* *result,
|
||||
PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer);
|
||||
|
||||
/**
|
||||
* Creates a new buffer, allocating segments from virtual memory pages.
|
||||
*/
|
||||
extern NS_COM nsresult
|
||||
NS_NewPageBuffer(nsIBuffer* *result,
|
||||
PRUint32 growBySize, PRUint32 maxSize,
|
||||
nsIBufferObserver* observer);
|
||||
|
||||
extern NS_COM nsresult
|
||||
NS_NewBufferInputStream(nsIBufferInputStream* *result,
|
||||
nsIBuffer* buffer, PRBool blocking = PR_FALSE);
|
||||
|
||||
extern NS_COM nsresult
|
||||
NS_NewBufferOutputStream(nsIBufferOutputStream* *result,
|
||||
nsIBuffer* buffer, PRBool blocking = PR_FALSE);
|
||||
|
||||
extern NS_COM nsresult
|
||||
NS_NewPipe(nsIBufferInputStream* *inStrResult,
|
||||
nsIBufferOutputStream* *outStrResult,
|
||||
PRUint32 growBySize, PRUint32 maxSize,
|
||||
PRBool blocking, nsIBufferObserver* observer);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // nsIBuffer_h___
|
||||
@@ -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 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.
|
||||
*/
|
||||
|
||||
#ifndef nsIByteBuffer_h___
|
||||
#define nsIByteBuffer_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
#define NS_IBYTE_BUFFER_IID \
|
||||
{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
|
||||
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
|
||||
#define NS_IBYTEBUFFER_IID \
|
||||
{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
|
||||
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
|
||||
#define NS_BYTEBUFFER_PROGID "component://netscape/byte-buffer"
|
||||
#define NS_BYTEBUFFER_CLASSNAME "Byte Buffer"
|
||||
|
||||
/** Interface to a buffer that holds bytes */
|
||||
class nsIByteBuffer : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IBYTEBUFFER_IID; return iid; }
|
||||
|
||||
NS_IMETHOD Init(PRUint32 aBufferSize) = 0;
|
||||
|
||||
/** @return length of buffer, i.e. how many bytes are currently in it. */
|
||||
NS_IMETHOD_(PRUint32) GetLength(void) const = 0;
|
||||
|
||||
/** @return number of bytes allocated in the buffer */
|
||||
NS_IMETHOD_(PRUint32) GetBufferSize(void) const = 0;
|
||||
|
||||
/** @return the buffer */
|
||||
NS_IMETHOD_(char*) GetBuffer(void) const = 0;
|
||||
|
||||
/** Grow buffer to aNewSize bytes. */
|
||||
NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize) = 0;
|
||||
|
||||
/** Fill the buffer with data from aStream. Don't grow the buffer, only
|
||||
* read until length of buffer equals buffer size. */
|
||||
NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
|
||||
PRUint32 aKeep) = 0;
|
||||
};
|
||||
|
||||
#define NS_BYTEBUFFER_CID \
|
||||
{ /* a49d5280-0d6b-11d3-9331-00104ba0fd40 */ \
|
||||
0xa49d5280, \
|
||||
0x0d6b, \
|
||||
0x11d3, \
|
||||
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
/** Create a new byte buffer using the given buffer size. */
|
||||
extern NS_COM nsresult
|
||||
NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
|
||||
nsISupports* aOuter,
|
||||
PRUint32 aBufferSize = 0);
|
||||
|
||||
#endif /* nsIByteBuffer_h___ */
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/* -*- Mode: IDL; 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.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIEnumerator.idl"
|
||||
|
||||
[scriptable, uuid(83b6019c-cbc4-11d2-8cca-0060b0fc14a3)]
|
||||
interface nsICollection : nsISupports
|
||||
{
|
||||
|
||||
PRUint32 Count();
|
||||
nsISupports GetElementAt(in PRUint32 index);
|
||||
void QueryElementAt(in PRUint32 index, in nsIIDRef uuid,
|
||||
[iid_is(uuid),retval] out nsQIResult result);
|
||||
void SetElementAt(in PRUint32 index, in nsISupports item);
|
||||
void AppendElement(in nsISupports item);
|
||||
void RemoveElement(in nsISupports item);
|
||||
|
||||
nsIEnumerator Enumerate();
|
||||
|
||||
void Clear();
|
||||
|
||||
};
|
||||
@@ -1,95 +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.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
|
||||
interface nsISimpleEnumerator : nsISupports {
|
||||
boolean HasMoreElements();
|
||||
nsISupports GetNext();
|
||||
};
|
||||
|
||||
/*
|
||||
* DO NOT USE THIS INTERFACE. IT IS HORRIBLY BROKEN, USES NS_COMFALSE
|
||||
* AND IS BASICALLY IMPOSSIBLE TO USE CORRECTLY THROUGH PROXIES OR
|
||||
* XPCONNECT. IF YOU SEE NEW USES OF THIS INTERFACE IN CODE YOU ARE
|
||||
* REVIEWING, YOU SHOULD INSIST ON nsISimpleEnumerator.
|
||||
*
|
||||
* DON'T MAKE ME COME OVER THERE.
|
||||
*/
|
||||
[scriptable, uuid(ad385286-cbc4-11d2-8cca-0060b0fc14a3)]
|
||||
interface nsIEnumerator : nsISupports {
|
||||
|
||||
/** First will reset the list. will return NS_FAILED if no items
|
||||
*/
|
||||
void first();
|
||||
|
||||
/** Next will advance the list. will return failed if already at end
|
||||
*/
|
||||
void next();
|
||||
|
||||
/** CurrentItem will return the CurrentItem item it will fail if the
|
||||
* list is empty
|
||||
*/
|
||||
nsISupports currentItem();
|
||||
|
||||
/** return if the collection is at the end. that is the beginning following
|
||||
* a call to Prev and it is the end of the list following a call to next
|
||||
*/
|
||||
void isDone();
|
||||
};
|
||||
|
||||
[uuid(75f158a0-cadd-11d2-8cca-0060b0fc14a3)]
|
||||
interface nsIBidirectionalEnumerator : nsIEnumerator {
|
||||
|
||||
/** Last will reset the list to the end. will return NS_FAILED if no items
|
||||
*/
|
||||
void Last();
|
||||
|
||||
/** Prev will decrement the list. will return failed if already at beginning
|
||||
*/
|
||||
void Prev();
|
||||
};
|
||||
|
||||
%{C++
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult);
|
||||
|
||||
// Construct and return an implementation of a "conjoining enumerator." This
|
||||
// enumerator lets you string together two other enumerators into one sequence.
|
||||
// The result is an nsIBidirectionalEnumerator, but if either input is not
|
||||
// also bidirectional, the Last and Prev operations will fail.
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewConjoiningEnumerator(nsIEnumerator* first, nsIEnumerator* second,
|
||||
nsIBidirectionalEnumerator* *aInstancePtrResult);
|
||||
|
||||
// Construct and return an implementation of a "union enumerator." This
|
||||
// enumerator will only return elements that are found in both constituent
|
||||
// enumerators.
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewUnionEnumerator(nsIEnumerator* first, nsIEnumerator* second,
|
||||
nsIEnumerator* *aInstancePtrResult);
|
||||
|
||||
// Construct and return an implementation of an "intersection enumerator." This
|
||||
// enumerator will return elements that are found in either constituent
|
||||
// enumerators, eliminating duplicates.
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewIntersectionEnumerator(nsIEnumerator* first, nsIEnumerator* second,
|
||||
nsIEnumerator* *aInstancePtrResult);
|
||||
|
||||
%}
|
||||
@@ -1,44 +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.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(DB242E01-E4D9-11d2-9DDE-000064657374)]
|
||||
interface nsIObserver : nsISupports {
|
||||
|
||||
/*------------------------------- Observe ----------------------------------
|
||||
| Called when aTopic changes for aSubject (presumably; it is actually |
|
||||
| called whenever anyone calls nsIObserverService::Notify for aTopic). |
|
||||
| |
|
||||
| Implement this in your class to handle the event appropriately. If |
|
||||
| your observer objects can respond to multiple topics and/or subjects, |
|
||||
| then you will have to filter accordingly. |
|
||||
--------------------------------------------------------------------------*/
|
||||
void Observe( in nsISupports aSubject,
|
||||
in wstring aTopic,
|
||||
in wstring someData );
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
#define NS_OBSERVER_PROGID "component://netscape/xpcom/observer"
|
||||
|
||||
#define NS_OBSERVER_CLASSNAME "Observer"
|
||||
|
||||
%}
|
||||
@@ -1,48 +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.
|
||||
*/
|
||||
|
||||
#ifndef nsIObserverList_h__
|
||||
#define nsIObserverList_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nscore.h"
|
||||
|
||||
|
||||
// {E777D482-E6E3-11d2-8ACD-00105A1B8860}
|
||||
#define NS_IOBSERVERLIST_IID \
|
||||
{ 0xe777d482, 0xe6e3, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } }
|
||||
|
||||
// {E777D484-E6E3-11d2-8ACD-00105A1B8860}
|
||||
#define NS_OBSERVERLIST_CID \
|
||||
{ 0xe777d484, 0xe6e3, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } }
|
||||
|
||||
class nsIObserverList : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IOBSERVERLIST_IID; return iid; }
|
||||
|
||||
NS_IMETHOD AddObserver(nsIObserver** anObserver) = 0;
|
||||
NS_IMETHOD RemoveObserver(nsIObserver** anObserver) = 0;
|
||||
NS_IMETHOD EnumerateObserverList(nsIEnumerator** anEnumerator) = 0;
|
||||
|
||||
};
|
||||
|
||||
extern NS_COM nsresult NS_NewObserverList(nsIObserverList** anObserverList);
|
||||
|
||||
#endif /* nsIObserverList_h__ */
|
||||
@@ -1,41 +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.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIObserver.idl"
|
||||
#include "nsIEnumerator.idl"
|
||||
|
||||
[scriptable, uuid(D07F5192-E3D1-11d2-8ACD-00105A1B8860)]
|
||||
interface nsIObserverService : nsISupports {
|
||||
|
||||
void AddObserver( in nsIObserver anObserver, in wstring aTopic );
|
||||
void RemoveObserver( in nsIObserver anObserver, in wstring nsString );
|
||||
nsIEnumerator EnumerateObserverList( in wstring aTopic );
|
||||
void Notify( in nsISupports aSubject,
|
||||
in wstring aTopic,
|
||||
in wstring someData );
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
#define NS_OBSERVERSERVICE_PROGID "component://netscape/observer-service"
|
||||
|
||||
#define NS_OBSERVERSERVICE_CLASSNAME "Observer Service"
|
||||
|
||||
%}
|
||||
@@ -1,57 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsIPageManager_h__
|
||||
#define nsIPageManager_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
#define NS_PAGEMGR_PAGE_BITS 12 // 4k pages
|
||||
#define NS_PAGEMGR_PAGE_SIZE (1 << NS_PAGEMGR_PAGE_BITS)
|
||||
#define NS_PAGEMGR_PAGE_MASK (NS_PAGEMGR_PAGE_SIZE - 1)
|
||||
#define NS_PAGEMGR_PAGE_COUNT(bytes) (((bytes) + NS_PAGEMGR_PAGE_MASK) >> NS_PAGEMGR_PAGE_BITS)
|
||||
|
||||
#define NS_IPAGEMANAGER_IID \
|
||||
{ /* bea98210-fb7b-11d2-9324-00104ba0fd40 */ \
|
||||
0xbea98210, \
|
||||
0xfb7b, \
|
||||
0x11d2, \
|
||||
{0x93, 0x24, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
#define NS_PAGEMANAGER_CID \
|
||||
{ /* cac907e0-fb7b-11d2-9324-00104ba0fd40 */ \
|
||||
0xcac907e0, \
|
||||
0xfb7b, \
|
||||
0x11d2, \
|
||||
{0x93, 0x24, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
#define NS_PAGEMANAGER_PROGID "component://netscape/page-manager"
|
||||
#define NS_PAGEMANAGER_CLASSNAME "Page Manager"
|
||||
|
||||
class nsIPageManager : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPAGEMANAGER_IID);
|
||||
|
||||
NS_IMETHOD AllocPages(PRUint32 pageCount, void* *result) = 0;
|
||||
|
||||
NS_IMETHOD DeallocPages(PRUint32 pageCount, void* pages) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // nsIPageManager_h__
|
||||
@@ -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 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.
|
||||
*/
|
||||
|
||||
#ifndef nsIProperties_h___
|
||||
#define nsIProperties_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
||||
#define NS_IPROPERTIES_IID \
|
||||
{ /* f42bc870-dc17-11d2-9311-00e09805570f */ \
|
||||
0xf42bc870, \
|
||||
0xdc17, \
|
||||
0x11d2, \
|
||||
{0x93, 0x11, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \
|
||||
}
|
||||
|
||||
#define NS_PROPERTIES_CID \
|
||||
{ /* b3efe4d0-0d6b-11d3-9331-00104ba0fd40 */ \
|
||||
0xb3efe4d0, \
|
||||
0x0d6b, \
|
||||
0x11d3, \
|
||||
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
#define NS_PROPERTIES_PROGID "component://netscape/properties"
|
||||
#define NS_PROPERTIES_CLASSNAME "Properties"
|
||||
|
||||
class nsIProperties : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IPROPERTIES_IID; return iid; }
|
||||
|
||||
/**
|
||||
* Defines a new property.
|
||||
* @return NS_ERROR_FAILURE if a property is already defined.
|
||||
*/
|
||||
NS_IMETHOD DefineProperty(const char* prop, nsISupports* initialValue) = 0;
|
||||
|
||||
/**
|
||||
* Undefines a property.
|
||||
* @return NS_ERROR_FAILURE if a property is not already defined.
|
||||
*/
|
||||
NS_IMETHOD UndefineProperty(const char* prop) = 0;
|
||||
|
||||
/**
|
||||
* Gets a property.
|
||||
* @return NS_ERROR_FAILURE if a property is not already defined.
|
||||
*/
|
||||
NS_IMETHOD GetProperty(const char* prop, nsISupports* *result) = 0;
|
||||
|
||||
/**
|
||||
* Sets a property.
|
||||
* @return NS_ERROR_FAILURE if a property is not already defined.
|
||||
*/
|
||||
NS_IMETHOD SetProperty(const char* prop, nsISupports* value) = 0;
|
||||
|
||||
/**
|
||||
* @return NS_OK if the property exists with the specified value
|
||||
* @return NS_COMFALSE if the property does not exist, or doesn't have
|
||||
* the specified value (values are compared with ==)
|
||||
*/
|
||||
NS_IMETHOD HasProperty(const char* prop, nsISupports* value) = 0;
|
||||
|
||||
};
|
||||
|
||||
// Returns a default implementation of an nsIProperties object.
|
||||
extern nsresult
|
||||
NS_NewIProperties(nsIProperties* *result);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "nsID.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsString.h"
|
||||
|
||||
// {1A180F60-93B2-11d2-9B8B-00805F8A16D9}
|
||||
#define NS_IPERSISTENTPROPERTIES_IID \
|
||||
{ 0x1a180f60, 0x93b2, 0x11d2, \
|
||||
{ 0x9b, 0x8b, 0x0, 0x80, 0x5f, 0x8a, 0x16, 0xd9 } }
|
||||
|
||||
// {2245E573-9464-11d2-9B8B-00805F8A16D9}
|
||||
NS_DECLARE_ID(kPersistentPropertiesCID,
|
||||
0x2245e573, 0x9464, 0x11d2, 0x9b, 0x8b, 0x0, 0x80, 0x5f, 0x8a, 0x16, 0xd9);
|
||||
|
||||
#define NS_PERSISTENTPROPERTIES_PROGID "component://netscape/persistent-properties"
|
||||
#define NS_PERSISTENTPROPERTIES_CLASSNAME "Persistent Properties"
|
||||
|
||||
class nsIPersistentProperties : public nsIProperties
|
||||
{
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IPERSISTENTPROPERTIES_IID; return iid; }
|
||||
|
||||
NS_IMETHOD Load(nsIInputStream* aIn) = 0;
|
||||
NS_IMETHOD Save(nsIOutputStream* aOut, const nsString& aHeader) = 0;
|
||||
NS_IMETHOD Subclass(nsIPersistentProperties* aSubclass) = 0;
|
||||
|
||||
/**
|
||||
* Enumerates the properties in the supplied enumerator.
|
||||
* @return NS_ERROR_FAILURE if no properties to enumerate
|
||||
*/
|
||||
NS_IMETHOD EnumerateProperties(nsIBidirectionalEnumerator** aResult) = 0;
|
||||
|
||||
// XXX these 2 methods will be subsumed by the ones from
|
||||
// nsIProperties once we figure this all out
|
||||
NS_IMETHOD GetStringProperty(const nsString& aKey, nsString& aValue) = 0;
|
||||
NS_IMETHOD SetStringProperty(const nsString& aKey, nsString& aNewValue,
|
||||
nsString& aOldValue) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// {C23C10B3-0E1A-11d3-A430-0060B0EB5963}
|
||||
#define NS_IPROPERTYELEMENT_IID \
|
||||
{ 0xc23c10b3, 0xe1a, 0x11d3, \
|
||||
{ 0xa4, 0x30, 0x0, 0x60, 0xb0, 0xeb, 0x59, 0x63 } }
|
||||
|
||||
// {579C0568-0E1B-11d3-A430-0060B0EB5963}
|
||||
NS_DECLARE_ID(kPropertyElementCID,
|
||||
0x579c0568, 0xe1b, 0x11d3, 0xa4, 0x30, 0x0, 0x60, 0xb0, 0xeb, 0x59, 0x63);
|
||||
|
||||
class nsIPropertyElement : public nsISupports
|
||||
{
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IPROPERTYELEMENT_IID; return iid; }
|
||||
|
||||
NS_IMETHOD SetKey(nsString* aKey) = 0;
|
||||
NS_IMETHOD SetValue(nsString* aValue) = 0;
|
||||
NS_IMETHOD GetKey(nsString** aReturnKey) = 0;
|
||||
NS_IMETHOD GetValue(nsString** aReturnValue) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // nsIProperties_h___
|
||||
@@ -1,26 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef nsISimpleEnumerator_h__
|
||||
#define nsISimpleEnumerator_h__
|
||||
|
||||
// This file is needed to pacify the xpidl-generated header files.
|
||||
#include "nsIEnumerator.h"
|
||||
|
||||
#endif // nsISimpleEnumerator_h__
|
||||
|
||||
@@ -1,100 +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.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.
|
||||
*/
|
||||
#ifndef nsISizeOfHandler_h___
|
||||
#define nsISizeOfHandler_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
/* c028d1f0-fc9e-11d1-89e4-006008911b81 */
|
||||
#define NS_ISIZEOF_HANDLER_IID \
|
||||
{ 0xc028d1f0, 0xfc9e, 0x11d1, {0x89, 0xe4, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
|
||||
|
||||
class nsIAtom;
|
||||
class nsISizeOfHandler;
|
||||
|
||||
/**
|
||||
* Function used by the Report method to report data gathered during
|
||||
* a collection of data.
|
||||
*/
|
||||
typedef void (*nsISizeofReportFunc)(nsISizeOfHandler* aHandler,
|
||||
nsIAtom* aKey,
|
||||
PRUint32 aCount,
|
||||
PRUint32 aTotalSize,
|
||||
PRUint32 aMinSize,
|
||||
PRUint32 aMaxSize,
|
||||
void* aArg);
|
||||
|
||||
/**
|
||||
* An API to managing a sizeof computation of an arbitrary graph.
|
||||
* The handler is responsible for remembering which objects have been
|
||||
* seen before (using RecordObject). Note that the handler doesn't
|
||||
* hold references to nsISupport's objects; the assumption is that the
|
||||
* objects being sized are stationary and will not be modified during
|
||||
* the sizing computation and therefore do not need an extra reference
|
||||
* count.
|
||||
*
|
||||
* Users of this API are responsible for the actual graph/tree walking.
|
||||
*/
|
||||
class nsISizeOfHandler : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISIZEOF_HANDLER_IID)
|
||||
|
||||
/**
|
||||
* Initialize the handler for a new collection of data. This empties
|
||||
* out the object prescence table and the keyed size table.
|
||||
*/
|
||||
NS_IMETHOD Init() = 0;
|
||||
|
||||
/**
|
||||
* Record the sizing status of a given object. The first time
|
||||
* aObject is recorded, aResult will be PR_FALSE. Subsequent times,
|
||||
* aResult will be PR_TRUE.
|
||||
*/
|
||||
NS_IMETHOD RecordObject(void* aObject, PRBool* aResult) = 0;
|
||||
|
||||
/**
|
||||
* Add size information to the running size data. The atom is used
|
||||
* as a key to keep type specific running totals of size
|
||||
* information. This increments the total count and the total size
|
||||
* as well as updates the minimum, maximum and total size for aKey's
|
||||
* type.
|
||||
*/
|
||||
NS_IMETHOD AddSize(nsIAtom* aKey, PRUint32 aSize) = 0;
|
||||
|
||||
/**
|
||||
* Enumerate data collected for each type and invoke the
|
||||
* reporting function with the data gathered.
|
||||
*/
|
||||
NS_IMETHOD Report(nsISizeofReportFunc aFunc, void* aArg) = 0;
|
||||
|
||||
/**
|
||||
* Get the current totals - the number of total objects sized (not
|
||||
* necessarily anything to do with RecordObject's tracking of
|
||||
* objects) and the total number of bytes that those object use. The
|
||||
* counters are not reset by this call (use Init to reset
|
||||
* everything).
|
||||
*/
|
||||
NS_IMETHOD GetTotals(PRUint32* aTotalCountResult,
|
||||
PRUint32* aTotalSizeResult) = 0;
|
||||
};
|
||||
|
||||
extern NS_COM nsresult
|
||||
NS_NewSizeOfHandler(nsISizeOfHandler** aInstancePtrResult);
|
||||
|
||||
#endif /* nsISizeofHandler_h___ */
|
||||
@@ -1,104 +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.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsICollection.idl"
|
||||
|
||||
native nsISupportsArrayEnumFunc(nsISupportsArrayEnumFunc);
|
||||
|
||||
%{C++
|
||||
|
||||
class nsIBidirectionalEnumerator;
|
||||
|
||||
#define NS_SUPPORTSARRAY_CID \
|
||||
{ /* bda17d50-0d6b-11d3-9331-00104ba0fd40 */ \
|
||||
0xbda17d50, \
|
||||
0x0d6b, \
|
||||
0x11d3, \
|
||||
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
#define NS_SUPPORTSARRAY_PROGID "component://netscape/supports-array"
|
||||
#define NS_SUPPORTSARRAY_CLASSNAME "Supports Array"
|
||||
|
||||
// Enumerator callback function. Return PR_FALSE to stop
|
||||
typedef PRBool (*nsISupportsArrayEnumFunc)(nsISupports* aElement, void *aData);
|
||||
|
||||
%}
|
||||
|
||||
[scriptable, uuid(791eafa0-b9e6-11d1-8031-006008159b5a)]
|
||||
interface nsISupportsArray : nsICollection {
|
||||
|
||||
[notxpcom] boolean Equals([const] in nsISupportsArray other);
|
||||
|
||||
[notxpcom] nsISupports ElementAt(in unsigned long aIndex);
|
||||
|
||||
[notxpcom] long IndexOf([const] in nsISupports aPossibleElement);
|
||||
[notxpcom] long IndexOfStartingAt([const] in nsISupports aPossibleElement,
|
||||
in unsigned long aStartIndex);
|
||||
[notxpcom] long LastIndexOf([const] in nsISupports aPossibleElement);
|
||||
|
||||
// xpcom-compatible versions
|
||||
long GetIndexOf(in nsISupports aPossibleElement);
|
||||
long GetIndexOfStartingAt(in nsISupports aPossibleElement,
|
||||
in unsigned long aStartIndex);
|
||||
long GetLastIndexOf(in nsISupports aPossibleElement);
|
||||
|
||||
[notxpcom] boolean InsertElementAt(in nsISupports aElement,
|
||||
in unsigned long aIndex);
|
||||
[notxpcom] boolean ReplaceElementAt(in nsISupports aElement,
|
||||
in unsigned long aIndex);
|
||||
|
||||
[notxpcom] boolean RemoveElementAt(in unsigned long aIndex);
|
||||
[notxpcom] boolean RemoveLastElement([const] in nsISupports aElement);
|
||||
|
||||
// xpcom-compatible versions
|
||||
void DeleteLastElement(in nsISupports aElement);
|
||||
void DeleteElementAt(in unsigned long aIndex);
|
||||
|
||||
[notxpcom] boolean AppendElements(in nsISupportsArray aElements);
|
||||
|
||||
void Compact();
|
||||
|
||||
[notxpcom, noscript]
|
||||
boolean EnumerateForwards(in nsISupportsArrayEnumFunc aFunc,
|
||||
in voidStar aData);
|
||||
[notxpcom, noscript]
|
||||
boolean EnumerateBackwards(in nsISupportsArrayEnumFunc aFunc,
|
||||
in voidStar aData);
|
||||
%{C++
|
||||
private:
|
||||
// NS_IMETHOD_(nsISupportsArray&) operator=(const nsISupportsArray& other) = 0;
|
||||
NS_IMETHOD_(PRBool) operator==(const nsISupportsArray& other) = 0;
|
||||
NS_IMETHOD_(nsISupports*) operator[](PRUint32 aIndex) = 0;
|
||||
%}
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
// Construct and return a default implementation of nsISupportsArray:
|
||||
extern NS_COM nsresult
|
||||
NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult);
|
||||
|
||||
// Construct and return a default implementation of an enumerator for nsISupportsArrays:
|
||||
extern NS_COM nsresult
|
||||
NS_NewISupportsArrayEnumerator(nsISupportsArray* array,
|
||||
nsIBidirectionalEnumerator* *aInstancePtrResult);
|
||||
|
||||
|
||||
%}
|
||||
@@ -1,263 +0,0 @@
|
||||
/* -*- Mode: IDL; 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.
|
||||
*/
|
||||
|
||||
/* nsISupports wrappers for single primitive pieces of data. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* These first three are pointer types and do data copying
|
||||
* using the nsIAllocator. Be careful!
|
||||
*/
|
||||
|
||||
[scriptable, uuid(d18290a0-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsID : nsISupports
|
||||
{
|
||||
attribute nsIDPtr data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(d65ff270-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsString : nsISupports
|
||||
{
|
||||
attribute string data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(d79dc970-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsWString : nsISupports
|
||||
{
|
||||
attribute wstring data;
|
||||
wstring toString();
|
||||
};
|
||||
|
||||
/**
|
||||
* The rest are truly primitive and are passed by value
|
||||
*/
|
||||
|
||||
[scriptable, uuid(ddc3b490-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRBool : nsISupports
|
||||
{
|
||||
attribute PRBool data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(dec2e4e0-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRUint8 : nsISupports
|
||||
{
|
||||
attribute PRUint8 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(dfacb090-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRUint16 : nsISupports
|
||||
{
|
||||
attribute PRUint16 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e01dc470-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRUint32 : nsISupports
|
||||
{
|
||||
attribute PRUint32 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e13567c0-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRUint64 : nsISupports
|
||||
{
|
||||
attribute PRUint64 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e2563630-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRTime : nsISupports
|
||||
{
|
||||
attribute PRTime data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e2b05e40-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsChar : nsISupports
|
||||
{
|
||||
attribute char data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e30d94b0-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRInt16 : nsISupports
|
||||
{
|
||||
attribute PRInt16 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e36c5250-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRInt32 : nsISupports
|
||||
{
|
||||
attribute PRInt32 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e3cb0ff0-4a1c-11d3-9890-006008962422)]
|
||||
interface nsISupportsPRInt64 : nsISupports
|
||||
{
|
||||
attribute PRInt64 data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(abeaa390-4ac0-11d3-baea-00805f8a5dd7)]
|
||||
interface nsISupportsFloat : nsISupports
|
||||
{
|
||||
attribute float data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(b32523a0-4ac0-11d3-baea-00805f8a5dd7)]
|
||||
interface nsISupportsDouble : nsISupports
|
||||
{
|
||||
attribute double data;
|
||||
string toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(464484f0-568d-11d3-baf8-00805f8a5dd7)]
|
||||
interface nsISupportsVoid : nsISupports
|
||||
{
|
||||
/*
|
||||
* This would be: "[noscript] attribute voidStar data;" but for...
|
||||
* http://bugzilla.mozilla.org/show_bug.cgi?id=11454
|
||||
*/
|
||||
[noscript] void GetData([shared,retval] out voidStar aData);
|
||||
[noscript] void SetData(in voidStar aData);
|
||||
string toString();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
%{C++
|
||||
// {ACF8DC40-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_ID_CID \
|
||||
{ 0xacf8dc40, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_ID_PROGID "component://netscape/supports-id"
|
||||
#define NS_SUPPORTS_ID_CLASSNAME "Supports ID"
|
||||
|
||||
// {ACF8DC41-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_STRING_CID \
|
||||
{ 0xacf8dc41, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_STRING_PROGID "component://netscape/supports-string"
|
||||
#define NS_SUPPORTS_STRING_CLASSNAME "Supports String"
|
||||
|
||||
// {ACF8DC42-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_WSTRING_CID \
|
||||
{ 0xacf8dc42, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_WSTRING_PROGID "component://netscape/supports-wstring"
|
||||
#define NS_SUPPORTS_WSTRING_CLASSNAME "Supports WString"
|
||||
|
||||
// {ACF8DC43-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRBOOL_CID \
|
||||
{ 0xacf8dc43, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRBOOL_PROGID "component://netscape/supports-PRBool"
|
||||
#define NS_SUPPORTS_PRBOOL_CLASSNAME "Supports PRBool"
|
||||
|
||||
// {ACF8DC44-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRUINT8_CID \
|
||||
{ 0xacf8dc44, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRUINT8_PROGID "component://netscape/supports-PRUint8"
|
||||
#define NS_SUPPORTS_PRUINT8_CLASSNAME "Supports PRUint8"
|
||||
|
||||
// {ACF8DC46-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRUINT16_CID \
|
||||
{ 0xacf8dc46, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRUINT16_PROGID "component://netscape/supports-PRUint16"
|
||||
#define NS_SUPPORTS_PRUINT16_CLASSNAME "Supports PRUint16"
|
||||
|
||||
// {ACF8DC47-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRUINT32_CID \
|
||||
{ 0xacf8dc47, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRUINT32_PROGID "component://netscape/supports-PRUint32"
|
||||
#define NS_SUPPORTS_PRUINT32_CLASSNAME "Supports PRUint32"
|
||||
|
||||
// {ACF8DC48-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRUINT64_CID \
|
||||
{ 0xacf8dc48, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRUINT64_PROGID "component://netscape/supports-PRUint64"
|
||||
#define NS_SUPPORTS_PRUINT64_CLASSNAME "Supports PRUint64"
|
||||
|
||||
// {ACF8DC49-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRTIME_CID \
|
||||
{ 0xacf8dc49, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRTIME_PROGID "component://netscape/supports-PRTime"
|
||||
#define NS_SUPPORTS_PRTIME_CLASSNAME "Supports PRTime"
|
||||
|
||||
// {ACF8DC4A-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_CHAR_CID \
|
||||
{ 0xacf8dc4a, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_CHAR_PROGID "component://netscape/supports-char"
|
||||
#define NS_SUPPORTS_CHAR_CLASSNAME "Supports Char"
|
||||
|
||||
// {ACF8DC4B-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRINT16_CID \
|
||||
{ 0xacf8dc4b, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRINT16_PROGID "component://netscape/supports-PRInt16"
|
||||
#define NS_SUPPORTS_PRINT16_CLASSNAME "Supports PRInt16"
|
||||
|
||||
// {ACF8DC4C-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRINT32_CID \
|
||||
{ 0xacf8dc4c, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRINT32_PROGID "component://netscape/supports-PRInt32"
|
||||
#define NS_SUPPORTS_PRINT32_CLASSNAME "Supports PRInt32"
|
||||
|
||||
// {ACF8DC4D-4A25-11d3-9890-006008962422}
|
||||
#define NS_SUPPORTS_PRINT64_CID \
|
||||
{ 0xacf8dc4d, 0x4a25, 0x11d3, \
|
||||
{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
#define NS_SUPPORTS_PRINT64_PROGID "component://netscape/supports-PRInt64"
|
||||
#define NS_SUPPORTS_PRINT64_CLASSNAME "Supports PRInt64"
|
||||
|
||||
// {CBF86870-4AC0-11d3-BAEA-00805F8A5DD7}
|
||||
#define NS_SUPPORTS_FLOAT_CID \
|
||||
{ 0xcbf86870, 0x4ac0, 0x11d3, \
|
||||
{ 0xba, 0xea, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
|
||||
#define NS_SUPPORTS_FLOAT_PROGID "component://netscape/supports-float"
|
||||
#define NS_SUPPORTS_FLOAT_CLASSNAME "Supports float"
|
||||
|
||||
// {CBF86871-4AC0-11d3-BAEA-00805F8A5DD7}
|
||||
#define NS_SUPPORTS_DOUBLE_CID \
|
||||
{ 0xcbf86871, 0x4ac0, 0x11d3, \
|
||||
{ 0xba, 0xea, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
|
||||
#define NS_SUPPORTS_DOUBLE_PROGID "component://netscape/supports-double"
|
||||
#define NS_SUPPORTS_DOUBLE_CLASSNAME "Supports double"
|
||||
|
||||
// {AF10F3E0-568D-11d3-BAF8-00805F8A5DD7}
|
||||
#define NS_SUPPORTS_VOID_CID \
|
||||
{ 0xaf10f3e0, 0x568d, 0x11d3, \
|
||||
{ 0xba, 0xf8, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
|
||||
#define NS_SUPPORTS_VOID_PROGID "component://netscape/supports-void"
|
||||
#define NS_SUPPORTS_VOID_CLASSNAME "Supports void"
|
||||
%}
|
||||
@@ -1,57 +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.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.
|
||||
*/
|
||||
#ifndef nsIUnicharBuffer_h___
|
||||
#define nsIUnicharBuffer_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
class nsIUnicharInputStream;
|
||||
|
||||
#define NS_IUNICHARBUFFER_IID \
|
||||
{ 0x14cf6970, 0x93b5, 0x11d1, \
|
||||
{0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
|
||||
|
||||
/// Interface to a buffer that holds unicode characters
|
||||
class nsIUnicharBuffer : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IUNICHARBUFFER_IID);
|
||||
|
||||
NS_IMETHOD Init(PRUint32 aBufferSize) = 0;
|
||||
NS_IMETHOD_(PRInt32) GetLength() const = 0;
|
||||
NS_IMETHOD_(PRInt32) GetBufferSize() const = 0;
|
||||
NS_IMETHOD_(PRUnichar*) GetBuffer() const = 0;
|
||||
NS_IMETHOD_(PRBool) Grow(PRInt32 aNewSize) = 0;
|
||||
NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIUnicharInputStream* aStream,
|
||||
PRInt32 aKeep) = 0;
|
||||
};
|
||||
|
||||
/// Factory method for nsIUnicharBuffer.
|
||||
extern NS_COM nsresult
|
||||
NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
|
||||
nsISupports* aOuter,
|
||||
PRUint32 aBufferSize = 0);
|
||||
|
||||
#define NS_UNICHARBUFFER_CID \
|
||||
{ /* c81fd8f0-0d6b-11d3-9331-00104ba0fd40 */ \
|
||||
0xc81fd8f0, \
|
||||
0x0d6b, \
|
||||
0x11d3, \
|
||||
{0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
#endif /* nsIUnicharBuffer_h___ */
|
||||
@@ -1,340 +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.
|
||||
*/
|
||||
|
||||
#ifndef nsInt64_h__
|
||||
#define nsInt64_h__
|
||||
|
||||
#include "prlong.h"
|
||||
#include "nscore.h"
|
||||
|
||||
/**
|
||||
* This class encapsulates full 64-bit integer functionality and
|
||||
* provides simple arithmetic and conversion operations.
|
||||
*/
|
||||
|
||||
// If you ever decide that you need to add a non-inline method to this
|
||||
// class, be sure to change the class declaration to "class NS_BASE
|
||||
// nsInt64".
|
||||
|
||||
class nsInt64
|
||||
{
|
||||
private:
|
||||
PRInt64 mValue;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new 64-bit integer.
|
||||
*/
|
||||
nsInt64(void) : mValue(LL_ZERO) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 64-bit integer from a 32-bit signed integer
|
||||
*/
|
||||
nsInt64(const PRInt32 aInt32) {
|
||||
LL_I2L(mValue, aInt32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 64-bit integer from a 32-bit unsigned integer
|
||||
*/
|
||||
nsInt64(const PRUint32 aUint32) {
|
||||
LL_UI2L(mValue, aUint32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 64-bit integer from a floating point value.
|
||||
*/
|
||||
nsInt64(const PRFloat64 aFloat64) {
|
||||
LL_D2L(mValue, aFloat64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 64-bit integer from a native 64-bit integer
|
||||
*/
|
||||
nsInt64(const PRInt64 aInt64) : mValue(aInt64) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 64-bit integer from another 64-bit integer
|
||||
*/
|
||||
nsInt64(const nsInt64& aObject) : mValue(aObject.mValue) {
|
||||
}
|
||||
|
||||
// ~nsInt64(void) -- XXX destructor unnecessary
|
||||
|
||||
/**
|
||||
* Assign a 64-bit integer to another 64-bit integer
|
||||
*/
|
||||
const nsInt64& operator =(const nsInt64& aObject) {
|
||||
mValue = aObject.mValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a 64-bit integer to a signed 32-bit value
|
||||
*/
|
||||
operator PRInt32(void) const {
|
||||
PRInt32 result;
|
||||
LL_L2I(result, mValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a 64-bit integer to an unsigned 32-bit value
|
||||
*/
|
||||
operator PRUint32(void) const {
|
||||
PRUint32 result;
|
||||
LL_L2UI(result, mValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a 64-bit integer to a floating point value
|
||||
*/
|
||||
operator PRFloat64(void) const {
|
||||
PRFloat64 result;
|
||||
LL_L2D(result, mValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a 64-bit integer to a native 64-bit integer.
|
||||
*/
|
||||
operator PRInt64(void) const {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform unary negation on a 64-bit integer.
|
||||
*/
|
||||
const nsInt64 operator -(void) {
|
||||
nsInt64 result;
|
||||
LL_NEG(result.mValue, mValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Arithmetic operators
|
||||
friend const nsInt64 operator +(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend const nsInt64 operator -(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend const nsInt64 operator *(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend const nsInt64 operator /(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend const nsInt64 operator %(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
|
||||
/**
|
||||
* Increment a 64-bit integer by a 64-bit integer amount.
|
||||
*/
|
||||
nsInt64& operator +=(const nsInt64& aObject) {
|
||||
LL_ADD(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement a 64-bit integer by a 64-bit integer amount.
|
||||
*/
|
||||
nsInt64& operator -=(const nsInt64& aObject) {
|
||||
LL_SUB(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply a 64-bit integer by a 64-bit integer amount.
|
||||
*/
|
||||
nsInt64& operator *=(const nsInt64& aObject) {
|
||||
LL_MUL(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide a 64-bit integer by a 64-bit integer amount.
|
||||
*/
|
||||
nsInt64& operator /=(const nsInt64& aObject) {
|
||||
LL_DIV(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the modulus of a 64-bit integer to a 64-bit value.
|
||||
*/
|
||||
nsInt64& operator %=(const nsInt64& aObject) {
|
||||
LL_MOD(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Comparison operators
|
||||
friend PRBool operator ==(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend PRBool operator !=(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend PRBool operator >(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend PRBool operator >=(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend PRBool operator <(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend PRBool operator <=(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
|
||||
// Bitwise operators
|
||||
friend const nsInt64 operator &(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend const nsInt64 operator |(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
friend const nsInt64 operator ^(const nsInt64& aObject1, const nsInt64& aObject2);
|
||||
|
||||
/**
|
||||
* Compute the bitwise NOT of a 64-bit integer
|
||||
*/
|
||||
const nsInt64 operator ~(void) {
|
||||
nsInt64 result;
|
||||
LL_NOT(result.mValue, mValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the bitwise AND with another 64-bit integer
|
||||
*/
|
||||
nsInt64& operator &=(const nsInt64& aObject) {
|
||||
LL_AND(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the bitwise OR with another 64-bit integer
|
||||
*/
|
||||
nsInt64& operator |=(const nsInt64& aObject) {
|
||||
LL_OR(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the bitwise XOR with another 64-bit integer
|
||||
*/
|
||||
nsInt64& operator ^=(const nsInt64& aObject) {
|
||||
LL_XOR(mValue, mValue, aObject.mValue);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add two 64-bit integers.
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator +(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) += aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract one 64-bit integer from another.
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator -(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) -= aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply two 64-bit integers
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator *(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) *= aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide one 64-bit integer by another
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator /(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) /= aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the modulus of two 64-bit integers
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator %(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) %= aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two 64-bit integers are equal
|
||||
*/
|
||||
inline PRBool
|
||||
operator ==(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return LL_EQ(aObject1.mValue, aObject2.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two 64-bit integers are not equal
|
||||
*/
|
||||
inline PRBool
|
||||
operator !=(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return LL_NE(aObject1.mValue, aObject2.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one 64-bit integer is strictly greater than another, using signed values
|
||||
*/
|
||||
inline PRBool
|
||||
operator >(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return LL_CMP(aObject1.mValue, >, aObject2.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one 64-bit integer is greater than or equal to another, using signed values
|
||||
*/
|
||||
inline PRBool
|
||||
operator >=(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return LL_CMP(aObject1.mValue, >=, aObject2.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one 64-bit integer is strictly less than another, using signed values
|
||||
*/
|
||||
inline PRBool
|
||||
operator <(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return LL_CMP(aObject1.mValue, <, aObject2.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one 64-bit integers is less than or equal to another, using signed values
|
||||
*/
|
||||
inline PRBool
|
||||
operator <=(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return LL_CMP(aObject1.mValue, <=, aObject2.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a bitwise AND of two 64-bit integers
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator &(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) &= aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a bitwise OR of two 64-bit integers
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator |(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) |= aObject2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a bitwise XOR of two 64-bit integers
|
||||
*/
|
||||
inline const nsInt64
|
||||
operator ^(const nsInt64& aObject1, const nsInt64& aObject2) {
|
||||
return nsInt64(aObject1) ^= aObject2;
|
||||
}
|
||||
|
||||
|
||||
#endif // nsInt64_h__
|
||||
@@ -1,92 +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.
|
||||
*/
|
||||
|
||||
#define NS_IMPL_IDS
|
||||
#include "pratom.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRepository.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsObserver.h"
|
||||
#include "nsString.h"
|
||||
|
||||
static NS_DEFINE_CID(kObserverCID, NS_OBSERVER_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsObserver Implementation
|
||||
|
||||
|
||||
NS_IMPL_AGGREGATED(nsObserver)
|
||||
|
||||
NS_COM nsresult NS_NewObserver(nsIObserver** anObserver, nsISupports* outer)
|
||||
{
|
||||
return nsObserver::Create(outer, NS_GET_IID(nsIObserver), (void**)anObserver);
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsObserver::Create(nsISupports* outer, const nsIID& aIID, void* *anObserver)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(anObserver);
|
||||
NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
|
||||
|
||||
nsObserver* it = new nsObserver(outer);
|
||||
if (it == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = it->AggregatedQueryInterface(aIID, anObserver);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete it;
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsObserver::nsObserver(nsISupports* outer)
|
||||
{
|
||||
NS_INIT_AGGREGATED(outer);
|
||||
}
|
||||
|
||||
nsObserver::~nsObserver(void)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObserver::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInstancePtr);
|
||||
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
|
||||
*aInstancePtr = GetInner();
|
||||
else if(aIID.Equals(nsIObserver::GetIID()))
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIObserver*, this);
|
||||
else {
|
||||
*aInstancePtr = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_ADDREF((nsISupports*)*aInstancePtr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObserver::Observe( nsISupports *, const PRUnichar *, const PRUnichar * ) {
|
||||
nsresult rv = NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,50 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsObserver_h___
|
||||
#define nsObserver_h___
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsAgg.h"
|
||||
|
||||
// {DB242E03-E4D9-11d2-9DDE-000064657374}
|
||||
#define NS_OBSERVER_CID \
|
||||
{ 0xdb242e03, 0xe4d9, 0x11d2, { 0x9d, 0xde, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
|
||||
class nsObserver : public nsIObserver {
|
||||
public:
|
||||
|
||||
NS_DEFINE_STATIC_CID_ACCESSOR( NS_OBSERVER_CID )
|
||||
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsObserver(nsISupports* outer);
|
||||
virtual ~nsObserver(void);
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
|
||||
|
||||
NS_DECL_AGGREGATED
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
extern NS_COM nsresult NS_NewObserver(nsIObserver** anObserver, nsISupports* outer = NULL);
|
||||
|
||||
#endif /* nsObserver_h___ */
|
||||
@@ -1,133 +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.
|
||||
*/
|
||||
|
||||
#define NS_IMPL_IDS
|
||||
#include "pratom.h"
|
||||
#include "nsIObserverList.h"
|
||||
#include "nsObserverList.h"
|
||||
#include "nsString.h"
|
||||
#include "nsAutoLock.h"
|
||||
|
||||
|
||||
#define NS_AUTOLOCK(__monitor) nsAutoLock __lock(__monitor)
|
||||
|
||||
static NS_DEFINE_CID(kObserverListCID, NS_OBSERVERLIST_CID);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsObserverList Implementation
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsObserverList, nsIObserverList)
|
||||
|
||||
NS_COM nsresult NS_NewObserverList(nsIObserverList** anObserverList)
|
||||
{
|
||||
|
||||
if (anObserverList == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsObserverList* it = new nsObserverList();
|
||||
|
||||
if (it == 0) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return it->QueryInterface(NS_GET_IID(nsIObserverList), (void **) anObserverList);
|
||||
}
|
||||
|
||||
nsObserverList::nsObserverList()
|
||||
: mLock(nsnull),
|
||||
mObserverList(NULL)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mLock = PR_NewLock();
|
||||
}
|
||||
|
||||
nsObserverList::~nsObserverList(void)
|
||||
{
|
||||
PR_DestroyLock(mLock);
|
||||
NS_IF_RELEASE(mObserverList);
|
||||
}
|
||||
|
||||
|
||||
nsresult nsObserverList::AddObserver(nsIObserver** anObserver)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inserted;
|
||||
|
||||
NS_AUTOLOCK(mLock);
|
||||
|
||||
if (anObserver == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if(!mObserverList) {
|
||||
rv = NS_NewISupportsArray(&mObserverList);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if(*anObserver) {
|
||||
inserted = mObserverList->AppendElement(*anObserver);
|
||||
return inserted ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsObserverList::RemoveObserver(nsIObserver** anObserver)
|
||||
{
|
||||
PRBool removed;
|
||||
|
||||
NS_AUTOLOCK(mLock);
|
||||
|
||||
if (anObserver == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if(!mObserverList) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if(*anObserver) {
|
||||
removed = mObserverList->RemoveElement(*anObserver);
|
||||
return removed ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsObserverList::EnumerateObserverList(nsIEnumerator** anEnumerator)
|
||||
{
|
||||
NS_AUTOLOCK(mLock);
|
||||
|
||||
if (anEnumerator == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if(!mObserverList) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mObserverList->Enumerate(anEnumerator);
|
||||
}
|
||||
|
||||
@@ -1,51 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsObserverList_h___
|
||||
#define nsObserverList_h___
|
||||
|
||||
#include "nsIObserverList.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
||||
|
||||
class nsObserverList : public nsIObserverList {
|
||||
public:
|
||||
|
||||
NS_IMETHOD AddObserver(nsIObserver** anObserver);
|
||||
NS_IMETHOD RemoveObserver(nsIObserver** anObserver);
|
||||
|
||||
NS_IMETHOD EnumerateObserverList(nsIEnumerator** anEnumerator);
|
||||
|
||||
nsObserverList();
|
||||
virtual ~nsObserverList(void);
|
||||
|
||||
// This is ObserverList monitor object.
|
||||
PRLock* mLock;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
||||
private:
|
||||
|
||||
nsISupportsArray *mObserverList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsObserverList_h___ */
|
||||
@@ -1,249 +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.
|
||||
*/
|
||||
|
||||
#define NS_IMPL_IDS
|
||||
#include "prlock.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRepository.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsObserverService.h"
|
||||
#include "nsIObserverList.h"
|
||||
#include "nsObserverList.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsString.h"
|
||||
|
||||
static NS_DEFINE_CID(kObserverServiceCID, NS_OBSERVERSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static nsObserverService* gObserverService = nsnull; // The one-and-only ObserverService
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsObserverService Implementation
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsObserverService, nsIObserverService)
|
||||
|
||||
NS_COM nsresult NS_NewObserverService(nsIObserverService** anObserverService)
|
||||
{
|
||||
return nsObserverService::GetObserverService(anObserverService);
|
||||
}
|
||||
|
||||
nsObserverService::nsObserverService()
|
||||
: mObserverTopicTable(NULL)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mObserverTopicTable = nsnull;
|
||||
}
|
||||
|
||||
nsObserverService::~nsObserverService(void)
|
||||
{
|
||||
if(mObserverTopicTable)
|
||||
delete mObserverTopicTable;
|
||||
gObserverService = nsnull;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsObserverService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsObserverService* os = new nsObserverService();
|
||||
if (os == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(os);
|
||||
rv = os->QueryInterface(aIID, aInstancePtr);
|
||||
NS_RELEASE(os);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsObserverService::GetObserverService(nsIObserverService** anObserverService)
|
||||
{
|
||||
if (! gObserverService) {
|
||||
nsObserverService* it = new nsObserverService();
|
||||
if (! it)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
gObserverService = it;
|
||||
}
|
||||
|
||||
NS_ADDREF(gObserverService);
|
||||
*anObserverService = gObserverService;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ReleaseObserverList(nsHashKey *aKey, void *aData, void* closure)
|
||||
{
|
||||
nsIObserverList* observerList = NS_STATIC_CAST(nsIObserverList*, aData);
|
||||
NS_RELEASE(observerList);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult nsObserverService::GetObserverList(const nsString& aTopic, nsIObserverList** anObserverList)
|
||||
{
|
||||
if (anObserverList == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if(mObserverTopicTable == NULL) {
|
||||
mObserverTopicTable = new nsObjectHashtable(nsnull, nsnull, // should never be cloned
|
||||
ReleaseObserverList, nsnull,
|
||||
256, PR_TRUE);
|
||||
if (mObserverTopicTable == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
nsStringKey key(aTopic);
|
||||
|
||||
nsIObserverList *topicObservers = nsnull;
|
||||
if (mObserverTopicTable->Exists(&key)) {
|
||||
topicObservers = (nsIObserverList *) mObserverTopicTable->Get(&key);
|
||||
if (topicObservers != NULL) {
|
||||
*anObserverList = topicObservers;
|
||||
} else {
|
||||
NS_NewObserverList(&topicObservers);
|
||||
mObserverTopicTable->Put(&key, topicObservers);
|
||||
}
|
||||
} else {
|
||||
NS_NewObserverList(&topicObservers);
|
||||
*anObserverList = topicObservers;
|
||||
mObserverTopicTable->Put(&key, topicObservers);
|
||||
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsObserverService::AddObserver(nsIObserver* anObserver, const PRUnichar* aTopic)
|
||||
{
|
||||
nsIObserverList* anObserverList;
|
||||
nsresult rv;
|
||||
|
||||
if (anObserver == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (aTopic == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsAutoString topic(aTopic);
|
||||
rv = GetObserverList(topic, &anObserverList);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (anObserverList) {
|
||||
return anObserverList->AddObserver(&anObserver);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsObserverService::RemoveObserver(nsIObserver* anObserver, const PRUnichar* aTopic)
|
||||
{
|
||||
nsIObserverList* anObserverList;
|
||||
nsresult rv;
|
||||
|
||||
if (anObserver == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (aTopic == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsAutoString topic(aTopic);
|
||||
rv = GetObserverList(topic, &anObserverList);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (anObserverList) {
|
||||
return anObserverList->RemoveObserver(&anObserver);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsObserverService::EnumerateObserverList(const PRUnichar* aTopic, nsIEnumerator** anEnumerator)
|
||||
{
|
||||
nsIObserverList* anObserverList;
|
||||
nsresult rv;
|
||||
|
||||
if (anEnumerator == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (aTopic == NULL)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsAutoString topic(aTopic);
|
||||
rv = GetObserverList(topic, &anObserverList);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (anObserverList) {
|
||||
return anObserverList->EnumerateObserverList(anEnumerator);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Enumerate observers of aTopic and call Observe on each.
|
||||
nsresult nsObserverService::Notify( nsISupports *aSubject,
|
||||
const PRUnichar *aTopic,
|
||||
const PRUnichar *someData ) {
|
||||
nsresult rv = NS_OK;
|
||||
nsIEnumerator *observers;
|
||||
// Get observer list enumerator.
|
||||
rv = this->EnumerateObserverList( aTopic, &observers );
|
||||
if ( NS_SUCCEEDED( rv ) ) {
|
||||
// Go to start of observer list.
|
||||
rv = observers->First();
|
||||
// Continue until error or end of list.
|
||||
while ( observers->IsDone() != NS_OK && NS_SUCCEEDED(rv) ) {
|
||||
// Get current item (observer).
|
||||
nsISupports *base;
|
||||
rv = observers->CurrentItem( &base );
|
||||
if ( NS_SUCCEEDED( rv ) ) {
|
||||
// Convert item to nsIObserver.
|
||||
nsIObserver *observer;
|
||||
rv = base->QueryInterface( nsIObserver::GetIID(), (void**)&observer );
|
||||
if ( NS_SUCCEEDED( rv ) && observer ) {
|
||||
// Tell the observer what's up.
|
||||
observer->Observe( aSubject, aTopic, someData );
|
||||
// Release the observer.
|
||||
observer->Release();
|
||||
}
|
||||
}
|
||||
// Go on to next observer in list.
|
||||
rv = observers->Next();
|
||||
}
|
||||
// Release the observer list.
|
||||
observers->Release();
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,56 +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.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.
|
||||
*/
|
||||
|
||||
#ifndef nsObserverService_h___
|
||||
#define nsObserverService_h___
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIObserverList.h"
|
||||
|
||||
class nsObjectHashtable;
|
||||
class nsString;
|
||||
|
||||
// {D07F5195-E3D1-11d2-8ACD-00105A1B8860}
|
||||
#define NS_OBSERVERSERVICE_CID \
|
||||
{ 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } }
|
||||
|
||||
class nsObserverService : public nsIObserverService {
|
||||
public:
|
||||
NS_DEFINE_STATIC_CID_ACCESSOR( NS_OBSERVERSERVICE_CID )
|
||||
|
||||
static nsresult GetObserverService(nsIObserverService** anObserverService);
|
||||
|
||||
NS_DECL_NSIOBSERVERSERVICE
|
||||
|
||||
nsObserverService();
|
||||
virtual ~nsObserverService(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
|
||||
|
||||
private:
|
||||
|
||||
NS_IMETHOD GetObserverList(const nsString& aTopic, nsIObserverList** anObserverList);
|
||||
|
||||
nsObjectHashtable* mObserverTopicTable;
|
||||
|
||||
};
|
||||
|
||||
#endif /* nsObserverService_h___ */
|
||||
@@ -1,914 +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.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.
|
||||
*/
|
||||
|
||||
#include "nsPageMgr.h"
|
||||
#include "prmem.h"
|
||||
|
||||
#if defined(XP_PC)
|
||||
#include <windows.h>
|
||||
#elif defined(XP_MAC)
|
||||
#include <stdlib.h>
|
||||
#elif defined(XP_BEOS)
|
||||
#include <fcntl.h>
|
||||
#elif defined(XP_UNIX)
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifndef MAP_FAILED
|
||||
#if defined (__STDC__) && __STDC__
|
||||
#define MAP_FAILED ((void *) -1)
|
||||
#else
|
||||
#define MAP_FAILED ((char *) -1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(VMS)
|
||||
#if defined(DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <starlet.h>
|
||||
#include <ssdef.h>
|
||||
#include <vadef.h>
|
||||
#include <va_rangedef.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#define NS_PAGEMGR_CLUSTERDESC_CLUMPSIZE 16
|
||||
|
||||
void
|
||||
nsPageMgr::DeleteFreeClusterDesc(nsClusterDesc *desc)
|
||||
{
|
||||
desc->mNext = mUnusedClusterDescs;
|
||||
mUnusedClusterDescs = desc;
|
||||
}
|
||||
|
||||
nsPageMgr::nsClusterDesc*
|
||||
nsPageMgr::NewFreeClusterDesc(void)
|
||||
{
|
||||
nsClusterDesc *desc = mUnusedClusterDescs;
|
||||
if (desc)
|
||||
mUnusedClusterDescs = desc->mNext;
|
||||
else {
|
||||
/* Allocate a clump of cluster records at once, and link all except
|
||||
the first onto the list of mUnusedClusterDescs */
|
||||
desc = (nsClusterDesc*)PR_Malloc(NS_PAGEMGR_CLUSTERDESC_CLUMPSIZE * sizeof(nsClusterDesc));
|
||||
if (desc) {
|
||||
nsClusterDesc* desc2 = desc + (NS_PAGEMGR_CLUSTERDESC_CLUMPSIZE - 1);
|
||||
while (desc2 != desc) {
|
||||
DeleteFreeClusterDesc(desc2--);
|
||||
}
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
/* Search the mFreeClusters looking for the first cluster of consecutive free
|
||||
pages that is at least size bytes long. If there is one, remove these pages
|
||||
from the free page list and return their address; if not, return nil. */
|
||||
nsPage*
|
||||
nsPageMgr::AllocClusterFromFreeList(PRUword nPages)
|
||||
{
|
||||
nsClusterDesc **p = &mFreeClusters;
|
||||
nsClusterDesc *desc;
|
||||
while ((desc = *p) != NULL) {
|
||||
if (desc->mPageCount >= nPages) {
|
||||
nsPage* addr = desc->mAddr;
|
||||
if (desc->mPageCount == nPages) {
|
||||
*p = desc->mNext;
|
||||
DeleteFreeClusterDesc(desc);
|
||||
}
|
||||
else {
|
||||
desc->mAddr += nPages;
|
||||
desc->mPageCount -= nPages;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
p = &desc->mNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add the segment to the nsClusterDesc list, coalescing it with any
|
||||
clusters already in the list when possible. */
|
||||
void
|
||||
nsPageMgr::AddClusterToFreeList(nsPage* addr, PRWord nPages)
|
||||
{
|
||||
nsClusterDesc **p = &mFreeClusters;
|
||||
nsClusterDesc *desc;
|
||||
nsClusterDesc *newDesc;
|
||||
|
||||
while ((desc = *p) != NULL) {
|
||||
if (desc->mAddr + desc->mPageCount == addr) {
|
||||
/* Coalesce with the previous cluster. */
|
||||
nsClusterDesc *next = desc->mNext;
|
||||
|
||||
desc->mPageCount += nPages;
|
||||
if (next && next->mAddr == addr + nPages) {
|
||||
/* We can coalesce with both the previous and the next cluster. */
|
||||
desc->mPageCount += next->mPageCount;
|
||||
desc->mNext = next->mNext;
|
||||
DeleteFreeClusterDesc(next);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (desc->mAddr == addr + nPages) {
|
||||
/* Coalesce with the next cluster. */
|
||||
desc->mAddr -= nPages;
|
||||
desc->mPageCount += nPages;
|
||||
return;
|
||||
}
|
||||
if (desc->mAddr > addr) {
|
||||
PR_ASSERT(desc->mAddr > addr + nPages);
|
||||
break;
|
||||
}
|
||||
PR_ASSERT(desc->mAddr + desc->mPageCount < addr);
|
||||
p = &desc->mNext;
|
||||
}
|
||||
newDesc = NewFreeClusterDesc();
|
||||
/* In the unlikely event that this malloc fails, we drop the free cluster
|
||||
on the floor. The only consequence is that the memory mapping table
|
||||
becomes slightly larger. */
|
||||
if (newDesc) {
|
||||
newDesc->mNext = desc;
|
||||
newDesc->mAddr = addr;
|
||||
newDesc->mPageCount = nPages;
|
||||
*p = newDesc;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_PAGEMGR_VERIFYCLUSTERS
|
||||
|
||||
#ifndef XP_PC
|
||||
#define OutputDebugString(x) puts(x)
|
||||
#endif
|
||||
|
||||
void
|
||||
nsPageMgr::VerifyClusters(PRWord nPagesDelta)
|
||||
{
|
||||
static PRUword expectedPagesUsed = 0;
|
||||
nsPageCount calculatedPagesUsed;
|
||||
nsPage* lastDescEnd = 0;
|
||||
nsClusterDesc* desc;
|
||||
char str[256];
|
||||
expectedPagesUsed += nPagesDelta;
|
||||
calculatedPagesUsed = mBoundary - mMemoryBase;
|
||||
sprintf(str, "[Clusters: %p", mMemoryBase);
|
||||
OutputDebugString(str);
|
||||
for (desc = mFreeClusters; desc; desc = desc->mNext) {
|
||||
PR_ASSERT(desc->mAddr > lastDescEnd);
|
||||
calculatedPagesUsed -= desc->mPageCount;
|
||||
lastDescEnd = desc->mAddr + desc->mPageCount;
|
||||
sprintf(str, "..%p, %p", desc->mAddr-1, desc->mAddr + desc->mPageCount);
|
||||
OutputDebugString(str);
|
||||
}
|
||||
sprintf(str, "..%p]\n", mBoundary);
|
||||
OutputDebugString(str);
|
||||
PR_ASSERT(lastDescEnd < mBoundary);
|
||||
PR_ASSERT(calculatedPagesUsed == expectedPagesUsed);
|
||||
}
|
||||
|
||||
#endif /* NS_PAGEMGR_VERIFYCLUSTERS */
|
||||
|
||||
/*******************************************************************************
|
||||
* Machine-dependent stuff
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(XP_PC)
|
||||
|
||||
#define GC_VMBASE 0x40000000 /* XXX move */
|
||||
#define GC_VMLIMIT 0x0FFFFFFF
|
||||
|
||||
#elif defined(XP_MAC)
|
||||
|
||||
#define NS_PAGEMGR_MAC_SEGMENT_SIZE
|
||||
#define NS_PAGEMGR_MAC_SEGMENT_COUNT
|
||||
|
||||
#endif
|
||||
|
||||
PRStatus
|
||||
nsPageMgr::InitPages(nsPageCount minPages, nsPageCount maxPages)
|
||||
{
|
||||
#if defined(XP_PC)
|
||||
|
||||
nsPage* addr = NULL;
|
||||
nsPageCount size = maxPages;
|
||||
|
||||
#ifdef NS_PAGEMGR_DEBUG
|
||||
/* first try to place the heap at a well-known address for debugging */
|
||||
addr = (nsPage*)VirtualAlloc((void*)GC_VMBASE, size << NS_PAGEMGR_PAGE_BITS,
|
||||
MEM_RESERVE, PAGE_READWRITE);
|
||||
#endif
|
||||
while (addr == NULL) {
|
||||
/* let the system place the heap */
|
||||
addr = (nsPage*)VirtualAlloc(0, size << NS_PAGEMGR_PAGE_BITS,
|
||||
MEM_RESERVE, PAGE_READWRITE);
|
||||
if (addr == NULL) {
|
||||
size--;
|
||||
if (size < minPages) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(addr, NS_PAGEMGR_PAGE_BITS));
|
||||
mMemoryBase = addr;
|
||||
mPageCount = size;
|
||||
mBoundary = addr;
|
||||
|
||||
return PR_SUCCESS;
|
||||
|
||||
#elif defined(XP_MAC)
|
||||
|
||||
OSErr err;
|
||||
void* seg;
|
||||
void* segLimit;
|
||||
Handle h;
|
||||
PRUword segSize = (minPages + 1) * NS_PAGEMGR_PAGE_SIZE;
|
||||
nsPage* firstPage;
|
||||
nsPage* lastPage;
|
||||
nsSegmentDesc* mSegTable;
|
||||
int mSegTableCount, otherCount;
|
||||
|
||||
h = TempNewHandle(segSize, &err);
|
||||
if (err || h == NULL) goto fail;
|
||||
MoveHHi(h);
|
||||
TempHLock(h, &err);
|
||||
if (err) goto fail;
|
||||
seg = *h;
|
||||
segLimit = (void*)((char*)seg + segSize);
|
||||
firstPage = NS_PAGEMGR_PAGE_ROUNDUP(seg);
|
||||
lastPage = NS_PAGEMGR_PAGE_ROUNDDN(((char*)seg + segSize));
|
||||
|
||||
/* Put the segment table in the otherwise wasted space at one
|
||||
end of the segment. We'll put it at which ever end is bigger. */
|
||||
mSegTable = (nsSegmentDesc*)seg;
|
||||
mSegTableCount = ((char*)firstPage - (char*)seg) / sizeof(nsSegmentDesc);
|
||||
otherCount = ((char*)segLimit - (char*)lastPage) / sizeof(nsSegmentDesc);
|
||||
if (otherCount > mSegTableCount) {
|
||||
mSegTable = (nsSegmentDesc*)lastPage;
|
||||
mSegTableCount = otherCount;
|
||||
}
|
||||
else if (mSegTableCount == 0) {
|
||||
mSegTable = (nsSegmentDesc*)firstPage;
|
||||
firstPage++;
|
||||
mSegTableCount = NS_PAGEMGR_PAGE_SIZE / sizeof(nsSegmentDesc);
|
||||
}
|
||||
PR_ASSERT(mSegTableCount > 0);
|
||||
mSegTable = mSegTable;
|
||||
mSegTableCount = mSegTableCount;
|
||||
|
||||
mSegTable[0].mHandle = h;
|
||||
mSegTable[0].mFirstPage = firstPage;
|
||||
mSegTable[0].mLastPage = lastPage;
|
||||
|
||||
/* XXX hack for now -- just one segment */
|
||||
mMemoryBase = firstPage;
|
||||
mBoundary = firstPage;
|
||||
mPageCount = lastPage - firstPage;
|
||||
|
||||
return PR_SUCCESS;
|
||||
|
||||
fail:
|
||||
if (h) {
|
||||
TempDisposeHandle(h, &err);
|
||||
}
|
||||
return PR_FAILURE;
|
||||
|
||||
#elif defined(XP_BEOS)
|
||||
|
||||
nsPage* addr = NULL;
|
||||
nsPageCount size = maxPages;
|
||||
|
||||
#if (1L<<NS_PAGEMGR_PAGE_BITS) != B_PAGE_SIZE
|
||||
#error can only work with 4096 byte pages
|
||||
#endif
|
||||
while(addr == NULL)
|
||||
{
|
||||
/* let the system place the heap */
|
||||
if((mAid = create_area("MozillaHeap", (void **)&addr, B_ANY_ADDRESS,
|
||||
size << NS_PAGEMGR_PAGE_BITS, B_NO_LOCK,
|
||||
B_READ_AREA | B_WRITE_AREA)) < 0)
|
||||
{
|
||||
addr = NULL;
|
||||
size--;
|
||||
if (size < minPages) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(addr, NS_PAGEMGR_PAGE_BITS));
|
||||
mMemoryBase = addr;
|
||||
mPageCount = size;
|
||||
mBoundary = addr;
|
||||
|
||||
return PR_SUCCESS;
|
||||
|
||||
#elif defined(VMS)
|
||||
|
||||
nsPage* addr = NULL;
|
||||
nsPageCount size = maxPages;
|
||||
struct _va_range retadr, retadr2;
|
||||
int status;
|
||||
|
||||
/*
|
||||
** The default is 32767 pages. This is quite a lot (the pages are 4k).
|
||||
** Let's at least make it configurable.
|
||||
*/
|
||||
|
||||
char *tmp;
|
||||
tmp = getenv("VMS_PAGE_MANAGER_SIZE");
|
||||
if (tmp)
|
||||
size=atoi(tmp);
|
||||
#if defined(DEBUG)
|
||||
printf("Requested page manager size is %d 4k pages\n",size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** $EXPREG will extend the virtual address region by the requested
|
||||
** number of pages (or pagelets on Alpha). The process must have
|
||||
** sufficient PGFLQUOTA for the operation, otherwise SS$_EXQUOTA will
|
||||
** be returned. However, in the case of SS$_EXQUOTA, $EXPREG will have
|
||||
** grown the region by the largest possible amount. In this case we will
|
||||
** put back the maximum amount and repeat the $EXPREG requesting half of
|
||||
** maximum (so as to leave some memory for others), just so long as its
|
||||
** over our minimum threshold.
|
||||
*/
|
||||
|
||||
status = sys$expreg(size << (NS_PAGEMGR_PAGE_BITS-VA$C_PAGELET_SHIFT_SIZE),
|
||||
&retadr,0,0);
|
||||
switch (status) {
|
||||
case SS$_NORMAL:
|
||||
break;
|
||||
case SS$_EXQUOTA:
|
||||
size = ( (int)retadr.va_range$ps_end_va -
|
||||
(int)retadr.va_range$ps_start_va + 1
|
||||
) >> NS_PAGEMGR_PAGE_BITS;
|
||||
status=sys$deltva(&retadr,&retadr2,0);
|
||||
size=size/2;
|
||||
if (size < minPages) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
status = sys$expreg(
|
||||
size << (NS_PAGEMGR_PAGE_BITS-VA$C_PAGELET_SHIFT_SIZE),
|
||||
&retadr,0,0);
|
||||
if (status != SS$_NORMAL) {
|
||||
status=sys$deltva(&retadr,&retadr2,0);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
size = ( (int)retadr.va_range$ps_end_va -
|
||||
(int)retadr.va_range$ps_start_va + 1
|
||||
) >> NS_PAGEMGR_PAGE_BITS;
|
||||
break;
|
||||
default:
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
printf("Actual page manager size is %d 4k pages\n",size);
|
||||
#endif
|
||||
|
||||
/* We got at least something */
|
||||
addr = (nsPage *)retadr.va_range$ps_start_va;
|
||||
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(addr, NS_PAGEMGR_PAGE_BITS));
|
||||
mMemoryBase = addr;
|
||||
mPageCount = size;
|
||||
mBoundary = addr;
|
||||
|
||||
return PR_SUCCESS;
|
||||
|
||||
#else
|
||||
|
||||
nsPage* addr = NULL;
|
||||
nsPageCount size = maxPages;
|
||||
mZero_fd = 0;
|
||||
|
||||
#ifdef HAVE_DEV_ZERO
|
||||
mZero_fd = open("/dev/zero", O_RDWR);
|
||||
while (addr == NULL) {
|
||||
/* let the system place the heap */
|
||||
addr = (nsPage*)mmap(0, size << NS_PAGEMGR_PAGE_BITS,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE,
|
||||
mZero_fd, 0);
|
||||
if (addr == (nsPage*)MAP_FAILED) {
|
||||
addr = NULL;
|
||||
size--;
|
||||
if (size < minPages) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_VALLOC
|
||||
while (addr == NULL) {
|
||||
addr = (nsPage*)valloc(size << NS_PAGEMGR_PAGE_BITS);
|
||||
if (NULL == addr) {
|
||||
size--;
|
||||
if (size < minPages) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(addr, '\0', size << NS_PAGEMGR_PAGE_BITS);
|
||||
#endif /* HAVE_VALLOC */
|
||||
#endif /* HAVE_DEV_ZERO */
|
||||
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(addr, NS_PAGEMGR_PAGE_BITS));
|
||||
mMemoryBase = addr;
|
||||
mPageCount = size;
|
||||
mBoundary = addr;
|
||||
|
||||
return PR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsPageMgr::FinalizePages()
|
||||
{
|
||||
#if defined(XP_PC)
|
||||
|
||||
BOOL ok;
|
||||
ok = VirtualFree((void*)mMemoryBase, 0, MEM_RELEASE);
|
||||
PR_ASSERT(ok);
|
||||
mMemoryBase = NULL;
|
||||
mPageCount = 0;
|
||||
nsAutoMonitor::DestroyMonitor(mMonitor);
|
||||
mMonitor = NULL;
|
||||
|
||||
#elif defined(XP_MAC)
|
||||
|
||||
OSErr err;
|
||||
PRUword i;
|
||||
for (i = 0; i < mSegTableCount; i++) {
|
||||
if (mSegTable[i].mHandle) {
|
||||
TempDisposeHandle(mSegTable[i].mHandle, &err);
|
||||
PR_ASSERT(err == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(XP_BEOS)
|
||||
|
||||
delete_area(mAid);
|
||||
|
||||
#elif defined(VMS)
|
||||
|
||||
struct _va_range retadr, retadr2;
|
||||
|
||||
retadr.va_range$ps_start_va = mMemoryBase;
|
||||
retadr.va_range$ps_end_va = mMemoryBase +
|
||||
(mPageCount << NS_PAGEMGR_PAGE_BITS) - 1;
|
||||
|
||||
sys$deltva(&retadr,&retadr2,0);
|
||||
|
||||
#else
|
||||
#ifdef HAVE_DEV_ZERO
|
||||
munmap((caddr_t)mMemoryBase, mPageCount << NS_PAGEMGR_PAGE_BITS);
|
||||
close(mZero_fd);
|
||||
#else /* HAVE_DEV_ZERO */
|
||||
#ifdef HAVE_VALLOC
|
||||
free(mMemoryBase);
|
||||
#endif /* HAVE_VALLOC */
|
||||
#endif /* HAVE_DEV_ZERO */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Page Manager
|
||||
******************************************************************************/
|
||||
|
||||
nsPageMgr::nsPageMgr()
|
||||
: mUnusedClusterDescs(nsnull),
|
||||
mFreeClusters(nsnull),
|
||||
mInUseClusters(nsnull),
|
||||
mMonitor(nsnull),
|
||||
mMemoryBase(nsnull),
|
||||
mBoundary(nsnull),
|
||||
#ifdef XP_PC
|
||||
mLastPageFreed(nsnull),
|
||||
mLastPageFreedSize(0),
|
||||
mLastPageTemp(nsnull),
|
||||
mLastPageTempSize(0),
|
||||
#ifdef NS_PAGEMGR_DEBUG
|
||||
mLastPageAllocTries(0),
|
||||
mLastPageAllocHits(0),
|
||||
mLastPageFreeTries(0),
|
||||
mLastPageFreeHits(0),
|
||||
#endif
|
||||
#endif
|
||||
#if defined(XP_MAC)
|
||||
mSegMap(nsnull),
|
||||
mSegTable(nsnull),
|
||||
mSegTableCount(0),
|
||||
#endif
|
||||
#if defined(XP_BEOS)
|
||||
mAid(B_ERROR),
|
||||
#endif
|
||||
mPageCount(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPageMgr::Init(nsPageCount minPages, nsPageCount maxPages)
|
||||
{
|
||||
PRStatus status;
|
||||
|
||||
mMonitor = nsAutoMonitor::NewMonitor("PageMgr");
|
||||
if (mMonitor == NULL)
|
||||
return PR_FAILURE;
|
||||
|
||||
status = InitPages(minPages, maxPages);
|
||||
if (status != PR_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* make sure these got set */
|
||||
PR_ASSERT(mMemoryBase);
|
||||
PR_ASSERT(mBoundary);
|
||||
|
||||
mFreeClusters = NULL;
|
||||
mInUseClusters = NULL;
|
||||
|
||||
return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsPageMgr::~nsPageMgr()
|
||||
{
|
||||
#if defined(XP_PC) && defined(NS_PAGEMGR_DEBUG)
|
||||
if (stderr) {
|
||||
fprintf(stderr, "Page Manager Cache: alloc hits: %u/%u %u%%, free hits: %u/%u %u%%\n",
|
||||
mLastPageAllocHits, mLastPageAllocTries,
|
||||
(mLastPageAllocHits * 100 / mLastPageAllocTries),
|
||||
mLastPageFreeHits, mLastPageFreeTries,
|
||||
(mLastPageFreeHits * 100 / mLastPageFreeTries));
|
||||
}
|
||||
#endif
|
||||
FinalizePages();
|
||||
|
||||
nsClusterDesc* chain = mUnusedClusterDescs;
|
||||
while (chain) {
|
||||
nsClusterDesc* desc = chain;
|
||||
chain = chain->mNext;
|
||||
PR_Free(desc);
|
||||
}
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsPageMgr::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
nsPageMgr* pageMgr = new nsPageMgr();
|
||||
if (pageMgr == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(pageMgr);
|
||||
nsresult rv = pageMgr->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(pageMgr);
|
||||
return rv;
|
||||
}
|
||||
rv = pageMgr->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(pageMgr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsPageMgr, nsIPageManager, nsIAllocator)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#ifdef XP_PC
|
||||
|
||||
#ifdef NS_PAGEMGR_PAGE_HYSTERESIS
|
||||
|
||||
#ifdef NS_PAGEMGR_DEBUG
|
||||
|
||||
void*
|
||||
nsPageMgr::NS_PAGEMGR_COMMIT_CLUSTER(void* addr, PRUword size)
|
||||
{
|
||||
mLastPageAllocTries++;
|
||||
if (mLastPageFreed == (void*)(addr) && mLastPageFreedSize == (size)) {
|
||||
#ifdef NS_PAGEMGR_COMMIT_TRACE
|
||||
char buf[64];
|
||||
PR_snprintf(buf, sizeof(buf), "lalloc %p %u\n",
|
||||
mLastPageFreed, mLastPageFreedSize);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
DBG_MEMSET(mLastPageFreed, NS_PAGEMGR_PAGE_ALLOC_PATTERN, mLastPageFreedSize);
|
||||
mLastPageTemp = mLastPageFreed;
|
||||
mLastPageFreed = NULL;
|
||||
mLastPageFreedSize = 0;
|
||||
mLastPageAllocHits++;
|
||||
return mLastPageTemp;
|
||||
}
|
||||
else {
|
||||
/* If the cached pages intersect the current request, we lose.
|
||||
Just free the cached request instead of trying to split it up. */
|
||||
if (mLastPageFreed &&
|
||||
nsOverlapping((char*)mLastPageFreed, ((char*)mLastPageFreed + mLastPageFreedSize),
|
||||
(char*)(addr), ((char*)(addr) + (size)))
|
||||
// ((char*)mLastPageFreed < ((char*)(addr) + (size))
|
||||
// && ((char*)mLastPageFreed + mLastPageFreedSize) > (char*)(addr))
|
||||
) {
|
||||
#ifdef NS_PAGEMGR_COMMIT_TRACE
|
||||
char buf[64];
|
||||
PR_snprintf(buf, sizeof(buf), "valloc %p %u (vfree %p %u last=%u:%u req=%u:%u)\n",
|
||||
addr, size,
|
||||
mLastPageFreed, mLastPageFreedSize,
|
||||
(char*)mLastPageFreed, ((char*)mLastPageFreed + mLastPageFreedSize),
|
||||
(char*)(addr), ((char*)(addr) + (size)));
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
VirtualFree(mLastPageFreed, mLastPageFreedSize, MEM_DECOMMIT);
|
||||
mLastPageFreed = NULL;
|
||||
mLastPageFreedSize = 0;
|
||||
mLastPageFreeHits--; /* lost after all */
|
||||
}
|
||||
else {
|
||||
#ifdef NS_PAGEMGR_COMMIT_TRACE
|
||||
char buf[64];
|
||||
PR_snprintf(buf, sizeof(buf), "valloc %p %u (skipping %p %u)\n",
|
||||
addr, size,
|
||||
mLastPageFreed, mLastPageFreedSize);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
}
|
||||
return VirtualAlloc((void*)(addr), (size), MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nsPageMgr::NS_PAGEMGR_DECOMMIT_CLUSTER(void* addr, PRUword size)
|
||||
{
|
||||
mLastPageFreeTries++;
|
||||
PR_ASSERT(mLastPageFreed != (void*)(addr));
|
||||
if (mLastPageFreed) {
|
||||
/* If we've already got a cached page, just keep it. Heuristically,
|
||||
this tends to give us a higher hit rate because of the order in
|
||||
which pages are decommitted. */
|
||||
#ifdef NS_PAGEMGR_COMMIT_TRACE
|
||||
char buf[64];
|
||||
PR_snprintf(buf, sizeof(buf), "vfree %p %u (cached %p %u)\n",
|
||||
addr, size, mLastPageFreed, mLastPageFreedSize);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
return VirtualFree(addr, size, MEM_DECOMMIT);
|
||||
}
|
||||
mLastPageFreed = (void*)(addr);
|
||||
mLastPageFreedSize = (size);
|
||||
DBG_MEMSET(mLastPageFreed, NS_PAGEMGR_PAGE_FREE_PATTERN, mLastPageFreedSize);
|
||||
#ifdef NS_PAGEMGR_COMMIT_TRACE
|
||||
{
|
||||
char buf[64];
|
||||
PR_snprintf(buf, sizeof(buf), "lfree %p %u\n",
|
||||
mLastPageFreed, mLastPageFreedSize);
|
||||
OutputDebugString(buf);
|
||||
}
|
||||
#endif
|
||||
mLastPageFreeHits++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* !NS_PAGEMGR_DEBUG */
|
||||
|
||||
#define NS_PAGEMGR_COMMIT_CLUSTER(addr, size) \
|
||||
(PR_ASSERT((void*)(addr) != NULL), \
|
||||
((mLastPageFreed == (void*)(addr) && mLastPageFreedSize == (size)) \
|
||||
? (DBG_MEMSET(mLastPageFreed, NS_PAGEMGR_PAGE_ALLOC_PATTERN, mLastPageFreedSize), \
|
||||
mLastPageTemp = mLastPageFreed, \
|
||||
mLastPageFreed = NULL, \
|
||||
mLastPageFreedSize = 0, \
|
||||
mLastPageTemp) \
|
||||
: (((mLastPageFreed && \
|
||||
((char*)mLastPageFreed < ((char*)(addr) + (size)) \
|
||||
&& ((char*)mLastPageFreed + mLastPageFreedSize) > (char*)(addr))) \
|
||||
? (VirtualFree(mLastPageFreed, mLastPageFreedSize, MEM_DECOMMIT), \
|
||||
mLastPageFreed = NULL, \
|
||||
mLastPageFreedSize = 0) \
|
||||
: ((void)0)), \
|
||||
VirtualAlloc((void*)(addr), (size), MEM_COMMIT, PAGE_READWRITE)))) \
|
||||
|
||||
#define NS_PAGEMGR_DECOMMIT_CLUSTER(addr, size) \
|
||||
(PR_ASSERT(mLastPageFreed != (void*)(addr)), \
|
||||
(mLastPageFreed \
|
||||
? (VirtualFree(addr, size, MEM_DECOMMIT)) \
|
||||
: (mLastPageFreed = (addr), \
|
||||
mLastPageFreedSize = (size), \
|
||||
DBG_MEMSET(mLastPageFreed, NS_PAGEMGR_PAGE_FREE_PATTERN, mLastPageFreedSize), \
|
||||
1))) \
|
||||
|
||||
#endif /* !NS_PAGEMGR_DEBUG */
|
||||
|
||||
#else /* !NS_PAGEMGR_PAGE_HYSTERESIS */
|
||||
|
||||
#define NS_PAGEMGR_COMMIT_CLUSTER(addr, size) \
|
||||
VirtualAlloc((void*)(addr), (size), MEM_COMMIT, PAGE_READWRITE)
|
||||
|
||||
#define NS_PAGEMGR_DECOMMIT_CLUSTER(addr, size) \
|
||||
VirtualFree((void*)(addr), (size), MEM_DECOMMIT)
|
||||
|
||||
#endif /* !NS_PAGEMGR_PAGE_HYSTERESIS */
|
||||
|
||||
#else /* !XP_PC */
|
||||
|
||||
#define NS_PAGEMGR_COMMIT_CLUSTER(addr, size) (addr)
|
||||
#define NS_PAGEMGR_DECOMMIT_CLUSTER(addr, size) 1
|
||||
|
||||
#endif /* !XP_PC */
|
||||
|
||||
nsPage*
|
||||
nsPageMgr::NewCluster(nsPageCount nPages)
|
||||
{
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
|
||||
nsPage* addr;
|
||||
PR_ASSERT(nPages > 0);
|
||||
addr = AllocClusterFromFreeList(nPages);
|
||||
if (!addr && mBoundary + nPages <= mMemoryBase + mPageCount) {
|
||||
addr = mBoundary;
|
||||
mBoundary += nPages;
|
||||
}
|
||||
if (addr) {
|
||||
/* Extend the mapping */
|
||||
nsPage* vaddr;
|
||||
PRUword size = nPages << NS_PAGEMGR_PAGE_BITS;
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(addr, NS_PAGEMGR_PAGE_BITS));
|
||||
vaddr = (nsPage*)NS_PAGEMGR_COMMIT_CLUSTER((void*)addr, size);
|
||||
#ifdef NS_PAGEMGR_VERIFYCLUSTERS
|
||||
VerifyClusters(nPages);
|
||||
#endif
|
||||
if (addr) {
|
||||
PR_ASSERT(vaddr == addr);
|
||||
}
|
||||
else {
|
||||
DestroyCluster(addr, nPages);
|
||||
}
|
||||
DBG_MEMSET(addr, NS_PAGEMGR_PAGE_ALLOC_PATTERN, size);
|
||||
}
|
||||
return (nsPage*)addr;
|
||||
}
|
||||
|
||||
void
|
||||
nsPageMgr::DestroyCluster(nsPage* basePage, nsPageCount nPages)
|
||||
{
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
|
||||
int freeResult;
|
||||
PRUword size = nPages << NS_PAGEMGR_PAGE_BITS;
|
||||
|
||||
PR_ASSERT(nPages > 0);
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(basePage, NS_PAGEMGR_PAGE_BITS));
|
||||
PR_ASSERT(mMemoryBase <= basePage);
|
||||
PR_ASSERT(basePage + nPages <= mMemoryBase + mPageCount);
|
||||
DBG_MEMSET(basePage, NS_PAGEMGR_PAGE_FREE_PATTERN, size);
|
||||
freeResult = NS_PAGEMGR_DECOMMIT_CLUSTER((void*)basePage, size);
|
||||
PR_ASSERT(freeResult);
|
||||
if (basePage + nPages == mBoundary) {
|
||||
nsClusterDesc **p;
|
||||
nsClusterDesc *desc;
|
||||
/* We deallocated the last set of clusters. Move the mBoundary lower. */
|
||||
mBoundary = basePage;
|
||||
/* The last free cluster might now be adjacent to the mBoundary; if so,
|
||||
move the mBoundary before that cluster and delete that cluster
|
||||
altogether. */
|
||||
p = &mFreeClusters;
|
||||
while ((desc = *p) != NULL) {
|
||||
if (!desc->mNext && desc->mAddr + desc->mPageCount == mBoundary) {
|
||||
*p = 0;
|
||||
mBoundary = desc->mAddr;
|
||||
DeleteFreeClusterDesc(desc);
|
||||
}
|
||||
else {
|
||||
p = &desc->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
AddClusterToFreeList(basePage, nPages);
|
||||
}
|
||||
#ifdef NS_PAGEMGR_VERIFYCLUSTERS
|
||||
VerifyClusters(-(PRWord)nPages);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIPageManager methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPageMgr::AllocPages(PRUint32 pageCount, void* *result)
|
||||
{
|
||||
nsPage* page = NewCluster(NS_STATIC_CAST(nsPageCount, pageCount));
|
||||
if (page == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
*result = page;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPageMgr::DeallocPages(PRUint32 pageCount, void* pages)
|
||||
{
|
||||
DestroyCluster(NS_STATIC_CAST(nsPage*, pages),
|
||||
NS_STATIC_CAST(nsPageCount, pageCount));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAllocator methods:
|
||||
//
|
||||
// Note: nsIAllocator needs to keep track of the size of the blocks it allocates
|
||||
// whereas, nsIPageManager doesn't. That means that there's a little extra
|
||||
// overhead for users of this interface. It also means that things allocated
|
||||
// with the nsIPageManager interface can't be freed with the nsIAllocator
|
||||
// interface and vice versa.
|
||||
|
||||
NS_IMETHODIMP_(void*)
|
||||
nsPageMgr::Alloc(PRUint32 size)
|
||||
{
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
|
||||
nsresult rv;
|
||||
void* page = nsnull;
|
||||
PRUint32 pageCount = NS_PAGEMGR_PAGE_COUNT(size);
|
||||
|
||||
rv = AllocPages(pageCount, &page);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
// Add this cluster to the mInUseClusters list:
|
||||
nsClusterDesc* desc = NewFreeClusterDesc();
|
||||
if (desc == nsnull) {
|
||||
rv = DeallocPages(pageCount, page);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "DeallocPages failed");
|
||||
return nsnull;
|
||||
}
|
||||
desc->mAddr = (nsPage*)page;
|
||||
desc->mPageCount = pageCount;
|
||||
desc->mNext = mInUseClusters;
|
||||
mInUseClusters = desc;
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void*)
|
||||
nsPageMgr::Realloc(void* ptr, PRUint32 size)
|
||||
{
|
||||
// XXX This realloc implementation could be made smarter by trying to
|
||||
// append to the current block, but I don't think we really care right now.
|
||||
nsresult rv;
|
||||
rv = Free(ptr);
|
||||
if (NS_FAILED(rv)) return nsnull;
|
||||
void* newPtr = Alloc(size);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPageMgr::Free(void* ptr)
|
||||
{
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
|
||||
PR_ASSERT(NS_PAGEMGR_IS_ALIGNED(ptr, NS_PAGEMGR_PAGE_BITS));
|
||||
|
||||
// Remove the cluster from the mInUseClusters list:
|
||||
nsClusterDesc** list = &mInUseClusters;
|
||||
nsClusterDesc* desc;
|
||||
while ((desc = *list) != nsnull) {
|
||||
if (desc->mAddr == ptr) {
|
||||
// found -- unlink the desc and free it
|
||||
*list = desc->mNext;
|
||||
nsresult rv = DeallocPages(desc->mPageCount, ptr);
|
||||
DeleteFreeClusterDesc(desc);
|
||||
return rv;
|
||||
}
|
||||
list = &desc->mNext;
|
||||
}
|
||||
NS_ASSERTION(0, "memory not allocated with nsPageMgr::Alloc");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPageMgr::HeapMinimize(void)
|
||||
{
|
||||
// can't compact this heap
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user