Compare commits
1 Commits
CVS
...
tags/Last1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
973a54719f |
@@ -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___ */
|
||||
|
||||
5
mozilla/js/src/liveconnect/MANIFEST
Normal file
5
mozilla/js/src/liveconnect/MANIFEST
Normal file
@@ -0,0 +1,5 @@
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
jsjava.h
|
||||
nsILiveconnect.h
|
||||
89
mozilla/js/src/liveconnect/Makefile
Normal file
89
mozilla/js/src/liveconnect/Makefile
Normal file
@@ -0,0 +1,89 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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 = ../../..
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
ifdef NSJVM
|
||||
DIRS = classes
|
||||
endif
|
||||
|
||||
MODULE = java
|
||||
LIBRARY_NAME = jsj
|
||||
|
||||
REQUIRES = java js applet nspr img util layer xpcom
|
||||
|
||||
CSRCS = jsj.c \
|
||||
jsj_JSObject.c \
|
||||
jsj_JavaArray.c \
|
||||
jsj_JavaClass.c \
|
||||
jsj_JavaMember.c \
|
||||
jsj_JavaObject.c \
|
||||
jsj_JavaPackage.c \
|
||||
jsj_array.c \
|
||||
jsj_class.c \
|
||||
jsj_convert.c \
|
||||
jsj_field.c \
|
||||
jsj_hash.c \
|
||||
jsj_method.c \
|
||||
jsj_utils.c \
|
||||
nsCLiveconnect.c \
|
||||
nsCLiveconnectFactory.c
|
||||
|
||||
|
||||
LLIBS=$(LIBNSPR) $(DIST)/lib/js$(MOZ_BITS)$(VERSION_NUMBER).lib \
|
||||
$(DIST)/lib/xpcom32.lib
|
||||
|
||||
|
||||
ifdef NSJVM
|
||||
JNI_GEN = netscape.javascript.JSObject netscape.javascript.JSException
|
||||
endif
|
||||
|
||||
EXPORTS = jsjava.h \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSObject.h \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSException.h \
|
||||
nsILiveconnect.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
######################################################################
|
||||
|
||||
# Generate jsj_nodl.c (so that you can check it in)
|
||||
# These make rules only works on IRIX...sigh
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
jsj_nodl.c: $(OBJDIR)/stubs.o Makefile $(DEPTH)/config/nodl.pl
|
||||
rm -f $@
|
||||
$(PERL) $(DEPTH)/config/nodl.pl "jsj_nodl_tab" \
|
||||
`nm -Bn $(OBJDIR)/stubs.o | egrep Java_.*_stub | awk '{print $$3;}'` > $@
|
||||
endif
|
||||
|
||||
ifdef JAVA_OR_OJI
|
||||
$(OBJDIR)/stubs.o: \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSObject.c \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSException.c \
|
||||
$(NULL)
|
||||
else
|
||||
$(OBJDIR)/stubs.o:
|
||||
endif
|
||||
|
||||
90
mozilla/js/src/liveconnect/Makefile.in
Normal file
90
mozilla/js/src/liveconnect/Makefile.in
Normal file
@@ -0,0 +1,90 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
ifdef NSJVM
|
||||
DIRS = classes
|
||||
endif
|
||||
|
||||
|
||||
MODULE = java
|
||||
LIBRARY_NAME = jsj
|
||||
|
||||
REQUIRES = java js applet nspr img util layer xpcom caps oji plugin
|
||||
|
||||
CSRCS = jsj.c \
|
||||
jsj_JSObject.c \
|
||||
jsj_JavaArray.c \
|
||||
jsj_JavaClass.c \
|
||||
jsj_JavaMember.c \
|
||||
jsj_JavaObject.c \
|
||||
jsj_JavaPackage.c \
|
||||
jsj_array.c \
|
||||
jsj_class.c \
|
||||
jsj_convert.c \
|
||||
jsj_field.c \
|
||||
jsj_hash.c \
|
||||
jsj_method.c \
|
||||
jsj_utils.c
|
||||
nsCLiveconnect.c \
|
||||
nsCLiveconnectFactory.c
|
||||
|
||||
|
||||
ifdef NSJVM
|
||||
JNI_GEN = netscape.javascript.JSObject netscape.javascript.JSException
|
||||
endif
|
||||
|
||||
EXPORTS = $(srcdir)/jsjava.h \
|
||||
$(srcdir)/$(JNI_GEN_DIR)/netscape_javascript_JSObject.h \
|
||||
$(srcdir)/$(JNI_GEN_DIR)/netscape_javascript_JSException.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
######################################################################
|
||||
|
||||
# Generate jsj_nodl.c (so that you can check it in)
|
||||
# These make rules only works on IRIX...sigh
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
jsj_nodl.c: $(OBJDIR)/stubs.o Makefile $(topsrcdir)/config/nodl.pl
|
||||
rm -f $@
|
||||
$(PERL) $(topsrcdir)/config/nodl.pl "jsj_nodl_tab" \
|
||||
`nm -Bn $(OBJDIR)/stubs.o | egrep Java_.*_stub | awk '{print $$3;}'` > $@
|
||||
endif
|
||||
|
||||
ifdef JAVA_OR_OJI
|
||||
$(OBJDIR)/stubs.o: \
|
||||
$(JRI_GEN_DIR)/netscape_javascript_JSObject.c \
|
||||
$(JRI_GEN_DIR)/netscape_javascript_JSException.c \
|
||||
$(NULL)
|
||||
else
|
||||
$(OBJDIR)/stubs.o:
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include "jni.h"
|
||||
|
||||
/* Header for class netscape_javascript_JSException */
|
||||
|
||||
#ifndef _Included_netscape_javascript_JSException
|
||||
#define _Included_netscape_javascript_JSException
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
102
mozilla/js/src/liveconnect/_jni/netscape_javascript_JSObject.h
Normal file
102
mozilla/js/src/liveconnect/_jni/netscape_javascript_JSObject.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include "jni.h"
|
||||
|
||||
/* Header for class netscape_javascript_JSObject */
|
||||
|
||||
#ifndef _Included_netscape_javascript_JSObject
|
||||
#define _Included_netscape_javascript_JSObject
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: initClass
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getMember
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getSlot
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot
|
||||
(JNIEnv *, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setMember
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember
|
||||
(JNIEnv *, jobject, jstring, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setSlot
|
||||
* Signature: (ILjava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot
|
||||
(JNIEnv *, jobject, jint, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: removeMember
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: call
|
||||
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call
|
||||
(JNIEnv *, jobject, jstring, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: eval
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: toString
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getWindow
|
||||
* Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: finalize
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
65
mozilla/js/src/liveconnect/classes/Makefile
Normal file
65
mozilla/js/src/liveconnect/classes/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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 = java
|
||||
|
||||
#
|
||||
# the idea is that the install phase for those modules will
|
||||
# make their own signed jar files
|
||||
# there are some exceptions here that we deal with
|
||||
# stuff in modules and in ns/js/jsj
|
||||
#
|
||||
JMODS = netscape/javascript netscape/javascript/adapters
|
||||
|
||||
#
|
||||
# JDIRS is dependant on JAVA_DESTPATH in config/rules.m[a]k.
|
||||
# Be sure to touch that directory if you add a new directory to
|
||||
# JDIRS, or else it will not build. FIXME
|
||||
#
|
||||
JDIRS = $(JMODS)
|
||||
|
||||
JAR_JSJ = jsj10.jar
|
||||
JAR_JSJ_CLASSES = $(JMODS)
|
||||
|
||||
#
|
||||
# jars to build at install time
|
||||
#
|
||||
JARS = $(JAR_JSJ)
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
JAVA_SOURCEPATH = $(DEPTH)/js/src/liveconnect/classes
|
||||
|
||||
doc::
|
||||
$(JAVADOC) -d $(DIST)/doc netscape.javascript
|
||||
|
||||
natives_list:: FORCE
|
||||
rm -rf $@
|
||||
find . -name "*.class" -print | sed 's@\./\(.*\)\.class$$@\1@' | \
|
||||
sed 's@/@.@g' | xargs $(JVH) -natives | sort > $@
|
||||
|
||||
check_natives:: natives_list
|
||||
rm -f found_natives
|
||||
nm -B ../$(OBJDIR)/*.o \
|
||||
| egrep "Java.*_stub" | awk '{ print $$3; }' | sort > found_natives
|
||||
diff found_natives natives_list
|
||||
|
||||
FORCE:
|
||||
70
mozilla/js/src/liveconnect/classes/Makefile.in
Normal file
70
mozilla/js/src/liveconnect/classes/Makefile.in
Normal file
@@ -0,0 +1,70 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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 = java
|
||||
|
||||
#
|
||||
# the idea is that the install phase for those modules will
|
||||
# make their own signed jar files
|
||||
# there are some exceptions here that we deal with
|
||||
# stuff in modules and in ns/js/jsj
|
||||
#
|
||||
JMODS = netscape/javascript netscape/javascript/adapters
|
||||
|
||||
#
|
||||
# JDIRS is dependant on JAVA_DESTPATH in config/rules.m[a]k.
|
||||
# Be sure to touch that directory if you add a new directory to
|
||||
# JDIRS, or else it will not build. FIXME
|
||||
#
|
||||
JDIRS = $(JMODS)
|
||||
|
||||
JAR_JSJ = jsj10.jar
|
||||
JAR_JSJ_CLASSES = $(JMODS)
|
||||
|
||||
#
|
||||
# jars to build at install time
|
||||
#
|
||||
JARS = $(JAR_JSJ)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
JAVA_SOURCEPATH = $(topsrcdir)/js/src/liveconnect/classes
|
||||
|
||||
doc::
|
||||
$(JAVADOC) -d $(DIST)/doc netscape.javascript
|
||||
|
||||
natives_list:: FORCE
|
||||
rm -rf $@
|
||||
find . -name "*.class" -print | sed 's@\./\(.*\)\.class$$@\1@' | \
|
||||
sed 's@/@.@g' | xargs $(JVH) -natives | sort > $@
|
||||
|
||||
check_natives:: natives_list
|
||||
rm -f found_natives
|
||||
nm -B ../$(OBJDIR)/*.o \
|
||||
| egrep "Java.*_stub" | awk '{ print $$3; }' | sort > found_natives
|
||||
diff found_natives natives_list
|
||||
|
||||
FORCE:
|
||||
78
mozilla/js/src/liveconnect/classes/makefile.win
Normal file
78
mozilla/js/src/liveconnect/classes/makefile.win
Normal file
@@ -0,0 +1,78 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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.
|
||||
|
||||
IGNORE_MANIFEST=1
|
||||
#
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Makefile to build the JavaScript-Java tree
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
DEPTH = ..\..\..\..
|
||||
|
||||
JAVA_SOURCEPATH=$(DEPTH)\js\src\liveconnect\classes
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define the files necessary to build the target (ie. OBJS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
JMOZ = \
|
||||
netscape/javascript \
|
||||
$(NULL)
|
||||
|
||||
|
||||
all::
|
||||
|
||||
MODULE=java
|
||||
JMODS=netscape/javascript
|
||||
!ifdef JAVA_OR_NSJVM
|
||||
JDIRS=$(JMODS)
|
||||
JAR_JSJ_CLASSES=$(JMODS)
|
||||
JAR_NAME = jsj10.jar
|
||||
!endif
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
!ifdef JAVA_OR_NSJVM
|
||||
install::
|
||||
cd $(JAVA_DESTPATH)
|
||||
@echo +++ building/updating $(JAR_NAME)
|
||||
-for %i in ($(JAR_JSJ_CLASSES:/=\)) do @$(ZIP_PROG) $(ZIP_FLAGS) $(JAR_NAME) %i\*.class
|
||||
cd $(MAKEDIR)
|
||||
|
||||
!ifdef REGENERATE
|
||||
install::
|
||||
cd $(JAVA_DESTPATH)
|
||||
@echo +++ updating $(DEPTH)\nav-java\stubs\classes\$(JAR_NAME) for checkin
|
||||
-for %i in ($(JAR_JSJ_CLASSES:/=\)) do @$(ZIP_PROG) $(ZIP_FLAGS) ..\..\nav-java\stubs\classes\$(JAR_NAME) %i\*.class
|
||||
cd $(MAKEDIR)
|
||||
!endif
|
||||
!endif
|
||||
|
||||
javadoc:
|
||||
-mkdir $(XPDIST)\javadoc 2> NUL
|
||||
echo $(JAVADOC) -sourcepath . -d $(XPDIST)\javadoc $(JDIRS:/=.)
|
||||
$(JAVADOC) -sourcepath . -d $(XPDIST)\javadoc $(JDIRS:/=.)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Insert copyright and license here 19** */
|
||||
|
||||
package netscape.javascript;
|
||||
|
||||
/**
|
||||
* JSException is an exception which is thrown when JavaScript code
|
||||
* returns an error.
|
||||
*/
|
||||
|
||||
public
|
||||
class JSException extends Exception {
|
||||
String filename;
|
||||
int lineno;
|
||||
String source;
|
||||
int tokenIndex;
|
||||
|
||||
/**
|
||||
* Constructs a JSException without a detail message.
|
||||
* A detail message is a String that describes this particular exception.
|
||||
*/
|
||||
public JSException() {
|
||||
super();
|
||||
filename = "unknown";
|
||||
lineno = 0;
|
||||
source = "";
|
||||
tokenIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSException with a detail message.
|
||||
* A detail message is a String that describes this particular exception.
|
||||
* @param s the detail message
|
||||
*/
|
||||
public JSException(String s) {
|
||||
super(s);
|
||||
filename = "unknown";
|
||||
lineno = 0;
|
||||
source = "";
|
||||
tokenIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSException with a detail message and all the
|
||||
* other info that usually comes with a JavaScript error.
|
||||
* @param s the detail message
|
||||
*/
|
||||
public JSException(String s, String filename, int lineno,
|
||||
String source, int tokenIndex) {
|
||||
super(s);
|
||||
this.filename = filename;
|
||||
this.lineno = lineno;
|
||||
this.source = source;
|
||||
this.tokenIndex = tokenIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/* -*- Mode: C; tab-width: 4; -*- */
|
||||
|
||||
/* Insert copyright and license here 19** */
|
||||
|
||||
/* more doc todo:
|
||||
* threads
|
||||
* gc
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package netscape.javascript;
|
||||
|
||||
import java.applet.Applet;
|
||||
|
||||
/**
|
||||
* JSObject allows Java to manipulate objects that are
|
||||
* defined in JavaScript.
|
||||
* Values passed from Java to JavaScript are converted as
|
||||
* follows:<ul>
|
||||
* <li>JSObject is converted to the original JavaScript object
|
||||
* <li>Any other Java object is converted to a JavaScript wrapper,
|
||||
* which can be used to access methods and fields of the java object.
|
||||
* Converting this wrapper to a string will call the toString method
|
||||
* on the original object, converting to a number will call the
|
||||
* floatValue method if possible and fail otherwise. Converting
|
||||
* to a boolean will try to call the booleanValue method in the
|
||||
* same way.
|
||||
* <li>Java arrays are wrapped with a JavaScript object that understands
|
||||
* array.length and array[index]
|
||||
* <li>A Java boolean is converted to a JavaScript boolean
|
||||
* <li>Java byte, char, short, int, long, float, and double are converted
|
||||
* to JavaScript numbers
|
||||
* </ul>
|
||||
* Values passed from JavaScript to Java are converted as follows:<ul>
|
||||
* <li>objects which are wrappers around java objects are unwrapped
|
||||
* <li>other objects are wrapped with a JSObject
|
||||
* <li>strings, numbers and booleans are converted to String, Float,
|
||||
* and Boolean objects respectively
|
||||
* </ul>
|
||||
* This means that all JavaScript values show up as some kind
|
||||
* of java.lang.Object in Java. In order to make much use of them,
|
||||
* you will have to cast them to the appropriate subclass of Object,
|
||||
* e.g. <code>(String) window.getMember("name");</code> or
|
||||
* <code>(JSObject) window.getMember("document");</code>.
|
||||
*/
|
||||
public final class JSObject {
|
||||
/* the internal object data */
|
||||
private int internal;
|
||||
|
||||
/**
|
||||
* initialize
|
||||
*/
|
||||
private static native void initClass();
|
||||
static {
|
||||
// On MRJ, this property won't exist, because the library is preloaded.
|
||||
String liveConnectLibrary = System.getProperty("netscape.jsj.dll", null);
|
||||
if (liveConnectLibrary != null) {
|
||||
System.loadLibrary(liveConnectLibrary);
|
||||
initClass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* it is illegal to construct a JSObject manually
|
||||
*/
|
||||
private JSObject(int jsobj_addr) {
|
||||
internal = jsobj_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a named member of a JavaScript object.
|
||||
* Equivalent to "this.<i>name</i>" in JavaScript.
|
||||
*/
|
||||
public native Object getMember(String name);
|
||||
|
||||
/**
|
||||
* Retrieves an indexed member of a JavaScript object.
|
||||
* Equivalent to "this[<i>index</i>]" in JavaScript.
|
||||
*/
|
||||
// public Object getMember(int index) { return getSlot(index); }
|
||||
public native Object getSlot(int index);
|
||||
|
||||
/**
|
||||
* Sets a named member of a JavaScript object.
|
||||
* Equivalent to "this.<i>name</i> = <i>value</i>" in JavaScript.
|
||||
*/
|
||||
public native void setMember(String name, Object value);
|
||||
|
||||
/**
|
||||
* Sets an indexed member of a JavaScript object.
|
||||
* Equivalent to "this[<i>index</i>] = <i>value</i>" in JavaScript.
|
||||
*/
|
||||
// public void setMember(int index, Object value) {
|
||||
// setSlot(index, value);
|
||||
// }
|
||||
public native void setSlot(int index, Object value);
|
||||
|
||||
/**
|
||||
* Removes a named member of a JavaScript object.
|
||||
*/
|
||||
public native void removeMember(String name);
|
||||
|
||||
/**
|
||||
* Calls a JavaScript method.
|
||||
* Equivalent to "this.<i>methodName</i>(<i>args</i>[0], <i>args</i>[1], ...)" in JavaScript.
|
||||
*/
|
||||
public native Object call(String methodName, Object args[]);
|
||||
|
||||
/**
|
||||
* Evaluates a JavaScript expression. The expression is a string
|
||||
* of JavaScript source code which will be evaluated in the context
|
||||
* given by "this".
|
||||
*/
|
||||
public native Object eval(String s);
|
||||
|
||||
/**
|
||||
* Converts a JSObject to a String.
|
||||
*/
|
||||
public native String toString();
|
||||
|
||||
// should use some sort of identifier rather than String
|
||||
// is "property" the right word?
|
||||
// native String[] listProperties();
|
||||
|
||||
|
||||
/**
|
||||
* get a JSObject for the window containing the given applet
|
||||
*/
|
||||
public static native JSObject getWindow(Applet applet);
|
||||
|
||||
/**
|
||||
* Finalization decrements the reference count on the corresponding
|
||||
* JavaScript object.
|
||||
*/
|
||||
protected native void finalize();
|
||||
|
||||
/**
|
||||
* Override java.lang.Object.equals() because identity is not preserved
|
||||
* with instances of JSObject.
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
JSObject jsobj;
|
||||
|
||||
if (!(obj instanceof JSObject))
|
||||
return false;
|
||||
jsobj = (JSObject)obj;
|
||||
return (internal == jsobj.internal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: Java; 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.
|
||||
*/
|
||||
/* ** */
|
||||
/**
|
||||
* The JSProxy interface allows applets and plugins to
|
||||
* share javascript contexts.
|
||||
*/
|
||||
|
||||
package netscape.javascript;
|
||||
import java.applet.Applet;
|
||||
|
||||
public interface JSProxy {
|
||||
Object getMember(JSObject jso, String name);
|
||||
Object getSlot(JSObject jso, int index);
|
||||
void setMember(JSObject jso, String name, Object value);
|
||||
void setSlot(JSObject jso, int index, Object value);
|
||||
void removeMember(JSObject jso, String name);
|
||||
Object call(JSObject jso, String methodName, Object args[]);
|
||||
Object eval(JSObject jso, String s);
|
||||
String toString(JSObject jso);
|
||||
JSObject getWindow(Applet applet);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package netscape.javascript;
|
||||
|
||||
/**
|
||||
* Runs a JavaScript object with a run() method in a separate thread.
|
||||
*/
|
||||
public class JSRunnable implements Runnable {
|
||||
private JSObject runnable;
|
||||
|
||||
public JSRunnable(JSObject runnable) {
|
||||
this.runnable = runnable;
|
||||
synchronized(this) {
|
||||
new Thread(this).start();
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
runnable.call("run", null);
|
||||
synchronized(this) {
|
||||
notifyAll();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.err.println(t);
|
||||
t.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: Java; 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
|
||||
@@ -15,13 +15,24 @@
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/* ** */
|
||||
|
||||
#include "nsIEnumerator.idl"
|
||||
package netscape.javascript;
|
||||
import java.io.*;
|
||||
|
||||
interface nsIFile;
|
||||
public class JSUtil {
|
||||
|
||||
[scriptable, uuid(D7BEA930-59D7-11d3-8C46-00609792278C)]
|
||||
interface nsIDirectoryEnumerator : nsISimpleEnumerator
|
||||
{
|
||||
void Init(in nsIFile parent, in boolean resolveSymlinks);
|
||||
};
|
||||
/* Return the stack trace of an exception or error as a String */
|
||||
public static String getStackTrace(Throwable t) {
|
||||
ByteArrayOutputStream captureStream;
|
||||
PrintStream p;
|
||||
|
||||
captureStream = new ByteArrayOutputStream();
|
||||
p = new PrintStream(captureStream);
|
||||
|
||||
t.printStackTrace(p);
|
||||
p.flush();
|
||||
|
||||
return captureStream.toString();
|
||||
}
|
||||
}
|
||||
876
mozilla/js/src/liveconnect/jsj.c
Normal file
876
mozilla/js/src/liveconnect/jsj.c
Normal file
@@ -0,0 +1,876 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the top-level initialization code and the implementation of the
|
||||
* public API.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsjava.h" /* LiveConnect external API */
|
||||
|
||||
/*
|
||||
* At certain times during initialization, there may be no JavaScript context
|
||||
* available to direct error reports to, in which case the error messages
|
||||
* are sent to this function. The caller is responsible for free'ing
|
||||
* the js_error_msg argument.
|
||||
*/
|
||||
static void
|
||||
report_java_initialization_error(JNIEnv *jEnv, const char *js_error_msg)
|
||||
{
|
||||
const char *error_msg, *java_error_msg;
|
||||
|
||||
java_error_msg = NULL;
|
||||
#if 0 /* This can never work here, because jsj_GetJavaErrorMessage relies on
|
||||
jlThrowable_toString which is set up by the initialization that calls
|
||||
this function. */
|
||||
if (jEnv) {
|
||||
java_error_msg = jsj_GetJavaErrorMessage(jEnv);
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
}
|
||||
#endif
|
||||
if (java_error_msg) {
|
||||
error_msg = PR_smprintf("initialization error: %s (%s)\n",
|
||||
js_error_msg, java_error_msg);
|
||||
free((void*)java_error_msg);
|
||||
} else {
|
||||
error_msg = PR_smprintf("initialization error: %s\n",
|
||||
js_error_msg);
|
||||
}
|
||||
|
||||
jsj_LogError(error_msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Opaque JVM handles to Java classes and methods required for Java reflection.
|
||||
* These are computed and cached during initialization.
|
||||
*/
|
||||
|
||||
jclass jlObject; /* java.lang.Object */
|
||||
jclass jlrMethod; /* java.lang.reflect.Method */
|
||||
jclass jlrField; /* java.lang.reflect.Field */
|
||||
jclass jlVoid; /* java.lang.Void */
|
||||
jclass jlrConstructor; /* java.lang.reflect.Constructor */
|
||||
jclass jlThrowable; /* java.lang.Throwable */
|
||||
jclass jlSystem; /* java.lang.System */
|
||||
jclass jlClass; /* java.lang.Class */
|
||||
jclass jlBoolean; /* java.lang.Boolean */
|
||||
jclass jlDouble; /* java.lang.Double */
|
||||
jclass jlString; /* java.lang.String */
|
||||
jclass njJSObject; /* netscape.javascript.JSObject */
|
||||
jclass njJSException; /* netscape.javascript.JSException */
|
||||
jclass njJSUtil; /* netscape.javascript.JSUtil */
|
||||
|
||||
jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */
|
||||
jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */
|
||||
jmethodID jlClass_getFields; /* java.lang.Class.getFields() */
|
||||
jmethodID jlClass_getName; /* java.lang.Class.getName() */
|
||||
jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */
|
||||
jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */
|
||||
jmethodID jlClass_isArray; /* java.lang.Class.isArray() */
|
||||
|
||||
jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */
|
||||
jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */
|
||||
jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */
|
||||
jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */
|
||||
|
||||
jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */
|
||||
jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */
|
||||
|
||||
jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */
|
||||
jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */
|
||||
jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */
|
||||
|
||||
jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */
|
||||
jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */
|
||||
jmethodID jlDouble_Double; /* java.lang.Double constructor */
|
||||
jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */
|
||||
|
||||
jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */
|
||||
jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */
|
||||
|
||||
jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */
|
||||
|
||||
jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */
|
||||
|
||||
jmethodID njJSException_JSException; /* netscape.javascript.JSexception constructor */
|
||||
jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */
|
||||
jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */
|
||||
jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */
|
||||
jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */
|
||||
jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */
|
||||
jfieldID njJSException_source; /* netscape.javascript.JSException.source */
|
||||
jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */
|
||||
|
||||
/* Obtain a reference to a Java class */
|
||||
#define LOAD_CLASS(qualified_name, class) \
|
||||
{ \
|
||||
jclass _##class = (*jEnv)->FindClass(jEnv, #qualified_name); \
|
||||
if (_##class == 0) { \
|
||||
(*jEnv)->ExceptionClear(jEnv); \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't load class " #qualified_name); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
class = (*jEnv)->NewGlobalRef(jEnv, _##class); \
|
||||
}
|
||||
|
||||
/* Obtain a methodID reference to a Java method or constructor */
|
||||
#define _LOAD_METHOD(qualified_class, method, mvar, signature, class, is_static)\
|
||||
if (is_static) { \
|
||||
class##_##mvar = \
|
||||
(*jEnv)->GetStaticMethodID(jEnv, class, #method, signature); \
|
||||
} else { \
|
||||
class##_##mvar = \
|
||||
(*jEnv)->GetMethodID(jEnv, class, #method, signature); \
|
||||
} \
|
||||
if (class##_##mvar == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't get mid for " #qualified_class "." #method "()"); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
/* Obtain a methodID reference to a Java instance method */
|
||||
#define LOAD_METHOD(qualified_class, method, signature, class) \
|
||||
_LOAD_METHOD(qualified_class, method, method, signature, class, JS_FALSE)
|
||||
|
||||
/* Obtain a methodID reference to a Java static method */
|
||||
#define LOAD_STATIC_METHOD(qualified_class, method, signature, class) \
|
||||
_LOAD_METHOD(qualified_class, method, method, signature, class, JS_TRUE)
|
||||
|
||||
/* Obtain a methodID reference to a Java constructor */
|
||||
#define LOAD_CONSTRUCTOR(qualified_class, method, signature, class) \
|
||||
_LOAD_METHOD(qualified_class,<init>, method, signature, class, JS_FALSE)
|
||||
|
||||
/* Obtain a fieldID reference to a Java instance or static field */
|
||||
#define _LOAD_FIELDID(qualified_class, field, signature, class, is_static) \
|
||||
if (is_static) { \
|
||||
class##_##field = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\
|
||||
} else { \
|
||||
class##_##field = (*jEnv)->GetFieldID(jEnv, class, #field, signature);\
|
||||
} \
|
||||
if (class##_##field == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't get fid for " #qualified_class "." #field); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
/* Obtain a fieldID reference to a Java instance field */
|
||||
#define LOAD_FIELDID(qualified_class, field, signature, class) \
|
||||
_LOAD_FIELDID(qualified_class, field, signature, class, JS_FALSE)
|
||||
|
||||
/* Obtain the value of a static field in a Java class */
|
||||
#define LOAD_FIELD_VAL(qualified_class, field, signature, class, type) \
|
||||
{ \
|
||||
jfieldID field_id; \
|
||||
field_id = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\
|
||||
if (field_id == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't get fid for " #qualified_class "." #field); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
class##_##field = \
|
||||
(*jEnv)->GetStatic##type##Field(jEnv, class, field_id); \
|
||||
if (class##_##field == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't read static field " #qualified_class "." #field); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Obtain the value of a static field in a Java class, which is known to
|
||||
contain an object value. */
|
||||
#define LOAD_FIELD_OBJ(qualified_class, field, signature, class) \
|
||||
LOAD_FIELD_VAL(qualified_class, field, signature, class, Object); \
|
||||
class##_##field = (*jEnv)->NewGlobalRef(jEnv, class##_##field);
|
||||
|
||||
/*
|
||||
* Load the Java classes, and the method and field descriptors required for Java reflection.
|
||||
* Returns JS_TRUE on success, JS_FALSE on failure.
|
||||
*/
|
||||
static JSBool
|
||||
init_java_VM_reflection(JSJavaVM *jsjava_vm, JNIEnv *jEnv)
|
||||
{
|
||||
/* Load Java system classes and method, including java.lang.reflect classes */
|
||||
LOAD_CLASS(java/lang/Object, jlObject);
|
||||
LOAD_CLASS(java/lang/Class, jlClass);
|
||||
LOAD_CLASS(java/lang/reflect/Method, jlrMethod);
|
||||
LOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor);
|
||||
LOAD_CLASS(java/lang/reflect/Field, jlrField);
|
||||
LOAD_CLASS(java/lang/Throwable, jlThrowable);
|
||||
LOAD_CLASS(java/lang/System, jlSystem);
|
||||
LOAD_CLASS(java/lang/Boolean, jlBoolean);
|
||||
LOAD_CLASS(java/lang/Double, jlDouble);
|
||||
LOAD_CLASS(java/lang/String, jlString);
|
||||
LOAD_CLASS(java/lang/Void, jlVoid);
|
||||
|
||||
LOAD_METHOD(java.lang.Class, getMethods, "()[Ljava/lang/reflect/Method;",jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getConstructors, "()[Ljava/lang/reflect/Constructor;",jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getFields, "()[Ljava/lang/reflect/Field;", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getName, "()Ljava/lang/String;", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, isArray, "()Z", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getComponentType, "()Ljava/lang/Class;", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getModifiers, "()I", jlClass);
|
||||
|
||||
LOAD_METHOD(java.lang.reflect.Method, getName, "()Ljava/lang/String;", jlrMethod);
|
||||
LOAD_METHOD(java.lang.reflect.Method, getParameterTypes, "()[Ljava/lang/Class;", jlrMethod);
|
||||
LOAD_METHOD(java.lang.reflect.Method, getReturnType, "()Ljava/lang/Class;", jlrMethod);
|
||||
LOAD_METHOD(java.lang.reflect.Method, getModifiers, "()I", jlrMethod);
|
||||
|
||||
LOAD_METHOD(java.lang.reflect.Constructor, getParameterTypes, "()[Ljava/lang/Class;", jlrConstructor);
|
||||
LOAD_METHOD(java.lang.reflect.Constructor, getModifiers, "()I", jlrConstructor);
|
||||
|
||||
LOAD_METHOD(java.lang.reflect.Field, getName, "()Ljava/lang/String;", jlrField);
|
||||
LOAD_METHOD(java.lang.reflect.Field, getType, "()Ljava/lang/Class;", jlrField);
|
||||
LOAD_METHOD(java.lang.reflect.Field, getModifiers, "()I", jlrField);
|
||||
|
||||
LOAD_METHOD(java.lang.Throwable, toString, "()Ljava/lang/String;", jlThrowable);
|
||||
LOAD_METHOD(java.lang.Throwable, getMessage, "()Ljava/lang/String;", jlThrowable);
|
||||
|
||||
LOAD_METHOD(java.lang.Double, doubleValue, "()D", jlDouble);
|
||||
|
||||
LOAD_METHOD(java.lang.Boolean, booleanValue, "()Z", jlBoolean);
|
||||
|
||||
LOAD_STATIC_METHOD(java.lang.System, identityHashCode, "(Ljava/lang/Object;)I", jlSystem);
|
||||
|
||||
LOAD_CONSTRUCTOR(java.lang.Boolean, Boolean, "(Z)V", jlBoolean);
|
||||
LOAD_CONSTRUCTOR(java.lang.Double, Double, "(D)V", jlDouble);
|
||||
|
||||
LOAD_FIELD_OBJ(java.lang.Void, TYPE, "Ljava/lang/Class;", jlVoid);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if XP_MAC
|
||||
|
||||
/**
|
||||
* Workaround for the fact that MRJ loads a different instance of the shared library.
|
||||
*/
|
||||
|
||||
#include "netscape_javascript_JSObject.h"
|
||||
|
||||
static JSObject_RegisterNativeMethods(JNIEnv* jEnv)
|
||||
{
|
||||
// Manually load the required native methods.
|
||||
static JNINativeMethod nativeMethods[] = {
|
||||
"initClass", "()V", (void*)&Java_netscape_javascript_JSObject_initClass,
|
||||
"getMember", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getMember,
|
||||
"getSlot", "(I)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getSlot,
|
||||
"setMember", "(Ljava/lang/String;Ljava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setMember,
|
||||
"setSlot", "(ILjava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setSlot,
|
||||
"removeMember", "(Ljava/lang/String;)V", (void*)&Java_netscape_javascript_JSObject_removeMember,
|
||||
"call", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_call,
|
||||
"eval", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_eval,
|
||||
|
||||
"toString", "()Ljava/lang/String;", (void*)&Java_netscape_javascript_JSObject_toString,
|
||||
"getWindow", "(Ljava/applet/Applet;)Lnetscape/javascript/JSObject;", (void*)&Java_netscape_javascript_JSObject_getWindow,
|
||||
"finalize", "()V", (void*)&Java_netscape_javascript_JSObject_finalize,
|
||||
/* "equals", "(Ljava/lang/Object;)Z", (void*)&Java_netscape_javascript_JSObject_equals */
|
||||
};
|
||||
(*jEnv)->RegisterNatives(jEnv, njJSObject, nativeMethods, sizeof(nativeMethods) / sizeof(JNINativeMethod));
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
report_java_initialization_error(jEnv, "Couldn't initialize JSObject native methods.");
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
}
|
||||
/* call the initClass method, since we nailed the static initializer for testing. */
|
||||
Java_netscape_javascript_JSObject_initClass(jEnv, njJSObject);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Load Netscape-specific Java extension classes, methods, and fields */
|
||||
static JSBool
|
||||
init_netscape_java_classes(JSJavaVM *jsjava_vm, JNIEnv *jEnv)
|
||||
{
|
||||
LOAD_CLASS(netscape/javascript/JSObject, njJSObject);
|
||||
LOAD_CLASS(netscape/javascript/JSException, njJSException);
|
||||
LOAD_CLASS(netscape/javascript/JSUtil, njJSUtil);
|
||||
|
||||
#if XP_MAC
|
||||
JSObject_RegisterNativeMethods(jEnv);
|
||||
#endif
|
||||
|
||||
LOAD_CONSTRUCTOR(netscape.javascript.JSObject,
|
||||
JSObject, "(I)V", njJSObject);
|
||||
LOAD_CONSTRUCTOR(netscape.javascript.JSException,
|
||||
JSException, "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V",
|
||||
njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSObject,
|
||||
internal, "I", njJSObject);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
lineno, "I", njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
tokenIndex, "I", njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
source, "Ljava/lang/String;", njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
filename, "Ljava/lang/String;", njJSException);
|
||||
|
||||
LOAD_STATIC_METHOD(netscape.javascript.JSUtil,
|
||||
getStackTrace, "(Ljava/lang/Throwable;)Ljava/lang/String;",
|
||||
njJSUtil);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSJavaVM *jsjava_vm_list = NULL;
|
||||
|
||||
/*
|
||||
* Called once per Java VM, this function initializes the classes, fields, and
|
||||
* methods required for Java reflection. If java_vm is NULL, a new Java VM is
|
||||
* created, using the provided classpath in addition to any default classpath.
|
||||
* The classpath argument is ignored, however, if java_vm_arg is non-NULL.
|
||||
*/
|
||||
JSJavaVM *
|
||||
JSJ_ConnectToJavaVM(SystemJavaVM *java_vm_arg, void* initargs)
|
||||
{
|
||||
SystemJavaVM* java_vm;
|
||||
JSJavaVM *jsjava_vm;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
PR_ASSERT(JSJ_callbacks);
|
||||
PR_ASSERT(JSJ_callbacks->attach_current_thread);
|
||||
PR_ASSERT(JSJ_callbacks->detach_current_thread);
|
||||
PR_ASSERT(JSJ_callbacks->get_java_vm);
|
||||
|
||||
jsjava_vm = (JSJavaVM*)malloc(sizeof(JSJavaVM));
|
||||
if (!jsjava_vm)
|
||||
return NULL;
|
||||
memset(jsjava_vm, 0, sizeof(JSJavaVM));
|
||||
|
||||
java_vm = java_vm_arg;
|
||||
|
||||
/* If a Java VM was passed in, try to attach to it on the current thread. */
|
||||
if (java_vm) {
|
||||
jEnv = JSJ_callbacks->attach_current_thread(java_vm);
|
||||
if (jEnv == NULL) {
|
||||
jsj_LogError("Failed to attach to Java VM thread\n");
|
||||
free(jsjava_vm);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PRBool ok;
|
||||
PR_ASSERT(JSJ_callbacks->create_java_vm);
|
||||
PR_ASSERT(JSJ_callbacks->destroy_java_vm);
|
||||
|
||||
ok = JSJ_callbacks->create_java_vm(&java_vm, &jEnv, initargs);
|
||||
if (!ok || java_vm == NULL) {
|
||||
jsj_LogError("Failed to create Java VM\n");
|
||||
free(jsjava_vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remember that we created the VM so that we know to destroy it later */
|
||||
jsjava_vm->jsj_created_java_vm = JS_TRUE;
|
||||
}
|
||||
|
||||
jsjava_vm->java_vm = java_vm;
|
||||
jsjava_vm->main_thread_env = jEnv;
|
||||
|
||||
/* Load the Java classes, and the method and field descriptors required for
|
||||
Java reflection. */
|
||||
if (!init_java_VM_reflection(jsjava_vm, jEnv)) {
|
||||
JSJ_DisconnectFromJavaVM(jsjava_vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* JVM initialization for netscape.javascript.JSObject is performed
|
||||
* independently of the other classes that are initialized in
|
||||
* init_java_VM_reflection, because we allow it to fail. In the case
|
||||
* of failure, LiveConnect is still operative, but only when calling
|
||||
* from JS to Java and not vice-versa.
|
||||
*/
|
||||
init_netscape_java_classes(jsjava_vm, jEnv);
|
||||
|
||||
/* Put this VM on the list of all created VMs */
|
||||
jsjava_vm->next = jsjava_vm_list;
|
||||
jsjava_vm_list = jsjava_vm;
|
||||
|
||||
return jsjava_vm;
|
||||
}
|
||||
|
||||
JSJCallbacks *JSJ_callbacks = NULL;
|
||||
|
||||
/* Called once to set up callbacks for all instances of LiveConnect */
|
||||
void
|
||||
JSJ_Init(JSJCallbacks *callbacks)
|
||||
{
|
||||
PR_ASSERT(callbacks);
|
||||
JSJ_callbacks = callbacks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
* reflection and by defining JavaPackage objects for the default Java packages
|
||||
* as properties of global_obj. Additional packages may be pre-defined by
|
||||
* setting the predefined_packages argument. (Pre-defining a Java package at
|
||||
* initialization time is not necessary, but it will make package lookup faster
|
||||
* and, more importantly, will avoid unnecessary network accesses if classes
|
||||
* are being loaded over the network.)
|
||||
*/
|
||||
JSBool
|
||||
JSJ_InitJSContext(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *predefined_packages)
|
||||
{
|
||||
/* Initialize the JavaScript classes used for reflection */
|
||||
if (!jsj_init_JavaObject(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
/* if (!jsj_init_JavaMember(cx, global_obj))
|
||||
return JS_FALSE; */
|
||||
|
||||
if (!jsj_init_JavaPackage(cx, global_obj, predefined_packages))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!jsj_init_JavaClass(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!jsj_init_JavaArray(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!jsj_init_JavaMember(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Eliminate a reference to a Java class */
|
||||
#define UNLOAD_CLASS(qualified_name, class) \
|
||||
if (class) { \
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, class); \
|
||||
class = NULL; \
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine severs the connection to a Java VM, freeing all related resources.
|
||||
* It shouldn't be called until the global scope has been cleared in all related
|
||||
* JSContexts (so that all LiveConnect objects are finalized) and a JavaScript
|
||||
* GC is performed. Otherwise, accessed to free'ed memory could result.
|
||||
*/
|
||||
void
|
||||
JSJ_DisconnectFromJavaVM(JSJavaVM *jsjava_vm)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
SystemJavaVM *java_vm;
|
||||
JSJavaVM *j, **jp;
|
||||
|
||||
java_vm = jsjava_vm->java_vm;
|
||||
jEnv = jsjava_vm->main_thread_env;
|
||||
|
||||
/* Drop all references to Java objects and classes */
|
||||
jsj_DiscardJavaObjReflections(jEnv);
|
||||
jsj_DiscardJavaClassReflections(jEnv);
|
||||
|
||||
if (jsjava_vm->jsj_created_java_vm) {
|
||||
(void)JSJ_callbacks->destroy_java_vm(java_vm, jEnv);
|
||||
} else {
|
||||
UNLOAD_CLASS(java/lang/Object, jlObject);
|
||||
UNLOAD_CLASS(java/lang/Class, jlClass);
|
||||
UNLOAD_CLASS(java/lang/reflect/Method, jlrMethod);
|
||||
UNLOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor);
|
||||
UNLOAD_CLASS(java/lang/reflect/Field, jlrField);
|
||||
UNLOAD_CLASS(java/lang/Throwable, jlThrowable);
|
||||
UNLOAD_CLASS(java/lang/System, jlSystem);
|
||||
UNLOAD_CLASS(java/lang/Boolean, jlBoolean);
|
||||
UNLOAD_CLASS(java/lang/Double, jlDouble);
|
||||
UNLOAD_CLASS(java/lang/String, jlString);
|
||||
UNLOAD_CLASS(java/lang/Void, jlVoid);
|
||||
UNLOAD_CLASS(netscape/javascript/JSObject, njJSObject);
|
||||
UNLOAD_CLASS(netscape/javascript/JSException, njJSException);
|
||||
UNLOAD_CLASS(netscape/javascript/JSUtil, njJSUtil);
|
||||
}
|
||||
|
||||
|
||||
/* Remove this VM from the list of all JSJavaVM objects. */
|
||||
for (jp = &jsjava_vm_list; (j = *jp) != NULL; jp = &j->next) {
|
||||
if (j == jsjava_vm) {
|
||||
*jp = jsjava_vm->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PR_ASSERT(j);
|
||||
|
||||
free(jsjava_vm);
|
||||
}
|
||||
|
||||
static JSJavaThreadState *thread_list = NULL;
|
||||
|
||||
static JSJavaThreadState *
|
||||
new_jsjava_thread_state(JSJavaVM *jsjava_vm, const char *thread_name, JNIEnv *jEnv)
|
||||
{
|
||||
JSJavaThreadState *jsj_env;
|
||||
|
||||
jsj_env = (JSJavaThreadState *)malloc(sizeof(JSJavaThreadState));
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
memset(jsj_env, 0, sizeof(JSJavaThreadState));
|
||||
|
||||
jsj_env->jEnv = jEnv;
|
||||
jsj_env->jsjava_vm = jsjava_vm;
|
||||
if (thread_name)
|
||||
jsj_env->name = strdup(thread_name);
|
||||
|
||||
/* THREADSAFETY - need to protect against races */
|
||||
jsj_env->next = thread_list;
|
||||
thread_list = jsj_env;
|
||||
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
static JSJavaThreadState *
|
||||
find_jsjava_thread(JNIEnv *jEnv)
|
||||
{
|
||||
JSJavaThreadState *e, **p, *jsj_env;
|
||||
jsj_env = NULL;
|
||||
|
||||
/* THREADSAFETY - need to protect against races in manipulating the thread list */
|
||||
|
||||
/* Search for the thread state among the list of all created
|
||||
LiveConnect threads */
|
||||
for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) {
|
||||
if (e->jEnv == jEnv) {
|
||||
jsj_env = e;
|
||||
*p = jsj_env->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move a found thread to head of list for faster search next time. */
|
||||
if (jsj_env)
|
||||
thread_list = jsj_env;
|
||||
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJavaThreadState *)
|
||||
JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *name, JNIEnv **java_envp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
SystemJavaVM *java_vm;
|
||||
JSJavaThreadState *jsj_env;
|
||||
|
||||
/* Try to attach a Java thread to the current native thread */
|
||||
java_vm = jsjava_vm->java_vm;
|
||||
jEnv = JSJ_callbacks->attach_current_thread(java_vm);
|
||||
if (jEnv == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If we found an existing thread state, just return it. */
|
||||
jsj_env = find_jsjava_thread(jEnv);
|
||||
if (jsj_env)
|
||||
return jsj_env;
|
||||
|
||||
/* Create a new wrapper around the thread/VM state */
|
||||
jsj_env = new_jsjava_thread_state(jsjava_vm, name, jEnv);
|
||||
|
||||
if (java_envp)
|
||||
*java_envp = jEnv;
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
static JSJavaVM *
|
||||
map_java_vm_to_jsjava_vm(SystemJavaVM *java_vm)
|
||||
{
|
||||
JSJavaVM *v;
|
||||
for (v = jsjava_vm_list; v; v = v->next) {
|
||||
if (v->java_vm == java_vm)
|
||||
return v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unfortunately, there's no standard means to associate any private data with
|
||||
* a JNI thread environment, so we need to use the Java environment pointer as
|
||||
* the key in a lookup table that maps it to a JSJavaThreadState structure,
|
||||
* where we store all our per-thread private data. If no existing thread state
|
||||
* is found, a new one is created.
|
||||
*
|
||||
* If an error occurs, returns NULL and sets the errp argument to an error
|
||||
* message, which the caller is responsible for free'ing.
|
||||
*/
|
||||
JSJavaThreadState *
|
||||
jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp)
|
||||
{
|
||||
JSJavaThreadState *jsj_env;
|
||||
SystemJavaVM *java_vm;
|
||||
JSJavaVM *jsjava_vm;
|
||||
|
||||
/* If we found an existing thread state, just return it. */
|
||||
jsj_env = find_jsjava_thread(jEnv);
|
||||
if (jsj_env)
|
||||
return jsj_env;
|
||||
|
||||
/* No one set up a LiveConnect thread state for a given Java thread.
|
||||
Invoke the callback to create one on-the-fly. */
|
||||
|
||||
/* First, figure out which Java VM is calling us */
|
||||
java_vm = JSJ_callbacks->get_java_vm(jEnv);
|
||||
if (jsjava_vm == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Get our private JavaVM data */
|
||||
jsjava_vm = map_java_vm_to_jsjava_vm(java_vm);
|
||||
if (!jsjava_vm) {
|
||||
*errp = PR_smprintf("Total weirdness: No JSJavaVM wrapper ever created "
|
||||
"for JavaVM 0x%08x", java_vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsj_env = new_jsjava_thread_state(jsjava_vm, NULL, jEnv);
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to specify a particular JSContext as *the* JavaScript
|
||||
* execution environment to be used when LiveConnect is accessed from the given
|
||||
* Java thread, i.e. by using one of the methods of netscape.javascript.JSObject.
|
||||
* (There can only be one such JS context for a given Java thread. To
|
||||
* multiplex JSContexts among a single thread, this function must be called
|
||||
* before Java is invoked on that thread.) The return value is the previous
|
||||
* context associated with the given Java thread.
|
||||
*/
|
||||
PR_IMPLEMENT(JSContext *)
|
||||
JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env)
|
||||
{
|
||||
JSContext *old_context;
|
||||
old_context = jsj_env->cx;
|
||||
jsj_env->cx = cx;
|
||||
return old_context;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env)
|
||||
{
|
||||
SystemJavaVM *java_vm;
|
||||
JNIEnv* jEnv;
|
||||
JSJavaThreadState *e, **p;
|
||||
|
||||
/* Disassociate the current native thread from its corresponding Java thread */
|
||||
java_vm = jsj_env->jsjava_vm->java_vm;
|
||||
jEnv = jsj_env->jEnv;
|
||||
if (!JSJ_callbacks->detach_current_thread(java_vm, jEnv))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Destroy the LiveConnect execution environment passed in */
|
||||
jsj_ClearPendingJSErrors(jsj_env);
|
||||
|
||||
/* THREADSAFETY - need to protect against races */
|
||||
for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) {
|
||||
if (e == jsj_env) {
|
||||
*p = jsj_env->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(jsj_env);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, vp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifndef MOZILLA_CLIENT
|
||||
|
||||
/* The convenience functions below present a complete, but simplified
|
||||
LiveConnect API which is designed to handle the special case of a single
|
||||
Java-VM, single-threaded operation, and use of only one JSContext. */
|
||||
|
||||
/* We can get away with global variables in our single-threaded,
|
||||
single-JSContext case. */
|
||||
static JSJavaVM * the_jsj_vm = NULL;
|
||||
static JSContext * the_cx = NULL;
|
||||
static JSJavaThreadState * the_jsj_thread = NULL;
|
||||
static JSObject * the_global_js_obj = NULL;
|
||||
|
||||
/* Trivial implementation of callback function */
|
||||
static JSJavaThreadState *
|
||||
default_map_js_context_to_jsj_thread(JSContext *cx, char **errp)
|
||||
{
|
||||
return the_jsj_thread;
|
||||
}
|
||||
|
||||
/* Trivial implementation of callback function */
|
||||
static JSContext *
|
||||
default_map_jsj_thread_to_js_context(JSJavaThreadState *jsj_env, JNIEnv *jEnv, char **errp)
|
||||
{
|
||||
return the_cx;
|
||||
}
|
||||
|
||||
/* Trivial implementation of callback function */
|
||||
static JSObject *
|
||||
default_map_java_object_to_js_object(JNIEnv *jEnv, jobject hint, char **errp)
|
||||
{
|
||||
return the_global_js_obj;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
default_create_java_vm(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs)
|
||||
{
|
||||
jint err;
|
||||
const char* user_classpath = (const char*)initargs;
|
||||
|
||||
/* No Java VM supplied, so create our own */
|
||||
JDK1_1InitArgs vm_args;
|
||||
|
||||
/* Magic constant indicates JRE version 1.1 */
|
||||
vm_args.version = 0x00010001;
|
||||
JNI_GetDefaultJavaVMInitArgs(&vm_args);
|
||||
|
||||
/* Prepend the classpath argument to the default JVM classpath */
|
||||
if (user_classpath) {
|
||||
#ifdef XP_UNIX
|
||||
const char *full_classpath = PR_smprintf("%s:%s", user_classpath, vm_args.classpath);
|
||||
#else
|
||||
const char *full_classpath = PR_smprintf("%s;%s", user_classpath, vm_args.classpath);
|
||||
#endif
|
||||
if (!full_classpath) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
vm_args.classpath = (char*)full_classpath;
|
||||
}
|
||||
|
||||
err = JNI_CreateJavaVM((JavaVM**)jvm, initialEnv, &vm_args);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
default_destroy_java_vm(SystemJavaVM* jvm, JNIEnv* initialEnv)
|
||||
{
|
||||
JavaVM* java_vm = (JavaVM*)jvm;
|
||||
jint err = (*java_vm)->DestroyJavaVM(java_vm);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
static JNIEnv* PR_CALLBACK
|
||||
default_attach_current_thread(SystemJavaVM* jvm)
|
||||
{
|
||||
JavaVM* java_vm = (JavaVM*)jvm;
|
||||
JNIEnv* env = NULL;
|
||||
jint err = (*java_vm)->AttachCurrentThread(java_vm, &env, NULL);
|
||||
return env;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
default_detach_current_thread(SystemJavaVM* jvm, JNIEnv* env)
|
||||
{
|
||||
JavaVM* java_vm = (JavaVM*)jvm;
|
||||
/* assert that env is the JNIEnv of the current thread */
|
||||
jint err = (*java_vm)->DetachCurrentThread(java_vm);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
static SystemJavaVM* PR_CALLBACK
|
||||
default_get_java_vm(JNIEnv* env)
|
||||
{
|
||||
JavaVM* java_vm = NULL;
|
||||
jint err = (*env)->GetJavaVM(env, &java_vm);
|
||||
return (SystemJavaVM*)java_vm;
|
||||
}
|
||||
|
||||
/* Trivial implementations of callback functions */
|
||||
JSJCallbacks jsj_default_callbacks = {
|
||||
default_map_jsj_thread_to_js_context,
|
||||
default_map_js_context_to_jsj_thread,
|
||||
default_map_java_object_to_js_object,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
default_create_java_vm,
|
||||
default_destroy_java_vm,
|
||||
default_attach_current_thread,
|
||||
default_detach_current_thread,
|
||||
default_get_java_vm
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
* reflection and by defining JavaPackage objects for the default Java packages
|
||||
* as properties of global_obj. If java_vm is NULL, a new Java VM is
|
||||
* created, using the provided classpath in addition to any default classpath.
|
||||
* The classpath argument is ignored, however, if java_vm is non-NULL.
|
||||
*/
|
||||
JSBool
|
||||
JSJ_SimpleInit(JSContext *cx, JSObject *global_obj, SystemJavaVM *java_vm, const char *classpath)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
|
||||
PR_ASSERT(!the_jsj_vm);
|
||||
the_jsj_vm = JSJ_ConnectToJavaVM(java_vm, (void*)classpath);
|
||||
if (!the_jsj_vm)
|
||||
return JS_FALSE;
|
||||
|
||||
JSJ_Init(&jsj_default_callbacks);
|
||||
|
||||
if (!JSJ_InitJSContext(cx, global_obj, NULL))
|
||||
goto error;
|
||||
the_cx = cx;
|
||||
the_global_js_obj = global_obj;
|
||||
|
||||
the_jsj_thread = JSJ_AttachCurrentThreadToJava(the_jsj_vm, "main thread", &jEnv);
|
||||
if (!the_jsj_thread)
|
||||
goto error;
|
||||
JSJ_SetDefaultJSContextForJavaThread(cx, the_jsj_thread);
|
||||
return JS_TRUE;
|
||||
|
||||
error:
|
||||
JSJ_SimpleShutdown();
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up all LiveConnect resources. Destroy the Java VM if it was
|
||||
* created by LiveConnect.
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_SimpleShutdown()
|
||||
{
|
||||
PR_ASSERT(the_jsj_vm);
|
||||
JSJ_DisconnectFromJavaVM(the_jsj_vm);
|
||||
the_jsj_vm = NULL;
|
||||
the_cx = NULL;
|
||||
the_global_js_obj = NULL;
|
||||
the_jsj_thread = NULL;
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_CLIENT */
|
||||
76
mozilla/js/src/liveconnect/jsj1640.rc
Normal file
76
mozilla/js/src/liveconnect/jsj1640.rc
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
// Version stamp for this .DLL
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ver.h>
|
||||
|
||||
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
|
||||
FILEVERSION 4 // major, minor, release (alpha 1), build #
|
||||
|
||||
PRODUCTVERSION 4
|
||||
|
||||
FILEFLAGSMASK 0
|
||||
|
||||
FILEFLAGS 0 // final version
|
||||
|
||||
FILEOS VOS_DOS_WINDOWS16
|
||||
|
||||
FILETYPE VFT_DLL
|
||||
|
||||
FILESUBTYPE 0 // not used
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "StringFileInfo"
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
|
||||
|
||||
BEGIN
|
||||
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
|
||||
VALUE "FileDescription", "Netscape 16-bit JavaScript-Java Module\0"
|
||||
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
|
||||
VALUE "InternalName", "JSJ1640\0"
|
||||
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
|
||||
VALUE "OriginalFilename","JSJ1640.DLL\0"
|
||||
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
1243
mozilla/js/src/liveconnect/jsj_JSObject.c
Normal file
1243
mozilla/js/src/liveconnect/jsj_JSObject.c
Normal file
File diff suppressed because it is too large
Load Diff
403
mozilla/js/src/liveconnect/jsj_JavaArray.c
Normal file
403
mozilla/js/src/liveconnect/jsj_JavaArray.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the definition of the JavaScript JavaArray class.
|
||||
* Instances of JavaArray are used to reflect Java arrays.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/* Shorthands for ASCII (7-bit) decimal and hex conversion. */
|
||||
#define JS7_ISDEC(c) (((c) >= '0') && ((c) <= '9'))
|
||||
#define JS7_UNDEC(c) ((c) - '0')
|
||||
|
||||
/*
|
||||
* Convert any jsval v to an integer jsval if ToString(v)
|
||||
* contains a base-10 integer that fits into 31 bits.
|
||||
* Otherwise return v.
|
||||
*/
|
||||
static jsval
|
||||
try_convert_to_jsint(JSContext *cx, jsval idval)
|
||||
{
|
||||
const jschar *cp;
|
||||
JSString *jsstr;
|
||||
|
||||
jsstr = JS_ValueToString(cx, idval);
|
||||
if (!jsstr)
|
||||
return idval;
|
||||
|
||||
cp = JS_GetStringChars(jsstr);
|
||||
if (JS7_ISDEC(*cp)) {
|
||||
jsuint index = JS7_UNDEC(*cp++);
|
||||
jsuint oldIndex = 0;
|
||||
jsuint c = 0;
|
||||
if (index != 0) {
|
||||
while (JS7_ISDEC(*cp)) {
|
||||
oldIndex = index;
|
||||
c = JS7_UNDEC(*cp);
|
||||
index = 10*index + c;
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
if (*cp == 0 &&
|
||||
(oldIndex < (JSVAL_INT_MAX / 10) ||
|
||||
(oldIndex == (JSVAL_INT_MAX / 10) && c < (JSVAL_INT_MAX % 10)))) {
|
||||
return INT_TO_JSVAL(index);
|
||||
}
|
||||
}
|
||||
return idval;
|
||||
}
|
||||
|
||||
|
||||
static JSBool
|
||||
access_java_array_element(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JSObject *obj,
|
||||
jsid id,
|
||||
jsval *vp,
|
||||
JSBool do_assignment)
|
||||
{
|
||||
jsval idval;
|
||||
jarray java_array;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
jsize array_length, index;
|
||||
JavaSignature *array_component_signature;
|
||||
|
||||
/* printf("In JavaArray_getProperty\n"); */
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper) {
|
||||
const char *property_name;
|
||||
if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) &&
|
||||
(property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) {
|
||||
if (!strcmp(property_name, "constructor")) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
JS_ReportError(cx, "illegal operation on JavaArray prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
java_array = java_wrapper->java_obj;
|
||||
|
||||
PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_ARRAY);
|
||||
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
|
||||
if (!JSVAL_IS_INT(idval))
|
||||
idval = try_convert_to_jsint(cx, idval);
|
||||
|
||||
if (!JSVAL_IS_INT(idval)) {
|
||||
/*
|
||||
* Usually, properties of JavaArray objects are indexed by integers, but
|
||||
* Java arrays also inherit all the methods of java.lang.Object, so a
|
||||
* string-valued property is also possible.
|
||||
*/
|
||||
if (JSVAL_IS_STRING(idval)) {
|
||||
const char *member_name;
|
||||
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
|
||||
if (do_assignment) {
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
|
||||
JS_ReportError(cx, "Attempt to write to invalid Java array "
|
||||
"element \"%s\"", member_name);
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(member_name, "length")) {
|
||||
array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array);
|
||||
if (array_length < 0)
|
||||
return JS_FALSE;
|
||||
if (vp)
|
||||
*vp = INT_TO_JSVAL(array_length);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Check to see if we're reflecting a Java array method */
|
||||
return JavaObject_getPropertyById(cx, obj, id, vp);
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "invalid Java array index expression");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
index = JSVAL_TO_INT(idval);
|
||||
|
||||
#if 0
|
||||
array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array);
|
||||
if (array_length < 0)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Just let Java throw an exception instead of checking array bounds here */
|
||||
if (index < 0 || index >= array_length) {
|
||||
JS_ReportError(cx, "Java array index %d out of range", index);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
array_component_signature = class_descriptor->array_component_signature;
|
||||
|
||||
if (!vp)
|
||||
return JS_TRUE;
|
||||
|
||||
if (do_assignment) {
|
||||
return jsj_SetJavaArrayElement(cx, jEnv, java_array, index,
|
||||
array_component_signature, *vp);
|
||||
} else {
|
||||
return jsj_GetJavaArrayElement(cx, jEnv, java_array, index,
|
||||
array_component_signature, vp);
|
||||
}
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaArray_getPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
return access_java_array_element(cx, jEnv, obj, id, vp, JS_FALSE);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaArray_setPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
return access_java_array_element(cx, jEnv, obj, id, vp, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
return access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot define a new property in a JavaArray");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_setAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Silently ignore all setAttribute attempts */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
*vp = JSVAL_FALSE;
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
JS_ReportError(cx, "Properties of JavaArray objects may not be deleted");
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/* Attempts to delete permanent properties are silently ignored
|
||||
by ECMAScript. */
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
/* printf("In JavaArray_defaultValue()\n"); */
|
||||
return JavaObject_convert(cx, obj, JSTYPE_STRING, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JNIEnv *jEnv;
|
||||
jsize array_length, index;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
/* Check for prototype object */
|
||||
if (!java_wrapper) {
|
||||
*statep = JSVAL_NULL;
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
array_length = jsj_GetJavaArrayLength(cx, jEnv, java_wrapper->java_obj);
|
||||
if (array_length < 0)
|
||||
return JS_FALSE;
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
*statep = INT_TO_JSVAL(0);
|
||||
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(array_length);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
index = JSVAL_TO_INT(*statep);
|
||||
if (index < array_length) {
|
||||
JS_ValueToId(cx, INT_TO_JSVAL(index), idp);
|
||||
index++;
|
||||
*statep = INT_TO_JSVAL(index);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through ... */
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
*statep = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_checkAccess(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSACC_WATCH:
|
||||
JS_ReportError(cx, "Cannot place watchpoints on JavaArray object properties");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSACC_IMPORT:
|
||||
JS_ReportError(cx, "Cannot export a JavaArray object's properties");
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
JSObjectOps JavaArray_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
NULL, /* newObjectMap */
|
||||
NULL, /* destroyObjectMap */
|
||||
JavaArray_lookupProperty,
|
||||
JavaArray_defineProperty,
|
||||
JavaArray_getPropertyById, /* getProperty */
|
||||
JavaArray_setPropertyById, /* setProperty */
|
||||
JavaArray_getAttributes,
|
||||
JavaArray_setAttributes,
|
||||
JavaArray_deleteProperty,
|
||||
JavaArray_defaultValue,
|
||||
JavaArray_newEnumerate,
|
||||
JavaArray_checkAccess,
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
NULL, /* thisObject */
|
||||
NULL, /* dropProperty */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL /* hasInstance */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
JavaArray_getObjectOps(JSContext *cx, JSClass *clazz)
|
||||
{
|
||||
return &JavaArray_ops;
|
||||
}
|
||||
|
||||
JSClass JavaArray_class = {
|
||||
"JavaArray", JSCLASS_HAS_PRIVATE,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, JavaObject_convert, JavaObject_finalize,
|
||||
JavaArray_getObjectOps,
|
||||
};
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
|
||||
/* Initialize the JS JavaArray class */
|
||||
JSBool
|
||||
jsj_init_JavaArray(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
JavaArray_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
JavaArray_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
|
||||
if (!JS_InitClass(cx, global_obj,
|
||||
0, &JavaArray_class, 0, 0,
|
||||
0, 0, 0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
586
mozilla/js/src/liveconnect/jsj_JavaClass.c
Normal file
586
mozilla/js/src/liveconnect/jsj_JavaClass.c
Normal file
@@ -0,0 +1,586 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of JS's JavaClass class.
|
||||
*
|
||||
* A JavaClass is JavaScript's representation of a Java class.
|
||||
* Its parent JS object is always a JavaPackage object. A JavaClass is not an
|
||||
* exact reflection of Java's corresponding java.lang.Class object. Rather,
|
||||
* the properties of a JavaClass are the static methods and properties of the
|
||||
* corresponding Java class.
|
||||
*
|
||||
* Note that there is no runtime equivalent to the JavaClass class in Java.
|
||||
* (Although there are instances of java.lang.String and there are static
|
||||
* methods of java.lang.String that can be invoked, there's no such thing as
|
||||
* a first-class object that can be referenced simply as "java.lang.String".)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
static JSBool
|
||||
JavaClass_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
char *name;
|
||||
JSString *str;
|
||||
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor)
|
||||
return JS_FALSE;
|
||||
|
||||
switch(type) {
|
||||
|
||||
|
||||
case JSTYPE_STRING:
|
||||
/* Convert '/' to '.' so that it looks like Java language syntax. */
|
||||
if (!class_descriptor->name)
|
||||
break;
|
||||
name = PR_smprintf("[JavaClass %s]", class_descriptor->name);
|
||||
if (!name) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
str = JS_NewString(cx, name, strlen(name));
|
||||
if (!str) {
|
||||
free(name);
|
||||
/* It's not necessary to call JS_ReportOutOfMemory(), as
|
||||
JS_NewString() will do so on failure. */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
lookup_static_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
JavaClassDescriptor **class_descriptorp,
|
||||
jsid id, JavaMemberDescriptor **memberp)
|
||||
{
|
||||
jsval idval;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
const char *member_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor) {
|
||||
*class_descriptorp = NULL;
|
||||
*memberp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (class_descriptorp)
|
||||
*class_descriptorp = class_descriptor;
|
||||
|
||||
member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (!member_descriptor) {
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
if (!JSVAL_IS_STRING(idval)) {
|
||||
JS_ReportError(cx, "invalid JavaClass property expression. "
|
||||
"(methods and fields of a JavaClass object can only be identified by their name)");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
|
||||
/* Why do we have to do this ? */
|
||||
if (!strcmp(member_name, "prototype")) {
|
||||
*memberp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "Java class %s has no public static field or method named \"%s\"",
|
||||
class_descriptor->name, member_name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (memberp)
|
||||
*memberp = member_descriptor;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaClass_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jsval idval;
|
||||
jclass java_class;
|
||||
const char *member_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* printf("In JavaClass_getProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
if (!member_descriptor) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
|
||||
if (member_descriptor->field) {
|
||||
if (!member_descriptor->methods) {
|
||||
return jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, vp);
|
||||
} else {
|
||||
PR_ASSERT(0);
|
||||
}
|
||||
} else {
|
||||
JSFunction *function;
|
||||
|
||||
/* TODO - eliminate JSFUN_BOUND_METHOD */
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
function = JS_NewFunction(cx, jsj_JavaStaticMethodWrapper, 0,
|
||||
JSFUN_BOUND_METHOD, obj, member_name);
|
||||
if (!function)
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(JS_GetFunctionObject(function));
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaClass_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jclass java_class;
|
||||
const char *member_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsval idval;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* printf("In JavaClass_setProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Check for the case where there is a method with the given name, but no field
|
||||
with that name */
|
||||
if (!member_descriptor->field)
|
||||
goto no_such_field;
|
||||
|
||||
/* Silently fail if field value is final (immutable), as required by ECMA spec */
|
||||
if (member_descriptor->field->modifiers & ACC_FINAL)
|
||||
return JS_TRUE;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
return jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, *vp);
|
||||
|
||||
no_such_field:
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
JS_ReportError(cx, "No static field named \"%s\" in Java class %s",
|
||||
member_name, class_descriptor->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the private native data associated with the JavaPackage object.
|
||||
*/
|
||||
PR_STATIC_CALLBACK(void)
|
||||
JavaClass_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
|
||||
JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor)
|
||||
return;
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return;
|
||||
|
||||
/* printf("Finalizing %s\n", class_descriptor->name); */
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);
|
||||
}
|
||||
|
||||
|
||||
static JSBool
|
||||
JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
JSErrorReporter old_reporter;
|
||||
|
||||
/* printf("In JavaClass_lookupProperty()\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
old_reporter = JS_SetErrorReporter(cx, NULL);
|
||||
if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
|
||||
*objp = obj;
|
||||
*propp = (JSProperty*)1;
|
||||
} else {
|
||||
*objp = NULL;
|
||||
*propp = NULL;
|
||||
}
|
||||
|
||||
JS_SetErrorReporter(cx, old_reporter);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot define a new property in a JavaClass");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_setAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Silently ignore all setAttribute attempts */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
*vp = JSVAL_FALSE;
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
JS_ReportError(cx, "Properties of JavaClass objects may not be deleted");
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/* Attempts to delete permanent properties are silently ignored
|
||||
by ECMAScript. */
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
/* printf("In JavaClass_defaultValue()\n"); */
|
||||
return JavaClass_convert(cx, obj, JSTYPE_STRING, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
|
||||
/* Check for prototype JavaClass object */
|
||||
if (!class_descriptor) {
|
||||
*statep = JSVAL_NULL;
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor);
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor);
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(class_descriptor->num_instance_members);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
member_descriptor = JSVAL_TO_PRIVATE(*statep);
|
||||
if (member_descriptor) {
|
||||
*idp = member_descriptor->id;
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor->next);
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* Fall through ... */
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
*statep = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_checkAccess(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSACC_WATCH:
|
||||
JS_ReportError(cx, "Cannot place watchpoints on JavaClass object properties");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSACC_IMPORT:
|
||||
JS_ReportError(cx, "Cannot export a JavaClass object's properties");
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the JavaScript instanceof operator for JavaClass objects by using
|
||||
* the equivalent Java instanceof operation.
|
||||
*/
|
||||
static JSBool
|
||||
JavaClass_hasInstance(JSContext *cx, JSObject *obj, jsval candidate_jsval,
|
||||
JSBool *has_instancep)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JSClass *js_class;
|
||||
JSBool has_instance;
|
||||
JSObject *candidate_obj;
|
||||
jclass java_class;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
has_instance = JS_FALSE;
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor) {
|
||||
JS_ReportError(cx, "illegal operation on JavaClass prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the thing to the left of the instanceof operator is a
|
||||
* Java object.
|
||||
*/
|
||||
if (!JSVAL_IS_OBJECT(candidate_jsval))
|
||||
goto done;
|
||||
candidate_obj = JSVAL_TO_OBJECT(candidate_jsval);
|
||||
js_class = JS_GetClass(candidate_obj);
|
||||
if ((js_class != &JavaObject_class) && (js_class != &JavaArray_class))
|
||||
goto done;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
java_wrapper = JS_GetPrivate(cx, candidate_obj);
|
||||
if (!java_wrapper) {
|
||||
JS_ReportError(cx, "illegal operation on prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
java_obj = java_wrapper->java_obj;
|
||||
/* Get JNI pointer */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
has_instance = (*jEnv)->IsInstanceOf(jEnv, java_obj, java_class);
|
||||
|
||||
done:
|
||||
*has_instancep = has_instance;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObjectOps JavaClass_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
NULL, /* newObjectMap */
|
||||
NULL, /* destroyObjectMap */
|
||||
JavaClass_lookupProperty,
|
||||
JavaClass_defineProperty,
|
||||
JavaClass_getPropertyById, /* getProperty */
|
||||
JavaClass_setPropertyById, /* setProperty */
|
||||
JavaClass_getAttributes,
|
||||
JavaClass_setAttributes,
|
||||
JavaClass_deleteProperty,
|
||||
JavaClass_defaultValue,
|
||||
JavaClass_newEnumerate,
|
||||
JavaClass_checkAccess,
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
NULL, /* thisObject */
|
||||
NULL, /* dropProperty */
|
||||
jsj_JavaConstructorWrapper, /* call */
|
||||
jsj_JavaConstructorWrapper, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
JavaClass_hasInstance, /* hasInstance */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
JavaClass_getObjectOps(JSContext *cx, JSClass *clazz)
|
||||
{
|
||||
return &JavaClass_ops;
|
||||
}
|
||||
|
||||
JSClass JavaClass_class = {
|
||||
"JavaClass", JSCLASS_HAS_PRIVATE,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, JavaClass_convert, JavaClass_finalize,
|
||||
JavaClass_getObjectOps,
|
||||
};
|
||||
|
||||
static JSObject *
|
||||
jsj_new_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JSObject *JavaClass_obj;
|
||||
|
||||
JavaClass_obj = JS_NewObject(cx, &JavaClass_class, 0, parent_obj);
|
||||
if (!JavaClass_obj)
|
||||
return NULL;
|
||||
|
||||
JS_SetPrivate(cx, JavaClass_obj, (void *)class_descriptor);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* printf("JavaClass \'%s\' created\n", class_descriptor->name); */
|
||||
#endif
|
||||
|
||||
return JavaClass_obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj,
|
||||
const char *simple_class_name,
|
||||
jclass java_class)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JSObject *JavaClass_obj;
|
||||
|
||||
class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class);
|
||||
if (!class_descriptor)
|
||||
return NULL;
|
||||
|
||||
JavaClass_obj = jsj_new_JavaClass(cx, jEnv, parent_obj, class_descriptor);
|
||||
if (!JavaClass_obj)
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, parent_obj, simple_class_name,
|
||||
OBJECT_TO_JSVAL(JavaClass_obj), 0, 0,
|
||||
JSPROP_PERMANENT|JSPROP_READONLY|JSPROP_ENUMERATE))
|
||||
return NULL;
|
||||
return JavaClass_obj;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The getClass() native JS method is defined as a property of the global
|
||||
* object. Given a JavaObject it returns the corresponding JavaClass. This
|
||||
* is useful for accessing static methods and fields.
|
||||
*
|
||||
* js> getClass(new java.lang.String("foo"))
|
||||
* [JavaClass java.lang.String]
|
||||
*/
|
||||
static JSBool
|
||||
getClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSObject *obj_arg, *JavaClass_obj;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (argc != 1 ||
|
||||
!JSVAL_IS_OBJECT(argv[0]) ||
|
||||
!(obj_arg = JSVAL_TO_OBJECT(argv[0])) ||
|
||||
(!JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) &&
|
||||
!JS_InstanceOf(cx, obj_arg, &JavaArray_class, 0))) {
|
||||
JS_ReportError(cx, "getClass expects a Java object argument");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj_arg);
|
||||
if (!java_wrapper) {
|
||||
JS_ReportError(cx, "getClass called on prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
|
||||
JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor);
|
||||
if (!JavaClass_obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(JavaClass_obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
JSBool
|
||||
jsj_init_JavaClass(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
JavaClass_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
JavaClass_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
|
||||
/* Define JavaClass class */
|
||||
if (!JS_InitClass(cx, global_obj, 0, &JavaClass_class, 0, 0, 0, 0, 0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_DefineFunction(cx, global_obj, "getClass", getClass, 0,
|
||||
JSPROP_READONLY))
|
||||
return JS_FALSE;
|
||||
|
||||
return jsj_InitJavaClassReflectionsTable();
|
||||
}
|
||||
|
||||
134
mozilla/js/src/liveconnect/jsj_JavaMember.c
Normal file
134
mozilla/js/src/liveconnect/jsj_JavaMember.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright (C) 1998 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of JS's JavaMember class.
|
||||
* JavaMember's are a strange beast required only to handle the special case
|
||||
* of a public field and a public method that appear in the same class and
|
||||
* have the same name. When such a field/method is used in Java, the compiler
|
||||
* can statically determine from context whether the field or the method is
|
||||
* being referenced, but that is not possible with JavaScript. For example:
|
||||
*
|
||||
* ambiguousVal = javaObj.fieldOrMethod; // ambiguousVal is a JavaMember object
|
||||
* a = ambiguousVal(); // ambiguousVal used as a method value
|
||||
* b = ambiguousVal + 4; // ambiguousVal used as a field value
|
||||
*
|
||||
* A JavaMember instance carries both the captured value of the Java field and
|
||||
* the method value until the context that the value is to be used in is known,
|
||||
* at which point conversion forces the use of one or the other.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/* Private, native portion of a JavaMember */
|
||||
typedef struct JavaMethodOrFieldValue {
|
||||
jsval method_val;
|
||||
jsval field_val;
|
||||
} JavaMethodOrFieldValue;
|
||||
|
||||
JSObject *
|
||||
jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val)
|
||||
{
|
||||
JavaMethodOrFieldValue *member_val;
|
||||
JSObject *JavaMember_obj;
|
||||
|
||||
member_val = (JavaMethodOrFieldValue *)JS_malloc(cx, sizeof(*member_val));
|
||||
if (!member_val)
|
||||
return NULL;
|
||||
|
||||
JavaMember_obj = JS_NewObject(cx, &JavaMember_class, 0, 0);
|
||||
if (!JavaMember_obj) {
|
||||
JS_free(cx, member_val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_SetPrivate(cx, JavaMember_obj, (void *)member_val);
|
||||
member_val->method_val = method_val;
|
||||
JS_AddRoot(cx, &member_val->method_val);
|
||||
member_val->field_val = field_val;
|
||||
if (JSVAL_IS_GCTHING(field_val))
|
||||
JS_AddRoot(cx, &member_val->field_val);
|
||||
|
||||
return JavaMember_obj;
|
||||
}
|
||||
|
||||
static void
|
||||
JavaMember_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JavaMethodOrFieldValue *member_val;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return;
|
||||
|
||||
member_val = JS_GetPrivate(cx, obj);
|
||||
if (!member_val)
|
||||
return;
|
||||
JS_RemoveRoot(cx, &member_val->method_val);
|
||||
if (JSVAL_IS_GCTHING(member_val->method_val))
|
||||
JS_RemoveRoot(cx, &member_val->method_val);
|
||||
JS_free(cx, member_val);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaMember_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
JavaMethodOrFieldValue *member_val;
|
||||
|
||||
member_val = JS_GetPrivate(cx, obj);
|
||||
if (!member_val) {
|
||||
if (type == JSTYPE_OBJECT) {
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "illegal operation on JavaObject prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case JSTYPE_VOID:
|
||||
case JSTYPE_STRING:
|
||||
case JSTYPE_NUMBER:
|
||||
case JSTYPE_BOOLEAN:
|
||||
case JSTYPE_OBJECT:
|
||||
*vp = member_val->field_val;
|
||||
return JS_TRUE;
|
||||
|
||||
case JSTYPE_FUNCTION:
|
||||
*vp = member_val->method_val;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JSClass JavaMember_class = {
|
||||
"JavaMember", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JavaMember_convert, JavaMember_finalize
|
||||
};
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
JSBool
|
||||
jsj_init_JavaMember(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
if (!JS_InitClass(cx, global_obj,
|
||||
0, &JavaMember_class, 0, 0,
|
||||
0, 0,
|
||||
0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
686
mozilla/js/src/liveconnect/jsj_JavaObject.c
Normal file
686
mozilla/js/src/liveconnect/jsj_JavaObject.c
Normal file
@@ -0,0 +1,686 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of JS's JavaObject class.
|
||||
*
|
||||
* An instance of JavaObject is the JavaScript reflection of a Java object.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsj_hash.h" /* Hash table with Java object as key */
|
||||
|
||||
|
||||
/*
|
||||
* This is a hash table that maps from Java objects to JS objects.
|
||||
* It is used to ensure that the same JS object is obtained when a Java
|
||||
* object is reflected more than once, so that JS object equality tests
|
||||
* work in the expected manner, i.e. the "==" and "===" operators.
|
||||
*
|
||||
* The table entry keys are Java objects (of type jobject) and the entry values
|
||||
* are JSObject pointers. Because the jobject type is an opaque handle and
|
||||
* not necessarily a pointer, the hashing and key comparison functions must
|
||||
* invoke the appropriate JVM functions.
|
||||
*
|
||||
* When the corresponding JS object instance is finalized, the entry is
|
||||
* removed from the table, and a Java GC root for the Java object is removed.
|
||||
*/
|
||||
static JSJHashTable *java_obj_reflections = NULL;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
static PRMonitor *java_obj_reflections_monitor = NULL;
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
init_java_obj_reflections_table()
|
||||
{
|
||||
java_obj_reflections =
|
||||
JSJ_NewHashTable(512, jsj_HashJavaObject, jsj_JavaObjectComparator,
|
||||
NULL, NULL, NULL);
|
||||
if (!java_obj_reflections)
|
||||
return JS_FALSE;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
java_obj_reflections_monitor = PR_NewNamedMonitor("java_obj_reflections");
|
||||
if (!java_obj_reflections_monitor) {
|
||||
PR_HashTableDestroy(java_obj_reflections);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
jsj_WrapJavaObject(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
jobject java_obj,
|
||||
jclass java_class)
|
||||
{
|
||||
JSJHashNumber hash_code;
|
||||
JSClass *js_class;
|
||||
JSObject *js_wrapper_obj;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
js_wrapper_obj = NULL;
|
||||
|
||||
hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_EnterMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
|
||||
hep = JSJ_HashTableRawLookup(java_obj_reflections,
|
||||
hash_code, java_obj, (void*)jEnv);
|
||||
he = *hep;
|
||||
if (he) {
|
||||
js_wrapper_obj = (JSObject *)he->value;
|
||||
if (js_wrapper_obj)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* No existing reflection found. Construct a new one */
|
||||
class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class);
|
||||
if (!class_descriptor)
|
||||
goto done;
|
||||
if (class_descriptor->type == JAVA_SIGNATURE_ARRAY) {
|
||||
js_class = &JavaArray_class;
|
||||
} else {
|
||||
PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_CLASS);
|
||||
js_class = &JavaObject_class;
|
||||
}
|
||||
|
||||
/* Create new JS object to reflect Java object */
|
||||
js_wrapper_obj = JS_NewObject(cx, js_class, NULL, NULL);
|
||||
if (!js_wrapper_obj)
|
||||
goto done;
|
||||
|
||||
/* Create private, native portion of JavaObject */
|
||||
java_wrapper =
|
||||
(JavaObjectWrapper *)JS_malloc(cx, sizeof(JavaObjectWrapper));
|
||||
if (!java_wrapper) {
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);
|
||||
goto done;
|
||||
}
|
||||
JS_SetPrivate(cx, js_wrapper_obj, java_wrapper);
|
||||
java_wrapper->class_descriptor = class_descriptor;
|
||||
|
||||
java_obj = (*jEnv)->NewGlobalRef(jEnv, java_obj);
|
||||
java_wrapper->java_obj = java_obj;
|
||||
if (!java_obj)
|
||||
goto out_of_memory;
|
||||
|
||||
/* Add the JavaObject to the hash table */
|
||||
he = JSJ_HashTableRawAdd(java_obj_reflections, hep, hash_code,
|
||||
java_obj, js_wrapper_obj, (void*)jEnv);
|
||||
if (!he) {
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_obj);
|
||||
goto out_of_memory;
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_ExitMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
|
||||
return js_wrapper_obj;
|
||||
|
||||
out_of_memory:
|
||||
/* No need to free js_wrapper_obj, as it will be finalized by GC. */
|
||||
JS_ReportOutOfMemory(cx);
|
||||
js_wrapper_obj = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_java_obj_reflection_from_hashtable(jobject java_obj, JNIEnv *jEnv)
|
||||
{
|
||||
JSJHashNumber hash_code;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_EnterMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
|
||||
hep = JSJ_HashTableRawLookup(java_obj_reflections, hash_code,
|
||||
java_obj, (void*)jEnv);
|
||||
he = *hep;
|
||||
|
||||
PR_ASSERT(he);
|
||||
if (he)
|
||||
JSJ_HashTableRawRemove(java_obj_reflections, hep, he, (void*)jEnv);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_ExitMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
JavaObject_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper)
|
||||
return;
|
||||
java_obj = java_wrapper->java_obj;
|
||||
|
||||
if (java_obj) {
|
||||
remove_java_obj_reflection_from_hashtable(java_obj, jEnv);
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_obj);
|
||||
}
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor);
|
||||
JS_free(cx, java_wrapper);
|
||||
}
|
||||
|
||||
/* Trivial helper for jsj_DiscardJavaObjReflections(), below */
|
||||
static PRIntn
|
||||
enumerate_remove_java_obj(JSJHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
JNIEnv *jEnv = (JNIEnv*)arg;
|
||||
jobject java_obj;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JSObject *java_wrapper_obj;
|
||||
|
||||
java_wrapper_obj = (JSObject *)he->value;
|
||||
java_wrapper = JS_GetPrivate(NULL, java_wrapper_obj);
|
||||
java_obj = java_wrapper->java_obj;
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_obj);
|
||||
java_wrapper->java_obj = NULL;
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
/* This shutdown routine discards all JNI references to Java objects
|
||||
that have been reflected into JS, even if there are still references
|
||||
to them from JS. */
|
||||
void
|
||||
jsj_DiscardJavaObjReflections(JNIEnv *jEnv)
|
||||
{
|
||||
if (java_obj_reflections) {
|
||||
JSJ_HashTableEnumerateEntries(java_obj_reflections,
|
||||
enumerate_remove_java_obj,
|
||||
(void*)jEnv);
|
||||
JSJ_HashTableDestroy(java_obj_reflections);
|
||||
java_obj_reflections = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PR_CALLBACK JSBool
|
||||
JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper) {
|
||||
if (type == JSTYPE_OBJECT) {
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "illegal operation on JavaObject prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
java_obj = java_wrapper->java_obj;
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
|
||||
switch (type) {
|
||||
case JSTYPE_OBJECT:
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSTYPE_FUNCTION:
|
||||
JS_ReportError(cx, "can't convert Java object to function");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSTYPE_VOID:
|
||||
case JSTYPE_STRING:
|
||||
/* Either extract a C-string from the java.lang.String object
|
||||
or call the Java toString() method */
|
||||
return jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, vp);
|
||||
|
||||
case JSTYPE_NUMBER:
|
||||
/* Call Java doubleValue() method, if applicable */
|
||||
return jsj_ConvertJavaObjectToJSNumber(cx, jEnv, class_descriptor, java_obj, vp);
|
||||
|
||||
case JSTYPE_BOOLEAN:
|
||||
/* Call booleanValue() method, if applicable */
|
||||
return jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, class_descriptor, java_obj, vp);
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
JavaObjectWrapper **java_wrapperp,
|
||||
jsid id,
|
||||
JavaMemberDescriptor **member_descriptorp)
|
||||
{
|
||||
jsval idval;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
const char *member_name, *property_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper) {
|
||||
if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) &&
|
||||
(property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) {
|
||||
if (!strcmp(property_name, "constructor")) {
|
||||
*java_wrapperp = NULL;
|
||||
*member_descriptorp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
JS_ReportError(cx, "illegal operation on JavaObject prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_CLASS ||
|
||||
class_descriptor->type == JAVA_SIGNATURE_ARRAY);
|
||||
|
||||
member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (!member_descriptor) {
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
if (!JSVAL_IS_STRING(idval)) {
|
||||
JS_ReportError(cx, "invalid JavaObject property expression. "
|
||||
"(methods and field properties of a JavaObject object can only be strings)");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
|
||||
JS_ReportError(cx, "Java class %s has no public instance field or "
|
||||
"method named \"%s\"",
|
||||
class_descriptor->name, member_name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Success. Handle the multiple return values */
|
||||
if (java_wrapperp)
|
||||
*java_wrapperp = java_wrapper;
|
||||
if (member_descriptorp)
|
||||
*member_descriptorp = member_descriptor;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_CALLBACK JSBool
|
||||
JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jobject java_obj;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JNIEnv *jEnv;
|
||||
JSObject *funobj;
|
||||
jsval field_val, method_val;
|
||||
JSBool success;
|
||||
|
||||
/* printf("In JavaObject_getProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Handle access to "constructor" property of prototype object with
|
||||
silent failure. */
|
||||
if (!member_descriptor) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
java_obj = java_wrapper->java_obj;
|
||||
field_val = method_val = JSVAL_VOID;
|
||||
|
||||
/* If a field member, get the value of the field */
|
||||
if (member_descriptor->field) {
|
||||
success = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, &field_val);
|
||||
if (!success)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* If a method member, build a wrapper around the Java method */
|
||||
if (member_descriptor->methods) {
|
||||
/* Create a function object with this JavaObject as its parent, so that
|
||||
JSFUN_BOUND_METHOD binds it as the default 'this' for the function. */
|
||||
funobj = JS_CloneFunctionObject(cx, member_descriptor->invoke_func_obj, obj);
|
||||
if (!funobj)
|
||||
return JS_FALSE;
|
||||
method_val = OBJECT_TO_JSVAL(funobj);
|
||||
}
|
||||
|
||||
#if TEST_JAVAMEMBER
|
||||
/* Always create a JavaMember object, even though it's inefficient */
|
||||
obj = jsj_CreateJavaMember(cx, method_val, field_val);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
#else /* !TEST_JAVAMEMBER */
|
||||
|
||||
if (member_descriptor->field) {
|
||||
if (!member_descriptor->methods) {
|
||||
/* Return value of Java field */
|
||||
*vp = field_val;
|
||||
} else {
|
||||
/* Handle special case of access to a property that could refer
|
||||
to either a Java field or a method that share the same name.
|
||||
In Java, such ambiguity is not possible because the compiler
|
||||
can statically determine which is being accessed. */
|
||||
obj = jsj_CreateJavaMember(cx, method_val, field_val);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Return wrapper around Java method */
|
||||
*vp = method_val;
|
||||
}
|
||||
|
||||
#endif /* !TEST_JAVAMEMBER */
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jobject java_obj;
|
||||
const char *member_name;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsval idval;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* printf("In JavaObject_setProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Check for the case where there is a method with the give name, but no field
|
||||
with that name */
|
||||
if (!member_descriptor->field)
|
||||
goto no_such_field;
|
||||
|
||||
/* Silently fail if field value is final (immutable), as required by ECMA spec */
|
||||
if (member_descriptor->field->modifiers & ACC_FINAL)
|
||||
return JS_TRUE;
|
||||
|
||||
java_obj = java_wrapper->java_obj;
|
||||
return jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, *vp);
|
||||
|
||||
no_such_field:
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
JS_ReportError(cx, "No instance field named \"%s\" in Java class %s",
|
||||
member_name, class_descriptor->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
JSErrorReporter old_reporter;
|
||||
|
||||
/* printf("In JavaObject_lookupProperty()\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
old_reporter = JS_SetErrorReporter(cx, NULL);
|
||||
if (lookup_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
|
||||
*objp = obj;
|
||||
*propp = (JSProperty*)1;
|
||||
} else {
|
||||
*objp = NULL;
|
||||
*propp = NULL;
|
||||
}
|
||||
|
||||
JS_SetErrorReporter(cx, old_reporter);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot define a new property in a JavaObject");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_setAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Silently ignore all setAttribute attempts */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
*vp = JSVAL_FALSE;
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
JS_ReportError(cx, "Properties of JavaObject objects may not be deleted");
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/* Attempts to delete permanent properties are silently ignored
|
||||
by ECMAScript. */
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
/* printf("In JavaObject_defaultValue()\n"); */
|
||||
return JavaObject_convert(cx, obj, type, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
/* Check for prototype object */
|
||||
if (!java_wrapper) {
|
||||
*statep = JSVAL_NULL;
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor);
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor);
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(class_descriptor->num_instance_members);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
member_descriptor = JSVAL_TO_PRIVATE(*statep);
|
||||
if (member_descriptor) {
|
||||
*idp = member_descriptor->id;
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor->next);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through ... */
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
*statep = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_checkAccess(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSACC_WATCH:
|
||||
JS_ReportError(cx, "Cannot place watchpoints on JavaObject object properties");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSACC_IMPORT:
|
||||
JS_ReportError(cx, "Cannot export a JavaObject object's properties");
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
JSObjectOps JavaObject_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
NULL, /* newObjectMap */
|
||||
NULL, /* destroyObjectMap */
|
||||
JavaObject_lookupProperty,
|
||||
JavaObject_defineProperty,
|
||||
JavaObject_getPropertyById, /* getProperty */
|
||||
JavaObject_setPropertyById, /* setProperty */
|
||||
JavaObject_getAttributes,
|
||||
JavaObject_setAttributes,
|
||||
JavaObject_deleteProperty,
|
||||
JavaObject_defaultValue,
|
||||
JavaObject_newEnumerate,
|
||||
JavaObject_checkAccess,
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
NULL, /* thisObject */
|
||||
NULL, /* dropProperty */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
JavaObject_getObjectOps(JSContext *cx, JSClass *clazz)
|
||||
{
|
||||
return &JavaObject_ops;
|
||||
}
|
||||
|
||||
JSClass JavaObject_class = {
|
||||
"JavaObject", JSCLASS_HAS_PRIVATE,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, JavaObject_convert, JavaObject_finalize,
|
||||
JavaObject_getObjectOps,
|
||||
};
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
|
||||
JSBool
|
||||
jsj_init_JavaObject(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
JavaObject_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
JavaObject_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
|
||||
if (!JS_InitClass(cx, global_obj,
|
||||
0, &JavaObject_class, 0, 0,
|
||||
0, 0,
|
||||
0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
return init_java_obj_reflections_table();
|
||||
}
|
||||
500
mozilla/js/src/liveconnect/jsj_JavaPackage.c
Normal file
500
mozilla/js/src/liveconnect/jsj_JavaPackage.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of the JavaPackage class.
|
||||
*
|
||||
* A JavaPackage is JavaScript's representation of a Java package. The
|
||||
* JavaPackage object contains only a string, which is the path to the package,
|
||||
* e.g. "java/lang". The JS properties of a JavaPackage are either nested packages
|
||||
* or a JavaClass object, which represents the path to a Java class.
|
||||
*
|
||||
* Note that there is no equivalent to a JavaPackage object in Java. Example:
|
||||
* Although there are instances of java.lang.String and there are static methods
|
||||
* of java.lang.String that can be invoked, there's no such thing as a java.lang
|
||||
* object in Java that exists at run time.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsjava.h"
|
||||
|
||||
|
||||
JSClass JavaPackage_class; /* Forward declaration */
|
||||
|
||||
/*
|
||||
* The native part of a JavaPackage object. It gets stored in the object's
|
||||
* private slot.
|
||||
*/
|
||||
typedef struct {
|
||||
const char * path; /* e.g. "java/lang" or NULL if top level package */
|
||||
int flags; /* e.g. PKG_SYSTEM, PKG_CLASS */
|
||||
} JavaPackage_Private;
|
||||
|
||||
static JSObject *
|
||||
define_JavaPackage(JSContext *cx, JSObject *parent_obj,
|
||||
const char *obj_name, const char *path, int flags)
|
||||
{
|
||||
JSObject *package_obj;
|
||||
JavaPackage_Private *package;
|
||||
|
||||
package_obj = JS_DefineObject(cx, parent_obj, obj_name, &JavaPackage_class, 0,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
if (!package_obj)
|
||||
return NULL;
|
||||
|
||||
/* Attach private, native data to the JS object */
|
||||
package = (JavaPackage_Private *)JS_malloc(cx, sizeof(JavaPackage_Private));
|
||||
JS_SetPrivate(cx, package_obj, (void *)package);
|
||||
if (path)
|
||||
package->path = JS_strdup(cx, path);
|
||||
else
|
||||
package->path = "";
|
||||
|
||||
package->flags = flags;
|
||||
|
||||
/* Check for OOM */
|
||||
if (!package->path) {
|
||||
JS_DeleteProperty(cx, parent_obj, obj_name);
|
||||
JS_free(cx, package);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return package_obj;
|
||||
}
|
||||
|
||||
/* JavaPackage uses standard JS getProperty */
|
||||
|
||||
/*
|
||||
* Don't allow user-defined properties to be set on Java package objects, e.g.
|
||||
* it is illegal to write "java.lang.myProperty = 4". We probably could relax
|
||||
* this restriction, but it's potentially confusing and not clearly useful.
|
||||
*/
|
||||
static JSBool
|
||||
JavaPackage_setProperty(JSContext *cx, JSObject *obj, jsval slot, jsval *vp)
|
||||
{
|
||||
JavaPackage_Private *package = JS_GetPrivate(cx, obj);
|
||||
if (!package) {
|
||||
JS_ReportError(cx, "illegal attempt to add property to "
|
||||
"JavaPackage prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_ReportError(cx, "You may not add properties to a JavaPackage object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool quiet_resolve_failure;
|
||||
|
||||
/*
|
||||
* Resolve a component name to be either the name of a class or a package.
|
||||
*/
|
||||
static JSBool
|
||||
JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id)
|
||||
{
|
||||
JavaPackage_Private *package;
|
||||
JSBool ok = JS_TRUE;
|
||||
jclass jclazz;
|
||||
char *subPath, *newPath;
|
||||
const char *path;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
package = (JavaPackage_Private *)JS_GetPrivate(cx, obj);
|
||||
if (!package)
|
||||
return JS_TRUE;
|
||||
|
||||
if (!JSVAL_IS_STRING(id))
|
||||
return JS_TRUE;
|
||||
subPath = JS_GetStringBytes(JSVAL_TO_STRING(id));
|
||||
|
||||
/*
|
||||
* There will be an attempt to invoke the toString() method when producing
|
||||
* the string representation of a JavaPackage. When this occurs, avoid
|
||||
* creating a bogus toString package. (This means that no one can ever
|
||||
* create a package with the simple name "toString", but we'll live with
|
||||
* that limitation.)
|
||||
*/
|
||||
if (!strcmp(subPath, "toString"))
|
||||
return JS_FALSE;
|
||||
|
||||
path = package->path;
|
||||
newPath = PR_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath);
|
||||
if (!newPath) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
Unfortunately, Java provides no way to find out whether a particular
|
||||
name is a package or not. The only way to tell is to try to load the
|
||||
name as a class file and, if that fails, assume it's a package. This
|
||||
makes things work as expected for the most part, but it has three
|
||||
noticeable problems that keep coming up:
|
||||
|
||||
- You can refer to a package like java.lang.i.buried.paul without
|
||||
generating a complaint. Of course, you'll never be able to refer to
|
||||
any classes through it.
|
||||
|
||||
- An annoying consequence of the above is that misspelling a class name
|
||||
results in a cryptic error about packages.
|
||||
|
||||
- In a browser context, i.e. where applets are involved, figuring out
|
||||
whether something is a class may require looking for it over the net
|
||||
using the current classloader. This means that the first time you
|
||||
refer to java.lang.System in a js context, there will be an attempt
|
||||
to search for [[DOCBASE]]/java.class on the server.
|
||||
|
||||
A solution is to explicitly tell jsjava the names of all the (local)
|
||||
packages on the CLASSPATH. (Not implemented yet.)
|
||||
|
||||
*/
|
||||
jclazz = (*jEnv)->FindClass(jEnv, newPath);
|
||||
if (jclazz) {
|
||||
JSObject *newClass;
|
||||
|
||||
newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz);
|
||||
if (!newClass) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* We assume that any failed attempt to load a class is because it
|
||||
doesn't exist. If we wanted to do a better job, we would check
|
||||
the exception type and make sure that it's NoClassDefFoundError */
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
|
||||
/* beard: this has to be done here, so built-in classes will be defined. */
|
||||
/* Painful hack for pre_define_java_packages() */
|
||||
if (quiet_resolve_failure) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no class of the given name, then we must be referring to
|
||||
* a package. However, don't allow bogus sub-packages of pre-defined
|
||||
* system packages to be created.
|
||||
*/
|
||||
if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) {
|
||||
JavaPackage_Private *package;
|
||||
|
||||
package = JS_GetPrivate(cx, obj);
|
||||
if (package->flags & PKG_SYSTEM) {
|
||||
char *msg, *cp;
|
||||
|
||||
msg = PR_smprintf("No Java system package with name \"%s\" was identified "
|
||||
"and no Java class with that name exists either",
|
||||
newPath);
|
||||
|
||||
/* Check for OOM */
|
||||
if (msg) {
|
||||
/* Convert package of form "java/lang" to "java.lang" */
|
||||
for (cp = msg; *cp != '\0'; cp++)
|
||||
if (*cp == '/')
|
||||
*cp = '.';
|
||||
JS_ReportError(cx, msg);
|
||||
free((char*)msg);
|
||||
}
|
||||
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!define_JavaPackage(cx, obj, subPath, newPath, 0)) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* printf("JavaPackage \'%s\' created\n", newPath); */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
free(newPath);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaPackage_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
char *name, *cp;
|
||||
|
||||
JavaPackage_Private *package = JS_GetPrivate(cx, obj);
|
||||
if (!package) {
|
||||
fprintf(stderr, "JavaPackage_resolve: no private data!\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
||||
/* Pretty-printing of JavaPackage */
|
||||
case JSTYPE_VOID: /* Default value */
|
||||
case JSTYPE_NUMBER:
|
||||
case JSTYPE_STRING:
|
||||
/* Convert '/' to '.' so that it looks like Java language syntax. */
|
||||
if (!package->path)
|
||||
break;
|
||||
name = PR_smprintf("[JavaPackage %s]", package->path);
|
||||
if (!name) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
for (cp = name; *cp != '\0'; cp++)
|
||||
if (*cp == '/')
|
||||
*cp = '.';
|
||||
str = JS_NewString(cx, name, strlen(name));
|
||||
if (!str) {
|
||||
free(name);
|
||||
/* It's not necessary to call JS_ReportOutOfMemory(), as
|
||||
JS_NewString() will do so on failure. */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
|
||||
case JSTYPE_OBJECT:
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the private native data associated with the JavaPackage object.
|
||||
*/
|
||||
static void
|
||||
JavaPackage_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JavaPackage_Private *package = JS_GetPrivate(cx, obj);
|
||||
if (!package)
|
||||
return;
|
||||
|
||||
if (package->path)
|
||||
JS_free(cx, (char *)package->path);
|
||||
JS_free(cx, package);
|
||||
}
|
||||
|
||||
/*
|
||||
* The definition of the JavaPackage class
|
||||
*/
|
||||
JSClass JavaPackage_class = {
|
||||
"JavaPackage", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JavaPackage_setProperty,
|
||||
JS_EnumerateStub, JavaPackage_resolve,
|
||||
JavaPackage_convert, JavaPackage_finalize
|
||||
};
|
||||
|
||||
JavaPackageDef
|
||||
standard_java_packages[] = {
|
||||
{"java", NULL, PKG_USER},
|
||||
{"java.applet", NULL, PKG_USER},
|
||||
{"java.awt", NULL, PKG_USER},
|
||||
{"java.awt.datatransfer",
|
||||
NULL, PKG_SYSTEM},
|
||||
{"java.awt.event", NULL, PKG_SYSTEM},
|
||||
{"java.awt.image", NULL, PKG_SYSTEM},
|
||||
{"java.awt.peer", NULL, PKG_SYSTEM},
|
||||
{"java.beans", NULL, PKG_USER},
|
||||
{"java.io", NULL, PKG_SYSTEM},
|
||||
{"java.lang", NULL, PKG_USER},
|
||||
{"java.lang.reflect", NULL, PKG_SYSTEM},
|
||||
{"java.math", NULL, PKG_SYSTEM},
|
||||
{"java.net", NULL, PKG_USER},
|
||||
{"java.rmi", NULL, PKG_USER},
|
||||
{"java.rmi.dgc", NULL, PKG_USER},
|
||||
{"java.rmi.user", NULL, PKG_USER},
|
||||
{"java.rmi.registry", NULL, PKG_USER},
|
||||
{"java.rmi.server", NULL, PKG_USER},
|
||||
{"java.security", NULL, PKG_USER},
|
||||
{"java.security.acl", NULL, PKG_SYSTEM},
|
||||
{"java.security.interfaces",
|
||||
NULL, PKG_SYSTEM},
|
||||
{"java.sql", NULL, PKG_USER},
|
||||
{"java.text", NULL, PKG_USER},
|
||||
{"java.text.resources", NULL, PKG_SYSTEM},
|
||||
{"java.util", NULL, PKG_USER},
|
||||
{"java.util.zip", NULL, PKG_SYSTEM},
|
||||
|
||||
{"netscape", NULL, PKG_USER},
|
||||
{"netscape.applet", NULL, PKG_SYSTEM},
|
||||
{"netscape.application",NULL, PKG_SYSTEM},
|
||||
{"netscape.debug", NULL, PKG_SYSTEM},
|
||||
{"netscape.javascript", NULL, PKG_SYSTEM},
|
||||
{"netscape.ldap", NULL, PKG_SYSTEM},
|
||||
{"netscape.misc", NULL, PKG_SYSTEM},
|
||||
{"netscape.net", NULL, PKG_SYSTEM},
|
||||
{"netscape.plugin", NULL, PKG_SYSTEM},
|
||||
{"netscape.util", NULL, PKG_SYSTEM},
|
||||
{"netscape.secfile", NULL, PKG_SYSTEM},
|
||||
{"netscape.security", NULL, PKG_SYSTEM},
|
||||
{"netscape.WAI", NULL, PKG_SYSTEM},
|
||||
|
||||
{"sun", NULL, PKG_USER},
|
||||
{"Packages", "", PKG_USER},
|
||||
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Pre-define a hierarchy of JavaPackage objects.
|
||||
* Pre-defining a Java package at initialization time is not necessary, but
|
||||
* it will make package lookup faster and, more importantly, will avoid
|
||||
* unnecessary network accesses if classes are being loaded over the network.
|
||||
*/
|
||||
static JSBool
|
||||
pre_define_java_packages(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *predefined_packages)
|
||||
{
|
||||
JSBool package_exists;
|
||||
JSObject *parent_obj;
|
||||
JavaPackageDef *package_def;
|
||||
char *simple_name, *cp, *package_name, *path;
|
||||
int flags;
|
||||
|
||||
if (!predefined_packages)
|
||||
return JS_TRUE;
|
||||
|
||||
/* Iterate over all pre-defined Java packages */
|
||||
for (package_def = predefined_packages; package_def->name; package_def++) {
|
||||
package_name = path = NULL;
|
||||
|
||||
parent_obj = global_obj;
|
||||
package_name = strdup(package_def->name);
|
||||
if (!package_name)
|
||||
goto out_of_memory;
|
||||
|
||||
/* Walk the chain of JavaPackage objects to get to the parent of the
|
||||
rightmost sub-package in the fully-qualified package name. */
|
||||
for (simple_name = strtok(package_name, "."); 1; simple_name = strtok(NULL, ".")) {
|
||||
jsval v;
|
||||
|
||||
if (!simple_name) {
|
||||
JS_ReportError(cx, "Package %s defined twice ?", package_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check to see if the sub-package already exists */
|
||||
quiet_resolve_failure = JS_TRUE;
|
||||
package_exists = JS_LookupProperty(cx, parent_obj, simple_name, &v) && JSVAL_IS_OBJECT(v);
|
||||
quiet_resolve_failure = JS_FALSE;
|
||||
|
||||
if (package_exists) {
|
||||
parent_obj = JSVAL_TO_OBJECT(v);
|
||||
continue;
|
||||
} else {
|
||||
/* New package objects should only be created at the terminal
|
||||
sub-package in a fully-qualified package-name */
|
||||
if (strtok(NULL, ".")) {
|
||||
JS_ReportError(cx, "Illegal predefined package definition for %s",
|
||||
package_def->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (package_def->path) {
|
||||
path = strdup(package_def->path);
|
||||
if (!path)
|
||||
goto out_of_memory;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* The default path is specified, so create it from the
|
||||
* fully-qualified package name.
|
||||
*/
|
||||
path = strdup(package_def->name);
|
||||
if (!path)
|
||||
goto out_of_memory;
|
||||
/* Transform package name, e.g. "java.lang" ==> "java/lang" */
|
||||
for (cp = path; *cp != '\0'; cp++) {
|
||||
if (*cp == '.')
|
||||
*cp = '/';
|
||||
}
|
||||
}
|
||||
flags = package_def->flags;
|
||||
parent_obj = define_JavaPackage(cx, parent_obj, simple_name, path, flags);
|
||||
if (!parent_obj)
|
||||
goto error;
|
||||
|
||||
free(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(package_name);
|
||||
}
|
||||
return JS_TRUE;
|
||||
|
||||
out_of_memory:
|
||||
JS_ReportOutOfMemory(cx);
|
||||
|
||||
error:
|
||||
JS_FREE_IF(cx, package_name);
|
||||
JS_FREE_IF(cx, path);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaPackage_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &JavaPackage_class, argv))
|
||||
return JS_FALSE;
|
||||
return JavaPackage_convert(cx, obj, JSTYPE_STRING, rval);
|
||||
}
|
||||
|
||||
static JSFunctionSpec JavaPackage_methods[] = {
|
||||
{"toString", JavaPackage_toString, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
/*
|
||||
* One-time initialization for the JavaPackage class. (This is not
|
||||
* run once per thread, rather it's run once for a given JSContext.)
|
||||
*/
|
||||
JSBool
|
||||
jsj_init_JavaPackage(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *additional_predefined_packages) {
|
||||
|
||||
/* Define JavaPackage class */
|
||||
if (!JS_InitClass(cx, global_obj, 0, &JavaPackage_class,
|
||||
0, 0, 0, JavaPackage_methods, 0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Add top-level packages, e.g. : java, netscape, sun */
|
||||
if (!pre_define_java_packages(cx, global_obj, standard_java_packages))
|
||||
return JS_FALSE;
|
||||
if (!pre_define_java_packages(cx, global_obj, additional_predefined_packages))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
180
mozilla/js/src/liveconnect/jsj_array.c
Normal file
180
mozilla/js/src/liveconnect/jsj_array.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the code for reading and writing elements of a Java array.
|
||||
*/
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/*
|
||||
* Read the Java value at a given index into a Java array and convert it
|
||||
* to a JS value. The array_component_signature describes the type of
|
||||
* the resulting Java value, which can be a primitive type or an object type.
|
||||
* More specifically it can be an array type in the case of multidimensional
|
||||
* arrays.
|
||||
*/
|
||||
JSBool
|
||||
jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index,
|
||||
JavaSignature *array_component_signature,
|
||||
jsval *vp)
|
||||
{
|
||||
jvalue java_value;
|
||||
JavaSignatureChar component_type;
|
||||
|
||||
#define GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \
|
||||
(*jEnv)->Get##Type##ArrayRegion(jEnv, java_array, index, 1, \
|
||||
&java_value.member); \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_ReportJavaError(cx, jEnv, "Error reading element of " \
|
||||
"Java primitive array"); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
component_type = array_component_signature->type;
|
||||
switch(component_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
java_value.l = (*jEnv)->GetObjectArrayElement(jEnv, java_array, index);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_ReportJavaError(cx, jEnv, "Error reading Java object array");
|
||||
return JS_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
#undef GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return jsj_ConvertJavaValueToJSValue(cx, jEnv, array_component_signature, &java_value, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index,
|
||||
JavaSignature *array_component_signature,
|
||||
jsval js_val)
|
||||
{
|
||||
int dummy_cost;
|
||||
jvalue java_value;
|
||||
JavaSignatureChar component_type;
|
||||
JSBool is_local_ref;
|
||||
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, array_component_signature,
|
||||
&dummy_cost, &java_value, &is_local_ref))
|
||||
return JS_FALSE;
|
||||
|
||||
#define SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \
|
||||
(*jEnv)->Set##Type##ArrayRegion(jEnv, java_array, index, 1, \
|
||||
&java_value.member); \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_ReportJavaError(cx, jEnv, "Error assigning to element of " \
|
||||
"Java primitive array"); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
component_type = array_component_signature->type;
|
||||
switch(component_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
(*jEnv)->SetObjectArrayElement(jEnv, java_array, index, java_value.l);
|
||||
if (is_local_ref) \
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_value.l);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_ReportJavaError(cx, jEnv, "Error assigning to Java object array");
|
||||
return JS_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
#undef SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
605
mozilla/js/src/liveconnect/jsj_class.c
Normal file
605
mozilla/js/src/liveconnect/jsj_class.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the code that constructs and manipulates JavaClassDescriptor
|
||||
* structs, which are the native wrappers for Java classes.
|
||||
* JavaClassDescriptors are used to describe the signatures of methods and
|
||||
* fields. There is a JavaClassDescriptor associated with the reflection of
|
||||
* each Java Object.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsj_hash.h" /* Hash tables */
|
||||
|
||||
/* A one-to-one mapping between all referenced java.lang.Class objects and
|
||||
their corresponding JavaClassDescriptor objects */
|
||||
static JSJHashTable *java_class_reflections;
|
||||
|
||||
/*
|
||||
* Given a JVM handle to a java.lang.Class object, malloc a C-string
|
||||
* containing the UTF8 encoding of the fully qualified name of the class.
|
||||
* It's the caller's responsibility to free the returned string.
|
||||
*
|
||||
* If an error occurs, NULL is returned and the error reporter called.
|
||||
*/
|
||||
const char *
|
||||
jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
jstring java_class_name_jstr;
|
||||
const char *java_class_name;
|
||||
|
||||
/* Get java.lang.String object containing class name */
|
||||
java_class_name_jstr =
|
||||
(*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getName);
|
||||
|
||||
|
||||
if (!java_class_name_jstr)
|
||||
goto error;
|
||||
|
||||
/* Convert to UTF8 encoding and copy */
|
||||
java_class_name = jsj_DupJavaStringUTF(cx, jEnv, java_class_name_jstr);
|
||||
if (!java_class_name)
|
||||
return NULL;
|
||||
|
||||
return java_class_name;
|
||||
|
||||
error:
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java class name using"
|
||||
"java.lang.Class.getName()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert in-place a string of the form "java.lang.String" into "java/lang/String".
|
||||
* Though the former style is conventionally used by Java programmers, the latter is
|
||||
* what the JNI functions require.
|
||||
*/
|
||||
void
|
||||
jsj_MakeJNIClassname(char * class_name)
|
||||
{
|
||||
char * c;
|
||||
for (c = class_name; *c; c++)
|
||||
if (*c == '.')
|
||||
*c = '/';
|
||||
}
|
||||
|
||||
/*
|
||||
* Classify an instance of java.lang.Class as either one of the primitive
|
||||
* types, e.g. int, char, etc., as an array type or as a non-array object type
|
||||
* (subclass of java.lang.Object) by returning the appropriate enum member.
|
||||
*
|
||||
*/
|
||||
static JavaSignatureChar
|
||||
get_signature_type(JSContext *cx, JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JavaSignatureChar type;
|
||||
const char *java_class_name;
|
||||
|
||||
/* Get UTF8 encoding of class name */
|
||||
java_class_name = class_descriptor->name;
|
||||
PR_ASSERT(java_class_name);
|
||||
if (!java_class_name)
|
||||
return JAVA_SIGNATURE_UNKNOWN;
|
||||
|
||||
if (!strcmp(java_class_name, "byte"))
|
||||
type = JAVA_SIGNATURE_BYTE;
|
||||
else if (!strcmp(java_class_name, "char"))
|
||||
type = JAVA_SIGNATURE_CHAR;
|
||||
else if (!strcmp(java_class_name, "float"))
|
||||
type = JAVA_SIGNATURE_FLOAT;
|
||||
else if (!strcmp(java_class_name, "double"))
|
||||
type = JAVA_SIGNATURE_DOUBLE;
|
||||
else if (!strcmp(java_class_name, "int"))
|
||||
type = JAVA_SIGNATURE_INT;
|
||||
else if (!strcmp(java_class_name, "long"))
|
||||
type = JAVA_SIGNATURE_LONG;
|
||||
else if (!strcmp(java_class_name, "short"))
|
||||
type = JAVA_SIGNATURE_SHORT;
|
||||
else if (!strcmp(java_class_name, "boolean"))
|
||||
type = JAVA_SIGNATURE_BOOLEAN;
|
||||
else if (!strcmp(java_class_name, "void"))
|
||||
type = JAVA_SIGNATURE_VOID;
|
||||
else
|
||||
/* Well, I guess it's a Java class, then. */
|
||||
type = JAVA_SIGNATURE_CLASS;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
is_java_array_class(JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
return (*jEnv)->CallBooleanMethod(jEnv, java_class, jlClass_isArray);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the class of a Java array's component type. This is not the same
|
||||
* as the array's element type. For example, the component type of an array
|
||||
* of type SomeType[][][] is SomeType[][], but its element type is SomeType.
|
||||
*
|
||||
* If an error occurs, NULL is returned and an error reported.
|
||||
*/
|
||||
static jclass
|
||||
get_java_array_component_class(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
jclass result;
|
||||
result = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getComponentType);
|
||||
if (!result) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't get Java array component class using "
|
||||
"java.lang.Class.getComponentType()");
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a Java class, fill in the signature structure that describes the class.
|
||||
* If an error occurs, JS_FALSE is returned and the error reporter called.
|
||||
*/
|
||||
static JSBool
|
||||
compute_java_class_signature(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature)
|
||||
{
|
||||
jclass java_class = signature->java_class;
|
||||
|
||||
if (is_java_array_class(jEnv, java_class)) {
|
||||
jclass component_class;
|
||||
|
||||
signature->type = JAVA_SIGNATURE_ARRAY;
|
||||
|
||||
component_class = get_java_array_component_class(cx, jEnv, java_class);
|
||||
if (!component_class)
|
||||
return JS_FALSE;
|
||||
|
||||
signature->array_component_signature =
|
||||
jsj_GetJavaClassDescriptor(cx, jEnv, component_class);
|
||||
if (!signature->array_component_signature)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
signature->type = get_signature_type(cx, signature);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a JavaSignature object into a string format as used by
|
||||
* the JNI functions, e.g. java.lang.Object ==> "Ljava/lang/Object;"
|
||||
* The caller is responsible for freeing the resulting string.
|
||||
*
|
||||
* If an error is encountered, NULL is returned and an error reported.
|
||||
*/
|
||||
const char *
|
||||
jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature)
|
||||
{
|
||||
char *sig;
|
||||
|
||||
if (signature->type == JAVA_SIGNATURE_CLASS) {
|
||||
/* A non-array object class */
|
||||
sig = PR_smprintf("L%s;", signature->name);
|
||||
if (sig)
|
||||
jsj_MakeJNIClassname(sig);
|
||||
|
||||
} else if (signature->type == JAVA_SIGNATURE_ARRAY) {
|
||||
/* An array class */
|
||||
const char *component_signature_string;
|
||||
|
||||
component_signature_string =
|
||||
jsj_ConvertJavaSignatureToString(cx, signature->array_component_signature);
|
||||
if (!component_signature_string)
|
||||
return NULL;
|
||||
sig = PR_smprintf("[%s", component_signature_string);
|
||||
JS_free(cx, (char*)component_signature_string);
|
||||
|
||||
} else {
|
||||
/* A primitive class */
|
||||
sig = PR_smprintf("%c", (char)signature->type);
|
||||
}
|
||||
|
||||
if (!sig) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a JavaSignature object into a human-readable string format as seen
|
||||
* in Java source files, e.g. "byte", or "int[][]" or "java.lang.String".
|
||||
* The caller is responsible for freeing the resulting string.
|
||||
*
|
||||
* If an error is encountered, NULL is returned and an error reported.
|
||||
*/
|
||||
const char *
|
||||
jsj_ConvertJavaSignatureToHRString(JSContext *cx,
|
||||
JavaSignature *signature)
|
||||
{
|
||||
char *sig;
|
||||
JavaSignature *acs;
|
||||
|
||||
if (signature->type == JAVA_SIGNATURE_ARRAY) {
|
||||
/* An array class */
|
||||
const char *component_signature_string;
|
||||
acs = signature->array_component_signature;
|
||||
component_signature_string =
|
||||
jsj_ConvertJavaSignatureToHRString(cx, acs);
|
||||
if (!component_signature_string)
|
||||
return NULL;
|
||||
sig = PR_smprintf("%s[]", component_signature_string);
|
||||
JS_free(cx, (char*)component_signature_string);
|
||||
|
||||
} else {
|
||||
/* A primitive class or a non-array object class */
|
||||
sig = JS_strdup(cx, signature->name);
|
||||
}
|
||||
|
||||
if (!sig) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_java_member_descriptor(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor)
|
||||
{
|
||||
JavaMethodSpec *method, *next_method;
|
||||
if (member_descriptor->field)
|
||||
jsj_DestroyFieldSpec(cx, jEnv, member_descriptor->field);
|
||||
|
||||
method = member_descriptor->methods;
|
||||
while (method) {
|
||||
next_method = method->next;
|
||||
jsj_DestroyMethodSpec(cx, jEnv, method);
|
||||
method = next_method;
|
||||
}
|
||||
|
||||
if (member_descriptor->invoke_func_obj)
|
||||
JS_RemoveRoot(cx, &member_descriptor->invoke_func_obj);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_class_member_descriptors(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor)
|
||||
{
|
||||
JavaMemberDescriptor *next_member;
|
||||
|
||||
while (member_descriptor) {
|
||||
next_member = member_descriptor->next;
|
||||
destroy_java_member_descriptor(cx, jEnv, member_descriptor);
|
||||
member_descriptor = next_member;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JS_FREE_IF(cx, (char *)class_descriptor->name);
|
||||
if (class_descriptor->java_class) {
|
||||
JSJ_HashTableRemove(java_class_reflections,
|
||||
class_descriptor->java_class, (void*)jEnv);
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, class_descriptor->java_class);
|
||||
}
|
||||
|
||||
if (class_descriptor->array_component_signature)
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor->array_component_signature);
|
||||
|
||||
destroy_class_member_descriptors(cx, jEnv, class_descriptor->instance_members);
|
||||
destroy_class_member_descriptors(cx, jEnv, class_descriptor->static_members);
|
||||
destroy_class_member_descriptors(cx, jEnv, class_descriptor->constructors);
|
||||
JS_free(cx, class_descriptor);
|
||||
}
|
||||
|
||||
static JavaClassDescriptor *
|
||||
new_class_descriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = (JavaClassDescriptor *)JS_malloc(cx, sizeof(JavaClassDescriptor));
|
||||
if (!class_descriptor)
|
||||
return NULL;
|
||||
memset(class_descriptor, 0, sizeof(JavaClassDescriptor));
|
||||
|
||||
class_descriptor->name = jsj_GetJavaClassName(cx, jEnv, java_class);
|
||||
if (!class_descriptor->name)
|
||||
goto error;
|
||||
|
||||
java_class = (*jEnv)->NewGlobalRef(jEnv, java_class);
|
||||
if (!java_class) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Unable to reference Java class");
|
||||
goto error;
|
||||
}
|
||||
class_descriptor->java_class = java_class;
|
||||
|
||||
if (!compute_java_class_signature(cx, jEnv, class_descriptor))
|
||||
goto error;
|
||||
|
||||
class_descriptor->modifiers =
|
||||
(*jEnv)->CallIntMethod(jEnv, java_class, jlClass_getModifiers);
|
||||
class_descriptor->ref_count = 1;
|
||||
|
||||
if (!JSJ_HashTableAdd(java_class_reflections, java_class, class_descriptor,
|
||||
(void*)jEnv))
|
||||
goto error;
|
||||
|
||||
return class_descriptor;
|
||||
|
||||
error:
|
||||
destroy_class_descriptor(cx, jEnv, class_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Trivial helper for jsj_DiscardJavaClassReflections(), below */
|
||||
static PRIntn
|
||||
enumerate_remove_java_class(JSJHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
JNIEnv *jEnv = (JNIEnv*)arg;
|
||||
jclass java_class;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = (JavaClassDescriptor*)he->value;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_class);
|
||||
class_descriptor->java_class = NULL;
|
||||
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
/* This shutdown routine discards all JNI references to Java objects
|
||||
that have been reflected into JS, even if there are still references
|
||||
to them from JS. */
|
||||
void
|
||||
jsj_DiscardJavaClassReflections(JNIEnv *jEnv)
|
||||
{
|
||||
if (java_class_reflections) {
|
||||
JSJ_HashTableEnumerateEntries(java_class_reflections,
|
||||
enumerate_remove_java_class,
|
||||
(void*)jEnv);
|
||||
JSJ_HashTableDestroy(java_class_reflections);
|
||||
java_class_reflections = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern JavaClassDescriptor *
|
||||
jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
class_descriptor = JSJ_HashTableLookup(java_class_reflections,
|
||||
(const void *)java_class,
|
||||
(void*)jEnv);
|
||||
if (!class_descriptor)
|
||||
return new_class_descriptor(cx, jEnv, java_class);
|
||||
|
||||
PR_ASSERT(class_descriptor->ref_count > 0);
|
||||
class_descriptor->ref_count++;
|
||||
return class_descriptor;
|
||||
}
|
||||
|
||||
void
|
||||
jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!--class_descriptor->ref_count)
|
||||
destroy_class_descriptor(cx, jEnv, class_descriptor);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
reflect_java_methods_and_fields(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_statics_only)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
if (reflect_statics_only)
|
||||
class_descriptor->static_members_reflected = JS_TRUE;
|
||||
else
|
||||
class_descriptor->instance_members_reflected = JS_TRUE;
|
||||
|
||||
if (!jsj_ReflectJavaMethods(cx, jEnv, class_descriptor, reflect_statics_only))
|
||||
return JS_FALSE;
|
||||
if (!jsj_ReflectJavaFields(cx, jEnv, class_descriptor, reflect_statics_only))
|
||||
return JS_FALSE;
|
||||
|
||||
if (reflect_statics_only) {
|
||||
member_descriptor = class_descriptor->static_members;
|
||||
while (member_descriptor) {
|
||||
class_descriptor->num_static_members++;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
} else {
|
||||
member_descriptor = class_descriptor->instance_members;
|
||||
while (member_descriptor) {
|
||||
class_descriptor->num_instance_members++;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetClassStaticMembers(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!class_descriptor->static_members_reflected)
|
||||
reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE);
|
||||
return class_descriptor->static_members;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetClassInstanceMembers(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!class_descriptor->instance_members_reflected)
|
||||
reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_FALSE);
|
||||
return class_descriptor->instance_members;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor);
|
||||
while (member_descriptor) {
|
||||
if (id == member_descriptor->id)
|
||||
return member_descriptor;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetJavaStaticMemberDescriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name_jstr)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsid id;
|
||||
|
||||
if (!JavaStringToId(cx, jEnv, member_name_jstr, &id))
|
||||
return NULL;
|
||||
|
||||
member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (member_descriptor)
|
||||
return member_descriptor;
|
||||
|
||||
member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
|
||||
if (!member_descriptor)
|
||||
return NULL;
|
||||
memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));
|
||||
|
||||
member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr);
|
||||
if (!member_descriptor->name) {
|
||||
JS_free(cx, member_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
member_descriptor->id = id;
|
||||
|
||||
member_descriptor->next = class_descriptor->static_members;
|
||||
class_descriptor->static_members = member_descriptor;
|
||||
|
||||
return member_descriptor;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetJavaClassConstructors(JSContext *cx,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
if (class_descriptor->constructors)
|
||||
return class_descriptor->constructors;
|
||||
|
||||
member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
|
||||
if (!member_descriptor)
|
||||
return NULL;
|
||||
memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));
|
||||
|
||||
member_descriptor->name = JS_strdup(cx, "<init>");
|
||||
if (!member_descriptor->name) {
|
||||
JS_free(cx, member_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class_descriptor->constructors = member_descriptor;
|
||||
|
||||
return member_descriptor;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!class_descriptor->static_members_reflected)
|
||||
reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE);
|
||||
return class_descriptor->constructors;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor);
|
||||
while (member_descriptor) {
|
||||
if (id == member_descriptor->id)
|
||||
return member_descriptor;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetJavaMemberDescriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name_jstr)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsid id;
|
||||
|
||||
if (!JavaStringToId(cx, jEnv, member_name_jstr, &id))
|
||||
return NULL;
|
||||
|
||||
member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (member_descriptor)
|
||||
return member_descriptor;
|
||||
|
||||
member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
|
||||
if (!member_descriptor)
|
||||
return NULL;
|
||||
memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));
|
||||
|
||||
member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr);
|
||||
if (!member_descriptor->name) {
|
||||
JS_free(cx, member_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
member_descriptor->id = id;
|
||||
|
||||
member_descriptor->next = class_descriptor->instance_members;
|
||||
class_descriptor->instance_members = member_descriptor;
|
||||
|
||||
return member_descriptor;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsj_InitJavaClassReflectionsTable()
|
||||
{
|
||||
java_class_reflections =
|
||||
JSJ_NewHashTable(64, jsj_HashJavaObject, jsj_JavaObjectComparator,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (!java_class_reflections)
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
806
mozilla/js/src/liveconnect/jsj_convert.c
Normal file
806
mozilla/js/src/liveconnect/jsj_convert.c
Normal file
@@ -0,0 +1,806 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* Below is the code that converts between Java and JavaScript values of all
|
||||
* types.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/* Floating-point double utilities, stolen from jsnum.h */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
|
||||
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
|
||||
#else
|
||||
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
|
||||
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
|
||||
#endif
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
|
||||
|
||||
#define JSDOUBLE_IS_NaN(x) \
|
||||
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
|
||||
(JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
|
||||
|
||||
#define JSDOUBLE_IS_INFINITE(x) \
|
||||
((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
|
||||
!JSDOUBLE_LO32(x))
|
||||
|
||||
static JSBool
|
||||
convert_js_obj_to_JSObject_wrapper(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj,
|
||||
JavaSignature *signature,
|
||||
int *cost, jobject *java_value)
|
||||
{
|
||||
if (!njJSObject) {
|
||||
if (java_value)
|
||||
JS_ReportError(cx, "Couldn't convert JavaScript object to an "
|
||||
"instance of netscape.javascript.JSObject "
|
||||
"because that class could not be loaded.");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!(*jEnv)->IsAssignableFrom(jEnv, njJSObject, signature->java_class))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!java_value)
|
||||
return JS_TRUE;
|
||||
|
||||
*java_value = jsj_WrapJSObject(cx, jEnv, js_obj);
|
||||
|
||||
return (*java_value != NULL);
|
||||
}
|
||||
|
||||
jstring
|
||||
jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str)
|
||||
{
|
||||
jstring result;
|
||||
result = (*jEnv)->NewString(jEnv, JS_GetStringChars(js_str),
|
||||
JS_GetStringLength(js_str));
|
||||
if (!result) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance "
|
||||
"of java.lang.String");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a JS value to an instance of java.lang.Object or one of its subclasses,
|
||||
* performing any necessary type coercion. If non-trivial coercion is required,
|
||||
* the cost value is incremented. If the java_value pass-by-reference argument
|
||||
* is non-NULL, the resulting Java value is stored there.
|
||||
*
|
||||
* Returns JS_TRUE if the conversion is possible, JS_FALSE otherwise
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jobject *java_value, JSBool *is_local_refp)
|
||||
{
|
||||
JSString *jsstr;
|
||||
jclass target_java_class;
|
||||
|
||||
PR_ASSERT(signature->type == JAVA_SIGNATURE_CLASS ||
|
||||
signature->type == JAVA_SIGNATURE_ARRAY);
|
||||
|
||||
/* Initialize to default case, in which no new Java object is
|
||||
synthesized to perform the conversion and, therefore, no JNI local
|
||||
references are being held. */
|
||||
*is_local_refp = JS_FALSE;
|
||||
|
||||
/* Get the Java type of the target value */
|
||||
target_java_class = signature->java_class;
|
||||
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
JSObject *js_obj = JSVAL_TO_OBJECT(v);
|
||||
|
||||
/* JS null is always assignable to a Java object */
|
||||
if (!js_obj) {
|
||||
if (java_value)
|
||||
*java_value = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0) ||
|
||||
JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) {
|
||||
|
||||
/* The source value is a Java object wrapped inside a JavaScript
|
||||
object. Unwrap the JS object and return the original Java
|
||||
object if it's class makes it assignment-compatible with the
|
||||
target class using Java's assignability rules. */
|
||||
JavaObjectWrapper *java_wrapper = JS_GetPrivate(cx, js_obj);
|
||||
jobject java_obj = java_wrapper->java_obj;
|
||||
|
||||
if ((*jEnv)->IsInstanceOf(jEnv, java_obj, target_java_class)) {
|
||||
if (java_value)
|
||||
*java_value = java_obj;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
/* Don't allow wrapped Java objects to be converted to strings */
|
||||
goto conversion_error;
|
||||
#else
|
||||
/* Fall through, to attempt conversion to a Java string */
|
||||
#endif
|
||||
|
||||
} else if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) {
|
||||
/* We're dealing with the reflection of a Java class */
|
||||
JavaClassDescriptor *java_class_descriptor = JS_GetPrivate(cx, js_obj);
|
||||
|
||||
/* Check if target type is java.lang.Class class */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlClass, target_java_class)) {
|
||||
if (java_value)
|
||||
*java_value = java_class_descriptor->java_class;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Check if target type is netscape.javascript.JSObject wrapper class */
|
||||
if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) {
|
||||
if (*java_value)
|
||||
*is_local_refp = JS_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through, to attempt conversion to a Java string */
|
||||
|
||||
} else if (JS_InstanceOf(cx, js_obj, &JavaMember_class, 0)) {
|
||||
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_OBJECT, &v))
|
||||
return JS_FALSE;
|
||||
return jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost,
|
||||
java_value, is_local_refp);
|
||||
|
||||
} else {
|
||||
/* Otherwise, see if the target type is the netscape.javascript.JSObject
|
||||
wrapper class or one of its subclasses, in which case a
|
||||
reference is passed to the original JS object by wrapping it
|
||||
inside an instance of netscape.javascript.JSObject */
|
||||
if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through, to attempt conversion to a Java string */
|
||||
}
|
||||
|
||||
} else if (JSVAL_IS_NUMBER(v)) {
|
||||
/* JS numbers, integral or not, can be converted to instances of java.lang.Double */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlDouble, target_java_class)) {
|
||||
if (java_value) {
|
||||
jsdouble d;
|
||||
if (!JS_ValueToNumber(cx, v, &d))
|
||||
goto conversion_error;
|
||||
*java_value = (*jEnv)->NewObject(jEnv, jlDouble, jlDouble_Double, d);
|
||||
if (*java_value) {
|
||||
*is_local_refp = JS_TRUE;
|
||||
} else {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Couldn't construct instance of java.lang.Double");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
(*cost)++;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* Fall through, to attempt conversion to a java.lang.String ... */
|
||||
|
||||
} else if (JSVAL_IS_BOOLEAN(v)) {
|
||||
/* JS boolean values can be converted to instances of java.lang.Boolean */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlBoolean, target_java_class)) {
|
||||
if (java_value) {
|
||||
JSBool b;
|
||||
if (!JS_ValueToBoolean(cx, v, &b))
|
||||
goto conversion_error;
|
||||
*java_value =
|
||||
(*jEnv)->NewObject(jEnv, jlBoolean, jlBoolean_Boolean, b);
|
||||
if (*java_value) {
|
||||
*is_local_refp = JS_TRUE;
|
||||
} else {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance "
|
||||
"of java.lang.Boolean");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
(*cost)++;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* Fall through, to attempt conversion to a java.lang.String ... */
|
||||
}
|
||||
|
||||
/* If no other conversion is possible, see if the target type is java.lang.String */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlString, target_java_class)) {
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
JSBool is_string = JSVAL_IS_STRING(v);
|
||||
#endif
|
||||
|
||||
/* Convert to JS string, if necessary, and then to a Java Unicode string */
|
||||
jsstr = JS_ValueToString(cx, v);
|
||||
if (jsstr) {
|
||||
if (java_value) {
|
||||
*java_value = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr);
|
||||
if (*java_value) {
|
||||
*is_local_refp = JS_TRUE;
|
||||
} else {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
if (!is_string)
|
||||
(*cost)++;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
conversion_error:
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Valid ranges for Java numeric types */
|
||||
#define jbyte_MAX_VALUE 127.0
|
||||
#define jbyte_MIN_VALUE -128.0
|
||||
#define jchar_MAX_VALUE 65535.0
|
||||
#define jchar_MIN_VALUE 0.0
|
||||
#define jshort_MAX_VALUE 32767.0
|
||||
#define jshort_MIN_VALUE -32768.0
|
||||
#define jint_MAX_VALUE 2147483647.0
|
||||
#define jint_MIN_VALUE -2147483648.0
|
||||
#define jlong_MAX_VALUE 9223372036854775807.0
|
||||
#define jlong_MIN_VALUE -9223372036854775808.0
|
||||
|
||||
/* Utility macro for jsj_ConvertJSValueToJavaValue(), below */
|
||||
#define JSVAL_TO_INTEGRAL_JVALUE(type_name, member_name, member_type, jsval, java_value) \
|
||||
if (!JSVAL_IS_NUMBER(v)) { \
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) \
|
||||
goto conversion_error; \
|
||||
(*cost)++; \
|
||||
} \
|
||||
{ \
|
||||
member_type member_name; \
|
||||
\
|
||||
if (JSVAL_IS_INT(v)) { \
|
||||
jsint ival = JSVAL_TO_INT(v); \
|
||||
member_name = (member_type) ival; \
|
||||
\
|
||||
/* Check to see if the jsval's magnitude is too large to be \
|
||||
representable in the target java type */ \
|
||||
if (member_name != ival) \
|
||||
goto numeric_conversion_error; \
|
||||
} else { \
|
||||
jdouble dval = *JSVAL_TO_DOUBLE(v); \
|
||||
\
|
||||
/* NaN becomes zero when converted to integral value */ \
|
||||
if (JSDOUBLE_IS_NaN(dval)) \
|
||||
member_name = 0; \
|
||||
\
|
||||
/* Unrepresentably large numbers, including infinities, */ \
|
||||
/* cause an error. */ \
|
||||
else if ((dval > member_type ## _MAX_VALUE) || \
|
||||
(dval < member_type ## _MIN_VALUE)) { \
|
||||
goto numeric_conversion_error; \
|
||||
} else \
|
||||
member_name = (member_type) dval; \
|
||||
\
|
||||
/* Don't allow a non-integral number to be converted \
|
||||
to an integral type */ \
|
||||
/* Actually, we have to allow this for LC1 compatibility */ \
|
||||
/* if ((jdouble)member_name != dval) \
|
||||
(*cost)++; */ \
|
||||
} \
|
||||
if (java_value) \
|
||||
java_value->member_name = member_name; \
|
||||
}
|
||||
|
||||
#if XP_MAC
|
||||
|
||||
/* on MRJ jlong is typedef'd to wide, which is a struct. */
|
||||
#include <Math64.h>
|
||||
|
||||
static jsint jlong_to_jsint(jlong lvalue)
|
||||
{
|
||||
SInt64 val = WideToSInt64(lvalue);
|
||||
return S32Set(val);
|
||||
}
|
||||
|
||||
static jlong jsint_to_jlong(jsint ivalue)
|
||||
{
|
||||
SInt64 val = S64Set(ivalue);
|
||||
wide wval =SInt64ToWide(val);
|
||||
return *(jlong*)&wval;
|
||||
}
|
||||
|
||||
static jdouble jlong_to_jdouble(jlong lvalue)
|
||||
{
|
||||
SInt64 val = WideToSInt64(lvalue);
|
||||
return SInt64ToLongDouble(val);
|
||||
}
|
||||
|
||||
static jlong jdouble_to_jlong(jdouble dvalue)
|
||||
{
|
||||
SInt64 val = LongDoubleToSInt64(dvalue);
|
||||
wide wval = SInt64ToWide(val);
|
||||
return *(jlong*)&wval;
|
||||
}
|
||||
|
||||
/* Mac utility macro for jsj_ConvertJSValueToJavaValue(), below */
|
||||
#define JSVAL_TO_JLONG_JVALUE(member_name, member_type, jsvalue, java_value) \
|
||||
if (!JSVAL_IS_NUMBER(jsvalue)) { \
|
||||
if (!JS_ConvertValue(cx, jsvalue, JSTYPE_NUMBER, &jsvalue)) \
|
||||
goto conversion_error; \
|
||||
(*cost)++; \
|
||||
} \
|
||||
{ \
|
||||
member_type member_name; \
|
||||
\
|
||||
if (JSVAL_IS_INT(jsvalue)) { \
|
||||
jsint ival = JSVAL_TO_INT(jsvalue); \
|
||||
member_name = jsint_to_jlong(ival); \
|
||||
\
|
||||
} else { \
|
||||
jdouble dval = *JSVAL_TO_DOUBLE(jsvalue); \
|
||||
\
|
||||
/* NaN becomes zero when converted to integral value */ \
|
||||
if (JSDOUBLE_IS_NaN(dval)) \
|
||||
member_name = jsint_to_jlong(0); \
|
||||
\
|
||||
/* Unrepresentably large numbers, including infinities, */ \
|
||||
/* cause an error. */ \
|
||||
else if ((dval > member_type ## _MAX_VALUE) || \
|
||||
(dval < member_type ## _MIN_VALUE)) { \
|
||||
goto numeric_conversion_error; \
|
||||
} else \
|
||||
member_name = jdouble_to_jlong(dval); \
|
||||
\
|
||||
/* Don't allow a non-integral number to be converted \
|
||||
to an integral type */ \
|
||||
/* Actually, we have to allow this for LC1 compatibility */ \
|
||||
/*if (jlong_to_jdouble(member_name) != dval) \
|
||||
(*cost)++;*/ \
|
||||
} \
|
||||
if (java_value) \
|
||||
java_value->member_name = member_name; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define jlong_to_jdouble(lvalue) ((jdouble) lvalue)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert a JS value to a Java value of the given type signature. The cost
|
||||
* variable is incremented if coercion is required, e.g. the source value is
|
||||
* a string, but the target type is a boolean.
|
||||
*
|
||||
* Returns JS_FALSE if no conversion is possible, either because the jsval has
|
||||
* a type that is wholly incompatible with the Java value, or because a scalar
|
||||
* jsval can't be represented in a variable of the target type without loss of
|
||||
* precision, e.g. the source value is "4.2" but the destination type is byte.
|
||||
* If conversion is not possible and java_value is non-NULL, the JS error
|
||||
* reporter is called with an appropriate message.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v,
|
||||
JavaSignature *signature,
|
||||
int *cost, jvalue *java_value, JSBool *is_local_refp)
|
||||
{
|
||||
JavaSignatureChar type;
|
||||
JSBool success = JS_FALSE;
|
||||
|
||||
/* Initialize to default case, in which no new Java object is
|
||||
synthesized to perform the conversion and, therefore, no JNI local
|
||||
references are being held. */
|
||||
*is_local_refp = JS_FALSE;
|
||||
|
||||
type = signature->type;
|
||||
switch (type) {
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
if (!JSVAL_IS_BOOLEAN(v)) {
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v))
|
||||
goto conversion_error;
|
||||
(*cost)++;
|
||||
}
|
||||
if (java_value)
|
||||
java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
/* A one-character string can be converted into a character */
|
||||
if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) {
|
||||
v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v)));
|
||||
}
|
||||
JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
#if XP_MAC
|
||||
JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value);
|
||||
#else
|
||||
JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
if (!JSVAL_IS_NUMBER(v)) {
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v))
|
||||
goto conversion_error;
|
||||
(*cost)++;
|
||||
}
|
||||
if (java_value) {
|
||||
if (JSVAL_IS_INT(v))
|
||||
java_value->f = (jfloat) JSVAL_TO_INT(v);
|
||||
else
|
||||
java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
if (!JSVAL_IS_NUMBER(v)) {
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v))
|
||||
goto conversion_error;
|
||||
(*cost)++;
|
||||
}
|
||||
if (java_value) {
|
||||
if (JSVAL_IS_INT(v))
|
||||
java_value->d = (jdouble) JSVAL_TO_INT(v);
|
||||
else
|
||||
java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost,
|
||||
&java_value->l, is_local_refp))
|
||||
goto conversion_error;
|
||||
break;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return JS_TRUE;
|
||||
|
||||
numeric_conversion_error:
|
||||
success = JS_TRUE;
|
||||
/* Fall through ... */
|
||||
|
||||
conversion_error:
|
||||
|
||||
if (java_value) {
|
||||
const char *jsval_string;
|
||||
JSString *jsstr;
|
||||
|
||||
jsval_string = NULL;
|
||||
jsstr = JS_ValueToString(cx, v);
|
||||
if (jsstr)
|
||||
jsval_string = JS_GetStringBytes(jsstr);
|
||||
if (!jsval_string)
|
||||
jsval_string = "";
|
||||
|
||||
JS_ReportError(cx, "Unable to convert JavaScript value %s to "
|
||||
"Java value of type %s",
|
||||
jsval_string, signature->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* A utility routine to create a JavaScript Unicode string from a
|
||||
* java.lang.String (Unicode) string.
|
||||
*/
|
||||
JSString *
|
||||
jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str)
|
||||
{
|
||||
JSString *js_str;
|
||||
jboolean is_copy;
|
||||
const jchar *ucs2_str;
|
||||
jchar *copy_ucs2_str;
|
||||
jsize ucs2_str_len, num_bytes;
|
||||
|
||||
ucs2_str_len = (*jEnv)->GetStringLength(jEnv, java_str);
|
||||
ucs2_str = (*jEnv)->GetStringChars(jEnv, java_str, &is_copy);
|
||||
if (!ucs2_str) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Unable to extract native Unicode from Java string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js_str = NULL;
|
||||
|
||||
/* The string data passed into JS_NewUCString() is
|
||||
not copied, so make a copy of the Unicode character vector. */
|
||||
num_bytes = ucs2_str_len * sizeof(jchar);
|
||||
copy_ucs2_str = (jchar*)JS_malloc(cx, num_bytes);
|
||||
if (!copy_ucs2_str)
|
||||
goto done;
|
||||
memcpy(copy_ucs2_str, ucs2_str, num_bytes);
|
||||
|
||||
js_str = JS_NewUCString(cx, (jschar*)copy_ucs2_str, ucs2_str_len);
|
||||
|
||||
done:
|
||||
(*jEnv)->ReleaseStringChars(jEnv, java_str, ucs2_str);
|
||||
return js_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to obtain a JS string representation of a Java object.
|
||||
* The java_obj argument must be of type java.lang.Object or a subclass.
|
||||
* If java_obj is a Java string, it's value is simply extracted and
|
||||
* copied into a JS string. Otherwise, the toString() method is called
|
||||
* on java_obj.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaObjectToJSString(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
JSString *js_str;
|
||||
jstring java_str;
|
||||
jmethodID toString;
|
||||
|
||||
/* Create a Java string, unless java_obj is already a java.lang.String */
|
||||
if ((*jEnv)->IsInstanceOf(jEnv, java_obj, jlString)) {
|
||||
java_str = java_obj;
|
||||
} else {
|
||||
jclass java_class;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
toString = (*jEnv)->GetMethodID(jEnv, java_class, "toString",
|
||||
"()Ljava/lang/String;");
|
||||
if (!toString) {
|
||||
/* All Java objects have a toString method */
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "No toString() method for class %s!",
|
||||
class_descriptor->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
java_str = (*jEnv)->CallObjectMethod(jEnv, java_obj, toString);
|
||||
if (!java_str) {
|
||||
jsj_ReportJavaError(cx, jEnv, "toString() method failed");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract Unicode from java.lang.String instance and convert to JS string */
|
||||
js_str = jsj_ConvertJavaStringToJSString(cx, jEnv, java_str);
|
||||
if (!js_str)
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = STRING_TO_JSVAL(js_str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a Java object to a number by attempting to call the
|
||||
* doubleValue() method on a Java object to get a double result.
|
||||
* This usually only works on instances of java.lang.Double, but the code
|
||||
* is generalized to work with any Java object that supports this method.
|
||||
*
|
||||
* Returns JS_TRUE if the call was successful.
|
||||
* Returns JS_FALSE if conversion is not possible or an error occurs.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
jdouble d;
|
||||
jmethodID doubleValue;
|
||||
jclass java_class;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
doubleValue = (*jEnv)->GetMethodID(jEnv, java_class, "doubleValue", "()D");
|
||||
if (!doubleValue) {
|
||||
/* There is no doubleValue() method for the object. Try toString()
|
||||
instead and the JS engine will attempt to convert the result to
|
||||
a number. */
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
return jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor,
|
||||
java_obj, vp);
|
||||
}
|
||||
|
||||
d = (*jEnv)->CallDoubleMethod(jEnv, java_obj, doubleValue);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "doubleValue() method failed");
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_NewDoubleValue(cx, d, vp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a Java object to a boolean by attempting to call the
|
||||
* booleanValue() method on a Java object to get a boolean result.
|
||||
* This usually only works on instances of java.lang.Boolean, but the code
|
||||
* is generalized to work with any Java object that supports this method.
|
||||
*
|
||||
* Returns JS_TRUE if the call was successful.
|
||||
* Returns JS_FALSE if conversion is not possible or an error occurs.
|
||||
*/
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
jboolean b;
|
||||
jmethodID booleanValue;
|
||||
jclass java_class;
|
||||
|
||||
/* Null converts to false. */
|
||||
if (!java_obj) {
|
||||
*vp = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
java_class = class_descriptor->java_class;
|
||||
booleanValue = (*jEnv)->GetMethodID(jEnv, java_obj, "booleanValue", "()Z");
|
||||
|
||||
/* Non-null Java object does not have a booleanValue() method, so
|
||||
it converts to true. */
|
||||
if (!booleanValue) {
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
*vp = JSVAL_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
b = (*jEnv)->CallBooleanMethod(jEnv, java_obj, booleanValue);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "booleanValue() method failed");
|
||||
return JS_FALSE;
|
||||
}
|
||||
*vp = BOOLEAN_TO_JSVAL(b);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reflect a Java object into a JS value. The source object, java_obj, must
|
||||
* be of type java.lang.Object or a subclass and may, therefore, be an array.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
jclass java_class;
|
||||
JSObject *js_obj;
|
||||
|
||||
/* A null in Java-land is also null in JS */
|
||||
if (!java_obj) {
|
||||
*vp = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
java_class = (*jEnv)->GetObjectClass(jEnv, java_obj);
|
||||
|
||||
/*
|
||||
* If it's an instance of netscape.javascript.JSObject, i.e. a wrapper
|
||||
* around a JS object that has been passed into the Java world, unwrap
|
||||
* it to obtain the original JS object.
|
||||
*/
|
||||
if (njJSObject && (*jEnv)->IsInstanceOf(jEnv, java_obj, njJSObject)) {
|
||||
#ifdef PRESERVE_JSOBJECT_IDENTITY
|
||||
js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_obj, njJSObject_internal));
|
||||
#else
|
||||
js_obj = jsj_UnwrapJSObjectWrapper(jEnv, java_obj);
|
||||
#endif
|
||||
PR_ASSERT(js_obj);
|
||||
if (!js_obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(js_obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Instances of java.lang.String are wrapped so we can call methods on
|
||||
* them, but they convert to a JS string if used in a string context.
|
||||
*/
|
||||
/* TODO - let's get rid of this annoying "feature" */
|
||||
|
||||
/* otherwise, wrap it inside a JavaObject */
|
||||
js_obj = jsj_WrapJavaObject(cx, jEnv, java_obj, java_class);
|
||||
if (!js_obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(js_obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a Java value (primitive or object) to a JS value.
|
||||
*
|
||||
* This is usually an infallible operation, but JS_FALSE is returned
|
||||
* on an out-of-memory condition and the error reporter is called.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaSignature *signature,
|
||||
jvalue *java_value,
|
||||
jsval *vp)
|
||||
{
|
||||
int32 ival32;
|
||||
|
||||
switch (signature->type) {
|
||||
case JAVA_SIGNATURE_VOID:
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
*vp = INT_TO_JSVAL((jsint)java_value->b);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
*vp = INT_TO_JSVAL((jsint)java_value->c);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
*vp = INT_TO_JSVAL((jsint)java_value->s);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
ival32 = java_value->i;
|
||||
if (INT_FITS_IN_JSVAL(ival32)) {
|
||||
*vp = INT_TO_JSVAL((jsint) ival32);
|
||||
return JS_TRUE;
|
||||
} else {
|
||||
return JS_NewDoubleValue(cx, ival32, vp);
|
||||
}
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
*vp = BOOLEAN_TO_JSVAL((JSBool) java_value->z);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
return JS_NewDoubleValue(cx, jlong_to_jdouble(java_value->j), vp);
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
return JS_NewDoubleValue(cx, java_value->f, vp);
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
return JS_NewDoubleValue(cx, java_value->d, vp);
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_value->l, vp);
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
383
mozilla/js/src/liveconnect/jsj_field.c
Normal file
383
mozilla/js/src/liveconnect/jsj_field.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the code used to reflect Java fields as properties of
|
||||
* JavaObject objects and the code to access those fields.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/*
|
||||
* Add a single field, described by java_field, to the JavaMemberDescriptor
|
||||
* named by field_name within the given JavaClassDescriptor.
|
||||
*
|
||||
* Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error.
|
||||
*/
|
||||
static JSBool
|
||||
add_java_field_to_class_descriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring field_name_jstr,
|
||||
jobject java_field, /* a java.lang.reflect.Field */
|
||||
jint modifiers)
|
||||
{
|
||||
jclass fieldType;
|
||||
jfieldID fieldID;
|
||||
jclass java_class;
|
||||
|
||||
JSBool is_static_field;
|
||||
JavaMemberDescriptor *member_descriptor = NULL;
|
||||
const char *sig_cstr = NULL;
|
||||
const char *field_name = NULL;
|
||||
JavaSignature *signature = NULL;
|
||||
JavaFieldSpec *field_spec = NULL;
|
||||
|
||||
is_static_field = modifiers & ACC_STATIC;
|
||||
if (is_static_field) {
|
||||
member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr);
|
||||
} else {
|
||||
member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr);
|
||||
}
|
||||
if (!member_descriptor)
|
||||
goto error;
|
||||
|
||||
field_spec = (JavaFieldSpec*)JS_malloc(cx, sizeof(JavaFieldSpec));
|
||||
if (!field_spec)
|
||||
goto error;
|
||||
|
||||
field_spec->modifiers = modifiers;
|
||||
|
||||
/* Get the Java class corresponding to the type of the field */
|
||||
fieldType = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getType);
|
||||
if (!fieldType) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Unable to determine type of field using"
|
||||
" java.lang.reflect.Field.getType()");
|
||||
goto error;
|
||||
}
|
||||
|
||||
signature = jsj_GetJavaClassDescriptor(cx, jEnv, fieldType);
|
||||
if (!signature)
|
||||
goto error;
|
||||
field_spec->signature = signature;
|
||||
|
||||
field_name = jsj_DupJavaStringUTF(cx, jEnv, field_name_jstr);
|
||||
if (!field_name)
|
||||
goto error;
|
||||
field_spec->name = field_name;
|
||||
|
||||
/* Compute the JNI-style (string-based) signature of the field type */
|
||||
sig_cstr = jsj_ConvertJavaSignatureToString(cx, signature);
|
||||
if (!sig_cstr)
|
||||
goto error;
|
||||
|
||||
/* Compute the JNI fieldID and cache it for quick field access */
|
||||
java_class = class_descriptor->java_class;
|
||||
if (is_static_field)
|
||||
fieldID = (*jEnv)->GetStaticFieldID(jEnv, java_class, field_name, sig_cstr);
|
||||
else
|
||||
fieldID = (*jEnv)->GetFieldID(jEnv, java_class, field_name, sig_cstr);
|
||||
if (!fieldID) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't get Java field ID for class %s, field %s (sig=%s)",
|
||||
class_descriptor->name, field_name, sig_cstr);
|
||||
goto error;
|
||||
}
|
||||
field_spec->fieldID = fieldID;
|
||||
|
||||
JS_free(cx, (char*)sig_cstr);
|
||||
|
||||
member_descriptor->field = field_spec;
|
||||
|
||||
/* Success */
|
||||
return JS_TRUE;
|
||||
|
||||
error:
|
||||
if (field_spec) {
|
||||
JS_FREE_IF(cx, (char*)field_spec->name);
|
||||
JS_free(cx, field_spec);
|
||||
}
|
||||
JS_FREE_IF(cx, (char*)sig_cstr);
|
||||
if (signature)
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, signature);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up a JavaFieldSpec and all its resources.
|
||||
*/
|
||||
void
|
||||
jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field)
|
||||
{
|
||||
JS_FREE_IF(cx, (char*)field->name);
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, field->signature);
|
||||
JS_free(cx, field);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a JavaMemberDescriptor to the collection of members in class_descriptor
|
||||
* for every public field of the identified Java class. (A separate collection
|
||||
* is kept in class_descriptor for static and instance members.)
|
||||
* If reflect_only_static_fields is set, instance fields are not reflected. If
|
||||
* it isn't set, only instance fields are reflected and static fields are not
|
||||
* reflected.
|
||||
*
|
||||
* Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_static_fields)
|
||||
{
|
||||
int i;
|
||||
JSBool ok;
|
||||
jint modifiers;
|
||||
jobject java_field;
|
||||
jstring field_name_jstr;
|
||||
jarray joFieldArray;
|
||||
jsize num_fields;
|
||||
jclass java_class;
|
||||
|
||||
/* Get a java array of java.lang.reflect.Field objects, by calling
|
||||
java.lang.Class.getFields(). */
|
||||
java_class = class_descriptor->java_class;
|
||||
joFieldArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getFields);
|
||||
if (!joFieldArray) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't determine Java object's fields "
|
||||
"using java.lang.Class.getFields()");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Iterate over the class fields */
|
||||
num_fields = (*jEnv)->GetArrayLength(jEnv, joFieldArray);
|
||||
for (i = 0; i < num_fields; i++) {
|
||||
|
||||
/* Get the i'th reflected field */
|
||||
java_field = (*jEnv)->GetObjectArrayElement(jEnv, joFieldArray, i);
|
||||
if (!java_field) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Can't access a Field[] array");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Get the field modifiers, e.g. static, public, private, etc. */
|
||||
modifiers = (*jEnv)->CallIntMethod(jEnv, java_field, jlrField_getModifiers);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't access a Field's modifiers using"
|
||||
"java.lang.reflect.Field.getModifiers()");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Don't allow access to private or protected Java fields. */
|
||||
if (!(modifiers & ACC_PUBLIC))
|
||||
continue;
|
||||
|
||||
/* Reflect all instance fields or all static fields, but not both */
|
||||
if (reflect_only_static_fields != ((modifiers & ACC_STATIC) != 0))
|
||||
continue;
|
||||
|
||||
/* Determine the unqualified name of the field */
|
||||
field_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getName);
|
||||
if (!field_name_jstr) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't obtain a Field's name"
|
||||
"java.lang.reflect.Field.getName()");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Add a JavaFieldSpec object to the JavaClassDescriptor */
|
||||
ok = add_java_field_to_class_descriptor(cx, jEnv, class_descriptor, field_name_jstr,
|
||||
java_field, modifiers);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the value of a Java field and return it as a JavaScript value.
|
||||
* If the field is static, then java_obj is a Java class, otherwise
|
||||
* it's a Java instance object.
|
||||
*
|
||||
* Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error.
|
||||
*/
|
||||
JSBool
|
||||
jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
JSBool is_static_field;
|
||||
jvalue java_value;
|
||||
JavaSignature *signature;
|
||||
JavaSignatureChar field_type;
|
||||
jfieldID fieldID = field_spec->fieldID;
|
||||
|
||||
is_static_field = field_spec->modifiers & ACC_STATIC;
|
||||
|
||||
#define GET_JAVA_FIELD(Type,member) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (is_static_field) \
|
||||
java_value.member = \
|
||||
(*jEnv)->GetStatic##Type##Field(jEnv, java_obj, fieldID); \
|
||||
else \
|
||||
java_value.member = \
|
||||
(*jEnv)->Get##Type##Field(jEnv, java_obj, fieldID); \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Error reading Java field"); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
signature = field_spec->signature;
|
||||
field_type = signature->type;
|
||||
switch(field_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
GET_JAVA_FIELD(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
GET_JAVA_FIELD(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
GET_JAVA_FIELD(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
GET_JAVA_FIELD(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
GET_JAVA_FIELD(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
GET_JAVA_FIELD(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
GET_JAVA_FIELD(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
GET_JAVA_FIELD(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
GET_JAVA_FIELD(Object,l);
|
||||
break;
|
||||
|
||||
#undef GET_JAVA_FIELD
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return jsj_ConvertJavaValueToJSValue(cx, jEnv, signature, &java_value, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jclass java_obj, jsval js_val)
|
||||
{
|
||||
JSBool is_static_field, is_local_ref;
|
||||
int dummy_cost;
|
||||
jvalue java_value;
|
||||
JavaSignature *signature;
|
||||
JavaSignatureChar field_type;
|
||||
jfieldID fieldID = field_spec->fieldID;
|
||||
|
||||
is_static_field = field_spec->modifiers & ACC_STATIC;
|
||||
|
||||
#define SET_JAVA_FIELD(Type,member) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (is_static_field) { \
|
||||
(*jEnv)->SetStatic##Type##Field(jEnv, java_obj, fieldID, \
|
||||
java_value.member); \
|
||||
} else { \
|
||||
(*jEnv)->Set##Type##Field(jEnv, java_obj, fieldID,java_value.member);\
|
||||
} \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Error assigning to Java field"); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
signature = field_spec->signature;
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, signature, &dummy_cost,
|
||||
&java_value, &is_local_ref))
|
||||
return JS_FALSE;
|
||||
|
||||
field_type = signature->type;
|
||||
switch(field_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
SET_JAVA_FIELD(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
SET_JAVA_FIELD(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
SET_JAVA_FIELD(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
SET_JAVA_FIELD(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
SET_JAVA_FIELD(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
SET_JAVA_FIELD(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
SET_JAVA_FIELD(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
SET_JAVA_FIELD(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
SET_JAVA_FIELD(Object,l);
|
||||
if (is_local_ref)
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_value.l);
|
||||
break;
|
||||
|
||||
#undef SET_JAVA_FIELD
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
487
mozilla/js/src/liveconnect/jsj_hash.c
Normal file
487
mozilla/js/src/liveconnect/jsj_hash.c
Normal file
@@ -0,0 +1,487 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 is a copy of the NSPR hash-table library, but it has been slightly
|
||||
* modified to allow an additional argument to be passed into the hash
|
||||
* key-comparision function. This is used to maintain thread-safety by
|
||||
* passing in a JNIEnv pointer to the key-comparison function rather
|
||||
* than storing it in a global. All types,function names, etc. have
|
||||
* been renamed from their original NSPR names to protect the innocent.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_hash.h"
|
||||
#include "prtypes.h"
|
||||
#ifdef NSPR20
|
||||
# include "prlog.h"
|
||||
# include "prbit.h"
|
||||
#else
|
||||
# include "prassert.h"
|
||||
#endif
|
||||
|
||||
/* Compute the number of buckets in ht */
|
||||
#define NBUCKETS(ht) (1 << (JSJ_HASH_BITS - (ht)->shift))
|
||||
|
||||
/* The smallest table has 16 buckets */
|
||||
#define MINBUCKETSLOG2 4
|
||||
#define MINBUCKETS (1 << MINBUCKETSLOG2)
|
||||
|
||||
/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
|
||||
#define OVERLOADED(n) ((n) - ((n) >> 3))
|
||||
|
||||
/* Compute the number of entries below which we shrink the table by half */
|
||||
#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
|
||||
|
||||
/*
|
||||
** Stubs for default hash allocator ops.
|
||||
*/
|
||||
static void *
|
||||
DefaultAllocTable(void *pool, size_t size)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeTable(void *pool, void *item)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
free(item);
|
||||
}
|
||||
|
||||
static JSJHashEntry *
|
||||
DefaultAllocEntry(void *pool, const void *key)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool,key)
|
||||
#endif
|
||||
|
||||
return malloc(sizeof(JSJHashEntry));
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeEntry(void *pool, JSJHashEntry *he, PRUintn flag)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
free(he);
|
||||
}
|
||||
|
||||
static JSJHashAllocOps defaultHashAllocOps = {
|
||||
DefaultAllocTable, DefaultFreeTable,
|
||||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
PR_IMPLEMENT(JSJHashTable *)
|
||||
JSJ_NewHashTable(PRUint32 n, JSJHashFunction keyHash,
|
||||
JSJHashComparator keyCompare, JSJHashComparator valueCompare,
|
||||
JSJHashAllocOps *allocOps, void *allocPriv)
|
||||
{
|
||||
JSJHashTable *ht;
|
||||
PRUint32 nb;
|
||||
|
||||
if (n <= MINBUCKETS) {
|
||||
n = MINBUCKETSLOG2;
|
||||
} else {
|
||||
n = PR_CeilingLog2(n);
|
||||
if ((PRInt32)n < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!allocOps) allocOps = &defaultHashAllocOps;
|
||||
|
||||
ht = (*allocOps->allocTable)(allocPriv, sizeof *ht);
|
||||
if (!ht)
|
||||
return 0;
|
||||
memset(ht, 0, sizeof *ht);
|
||||
ht->shift = JSJ_HASH_BITS - n;
|
||||
n = 1 << n;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (n > 16000) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
nb = n * sizeof(JSJHashEntry *);
|
||||
ht->buckets = (*allocOps->allocTable)(allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
ht->keyHash = keyHash;
|
||||
ht->keyCompare = keyCompare;
|
||||
ht->valueCompare = valueCompare;
|
||||
ht->allocOps = allocOps;
|
||||
ht->allocPriv = allocPriv;
|
||||
return ht;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_HashTableDestroy(JSJHashTable *ht)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
JSJHashEntry *he, *next;
|
||||
JSJHashAllocOps *allocOps = ht->allocOps;
|
||||
void *allocPriv = ht->allocPriv;
|
||||
|
||||
n = NBUCKETS(ht);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = ht->buckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
(*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht->buckets);
|
||||
#ifdef DEBUG
|
||||
memset(ht, 0xDB, sizeof *ht);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
}
|
||||
|
||||
/*
|
||||
** Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
#define GOLDEN_RATIO 0x9E3779B9U
|
||||
|
||||
PR_IMPLEMENT(JSJHashEntry **)
|
||||
JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg)
|
||||
{
|
||||
JSJHashEntry *he, **hep, **hep0;
|
||||
JSJHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = hep0 = &ht->buckets[h];
|
||||
while ((he = *hep) != 0) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key, arg)) {
|
||||
/* Move to front of chain if not already there */
|
||||
if (hep != hep0) {
|
||||
*hep = he->next;
|
||||
he->next = *hep0;
|
||||
*hep0 = he;
|
||||
}
|
||||
return hep0;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJHashEntry *)
|
||||
JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep,
|
||||
JSJHashNumber keyHash, const void *key, void *value,
|
||||
void *arg)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
JSJHashEntry *he, *next, **oldbuckets;
|
||||
PRUint32 nb;
|
||||
|
||||
/* Grow the table if it is overloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (ht->nentries >= OVERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->ngrows++;
|
||||
#endif
|
||||
ht->shift--;
|
||||
oldbuckets = ht->buckets;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (2 * n > 16000)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
nb = 2 * n * sizeof(JSJHashEntry *);
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
}
|
||||
|
||||
/* Make a new key value entry */
|
||||
he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
|
||||
if (!he)
|
||||
return 0;
|
||||
he->keyHash = keyHash;
|
||||
he->key = key;
|
||||
he->value = value;
|
||||
he->next = *hep;
|
||||
*hep = he;
|
||||
ht->nentries++;
|
||||
return he;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJHashEntry *)
|
||||
JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg)
|
||||
{
|
||||
JSJHashNumber keyHash;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key, arg);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
if ((he = *hep) != 0) {
|
||||
/* Hit; see if values match */
|
||||
if ((*ht->valueCompare)(he->value, value, arg)) {
|
||||
/* key,value pair is already present in table */
|
||||
return he;
|
||||
}
|
||||
if (he->value)
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
|
||||
he->value = value;
|
||||
return he;
|
||||
}
|
||||
return JSJ_HashTableRawAdd(ht, hep, keyHash, key, value, arg);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
JSJHashEntry *next, **oldbuckets;
|
||||
PRUint32 nb;
|
||||
|
||||
*hep = he->next;
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
|
||||
|
||||
/* Shrink table if it's underloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (--ht->nentries < UNDERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->nshrinks++;
|
||||
#endif
|
||||
ht->shift++;
|
||||
oldbuckets = ht->buckets;
|
||||
nb = n * sizeof(JSJHashEntry*) / 2;
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRBool)
|
||||
JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg)
|
||||
{
|
||||
JSJHashNumber keyHash;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key, arg);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
if ((he = *hep) == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
/* Hit; remove element */
|
||||
JSJ_HashTableRawRemove(ht, hep, he, arg);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *)
|
||||
JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg)
|
||||
{
|
||||
JSJHashNumber keyHash;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key, arg);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
if ((he = *hep) != 0) {
|
||||
return he->value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over the entries in the hash table calling func for each
|
||||
** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg)
|
||||
{
|
||||
JSJHashEntry *he, **hep;
|
||||
PRUint32 i, nbuckets;
|
||||
int rv, n = 0;
|
||||
JSJHashEntry *todo = 0;
|
||||
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
hep = &ht->buckets[i];
|
||||
while ((he = *hep) != 0) {
|
||||
rv = (*f)(he, n, arg);
|
||||
n++;
|
||||
if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
|
||||
*hep = he->next;
|
||||
if (rv & HT_ENUMERATE_REMOVE) {
|
||||
he->next = todo;
|
||||
todo = he;
|
||||
}
|
||||
} else {
|
||||
hep = &he->next;
|
||||
}
|
||||
if (rv & HT_ENUMERATE_STOP) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
hep = &todo;
|
||||
while ((he = *hep) != 0) {
|
||||
JSJ_HashTableRawRemove(ht, hep, he, arg);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef HASHMETER
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_HashTableDumpMeter(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double mean, variance;
|
||||
PRUint32 nchains, nbuckets;
|
||||
PRUint32 i, n, maxChain, maxChainLen;
|
||||
JSJHashEntry *he;
|
||||
|
||||
variance = 0;
|
||||
nchains = 0;
|
||||
maxChainLen = 0;
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
he = ht->buckets[i];
|
||||
if (!he)
|
||||
continue;
|
||||
nchains++;
|
||||
for (n = 0; he; he = he->next)
|
||||
n++;
|
||||
variance += n * n;
|
||||
if (n > maxChainLen) {
|
||||
maxChainLen = n;
|
||||
maxChain = i;
|
||||
}
|
||||
}
|
||||
mean = (double)ht->nentries / nchains;
|
||||
variance = fabs(variance / nchains - mean * mean);
|
||||
|
||||
fprintf(fp, "\nHash table statistics:\n");
|
||||
fprintf(fp, " number of lookups: %u\n", ht->nlookups);
|
||||
fprintf(fp, " number of entries: %u\n", ht->nentries);
|
||||
fprintf(fp, " number of grows: %u\n", ht->ngrows);
|
||||
fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
|
||||
fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
|
||||
/ ht->nlookups);
|
||||
fprintf(fp, "mean hash chain length: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " max hash chain length: %u\n", maxChainLen);
|
||||
fprintf(fp, " max hash chain: [%u]\n", maxChain);
|
||||
|
||||
for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
|
||||
if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
|
||||
break;
|
||||
}
|
||||
#endif /* HASHMETER */
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = JSJ_HashTableEnumerateEntries(ht, dump, fp);
|
||||
#ifdef HASHMETER
|
||||
JSJ_HashTableDumpMeter(ht, dump, fp);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJHashNumber)
|
||||
JSJ_HashString(const void *key)
|
||||
{
|
||||
JSJHashNumber h;
|
||||
const unsigned char *s;
|
||||
|
||||
h = 0;
|
||||
for (s = key; *s; s++)
|
||||
h = (h >> 28) ^ (h << 4) ^ *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_CompareStrings(const void *v1, const void *v2)
|
||||
{
|
||||
return strcmp(v1, v2) == 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
141
mozilla/js/src/liveconnect/jsj_hash.h
Normal file
141
mozilla/js/src/liveconnect/jsj_hash.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 is a copy of the NSPR hash-table library, but it has been slightly
|
||||
* modified to allow an additional argument to be passed into the hash
|
||||
* key-comparision function. This is used to maintain thread-safety by
|
||||
* passing in a JNIEnv pointer to the key-comparison function rather
|
||||
* than storing it in a global. All types,function names, etc. have
|
||||
* been renamed from their original NSPR names to protect the innocent.
|
||||
*/
|
||||
|
||||
#ifndef jsj_hash_h___
|
||||
#define jsj_hash_h___
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSJHashEntry JSJHashEntry;
|
||||
typedef struct JSJHashTable JSJHashTable;
|
||||
typedef PRUint32 JSJHashNumber;
|
||||
#define JSJ_HASH_BITS 32
|
||||
typedef JSJHashNumber (*JSJHashFunction)(const void *key, void *arg);
|
||||
typedef PRIntn (*JSJHashComparator)(const void *v1, const void *v2, void *arg);
|
||||
typedef PRIntn (*JSJHashEnumerator)(JSJHashEntry *he, PRIntn i, void *arg);
|
||||
|
||||
/* Flag bits in JSJHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
|
||||
|
||||
typedef struct JSJHashAllocOps {
|
||||
void * (*allocTable)(void *pool, size_t size);
|
||||
void (*freeTable)(void *pool, void *item);
|
||||
JSJHashEntry * (*allocEntry)(void *pool, const void *key);
|
||||
void (*freeEntry)(void *pool, JSJHashEntry *he, PRUintn flag);
|
||||
} JSJHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct JSJHashEntry {
|
||||
JSJHashEntry *next; /* hash chain linkage */
|
||||
JSJHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct JSJHashTable {
|
||||
JSJHashEntry **buckets; /* vector of hash buckets */
|
||||
PRUint32 nentries; /* number of entries in table */
|
||||
PRUint32 shift; /* multiplicative hash shift */
|
||||
JSJHashFunction keyHash; /* key hash function */
|
||||
JSJHashComparator keyCompare; /* key comparison function */
|
||||
JSJHashComparator valueCompare; /* value comparison function */
|
||||
JSJHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef HASHMETER
|
||||
PRUint32 nlookups; /* total number of lookups */
|
||||
PRUint32 nsteps; /* number of hash chains traversed */
|
||||
PRUint32 ngrows; /* number of table expansions */
|
||||
PRUint32 nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
PR_EXTERN(JSJHashTable *)
|
||||
JSJ_NewHashTable(PRUint32 n, JSJHashFunction keyHash,
|
||||
JSJHashComparator keyCompare, JSJHashComparator valueCompare,
|
||||
JSJHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
PR_EXTERN(void)
|
||||
JSJ_HashTableDestroy(JSJHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
PR_EXTERN(JSJHashEntry **)
|
||||
JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg);
|
||||
|
||||
PR_EXTERN(JSJHashEntry *)
|
||||
JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep, JSJHashNumber keyHash,
|
||||
const void *key, void *value, void *arg);
|
||||
|
||||
PR_EXTERN(void)
|
||||
JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg);
|
||||
|
||||
/* Higher level access methods */
|
||||
PR_EXTERN(JSJHashEntry *)
|
||||
JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg);
|
||||
|
||||
PR_EXTERN(PRBool)
|
||||
JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg);
|
||||
|
||||
PR_EXTERN(void *)
|
||||
JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
PR_EXTERN(JSJHashNumber)
|
||||
JSJ_HashString(const void *key);
|
||||
|
||||
/* Compare strings using strcmp(), return true if equal. */
|
||||
PR_EXTERN(int)
|
||||
JSJ_CompareStrings(const void *v1, const void *v2);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
PR_EXTERN(PRIntn)
|
||||
JSJ_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* jsj_hash_h___ */
|
||||
1164
mozilla/js/src/liveconnect/jsj_method.c
Normal file
1164
mozilla/js/src/liveconnect/jsj_method.c
Normal file
File diff suppressed because it is too large
Load Diff
0
mozilla/js/src/liveconnect/jsj_nodl.c
Normal file
0
mozilla/js/src/liveconnect/jsj_nodl.c
Normal file
552
mozilla/js/src/liveconnect/jsj_private.h
Normal file
552
mozilla/js/src/liveconnect/jsj_private.h
Normal file
@@ -0,0 +1,552 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* Declarations of private (internal) functions/data/types for
|
||||
* JavaScript <==> Java communication.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _JSJAVA_PVT_H
|
||||
#define _JSJAVA_PVT_H
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
/* NSPR1 compatibility definitions */
|
||||
#ifdef NSPR20
|
||||
# include "prprf.h"
|
||||
# include "prlog.h"
|
||||
# include "plhash.h" /* NSPR hash-tables */
|
||||
#else
|
||||
# include "prprintf.h"
|
||||
# include "prassert.h"
|
||||
# include "prhash.h" /* NSPR hash-tables */
|
||||
# define PRHashNumber prhashcode
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
# include "prosdep.h"
|
||||
#endif
|
||||
|
||||
#include "jsj_hash.h" /* Hash tables */
|
||||
#include "jni.h" /* Java Native Interface */
|
||||
#include "jsapi.h" /* JavaScript engine API */
|
||||
#include "jsjava.h" /* LiveConnect public API */
|
||||
|
||||
|
||||
/*************************** Type Declarations ******************************/
|
||||
|
||||
/* Forward type declarations */
|
||||
typedef struct JavaMemberDescriptor JavaMemberDescriptor;
|
||||
typedef struct JavaMethodSpec JavaMethodSpec;
|
||||
typedef struct JavaClassDescriptor JavaClassDescriptor;
|
||||
typedef struct JavaClassDescriptor JavaSignature;
|
||||
typedef struct CapturedJSError CapturedJSError;
|
||||
typedef struct JavaMemberVal JavaMemberVal;
|
||||
|
||||
/*
|
||||
* This enum uses the same character encoding used by the JDK to encode
|
||||
* Java type signatures, but the enum is easier to debug/compile with.
|
||||
*/
|
||||
typedef enum {
|
||||
JAVA_SIGNATURE_ARRAY = '[',
|
||||
JAVA_SIGNATURE_BYTE = 'B',
|
||||
JAVA_SIGNATURE_CHAR = 'C',
|
||||
JAVA_SIGNATURE_CLASS = 'L',
|
||||
JAVA_SIGNATURE_FLOAT = 'F',
|
||||
JAVA_SIGNATURE_DOUBLE = 'D',
|
||||
JAVA_SIGNATURE_INT = 'I',
|
||||
JAVA_SIGNATURE_LONG = 'J',
|
||||
JAVA_SIGNATURE_SHORT = 'S',
|
||||
JAVA_SIGNATURE_VOID = 'V',
|
||||
JAVA_SIGNATURE_BOOLEAN = 'Z',
|
||||
JAVA_SIGNATURE_UNKNOWN = 0
|
||||
} JavaSignatureChar;
|
||||
|
||||
/* The signature of a Java method consists of the signatures of all its
|
||||
arguments and its return type signature. */
|
||||
typedef struct JavaMethodSignature {
|
||||
jsize num_args; /* Length of arg_signatures array */
|
||||
JavaSignature ** arg_signatures; /* Array of argument signatures */
|
||||
JavaSignature * return_val_signature; /* Return type signature */
|
||||
} JavaMethodSignature;
|
||||
|
||||
/* A descriptor for the reflection of a single Java field */
|
||||
typedef struct JavaFieldSpec {
|
||||
jfieldID fieldID; /* JVM opaque access handle for field */
|
||||
JavaSignature * signature; /* Java type of field */
|
||||
int modifiers; /* Bitfield indicating field qualifiers */
|
||||
const char * name; /* UTF8; TODO - Should support Unicode field names */
|
||||
} JavaFieldSpec;
|
||||
|
||||
/* A descriptor for the reflection of a single Java method.
|
||||
Each overloaded method has a separate corresponding JavaMethodSpec. */
|
||||
struct JavaMethodSpec {
|
||||
jmethodID methodID; /* JVM opaque access handle for method */
|
||||
JavaMethodSignature signature;
|
||||
const char * name; /* UTF8; TODO - Should support Unicode method names */
|
||||
JavaMethodSpec * next; /* next method in chain of overloaded methods */
|
||||
};
|
||||
|
||||
/*
|
||||
* A descriptor for the reflection of a single member of a Java object.
|
||||
* This can represent one or more Java methods and/or a single field.
|
||||
* (When there is more than one method attached to a single JavaMemberDescriptor
|
||||
* they are overloaded methods sharing the same simple name.) This same
|
||||
* descriptor type is used for both static or instance members.
|
||||
*/
|
||||
struct JavaMemberDescriptor {
|
||||
const char * name; /* simple name of field and/or method */
|
||||
jsid id; /* hashed name for quick JS property lookup */
|
||||
JavaFieldSpec * field; /* field with the given name, if any */
|
||||
JavaMethodSpec * methods; /* Overloaded methods which share the same name, if any */
|
||||
JavaMemberDescriptor * next; /* next descriptor in same defining class */
|
||||
JSObject * invoke_func_obj; /* If non-null, JSFunction obj to invoke method */
|
||||
};
|
||||
|
||||
/* This is the native portion of a reflected Java class */
|
||||
struct JavaClassDescriptor {
|
||||
const char * name; /* Name of class, e.g. "java/lang/Byte" */
|
||||
JavaSignatureChar type; /* class category: primitive type, object, array */
|
||||
jclass java_class; /* Opaque JVM handle to corresponding java.lang.Class */
|
||||
int num_instance_members;
|
||||
int num_static_members;
|
||||
JSBool instance_members_reflected;
|
||||
JavaMemberDescriptor * instance_members;
|
||||
JSBool static_members_reflected;
|
||||
JavaMemberDescriptor * static_members;
|
||||
JavaMemberDescriptor * constructors;
|
||||
int modifiers; /* Class declaration qualifiers,
|
||||
e.g. abstract, private */
|
||||
int ref_count; /* # of references to this struct */
|
||||
JavaSignature * array_component_signature; /* Only non-NULL for array classes */
|
||||
};
|
||||
|
||||
/* This is the native portion of a reflected Java method or field */
|
||||
struct JavaMemberVal {
|
||||
jsval field_val; /* Captured value of Java field */
|
||||
jsval invoke_method_func_val; /* JSFunction wrapper around Java method invoker */
|
||||
JavaMemberDescriptor * descriptor;
|
||||
JavaMemberVal * next;
|
||||
};
|
||||
|
||||
/* This is the native portion of a reflected Java object */
|
||||
typedef struct JavaObjectWrapper {
|
||||
jobject java_obj; /* Opaque JVM ref to Java object */
|
||||
JavaClassDescriptor * class_descriptor; /* Java class info */
|
||||
} JavaObjectWrapper;
|
||||
|
||||
/* These are definitions of the Java class/method/field modifier bits.
|
||||
These really shouldn't be hard-coded here. Rather,
|
||||
they should be read from java.lang.reflect.Modifier */
|
||||
#define ACC_PUBLIC 0x0001 /* visible to everyone */
|
||||
#define ACC_STATIC 0x0008 /* instance variable is static */
|
||||
#define ACC_FINAL 0x0010 /* no further subclassing,overriding */
|
||||
#define ACC_INTERFACE 0x0200 /* class is an interface */
|
||||
#define ACC_ABSTRACT 0x0400 /* no definition provided */
|
||||
|
||||
/* A JSJavaVM structure must be created for each Java VM that is accessed
|
||||
via LiveConnect */
|
||||
struct JSJavaVM {
|
||||
/* TODO - all LiveConnect global variables should be migrated into this
|
||||
structure in order to allow more than one LiveConnect-enabled
|
||||
Java VM to exist within the same process. */
|
||||
SystemJavaVM * java_vm;
|
||||
JNIEnv * main_thread_env; /* Main-thread Java environment */
|
||||
JSBool jsj_created_java_vm;
|
||||
int num_attached_threads;
|
||||
JSJavaVM * next; /* next VM among all created VMs */
|
||||
};
|
||||
|
||||
/* Per-thread state that encapsulates the connection to the Java VM */
|
||||
struct JSJavaThreadState {
|
||||
const char * name; /* Thread name, for debugging */
|
||||
JSJavaVM * jsjava_vm; /* All per-JVM state */
|
||||
JNIEnv * jEnv; /* Per-thread opaque handle to Java VM */
|
||||
CapturedJSError * pending_js_errors; /* JS errors to be thrown as Java exceptions */
|
||||
JSContext * cx; /* current JS context for thread */
|
||||
JSJavaThreadState * next; /* next thread state among all created threads */
|
||||
};
|
||||
|
||||
struct JavaToJSSavedState {
|
||||
JSErrorReporter error_reporter;
|
||||
JSJavaThreadState* java_jsj_env;
|
||||
};
|
||||
typedef struct JavaToJSSavedState JavaToJSSavedState;
|
||||
|
||||
|
||||
|
||||
/******************************** Globals ***********************************/
|
||||
|
||||
extern JSJCallbacks *JSJ_callbacks;
|
||||
|
||||
/* JavaScript classes that reflect Java objects */
|
||||
extern JSClass JavaObject_class;
|
||||
extern JSClass JavaArray_class;
|
||||
extern JSClass JavaClass_class;
|
||||
extern JSClass JavaMember_class;
|
||||
|
||||
/*
|
||||
* Opaque JVM handles to Java classes, methods and objects required for
|
||||
* Java reflection. These are computed and cached during initialization.
|
||||
* TODO: These should be moved inside the JSJavaVM struct
|
||||
*/
|
||||
extern jclass jlObject; /* java.lang.Object */
|
||||
extern jclass jlrConstructor; /* java.lang.reflect.Constructor */
|
||||
extern jclass jlThrowable; /* java.lang.Throwable */
|
||||
extern jclass jlSystem; /* java.lang.System */
|
||||
extern jclass jlClass; /* java.lang.Class */
|
||||
extern jclass jlBoolean; /* java.lang.Boolean */
|
||||
extern jclass jlDouble; /* java.lang.Double */
|
||||
extern jclass jlString; /* java.lang.String */
|
||||
extern jclass njJSObject; /* netscape.javascript.JSObject */
|
||||
extern jclass njJSException; /* netscape.javascript.JSException */
|
||||
extern jclass njJSUtil; /* netscape.javascript.JSUtil */
|
||||
|
||||
extern jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */
|
||||
extern jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */
|
||||
extern jmethodID jlClass_getFields; /* java.lang.Class.getFields() */
|
||||
extern jmethodID jlClass_getName; /* java.lang.Class.getName() */
|
||||
extern jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */
|
||||
extern jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */
|
||||
extern jmethodID jlClass_isArray; /* java.lang.Class.isArray() */
|
||||
|
||||
extern jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */
|
||||
extern jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */
|
||||
extern jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */
|
||||
extern jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */
|
||||
|
||||
extern jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */
|
||||
extern jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */
|
||||
|
||||
extern jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */
|
||||
extern jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */
|
||||
extern jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */
|
||||
|
||||
extern jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */
|
||||
extern jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */
|
||||
|
||||
extern jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */
|
||||
extern jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */
|
||||
extern jmethodID jlDouble_Double; /* java.lang.Double constructor */
|
||||
extern jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */
|
||||
|
||||
extern jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */
|
||||
|
||||
extern jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */
|
||||
|
||||
extern jmethodID njJSException_JSException; /* netscape.javascipt.JSexception constructor */
|
||||
extern jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */
|
||||
extern jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */
|
||||
extern jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */
|
||||
extern jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */
|
||||
extern jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */
|
||||
extern jfieldID njJSException_source; /* netscape.javascript.JSException.source */
|
||||
extern jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */
|
||||
|
||||
|
||||
/**************** Java <==> JS conversions and Java types *******************/
|
||||
extern JSBool
|
||||
jsj_ComputeJavaClassSignature(JSContext *cx,
|
||||
JavaSignature *signature,
|
||||
jclass java_class);
|
||||
|
||||
extern const char *
|
||||
jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature);
|
||||
extern const char *
|
||||
jsj_ConvertJavaSignatureToHRString(JSContext *cx,
|
||||
JavaSignature *signature);
|
||||
extern JavaMethodSignature *
|
||||
jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, jobject method,
|
||||
JavaMethodSignature *method_signature);
|
||||
|
||||
extern const char *
|
||||
jsj_ConvertJavaMethodSignatureToString(JSContext *cx,
|
||||
JavaMethodSignature *method_signature);
|
||||
extern const char *
|
||||
jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx,
|
||||
const char *method_name,
|
||||
JavaMethodSignature *method_signature);
|
||||
extern void
|
||||
jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *signature);
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jvalue *java_value, JSBool *is_local_refp);
|
||||
extern JSBool
|
||||
jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jobject *java_value, JSBool *is_local_refp);
|
||||
extern jstring
|
||||
jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str);
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature,
|
||||
jvalue *java_value, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv,
|
||||
jobject java_obj, jsval *vp);
|
||||
|
||||
extern JSString *
|
||||
jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str);
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSString(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSJavaThreadState *
|
||||
jsj_enter_js(JNIEnv *jEnv, jobject java_wrapper_obj,
|
||||
JSContext **cxp, JSObject **js_objp, JavaToJSSavedState* saved_state);
|
||||
extern JSBool
|
||||
jsj_exit_js(JSContext *cx, JSJavaThreadState *jsj_env, JavaToJSSavedState* original_state);
|
||||
|
||||
extern JavaClassDescriptor *
|
||||
jsj_get_jlObject_descriptor(JSContext *cx, JNIEnv *jEnv);
|
||||
|
||||
extern JSBool
|
||||
jsj_remove_js_obj_reflection_from_hashtable(JSContext *cx, JSObject *js_obj);
|
||||
|
||||
extern JSBool
|
||||
jsj_init_js_obj_reflections_table();
|
||||
|
||||
/************************ Java package reflection **************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaPackage(JSContext *, JSObject *,
|
||||
JavaPackageDef *predefined_packages);
|
||||
|
||||
/************************* Java class reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaClass(JSContext *cx, JSObject *global_obj);
|
||||
|
||||
extern void
|
||||
jsj_DiscardJavaClassReflections(JNIEnv *jEnv);
|
||||
|
||||
extern const char *
|
||||
jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class);
|
||||
|
||||
extern JavaClassDescriptor *
|
||||
jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class);
|
||||
|
||||
extern void
|
||||
jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JSObject *
|
||||
jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
const char *unqualified_class_name,
|
||||
jclass jclazz);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetJavaMemberDescriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetJavaStaticMemberDescriptor(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetJavaClassConstructors(JSContext *cx,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetClassInstanceMembers(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetClassStaticMembers(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JSBool
|
||||
jsj_InitJavaClassReflectionsTable();
|
||||
|
||||
/************************* Java field reflection ***************************/
|
||||
|
||||
extern JSBool
|
||||
jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jobject java_obj, jsval js_val);
|
||||
extern JSBool
|
||||
jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_static_fields);
|
||||
extern void
|
||||
jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field);
|
||||
|
||||
/************************* Java method reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_JavaInstanceMethodWrapper(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_JavaStaticMethodWrapper(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_JavaConstructorWrapper(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_static_methods);
|
||||
extern void
|
||||
jsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec);
|
||||
|
||||
/************************* Java member reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaMember(JSContext *, JSObject *);
|
||||
|
||||
extern JSBool
|
||||
jsj_ReflectJavaMethodsAndFields(JSContext *cx, JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_statics);
|
||||
|
||||
extern JSObject *
|
||||
jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val);
|
||||
|
||||
/************************* Java object reflection **************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaObject(JSContext *, JSObject *);
|
||||
|
||||
extern JSObject *
|
||||
jsj_WrapJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_obj, jclass java_class);
|
||||
|
||||
extern void
|
||||
jsj_DiscardJavaObjReflections(JNIEnv *jEnv);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
|
||||
|
||||
extern void
|
||||
JavaObject_finalize(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_resolve(JSContext *cx, JSObject *obj, jsval id);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
/************************* Java array reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaArray(JSContext *cx, JSObject *global_obj);
|
||||
|
||||
extern JSBool
|
||||
jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array,
|
||||
jsize index, JavaSignature *array_component_signature,
|
||||
jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array,
|
||||
jsize index, JavaSignature *array_component_signature,
|
||||
jsval js_val);
|
||||
|
||||
/********************* JavaScript object reflection ************************/
|
||||
extern jobject
|
||||
jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj);
|
||||
|
||||
extern JSObject *
|
||||
jsj_UnwrapJSObjectWrapper(JNIEnv *jEnv, jobject java_wrapper_obj);
|
||||
|
||||
extern void
|
||||
jsj_ClearPendingJSErrors(JSJavaThreadState *jsj_env);
|
||||
|
||||
extern JSBool
|
||||
jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception);
|
||||
|
||||
/**************************** Utilities ************************************/
|
||||
extern void
|
||||
jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...);
|
||||
|
||||
extern void
|
||||
jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...);
|
||||
|
||||
extern const char *
|
||||
jsj_GetJavaErrorMessage(JNIEnv *env);
|
||||
|
||||
extern void
|
||||
jsj_LogError(const char *error_msg);
|
||||
|
||||
PR_CALLBACK JSJHashNumber
|
||||
jsj_HashJavaObject(const void *key, void* env);
|
||||
|
||||
PR_CALLBACK intN
|
||||
jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg);
|
||||
|
||||
extern JSJavaThreadState *
|
||||
jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp);
|
||||
|
||||
extern void
|
||||
jsj_MakeJNIClassname(char *jClassName);
|
||||
|
||||
extern const char *
|
||||
jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object);
|
||||
|
||||
extern jsize
|
||||
jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array);
|
||||
|
||||
extern JSBool
|
||||
JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp);
|
||||
|
||||
extern const char *
|
||||
jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr);
|
||||
|
||||
JSJavaThreadState *
|
||||
jsj_MapJSContextToJSJThread(JSContext *cx, JNIEnv **envp);
|
||||
|
||||
JSJavaThreadState *
|
||||
jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_LOG(args) printf args
|
||||
#endif
|
||||
|
||||
#define JS_FREE_IF(cx, x) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (x) \
|
||||
JS_free(cx, x); \
|
||||
PR_END_MACRO
|
||||
|
||||
#endif /* _JSJAVA_PVT_H */
|
||||
361
mozilla/js/src/liveconnect/jsj_utils.c
Normal file
361
mozilla/js/src/liveconnect/jsj_utils.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains low-level utility code.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsjava.h" /* External LiveConnect API */
|
||||
|
||||
|
||||
/*
|
||||
* This is a hash-table utility routine that computes the hash code of a Java
|
||||
* object by calling java.lang.System.identityHashCode()
|
||||
*/
|
||||
PR_CALLBACK JSJHashNumber
|
||||
jsj_HashJavaObject(const void *key, void* env)
|
||||
{
|
||||
PRHashNumber hash_code;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
java_obj = (jobject)key;
|
||||
jEnv = (JNIEnv*) env;
|
||||
hash_code = (*jEnv)->CallStaticIntMethod(jEnv, jlSystem,
|
||||
jlSystem_identityHashCode, java_obj);
|
||||
PR_ASSERT(!(*jEnv)->ExceptionOccurred(jEnv));
|
||||
return hash_code;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a hash-table utility routine for comparing two Java objects.
|
||||
* It's not possible to use the == operator to directly compare two jobject's,
|
||||
* since they're opaque references and aren't guaranteed to be simple pointers
|
||||
* or handles (though they may be in some JVM implementations). Instead,
|
||||
* use the JNI routine for comparing the two objects.
|
||||
*/
|
||||
PR_CALLBACK intN
|
||||
jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg)
|
||||
{
|
||||
jobject java_obj1, java_obj2;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jEnv = (JNIEnv*)arg;
|
||||
java_obj1 = (jobject)v1;
|
||||
java_obj2 = (jobject)v2;
|
||||
|
||||
if (java_obj1 == java_obj2)
|
||||
return 1;
|
||||
return (*jEnv)->IsSameObject(jEnv, java_obj1, java_obj2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a UTF8, null-terminated encoding of a Java string. The string must
|
||||
* be free'ed by the caller.
|
||||
*
|
||||
* If an error occurs, returns NULL and calls the JS error reporter.
|
||||
*/
|
||||
const char *
|
||||
jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr)
|
||||
{
|
||||
const char *str, *retval;
|
||||
|
||||
str = (*jEnv)->GetStringUTFChars(jEnv, jstr, 0);
|
||||
if (!str) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Can't get UTF8 characters from "
|
||||
"Java string");
|
||||
return NULL;
|
||||
}
|
||||
retval = JS_strdup(cx, str);
|
||||
(*jEnv)->ReleaseStringUTFChars(jEnv, jstr, str);
|
||||
return retval;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp)
|
||||
{
|
||||
const jschar *ucs2;
|
||||
JSString *jsstr;
|
||||
jsize ucs2_len;
|
||||
jsval val;
|
||||
|
||||
ucs2 = (*jEnv)->GetStringChars(jEnv, jstr, 0);
|
||||
if (!ucs2) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain Unicode characters"
|
||||
"from Java string");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
ucs2_len = (*jEnv)->GetStringLength(jEnv, jstr);
|
||||
jsstr = JS_InternUCStringN(cx, ucs2, ucs2_len);
|
||||
(*jEnv)->ReleaseStringChars(jEnv, jstr, ucs2);
|
||||
if (!jsstr)
|
||||
return JS_FALSE;
|
||||
|
||||
val = STRING_TO_JSVAL(jsstr);
|
||||
JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Not used ?
|
||||
const char *
|
||||
jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object)
|
||||
{
|
||||
jobject java_class;
|
||||
|
||||
java_class = (*jEnv)->GetObjectClass(jEnv, java_object);
|
||||
|
||||
if (!java_class) {
|
||||
PR_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return jsj_GetJavaClassName(cx, jEnv, java_class);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return, as a C string, the error message associated with a Java exception
|
||||
* that occurred as a result of a JNI call, preceded by the class name of
|
||||
* the exception. As a special case, if the class of the exception is
|
||||
* netscape.javascript.JSException, the exception class name is omitted.
|
||||
*
|
||||
* NULL is returned if no Java exception is pending. The caller is
|
||||
* responsible for free'ing the returned string. On exit, the Java exception
|
||||
* is *not* cleared.
|
||||
*/
|
||||
const char *
|
||||
jsj_GetJavaErrorMessage(JNIEnv *jEnv)
|
||||
{
|
||||
const char *java_error_msg;
|
||||
char *error_msg = NULL;
|
||||
jthrowable exception;
|
||||
jstring java_exception_jstring;
|
||||
|
||||
exception = (*jEnv)->ExceptionOccurred(jEnv);
|
||||
if (exception && jlThrowable_toString) {
|
||||
java_exception_jstring =
|
||||
(*jEnv)->CallObjectMethod(jEnv, exception, jlThrowable_toString);
|
||||
java_error_msg = (*jEnv)->GetStringUTFChars(jEnv, java_exception_jstring, NULL);
|
||||
error_msg = strdup((char*)java_error_msg);
|
||||
(*jEnv)->ReleaseStringUTFChars(jEnv, java_exception_jstring, java_error_msg);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* (*jEnv)->ExceptionDescribe(jEnv); */
|
||||
#endif
|
||||
}
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return, as a C string, the JVM stack trace associated with a Java
|
||||
* exception, as would be printed by java.lang.Throwable.printStackTrace().
|
||||
* The caller is responsible for free'ing the returned string.
|
||||
*
|
||||
* Returns NULL if an error occurs.
|
||||
*/
|
||||
static const char *
|
||||
get_java_stack_trace(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception)
|
||||
{
|
||||
const char *backtrace;
|
||||
jstring backtrace_jstr;
|
||||
|
||||
backtrace = NULL;
|
||||
if (java_exception && njJSUtil_getStackTrace) {
|
||||
backtrace_jstr = (*jEnv)->CallStaticObjectMethod(jEnv, njJSUtil,
|
||||
njJSUtil_getStackTrace,
|
||||
java_exception);
|
||||
if (!backtrace_jstr) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Unable to get exception stack trace");
|
||||
return NULL;
|
||||
}
|
||||
backtrace = jsj_DupJavaStringUTF(cx, jEnv, backtrace_jstr);
|
||||
}
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
/* Full Java backtrace when Java exceptions reported to JavaScript */
|
||||
#define REPORT_JAVA_EXCEPTION_STACK_TRACE
|
||||
|
||||
/*
|
||||
* This is a wrapper around JS_ReportError(), useful when an error condition
|
||||
* is the result of a JVM failure or exception condition. It appends the
|
||||
* message associated with the pending Java exception to the passed in
|
||||
* printf-style format string and arguments.
|
||||
*/
|
||||
static void
|
||||
vreport_java_error(JSContext *cx, JNIEnv *jEnv, const char *format, va_list ap)
|
||||
{
|
||||
char *error_msg, *js_error_msg;
|
||||
const char *java_stack_trace;
|
||||
const char *java_error_msg;
|
||||
jthrowable java_exception;
|
||||
|
||||
java_error_msg = NULL;
|
||||
java_exception = (*jEnv)->ExceptionOccurred(jEnv);
|
||||
if (java_exception && njJSException &&
|
||||
(*jEnv)->IsInstanceOf(jEnv, java_exception, njJSException)) {
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
jsj_ReportUncaughtJSException(cx, jEnv, java_exception);
|
||||
return;
|
||||
}
|
||||
|
||||
js_error_msg = PR_vsmprintf(format, ap);
|
||||
|
||||
if (!js_error_msg) {
|
||||
PR_ASSERT(0); /* Out-of-memory */
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef REPORT_JAVA_EXCEPTION_STACK_TRACE
|
||||
|
||||
java_stack_trace = get_java_stack_trace(cx, jEnv, java_exception);
|
||||
if (java_stack_trace) {
|
||||
error_msg = PR_smprintf("%s\n%s", js_error_msg, java_stack_trace);
|
||||
free((char*)java_stack_trace);
|
||||
if (!error_msg) {
|
||||
PR_ASSERT(0); /* Out-of-memory */
|
||||
return;
|
||||
}
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
java_error_msg = jsj_GetJavaErrorMessage(jEnv);
|
||||
if (java_error_msg) {
|
||||
error_msg = PR_smprintf("%s (%s)\n", js_error_msg, java_error_msg);
|
||||
free((char*)java_error_msg);
|
||||
free(js_error_msg);
|
||||
} else {
|
||||
error_msg = js_error_msg;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, error_msg);
|
||||
|
||||
/* Important: the Java exception must not be cleared until the reporter
|
||||
has been called, because the capture_js_error_reports_for_java(),
|
||||
called from JS_ReportError(), needs to read the exception from the JVM */
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
free(error_msg);
|
||||
}
|
||||
|
||||
void
|
||||
jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vreport_java_error(cx, env, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as jsj_ReportJavaError, except "internal error: " is prepended
|
||||
* to message.
|
||||
*/
|
||||
void
|
||||
jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
const char *format2;
|
||||
|
||||
va_start(ap, format);
|
||||
format2 = PR_smprintf("internal error: %s", format);
|
||||
if (format2) {
|
||||
vreport_java_error(cx, env, format2, ap);
|
||||
free((void*)format2);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Most LiveConnect errors are signaled by calling JS_ReportError(),
|
||||
* but in some circumstances, the target JSContext for such errors
|
||||
* is not determinable, e.g. during initialization. In such cases
|
||||
* any error messages are routed to this function.
|
||||
*/
|
||||
void
|
||||
jsj_LogError(const char *error_msg)
|
||||
{
|
||||
if (JSJ_callbacks && JSJ_callbacks->error_print)
|
||||
JSJ_callbacks->error_print(error_msg);
|
||||
else
|
||||
fputs(error_msg, stderr);
|
||||
}
|
||||
|
||||
jsize
|
||||
jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array)
|
||||
{
|
||||
jsize array_length = (*jEnv)->GetArrayLength(jEnv, java_array);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain array length");
|
||||
return -1;
|
||||
}
|
||||
return array_length;
|
||||
}
|
||||
|
||||
static JSJavaThreadState *the_java_jsj_env = NULL;
|
||||
|
||||
JSJavaThreadState *
|
||||
jsj_MapJSContextToJSJThread(JSContext *cx, JNIEnv **envp)
|
||||
{
|
||||
JSJavaThreadState *jsj_env;
|
||||
char *err_msg;
|
||||
|
||||
*envp = NULL;
|
||||
err_msg = NULL;
|
||||
|
||||
jsj_env = the_java_jsj_env;
|
||||
if (jsj_env == NULL)
|
||||
jsj_env = JSJ_callbacks->map_js_context_to_jsj_thread(cx, &err_msg);
|
||||
if (!jsj_env) {
|
||||
if (err_msg) {
|
||||
JS_ReportError(cx, err_msg);
|
||||
free(err_msg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (envp)
|
||||
*envp = jsj_env->jEnv;
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since only one Java thread is allowed to enter JavaScript, this function is
|
||||
* used to enforce the use of that thread's state. The static global the_java_jsj_env
|
||||
* overrides using JSJ_callbacks->map_js_context_to_jsj_thread, which maps
|
||||
* native threads to JSJavaThreadStates. This isn't appropriate when Java calls
|
||||
* JavaScript, as there can be a many to one mapping from Java threads to native
|
||||
* threads.
|
||||
*/
|
||||
JSJavaThreadState *
|
||||
jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env)
|
||||
{
|
||||
JSJavaThreadState *old_jsj_env = the_java_jsj_env;
|
||||
the_java_jsj_env = java_jsj_env;
|
||||
return old_jsj_env;
|
||||
}
|
||||
264
mozilla/js/src/liveconnect/jsjava.h
Normal file
264
mozilla/js/src/liveconnect/jsjava.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* Publicly exported functions for JavaScript <==> Java communication.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _JSJAVA_H
|
||||
#define _JSJAVA_H
|
||||
|
||||
#ifndef prtypes_h___
|
||||
#include "prtypes.h"
|
||||
#endif
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
#include "jni.h" /* Java Native Interface */
|
||||
#include "jsapi.h" /* JavaScript engine API */
|
||||
|
||||
/*
|
||||
* A JSJavaVM structure is a wrapper around a JavaVM which incorporates
|
||||
* additional LiveConnect state.
|
||||
*/
|
||||
typedef struct JSJavaVM JSJavaVM;
|
||||
|
||||
/* LiveConnect and Java state, one per thread */
|
||||
typedef struct JSJavaThreadState JSJavaThreadState;
|
||||
|
||||
/*
|
||||
* An opaque type that represents the connection to the Java VM. In stand-alone
|
||||
* Java environments, this may be a JNI JavaVM object; in the browser environment
|
||||
* it is a reference to a JVM plugin. A set of callbacks in the JSJCallbacks
|
||||
* struct allow it to be manipulated.
|
||||
*/
|
||||
typedef struct SystemJavaVM SystemJavaVM;
|
||||
|
||||
/*
|
||||
* This callback table provides hooks to external functions that implement
|
||||
* functionality specific to the embedding. For example, these callbacks are
|
||||
* necessary in multi-threaded environments or to implement a security
|
||||
* policy.
|
||||
*/
|
||||
typedef struct JSJCallbacks {
|
||||
|
||||
/* This callback is invoked when there is no JavaScript execution
|
||||
environment (JSContext) associated with the current Java thread and
|
||||
a call is made from Java into JavaScript. (A JSContext is associated
|
||||
with a Java thread by calling the JSJ_SetJSContextForJavaThread()
|
||||
function.) This callback is only invoked when Java spontaneously calls
|
||||
into JavaScript, i.e. it is not called when JS calls into Java which
|
||||
calls back into JS.
|
||||
|
||||
This callback can be used to create a JSContext lazily, or obtain
|
||||
one from a pool of available JSContexts. The implementation of this
|
||||
callback can call JSJ_SetJSContextForJavaThread() to avoid any further
|
||||
callbacks of this type for this Java thread. */
|
||||
JSContext * (*map_jsj_thread_to_js_context)(JSJavaThreadState *jsj_env,
|
||||
JNIEnv *jEnv,
|
||||
char **errp);
|
||||
|
||||
/* This callback is invoked whenever a call is made into Java from
|
||||
JavaScript. It's responsible for mapping from a JavaScript execution
|
||||
environment (JSContext) to a Java thread. (A JavaContext can only
|
||||
be associated with one Java thread at a time.) */
|
||||
JSJavaThreadState * (*map_js_context_to_jsj_thread)(JSContext *cx,
|
||||
char **errp);
|
||||
|
||||
/* This callback implements netscape.javascript.JSObject.getWindow(),
|
||||
a method named for its behavior in the browser environment, where it
|
||||
returns the JS "Window" object corresponding to the HTML window that an
|
||||
applet is embedded within. More generally, it's a way for Java to get
|
||||
hold of a JS object that has not been explicitly passed to it. */
|
||||
JSObject * (*map_java_object_to_js_object)(JNIEnv *jEnv, void *pJavaObject,
|
||||
char **errp);
|
||||
|
||||
/* An interim callback function until the LiveConnect security story is
|
||||
straightened out. This function pointer can be set to NULL. */
|
||||
JSPrincipals * (*get_JSPrincipals_from_java_caller)(JNIEnv *jEnv, JSContext *pJSContext);
|
||||
|
||||
/* The following two callbacks sandwich any JS evaluation performed
|
||||
from Java. They may be used to implement concurrency constraints, e.g.
|
||||
by suspending the current thread until some condition is met. In the
|
||||
browser embedding, these are used to maintain the run-to-completion
|
||||
semantics of JavaScript. It is acceptable for either function pointer
|
||||
to be NULL. */
|
||||
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp);
|
||||
void (*exit_js)(JNIEnv *jEnv);
|
||||
|
||||
/* Most LiveConnect errors are signaled by calling JS_ReportError(), but in
|
||||
some circumstances, the target JSContext for such errors is not
|
||||
determinable, e.g. during initialization. In such cases any error
|
||||
messages are routed to this function. If the function pointer is set to
|
||||
NULL, error messages are sent to stderr. */
|
||||
void (*error_print)(const char *error_msg);
|
||||
|
||||
/* This enables liveconnect to ask the VM for a java wrapper so that VM gets a chance to
|
||||
store a mapping between a jsobject and java wrapper. So the unwrapping can be done on the
|
||||
VM side before calling nsILiveconnect apis. This saves on a round trip request. */
|
||||
jobject (*get_java_wrapper)(JNIEnv *jEnv, jint jsobject);
|
||||
|
||||
/* The following set of methods abstract over the JavaVM object. */
|
||||
PRBool (*create_java_vm)(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs);
|
||||
PRBool (*destroy_java_vm)(SystemJavaVM* jvm, JNIEnv* initialEnv);
|
||||
JNIEnv* (*attach_current_thread)(SystemJavaVM* jvm);
|
||||
PRBool (*detach_current_thread)(SystemJavaVM* jvm, JNIEnv* env);
|
||||
SystemJavaVM* (*get_java_vm)(JNIEnv* env);
|
||||
|
||||
/* Reserved for future use */
|
||||
void * reserved[10];
|
||||
} JSJCallbacks;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
/* A flag that denotes that a Java package has no sub-packages other than those
|
||||
explicitly pre-defined at the time of initialization. An access
|
||||
to a simple name within such a package, therefore, must either correspond to
|
||||
one of these explicitly pre-defined sub-packages or to a class within this
|
||||
package. It is reasonable for LiveConnect to signal an error if a simple
|
||||
name does not comply with these criteria. */
|
||||
#define PKG_SYSTEM 1
|
||||
|
||||
/* A flag that denotes that a Java package which might contain sub-packages
|
||||
that are not pre-defined at initialization time, because the sub-packages
|
||||
may not be the same in all installations. Therefore, an access to a simple
|
||||
name within such a a package which does not correspond to either a
|
||||
pre-defined sub-package or to a class, must be assummed to refer to an
|
||||
unknown sub-package. This behavior may cause bogus JavaPackage objects to be
|
||||
created if a package name is misspelled, e.g. sun.oi.net. */
|
||||
#define PKG_USER 2
|
||||
|
||||
/* A Java package defined at initialization time. */
|
||||
typedef struct JavaPackageDef {
|
||||
const char * name; /* e.g. "java.lang" */
|
||||
const char * path; /* e.g. "java/lang", or NULL for default */
|
||||
int flags; /* PKG_USER, PKG_SYSTEM, etc. */
|
||||
} JavaPackageDef;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The following two convenience functions present a complete, but simplified
|
||||
LiveConnect API which is designed to handle the special case of a single
|
||||
Java-VM, with single-threaded operation, and the use of only one JSContext.
|
||||
The full API is in the section below. */
|
||||
|
||||
/* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
reflection and by defining JavaPackage objects for the default Java packages
|
||||
as properties of global_obj. If java_vm is NULL, a new Java VM is
|
||||
created, using the provided classpath in addition to any default classpath.
|
||||
The classpath argument is ignored, however, if java_vm is non-NULL. */
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_SimpleInit(JSContext *cx, JSObject *global_obj,
|
||||
SystemJavaVM *java_vm, const char *classpath);
|
||||
|
||||
/* Free up all resources. Destroy the Java VM if it was created by LiveConnect */
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_SimpleShutdown();
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The "full" LiveConnect API, required when more than one thread, Java VM, or
|
||||
JSContext is involved. Initialization pseudocode might go roughly like
|
||||
this:
|
||||
|
||||
JSJ_Init() // Setup callbacks
|
||||
for each JavaVM {
|
||||
JSJ_ConnectToJavaVM(...)
|
||||
}
|
||||
for each JSContext {
|
||||
JSJ_InitJSContext(...)
|
||||
}
|
||||
for each JS evaluation {
|
||||
run JavaScript code in the JSContext;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Called once for all instances of LiveConnect to set up callbacks */
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_Init(JSJCallbacks *callbacks);
|
||||
|
||||
/* Called once per Java VM, this function initializes the classes, fields, and
|
||||
methods required for Java reflection. If java_vm is NULL, a new Java VM is
|
||||
created according to the create_java_vm callback in the JSJCallbacks,
|
||||
using the provided classpath in addition to any default initargs.
|
||||
The initargs argument is ignored, however, if java_vm is non-NULL. */
|
||||
PR_IMPLEMENT(JSJavaVM *)
|
||||
JSJ_ConnectToJavaVM(SystemJavaVM *java_vm, void* initargs);
|
||||
|
||||
/* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
reflection and by defining JavaPackage objects for the default Java packages
|
||||
as properties of global_obj. Additional packages may be pre-defined by
|
||||
setting the predefined_packages argument. (Pre-defining a Java package at
|
||||
initialization time is not necessary, but it will make package lookup faster
|
||||
and, more importantly, will avoid unnecessary network accesses if classes
|
||||
are being loaded over the network.) */
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_InitJSContext(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *predefined_packages);
|
||||
|
||||
/* This function returns a structure that encapsulates the Java and JavaScript
|
||||
execution environment for the current native thread. It is intended to
|
||||
be called from the embedder's implementation of JSJCallback's
|
||||
map_js_context_to_jsj_thread() function. The thread_name argument is only
|
||||
used for debugging purposes and can be set to NULL. The Java JNI
|
||||
environment associated with this thread is returned through the java_envp
|
||||
argument if java_envp is non-NULL. */
|
||||
PR_IMPLEMENT(JSJavaThreadState *)
|
||||
JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *thread_name,
|
||||
JNIEnv **java_envp);
|
||||
|
||||
/* Destructor routine for per-thread JSJavaThreadState structure */
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env);
|
||||
|
||||
/* This function is used to specify a particular JSContext as *the* JavaScript
|
||||
execution environment to be used when LiveConnect is accessed from the given
|
||||
Java thread, i.e. when one of the methods of netscape.javascript.JSObject
|
||||
has been called. There can only be one such JS context for any given Java
|
||||
thread at a time. (To multiplex JSContexts among a single thread, this
|
||||
function could be called before Java is invoked on that thread.) The return
|
||||
value is the previous JSContext associated with the given Java thread.
|
||||
|
||||
If this function has not been called for a thread and a crossing is made
|
||||
into JavaScript from Java, the map_jsj_thread_to_js_context() callback will
|
||||
be invoked to determine the JSContext for the thread. The purpose of the
|
||||
function is to improve performance by avoiding the expense of the callback.
|
||||
*/
|
||||
PR_IMPLEMENT(JSContext *)
|
||||
JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env);
|
||||
|
||||
/* This routine severs the connection to a Java VM, freeing all related resources.
|
||||
It shouldn't be called until the global scope has been cleared in all related
|
||||
JSContexts (so that all LiveConnect objects are finalized) and a JavaScript
|
||||
GC is performed. Otherwise, accessed to free'ed memory could result. */
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_DisconnectFromJavaVM(JSJavaVM *);
|
||||
|
||||
/*
|
||||
* Reflect a Java object into a JS value. The source object, java_obj, must
|
||||
* be of type java.lang.Object or a subclass and may, therefore, be an array.
|
||||
*/
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
#endif /* _JSJAVA_H */
|
||||
182
mozilla/js/src/liveconnect/makefile.win
Normal file
182
mozilla/js/src/liveconnect/makefile.win
Normal file
@@ -0,0 +1,182 @@
|
||||
# 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.
|
||||
|
||||
IGNORE_MANIFEST=1
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Makefile to build the Java reflections of JavaScript objects
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Specify the depth of the current directory relative to the
|
||||
#// root of NS
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DEPTH= ..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
!ifdef NSJVM
|
||||
DIRS = classes
|
||||
!endif
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DLLNAME=jsj$(MOZ_BITS)$(VERSION_NUMBER)
|
||||
PDBFILE=$(DLLNAME).pdb
|
||||
MAPFILE = $(DLLNAME).map
|
||||
RESFILE = jsj1640.res
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
MAKE_OBJ_TYPE = DLL
|
||||
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
DEFFILE = $(DLLNAME).def
|
||||
!endif
|
||||
|
||||
LLIBS=$(LIBNSPR) $(DIST)\lib\js$(MOZ_BITS)$(VERSION_NUMBER).lib \
|
||||
$(DIST)\lib\xpcom32.lib
|
||||
|
||||
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
|
||||
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define the files necessary to build the target (ie. OBJS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
OBJS= \
|
||||
.\$(OBJDIR)\jsj.obj \
|
||||
.\$(OBJDIR)\jsj_JSObject.obj \
|
||||
.\$(OBJDIR)\jsj_JavaArray.obj \
|
||||
.\$(OBJDIR)\jsj_JavaClass.obj \
|
||||
.\$(OBJDIR)\jsj_JavaMember.obj \
|
||||
.\$(OBJDIR)\jsj_JavaObject.obj \
|
||||
.\$(OBJDIR)\jsj_JavaPackage.obj \
|
||||
.\$(OBJDIR)\jsj_array.obj \
|
||||
.\$(OBJDIR)\jsj_class.obj \
|
||||
.\$(OBJDIR)\jsj_convert.obj \
|
||||
.\$(OBJDIR)\jsj_field.obj \
|
||||
.\$(OBJDIR)\jsj_hash.obj \
|
||||
.\$(OBJDIR)\jsj_method.obj \
|
||||
.\$(OBJDIR)\jsj_utils.obj \
|
||||
.\$(OBJDIR)\nsCLiveconnect.obj \
|
||||
.\$(OBJDIR)\nsCLiveconnectFactory.obj \
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
.\$(OBJDIR)\jsj_nodl.obj \
|
||||
!endif
|
||||
$(NULL)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// install headers
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
INSTALL_DIR=$(PUBLIC)\js
|
||||
INSTALL_FILE_LIST= \
|
||||
jsjava.h nsILiveconnect.h
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
|
||||
#// (these must be defined before the common makefiles are included)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifdef NSJVM
|
||||
JNI_GEN= \
|
||||
netscape.javascript.JSObject \
|
||||
netscape.javascript.JSException \
|
||||
$(NULL)
|
||||
|
||||
!endif
|
||||
|
||||
MODULE = java
|
||||
EXPORTS = \
|
||||
$(JNI_GEN_DIR)\netscape_javascript_JSObject.h \
|
||||
$(JNI_GEN_DIR)\netscape_javascript_JSException.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any local options for the make tools
|
||||
#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
LINCS=$(LINCS) -I$(JNI_GEN_DIR) \
|
||||
-I$(PUBLIC)\js \
|
||||
-I$(PUBLIC)\java \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
$(NULL)
|
||||
|
||||
|
||||
#!ifdef SERVER_BUILD
|
||||
#LLIBS=$(DIST)/lib/httpdlw.lib $(DIST)/lib/libsjboot.lib
|
||||
#!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Include the common makefile rules
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
export:: INSTALL_FILES
|
||||
|
||||
libs:: $(DLL)
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
|
||||
|
||||
####
|
||||
# this bit of extreme scariness came from the js/src makefile
|
||||
# reproduced here since that's where jsjava.c lives now...
|
||||
|
||||
!if ("$(MOZ_BITS)" == "16")
|
||||
#//
|
||||
#// Win16 Hoovers SO BAD!!!
|
||||
#//
|
||||
|
||||
!if !defined(MOZ_DEBUG)
|
||||
#//
|
||||
#// We must turn off codeview debug info so jni.c can build.
|
||||
#// Otherwise the linker gives errors about data in the $SYMBOLS
|
||||
#// segment being beyond a segment boundary.
|
||||
#//
|
||||
$(OBJDIR)\jsjava.obj: jsjava.c
|
||||
@$(CC) @<<$(CFGFILE)
|
||||
-c
|
||||
-Od
|
||||
$(CFLAGS)
|
||||
$(LCFLAGS)
|
||||
$(LINCS)
|
||||
$(LINCS_1)
|
||||
$(INCS)
|
||||
-Fd$(PDBFILE)
|
||||
-Fo.\$(OBJDIR)\
|
||||
$(*B).c
|
||||
<<KEEP
|
||||
!endif
|
||||
!endif
|
||||
111
mozilla/js/src/liveconnect/netscape_javascript_JSObject.h
Normal file
111
mozilla/js/src/liveconnect/netscape_javascript_JSObject.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright (C) 1998 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
#include <jni.h>
|
||||
/* Header for class netscape_javascript_JSObject */
|
||||
|
||||
#ifndef _Included_netscape_javascript_JSObject
|
||||
#define _Included_netscape_javascript_JSObject
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: initClass
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getMember
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getSlot
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot
|
||||
(JNIEnv *, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setMember
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember
|
||||
(JNIEnv *, jobject, jstring, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setSlot
|
||||
* Signature: (ILjava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot
|
||||
(JNIEnv *, jobject, jint, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: removeMember
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: call
|
||||
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call
|
||||
(JNIEnv *, jobject, jstring, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: eval
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: toString
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getWindow
|
||||
* Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: finalize
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: equals
|
||||
* Signature: (Ljava/lang/Object;)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_netscape_javascript_JSObject_equals
|
||||
(JNIEnv *, jobject, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
567
mozilla/js/src/liveconnect/nsCLiveconnect.cpp
Normal file
567
mozilla/js/src/liveconnect/nsCLiveconnect.cpp
Normal file
@@ -0,0 +1,567 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the implementation providing nsIFactory XP-COM interface.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "prtypes.h"
|
||||
#include "prprf.h"
|
||||
#include "prlog.h"
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
#ifdef XP_MAC
|
||||
#include "prosdep.h"
|
||||
#endif
|
||||
|
||||
#include "jsj_private.h"
|
||||
#include "jsjava.h"
|
||||
|
||||
#include "jscntxt.h" /* For js_ReportErrorAgain().
|
||||
TODO - get rid of private header */
|
||||
|
||||
#include "netscape_javascript_JSObject.h" /* javah-generated headers */
|
||||
|
||||
|
||||
/* A captured JavaScript error, created when JS_ReportError() is called while
|
||||
running JavaScript code that is itself called from Java. */
|
||||
struct CapturedJSError {
|
||||
char * message;
|
||||
JSErrorReport report; /* Line # of error, etc. */
|
||||
jthrowable java_exception; /* Java exception, error, or null */
|
||||
CapturedJSError * next; /* Next oldest captured JS error */
|
||||
};
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#include "nsCLiveconnect.h"
|
||||
|
||||
static NS_DEFINE_IID(kILiveconnectIID, NS_ILIVECONNECT_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports and AggregatedQueryInterface:
|
||||
|
||||
// Thes macro expands to the aggregated query interface scheme.
|
||||
|
||||
NS_IMPL_AGGREGATED(nsCLiveconnect);
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnect::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = GetInner();
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kILiveconnectIID)) {
|
||||
*aInstancePtr = this;
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsILiveconnect:
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member. If it is a basic data type it is converted to
|
||||
* a corresponding java type. If it is a NJSObject, then it is
|
||||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject *pjobj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null member name");
|
||||
member = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (!JS_GetProperty(cx, js_obj, name, &js_val))
|
||||
goto done;
|
||||
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &member, &dummy_bool);
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*pjobj = member;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject *pjobj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// =-= sudu: check to see if slot can be passed in as is.
|
||||
// Should it be converted to a jsint?
|
||||
if (!JS_GetElement(cx, js_obj, slot, &js_val))
|
||||
goto done;
|
||||
if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &member, &dummy_bool))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*pjobj = member;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::SetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject java_obj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null member name");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
|
||||
goto done;
|
||||
|
||||
JS_SetProperty(cx, js_obj, name, &js_val);
|
||||
|
||||
done:
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::SetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject java_obj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jsval js_val = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
|
||||
goto done;
|
||||
JS_SetElement(cx, js_obj, slot, &js_val);
|
||||
|
||||
done:
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* remove member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::RemoveMember(JNIEnv *jEnv, jsobject obj, const char *name)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jsval js_val = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null member name");
|
||||
goto done;
|
||||
}
|
||||
JS_DeleteProperty2(cx, js_obj, name, &js_val);
|
||||
|
||||
done:
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* call a method of Native JSObject.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a method.
|
||||
* @param jobjArr - Array of jobjects representing parameters of method being caled.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::Call(JNIEnv *jEnv, jsobject obj, const char *name, jobjectArray java_args, jobject *pjobj)
|
||||
{
|
||||
int i = 0;
|
||||
int argc = 0;
|
||||
int arg_num = 0;
|
||||
jsval *argv = 0;
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
jsval function_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
jobject result = NULL;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
result = NULL;
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null JavaScript function name");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: What about security stuff ? Don't principals need to be set here ? */
|
||||
|
||||
/* Allocate space for JS arguments */
|
||||
if (java_args) {
|
||||
argc = jEnv->GetArrayLength(java_args);
|
||||
argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval));
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = 0;
|
||||
}
|
||||
|
||||
/* Convert arguments from Java to JS values */
|
||||
for (arg_num = 0; arg_num < argc; arg_num++) {
|
||||
jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num);
|
||||
|
||||
if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]))
|
||||
goto cleanup_argv;
|
||||
JS_AddRoot(cx, &argv[arg_num]);
|
||||
}
|
||||
|
||||
if (!JS_GetProperty(cx, js_obj, name, &function_val))
|
||||
goto cleanup_argv;
|
||||
|
||||
if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val))
|
||||
goto cleanup_argv;
|
||||
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &result, &dummy_bool);
|
||||
|
||||
cleanup_argv:
|
||||
if (argv) {
|
||||
for (i = 0; i < arg_num; i++)
|
||||
JS_RemoveRoot(cx, &argv[i]);
|
||||
JS_free(cx, argv);
|
||||
}
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*pjobj = result;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate a script with a Native JS Object representing scope.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param pNSIPrincipaArray - Array of principals to be used to compare privileges.
|
||||
* @param numPrincipals - Number of principals being passed.
|
||||
* @param script - Script to be executed.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::Eval(JNIEnv *jEnv, jsobject obj, const char *script, jobject *pjobj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
jsval function_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
jobject result = NULL;
|
||||
const char *codebase = NULL;
|
||||
JSPrincipals *principals = NULL;
|
||||
JSBool eval_succeeded = PR_FALSE;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
|
||||
result = NULL;
|
||||
if (!script) {
|
||||
JS_ReportError(cx, "illegal null string eval argument");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* Set up security stuff */
|
||||
principals = NULL;
|
||||
if (JSJ_callbacks->get_JSPrincipals_from_java_caller)
|
||||
principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx);
|
||||
codebase = principals ? principals->codebase : NULL;
|
||||
|
||||
/* Have the JS engine evaluate the unicode string */
|
||||
eval_succeeded = JS_EvaluateScriptForPrincipals(cx, js_obj, principals,
|
||||
script, strlen(script),
|
||||
codebase, 0, &js_val);
|
||||
if (!eval_succeeded)
|
||||
goto done;
|
||||
|
||||
/* Convert result to a subclass of java.lang.Object */
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &result, &dummy_bool);
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NULL;
|
||||
|
||||
*pjobj = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param pJavaObject - Either a jobject or a pointer to a plugin instance
|
||||
* representing the java object.
|
||||
* @param pjobj - return value. This is a native js object
|
||||
* representing the window object of a frame
|
||||
* in which a applet/bean resides.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject, jsobject *pobj)
|
||||
{
|
||||
char *err_msg = NULL;
|
||||
JSContext *cx = NULL;
|
||||
JSObject *js_obj = NULL;
|
||||
jsval js_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
jobject java_obj = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
|
||||
err_msg = NULL;
|
||||
java_obj = NULL;
|
||||
js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, pJavaObject, &err_msg);
|
||||
if (!js_obj) {
|
||||
if (err_msg) {
|
||||
JS_ReportError(cx, err_msg);
|
||||
free(err_msg);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
#if 0
|
||||
js_val = OBJECT_TO_JSVAL(js_obj);
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &java_obj, &dummy_bool);
|
||||
#endif
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NULL;
|
||||
|
||||
//*pjobj = java_obj;
|
||||
*pobj = (jint)js_obj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, jsobject obj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env) /* Note: memory leak if we exit here */
|
||||
return NS_ERROR_FAILURE;
|
||||
#ifdef PRESERVE_JSOBJECT_IDENTITY
|
||||
jsj_remove_js_obj_reflection_from_hashtable(cx, js_obj);
|
||||
#endif /* PRESERVE_JSOBJECT_IDENTITY */
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnect:
|
||||
|
||||
nsCLiveconnect::nsCLiveconnect(nsISupports *aOuter)
|
||||
{
|
||||
NS_INIT_AGGREGATED(aOuter);
|
||||
jsj_init_js_obj_reflections_table();
|
||||
}
|
||||
|
||||
nsCLiveconnect::~nsCLiveconnect()
|
||||
{
|
||||
}
|
||||
|
||||
166
mozilla/js/src/liveconnect/nsCLiveconnect.h
Normal file
166
mozilla/js/src/liveconnect/nsCLiveconnect.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains class definition implementing the public interface.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the class definition to implement nsILiveconnect XP-COM interface.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef nsCLiveconnect_h___
|
||||
#define nsCLiveconnect_h___
|
||||
|
||||
#include "nsILiveconnect.h"
|
||||
#include "nsAgg.h"
|
||||
|
||||
|
||||
/**
|
||||
* nsCLiveconnect implements nsILiveconnect interface for navigator.
|
||||
* This is used by a JVM to implement netscape.javascript.JSObject functionality.
|
||||
*/
|
||||
class nsCLiveconnect :public nsILiveconnect {
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports and AggregatedQueryInterface:
|
||||
|
||||
NS_DECL_AGGREGATED
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsILiveconnect:
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member. If it is a basic data type it is converted to
|
||||
* a corresponding java type. If it is a NJSObject, then it is
|
||||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetSlot(JNIEnv *jEnv, jsobject obj, int index, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject jobj);
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject jobj);
|
||||
|
||||
/**
|
||||
* remove member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
RemoveMember(JNIEnv *jEnv, jsobject obj, const char *name);
|
||||
|
||||
/**
|
||||
* call a method of Native JSObject.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a method.
|
||||
* @param jobjArr - Array of jobjects representing parameters of method being caled.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Call(JNIEnv *jEnv, jsobject obj, const char *name, jobjectArray jobjArr, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* Evaluate a script with a Native JS Object representing scope.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param pNSIPrincipaArray - Array of principals to be used to compare privileges.
|
||||
* @param numPrincipals - Number of principals being passed.
|
||||
* @param script - Script to be executed.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
//Eval(JNIEnv *jEnv, jsobject obj, nsIPrincipal **pNSIPrincipaArray, PRInt32 numPrincipals, const char *script, jobject *pjobj);
|
||||
Eval(JNIEnv *jEnv, jsobject obj, const char *script, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param pJavaObject - Either a jobject or a pointer to a plugin instance
|
||||
* representing the java object.
|
||||
* @param pjobj - return value. This is a native js object
|
||||
* representing the window object of a frame
|
||||
* in which a applet/bean resides.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetWindow(JNIEnv *jEnv, void *pJavaObject, jsobject *pobj);
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
FinalizeJSObject(JNIEnv *jEnv, jsobject obj);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnect:
|
||||
|
||||
nsCLiveconnect(nsISupports *aOuter);
|
||||
virtual ~nsCLiveconnect(void);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // nsCLiveconnect_h___
|
||||
168
mozilla/js/src/liveconnect/nsCLiveconnectFactory.cpp
Normal file
168
mozilla/js/src/liveconnect/nsCLiveconnectFactory.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the implementation providing nsILiveconnect XP-COM interface.
|
||||
*
|
||||
*/
|
||||
#include "prtypes.h"
|
||||
#include "nspr.h"
|
||||
#include "prmem.h"
|
||||
#include "prmon.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsCLiveconnect.h"
|
||||
#include "nsCLiveconnectFactory.h"
|
||||
#include "nsRepository.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
static NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
|
||||
static NS_DEFINE_IID(kILiveconnectIID, NS_ILIVECONNECT_IID);
|
||||
|
||||
nsIFactory *nsCLiveconnectFactory::m_pNSIFactory = NULL;
|
||||
nsCLiveconnect *nsCLiveconnectFactory::m_pNSCLiveconnect = NULL;
|
||||
|
||||
|
||||
|
||||
/*+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* NSGetFactory:
|
||||
* Provides entry point to liveconnect dll.
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
extern "C" NS_EXPORT nsresult
|
||||
NSGetFactory(const nsCID &aClass, nsIFactory **aFactory)
|
||||
{
|
||||
|
||||
if (!aClass.Equals(kCLiveconnectCID)) {
|
||||
return NS_ERROR_FACTORY_NOT_LOADED; // XXX right error?
|
||||
}
|
||||
nsCLiveconnectFactory* pCLiveConnectFactory = new nsCLiveconnectFactory();
|
||||
if (pCLiveConnectFactory == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
pCLiveConnectFactory->AddRef();
|
||||
*aFactory = pCLiveConnectFactory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT PRBool
|
||||
NSCanUnload(void)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnectFactory::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
PR_ASSERT(NULL != aInstancePtr);
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kIFactoryIID) ||
|
||||
aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*) this;
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsCLiveconnectFactory)
|
||||
NS_IMPL_RELEASE(nsCLiveconnectFactory)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsIFactory:
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnectFactory::CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
nsCLiveconnect *pNSCLiveconnect = NULL;
|
||||
*aResult = NULL;
|
||||
|
||||
if (aOuter && !aIID.Equals(kISupportsIID))
|
||||
return NS_NOINTERFACE; // XXX right error?
|
||||
if (m_pNSCLiveconnect == NULL)
|
||||
{
|
||||
m_pNSCLiveconnect = new nsCLiveconnect(aOuter);
|
||||
}
|
||||
if (m_pNSCLiveconnect == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (m_pNSCLiveconnect->QueryInterface(aIID,
|
||||
(void**)aResult) != NS_OK) {
|
||||
// then we're trying get a interface other than nsISupports and
|
||||
// nsICapsManager
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnectFactory::LockFactory(PRBool aLock)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnectFactory:
|
||||
|
||||
nsCLiveconnectFactory::nsCLiveconnectFactory(void)
|
||||
{
|
||||
if( m_pNSIFactory != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
nsresult err = NS_OK;
|
||||
NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
|
||||
err = this->QueryInterface(kIFactoryIID, (void**)&m_pNSIFactory);
|
||||
if ( (err == NS_OK) && (m_pNSIFactory != NULL) )
|
||||
{
|
||||
NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
|
||||
nsRepository::RegisterFactory(kCLiveconnectCID, m_pNSIFactory,
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
nsCLiveconnectFactory::~nsCLiveconnectFactory()
|
||||
{
|
||||
if(mRefCnt == 0)
|
||||
{
|
||||
NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
|
||||
nsRepository::UnregisterFactory(kCLiveconnectCID, (nsIFactory *)m_pNSIFactory);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
59
mozilla/js/src/liveconnect/nsCLiveconnectFactory.h
Normal file
59
mozilla/js/src/liveconnect/nsCLiveconnectFactory.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the class definition to implement nsIFactory XP-COM interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsCLiveconnectFactory_h___
|
||||
#define nsCLiveconnectFactory_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
|
||||
class nsCLiveconnectFactory : public nsIFactory {
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports and AggregatedQueryInterface:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsIFactory:
|
||||
|
||||
NS_IMETHOD
|
||||
CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
NS_IMETHOD
|
||||
LockFactory(PRBool aLock);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnectFactory:
|
||||
|
||||
nsCLiveconnectFactory(void);
|
||||
virtual ~nsCLiveconnectFactory(void);
|
||||
|
||||
protected:
|
||||
static nsIFactory *m_pNSIFactory;
|
||||
static nsCLiveconnect *m_pNSCLiveconnect;
|
||||
};
|
||||
|
||||
#endif // nsCLiveconnectFactory_h___
|
||||
157
mozilla/js/src/liveconnect/nsILiveconnect.h
Normal file
157
mozilla/js/src/liveconnect/nsILiveconnect.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the public XP-COM based interface for java to javascript communication.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsILiveconnect_h___
|
||||
#define nsILiveconnect_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "jni.h"
|
||||
|
||||
|
||||
typedef jint jsobject;
|
||||
|
||||
class nsILiveconnect : public nsISupports {
|
||||
public:
|
||||
/**
|
||||
* get member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member. If it is a basic data type it is converted to
|
||||
* a corresponding java type. If it is a NJSObject, then it is
|
||||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetSlot(JNIEnv *jEnv, jsobject obj, int index, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject jobj) = 0;
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject jobj) = 0;
|
||||
|
||||
/**
|
||||
* remove member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
RemoveMember(JNIEnv *jEnv, jsobject obj, const char *name) = 0;
|
||||
|
||||
/**
|
||||
* call a method of Native JSObject.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a method.
|
||||
* @param jobjArr - Array of jobjects representing parameters of method being caled.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Call(JNIEnv *jEnv, jsobject obj, const char *name, jobjectArray jobjArr, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* Evaluate a script with a Native JS Object representing scope.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param pNSIPrincipaArray - Array of principals to be used to compare privileges.
|
||||
* @param numPrincipals - Number of principals being passed.
|
||||
* @param script - Script to be executed.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
//Eval(jsobject obj, nsIPrincipal **pNSIPrincipaArray, PRInt32 numPrincipals, const char *script, jobject *pjobj) = 0;
|
||||
Eval(JNIEnv *jEnv, jsobject obj, const char *script, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param pJavaObject - Either a jobject or a pointer to a plugin instance
|
||||
* representing the java object.
|
||||
* @param pjobj - return value. This is a native js object
|
||||
* representing the window object of a frame
|
||||
* in which a applet/bean resides.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetWindow(JNIEnv *jEnv, void *pJavaObject, jsobject *pobj) = 0;
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
FinalizeJSObject(JNIEnv *jEnv, jsobject obj) = 0;
|
||||
|
||||
};
|
||||
|
||||
#define NS_ILIVECONNECT_IID \
|
||||
{ /* 68190910-3318-11d2-97f0-00805f8a28d0 */ \
|
||||
0x68190910, \
|
||||
0x3318, \
|
||||
0x11d2, \
|
||||
{0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \
|
||||
};
|
||||
|
||||
#define NS_CLIVECONNECT_CID \
|
||||
{ /* b8f0cef0-3931-11d2-97f0-00805f8a28d0 */ \
|
||||
0xb8f0cef0, \
|
||||
0x3931, \
|
||||
0x11d2, \
|
||||
{0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \
|
||||
};
|
||||
|
||||
#endif // nsILiveconnect_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__
|
||||
@@ -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